keepalived与nginx与MySQL
keepalived VRRP介绍
集群(cluster)技术是一种较新的技术,通过集群技术,可以在付出较低成本的情况下获得在性能、可靠性、灵活性方面的相对较高的收益,其任务调度则是集群系统中的核心技术。
集群组成后,可以利用多个计算机和组合进行海量请求处理(**负载均衡**),从而获得很高的处理效率,也可以用多个计算机做备份(高可用),使得任何一个机器坏了整个系统还是能正常运行。
keepalived工作原理
keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundancy Protocol,即虚拟路由冗余协议。虚拟路由冗余协议,可以认为是实现路由器高可用的协议,即将N台提供相同功能的路由器组成一个路由器组,这个组里面有一个master和多个backup,master上面有一个对外提供服务的vip(该路由器所在局域网内其他机器的默认路由为该vip),master会发组播,当backup收不到vrrp包时就认为master宕掉了,这时就需要根据VRRP的优先级来选举一个backup当master。这样的话就可以保证路由器的高可用了。
keepalived主要有三个模块,分别是core、check和vrrp。core模块为keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。check负责健康检查,包括常见的各种检查方式。vrrp模块是来实现VRRP协议的。
脑裂 split barin:
Keepalived的BACKUP主机在收到不MASTER主机报文后就会切换成为master,如果是它们之间的通信线路出现问题,无法接收到彼此的组播通知,但是两个节点实际都处于正常工作状态,这时两个节点均为master强行绑定虚拟IP,导致不可预料的后果,这就是脑裂。
解决方式:
1、添加更多的检测手段,比如冗余的心跳线(两块网卡做健康监测),ping对方等等。尽量减少"裂脑"发生机会。(指标不治本,只是提高了检测到的概率);
2、设置仲裁机制。两方都不可靠,那就依赖第三方。比如启用共享磁盘锁,ping网关等。(针对不同的手段还需具体分析);
3、爆头,将master停掉。然后检查机器之间的防火墙。网络之间的通信
Nginx+keepalived实现七层负载均衡
Nginx通过Upstream模块实现负载均衡
upstream支持的负载均衡算法
主机清单:
主机名 IP 系统 用途 Proxy-master 172.16.147.155 centos7.5 主负载 Proxy-slave 172.16.147.156 centos7.5 主备 Real-server1 172.16.147.153 Centos7.5 web1 Real-server2 172.16.147.154 centos7.5 Web2 Vip for proxy 172.16.147.100
配置安装nginx 所有的机器,关闭防火墙和selinux
[root@proxy-master ~]# systemctl stop firewalld //关闭防火墙
[root@proxy-master ~]# sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/sysconfig/selinux //关闭selinux,重启生效
[root@proxy-master ~]# setenforce 0 //关闭selinux,临时生效
安装nginx, 全部4台
[root@proxy-master ~]# cd /etc/yum.repos.d/
[root@proxy-master yum.repos.d]# vim nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1
[root@proxy-master yum.repos.d]# yum install yum-utils -y
[root@proxy-master yum.repos.d]# yum install nginx -y
一、实施过程
1、选择两台nginx服务器作为代理服务器。
2、给两台代理服务器安装keepalived制作高可用生成VIP
3、配置nginx的负载均衡
# 两台配置完全一样
[root@proxy-master ~]# vim /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {worker_connections 1024;
}
http {log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';access_log /var/log/nginx/access.log main;sendfile on;tcp_nopush on;tcp_nodelay on;keepalive_timeout 65;types_hash_max_size 2048;include /etc/nginx/mime.types;default_type application/octet-stream;include /etc/nginx/conf.d/*.conf;upstream backend {server 172.16.147.154:80 weight=1 max_fails=3 fail_timeout=20s;server 172.16.147.153:80 weight=1 max_fails=3 fail_timeout=20s;}server {listen 80;server_name localhost;location / {proxy_pass http://backend;proxy_set_header Host $host:$proxy_port;proxy_set_header X-Forwarded-For $remote_addr;}}
}
keepalived实现调度器HA
注:主/备调度器均能够实现正常调度
1. 主/备调度器安装软件
[root@proxy-master ~]# yum install -y keepalived
[root@proxy-slave ~]# yum install -y keepalived
[root@proxy-master ~]# cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak
[root@proxy-master ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalivedglobal_defs {router_id directory1 #辅助改为directory2
}vrrp_instance VI_1 {state MASTER #定义主还是备interface ens33 #VIP绑定接口virtual_router_id 80 #整个集群的调度器一致priority 100 #back改为50advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {172.16.147.100/24 # vip}
}[root@proxy-slave ~]# cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak
[root@proxy-slave ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalivedglobal_defs {router_id directory2
}vrrp_instance VI_1 {state BACKUP #设置为backupinterface ens33nopreempt #设置到back上面,不抢占资源virtual_router_id 80priority 50 #辅助改为50advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {172.16.147.100/24}
}
启动KeepAlived(主备均启动)
[root@proxy-master ~]# systemctl enable keepalived
[root@proxy-slave ~]# systemctl start keepalived
[root@proxy-master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet 172.16.147.100/32 scope global lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 00:0c:29:ec:8a:fe brd ff:ff:ff:ff:ff:ffinet 172.16.147.155/24 brd 172.16.147.255 scope global noprefixroute dynamic ens33valid_lft 1115sec preferred_lft 1115secinet 172.16.147.101/24 scope global secondary ens33valid_lft forever preferred_lft forever
可以解决心跳故障keepalived
不能解决Nginx服务故障
扩展对调度器Nginx健康检查(可选)两台都设置
思路:
让Keepalived以一定时间间隔执行一个外部脚本,脚本的功能是当Nginx失败,则关闭本机的Keepalived
(1) script
[root@proxy-master ~]# vim /etc/keepalived/check_nginx_status.sh
#!/bin/bash
/usr/bin/curl -I http://localhost &>/dev/null
if [ $? -ne 0 ];then
# /etc/init.d/keepalived stopsystemctl stop keepalived
fi
[root@proxy-master ~]# chmod a+x /etc/keepalived/check_nginx_status.sh
(2). keepalived使用script
! Configuration File for keepalivedglobal_defs {router_id director1
}
vrrp_script check_nginx {script "/etc/keepalived/check_nginx_status.sh"interval 5
}vrrp_instance VI_1 {state MASTERinterface ens33virtual_router_id 80priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.246.16/24}track_script {check_nginx}
}
注:必须先启动nginx,再启动keepalived
客户端访问的是虚拟VIP,由虚拟vip去连接负载均衡的ip,让负载均衡去访问后端的nginx页面。而keepalived是提供VIP的,服务器分为主备,当主服务器的keepalived开启时, 那么VIP就会在主服务器上。只有当主服务器的keepalived关闭时,VIP才会飘向备服务器,客户端访问的才是备负载均衡服务器的内容。
但是当主负载均衡服务器的nginx关闭时,不会影响vip的存在,他还会在主负载均衡服务器上,但是客户端访问的 时候会显示拒绝连接,因为vip是与负载均衡服务器的IP连接的,他是去找她的。
MySQL+Keepalived
项目环境: IP1:192.168.231.185 keepalived:master
IP2:192.168.231.187 keepalived:salve
VIP:192.168.231.66
俩台机器都做相同的操作:
安装MySQL
# yum -y install mysql-server mysql启动myslqd
# systemctl start mysqld查看密码,修改密码
grep password /var/log/mysqld.log修改密码
mysqladmin -uroot -p'旧密码' password '新密码'登录MySQL
mysql -p'password'创建远程登录这俩台mysql的用户grant all on *.* to 'root'@'%' identified by 'Qianfeng@123!';
为了体现实验结果
在IP1的数据库上创建数据库db1,IP2不创建数据库。
IP1创建新数据库:
create database db1;mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
安装keepalived
俩台机器安装keepalived
[root@mysql-keepalived-master ~]# yum -y install keepalived
[root@mysql-keepalived-slave ~]# yum -y install keepalived
修改配置文件
192.168.231.185的配置文件
# vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived
global_defs {router_id master
}
vrrp_instance VI_1 {state MASTER #定义主还是备interface ens33 #VIP绑定接口virtual_router_id 89 #整个集群的调度器一致priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.231.66/24 #定义的虚拟ip VIP}
}
192.168.231.187配置文件
! Configuration File for keepalivedglobal_defs {router_id backup
}
vrrp_instance VI_1 {state BACKUP #设置成backupnopreempt #设置到back上面,不抢占资源interface ens33virtual_router_id 89priority 50advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.231.66/24 #虚拟VIP}
}
主备同时启动keepalived
[root@proxy-master ~]# systemctl enable keepalived
[root@proxy-slave ~]# systemctl start keepalived
查看IP
[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 00:0c:29:b5:2b:5c brd ff:ff:ff:ff:ff:ffinet 192.168.231.185/24 brd 192.168.231.255 scope global noprefixroute dynamic ens33valid_lft 1348sec preferred_lft 1348secinet 192.168.231.66/24 scope global secondary ens33valid_lft forever preferred_lft forever
远程登录MySQL
在第三台拥有MySQL的服务器上进行远程登录MySQL
mysql -uroot -p'Qianfeng@123!' -h192.168.231.66 -P3306-p密码是之前在俩台服务器创建的用户
-h的IP是虚拟vip
-p是MySQL的端口3306
当IP1,keepalived开启,MySQL开启时,此时VIP在IP1上 查询到的是MySQL1
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
当IP1,keepalived关闭,IP1的MySQL开启时,此时VIP在IP2上 查询到的是MySQL2
mysql> show databases;
ERROR 2013 (HY000): Lost connection to MySQL server during query
mysql> show databases;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 18
Current database: *** NONE ***+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.01 sec)###连接到IP1的数据库切换到IP2的数据库上
当IP1,keepalived关闭,IP1的MySQL开启时,此时VIP在IP2上,接着将IP1的keepalived开启,那么此时vip会跑到IP1上, 查询到的是 MySQL1
mysql> show databases;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 4
Current database: *** NONE ***+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.01 sec)
当IP1的keepalived开启,IP1的MySQL开启,此时关闭IP1的MySQL,那么VIP还是在IP1上,那么此时查询到的数据库是 : 无法连接
mysql> show databases;
ERROR 2013 (HY000): Lost connection to MySQL server during query
mysql> show databases;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.231.66' (111)
ERROR:
Can't connect to the server
此时将IP1的keepalived也停掉,那么VIP会飘逸到IP2上,此时查询到的数据库是 MySQL2
mysql> show databases;
No connection. Trying to reconnect...
Connection id: 19
Current database: *** NONE ***+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
因此也就是说
客户端访问的是虚拟VIP,由虚拟vip去连接后端的MySQL。而keepalived是提供VIP的,服务器分为主备,当主服务器的keepalived开启时, 那么VIP就会在主服务器上。只有当主服务器的keepalived关闭时,VIP才会飘向备服务器,客户端访问的才是备服务器的内容。
但是当主服务器的MySQL关闭时,不会影响vip的存在,他还会在主服务器上,但是客户端访问的 时候会显示拒绝连接,因为vip是与MySQL服务器的IP连接的,他是去找她的。
在企业生产环境中,我们不可能一直在观察MySQL与keepalived的状态,那么我们需要使用脚本,但是脚本多久执行一次 回花费大量精力,这时候我们可以将脚本放至keepalived的配置文件中。只要检查到服务器的MySQL关闭,那么就会停止该服务器的keepalived。让其他服务器工作,从而保证了高可用
脚本:
vim keepalived_check_mysql.sh #!/bin/bash
/usr/bin/mysql -uroot -p'QianFeng@2019!' -e "show status" &>/dev/null
if [ $? -ne 0 ] ;then
# service keepalived stopsystemctl stop keepalived
fi
~
在keepalived的配置文件中引用
! Configuration File for keepalivedglobal_defs {router_id master
}
vrrp_script check_run { ####定义脚本script "/etc/keepalived/keepalived_chech_mysql.sh"interval 5
}vrrp_instance VI_1 {state MASTERinterface ens33virtual_router_id 89priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.231.66/24}track_script { ####引用脚本}
}
实验过程遇到的错误:
虚拟IP是自己提供的,避免虚拟ip在其他服务器上已经存在的情况
脚本的引用,可以不使用引号,或者使用双引号
相关文章:

keepalived与nginx与MySQL
keepalived VRRP介绍 集群(cluster)技术是一种较新的技术,通过集群技术,可以在付出较低成本的情况下获得在性能、可靠性、灵活性方面的相对较高的收益,其任务调度则是集群系统中的核心技术。 集群组成后,可…...
Pod基础概念
Pod是kubernetes中最小的资源管理组件,Pod也是最小化运行容器化应用的资源对象。一个Pod代表着集群中运行的一个进程。kubernetes中其他大多数组件都是围绕着Pod来进行支撑和扩展Pod功能的,例如,用于管理Pod运行的StatefulSet和Deployment等控…...

WebDAV之π-Disk派盘 + 一叶日记
推荐一款操作方便、界面简洁,记录生活点滴与心情,具有诗情画意的日记软件。 一叶日记是一款记录日记的手机软件,在这款软件中它里面有着各种不同的工具,可以方便用户去随时随地的记录日记,同时里面还有着各种不同的主题背景,可以供用户去选择使用各种功能,给用户记录带…...

在IDEA运行spark程序(搭建Spark开发环境)
建议大家写在Linux上搭建好Hadoop的完全分布式集群环境和Spark集群环境,以下在IDEA中搭建的环境仅仅是在window系统上进行spark程序的开发学习,在window系统上可以不用安装hadoop和spark,spark程序可以通过pom.xml的文件配置,添加…...
无穷级数例子
计算 lim x → ∞ ( 1 n 1 1 n 2 1 n 3 . . . 1 n 2 n − 1 1 n 2 n ) 计算\lim _{x\to \infty} (\frac{1}{n1} \frac{1}{n2}\frac{1}{n3} ... \frac{1}{n2n-1} \frac{1}{n2n} ) 计算x→∞lim(n11n21n31...n2n−11n2n1) 解: lim x …...

C++构造函数和析构函数详解
一、构造函数 1、概念 构造函数是特殊的成员函数,需要注意的是,构造函数虽然名叫做构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。 2、特征 函数名与类名相同。无返回值对象实例化时编译器自动调用对应的…...

MySQL数据库干货_16—— SQL99标准中的查询
SQL99标准中的查询 MySQL5.7 支持部分的SQL99 标准。 SQL99中的交叉连接(CROSS JOIN) 示例: 使用交叉连接查询 employees 表与 departments 表。 select * from employees cross join departments;SQL99中的自然连接(NATURAL JOIN) 自然连接 连接只能发生在两…...
LLM大语言模型训练中常见的技术:微调与嵌入
微调(Fine-Tuning): 微调是一种用于预训练语言模型的技术。在预训练阶段,语言模型(如GPT-3.5)通过大规模的文本数据集进行训练,从而学会了语言的语法、语义和世界知识。然后,在微调阶…...

每日一练 | 网络工程师软考真题Day47
阅读以下关于Linux文件系统和Samba效劳的说明,答复以下【问题1】至【问题3】。 【说明】 Linux系统采用了树型多级目录来管理文件,树型结构的最上层是根目录,其他的所有目录都是从根目录生成的。通过Samba可以实现基于Linux操作系统的效劳器和…...

Kafka - 监控工具 Kafka Eagle:实时洞察Kafka集群的利器
文章目录 引言Kafka Eagle简介Kafka Eagle的特点Kafka Eagle的优势使用Kafka Eagle的步骤结论 引言 在现代大数据架构中,Apache Kafka已成为一个不可或缺的组件,用于可靠地处理和传输大规模的数据流。然而,随着Kafka集群规模的不断增长&…...
infercnv hpc东南服务器 .libpath 最终使用monocle2环境安装
安装不成功就用conda安装 conda install -c bioconda bioconductor-infercnv Installing infercnv There are several options for installing inferCNV. Choose whichever you prefer: Option A: Install infercnv from BioConductor (preferred) From within R, run the…...

【音视频 | Ogg】RFC3533 :Ogg封装格式版本 0(The Ogg Encapsulation Format Version 0)
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…...
Hadoop时代落幕,开源大数据将何去何从?
Hadoop时代落幕,谁是大数据的新宠儿? 1、 1、...

作为一名程序员面临哪些挑战?应该如何应对?
在现今互联网失业潮的大环境下,每一位程序员都面临着被淘汰的风险,但逃避没有用,今天我们就来总结这些挑战与风险,找准自己的方向与定位,做好职业规划,希望这些信息能对大家有所帮助。 一、面临的挑战 老…...

flink的安装与使用(ubuntu)
组件版本 虚拟机:ubuntu-20.04.6-live-server-amd64.iso flink:flink-1.18.0-bin-scala_2.12.tgz jdk:jdk-8u291-linux-x64.tar flink 下载 1、官网:https://flink.apache.org/downloads/ 2、清华镜像:https://mirr…...

容器:软件性能测试的最佳环境
容器总体上提供了一种经济的和可扩展的方法来测试产品在实际情况下的性能,同时还能保持较低的资源成本和开销成本。 软件性能和可伸缩性是我们谈论应用程序开发时经常遇到的话题。一个很大的原因是应用程序的性能和可伸缩性直接影响其在市场上的成功。一个应用程序…...

【Qt控件之QMovie】详解
Qt控件之QMovies 概述公共类型属性公共函数公共槽函数信号静态公共成员示例使用场景 概述 QMovie类是一个方便的类,用于播放具有QImageReader的动画。此类用于显示没有声音的简单动画。如果您想显示视频和媒体内容,请改用Qt多媒体框架Qt Multimedia mul…...

Star History 九月开源精选 |开源 GitHub Copilot 替代
虽然大火了近一年,但是截至目前 AI 唯一破圈的场景是帮助写代码(谷歌云旗下的 DORA 年度报告也给 AI 泼了盆冷水)。不过对于软件开发来说,生成式人工智能绝对已经是新的标配。 本期 Star History 收集了一些开源 GitHub Copilot …...

【Rabbit MQ】Rabbit MQ 消息的可靠性 —— 生产者和消费者消息的确认,消息的持久化以及消费失败的重试机制
文章目录 前言:消息的可靠性问题一、生产者消息的确认1.1 生产者确认机制1.2 实现生产者消息的确认1.3 验证生产者消息的确认 二、消息的持久化2.1 演示消息的丢失2.2 声明持久化的交换机和队列2.3 发送持久化的消息 三、消费者消息的确认3.1 配置消费者消息确认3.2…...
C++设计模式_25_Interpreter 解析器
Interpreter 解析器被归为“领域规则”模式。Interpreter模式比较适合简单的文法表示,应用场景是比较有限的,解决问题的思路和场景都是一样的。 文章目录 1. “领域规则”模式1.1 典型模式2. 动机( Motivation)3. 代码演示Interpreter 解析器模式4. 模式定义5. 结构( Structu…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...