当前位置: 首页 > news >正文

Keepalived实现LVS高可用

6.1 Keepalived+LVS集群介绍

  • Keepalived和LVS共同构建了一个高效的负载均衡和高可用性解决方案:LVS作为负载均衡器,负责在集群中的多个服务器间分配流量,以其高性能和可扩展性确保应用程序能够处理大量的并发请求;而Keepalived则作为高可用性保证,通过VRRP协议监控LVS服务的状态并在主服务器发生故障时自动进行故障转移,确保服务的持续可用性和无感知切换。这种结合利用了两者的优势,为关键的网络服务提供了一个稳定、可靠且高效的运行环境。

image-20240506100440332

机器名称IP地址子网掩码说明
Keepalived-01192.168.110.31255.255.255.0负载均衡+高可用
Keepalived-02192.168.110.32255.255.255.0负载均衡+高可用
RS1192.168.110.33255.255.255.0真实服务器1
RS2192.168.110.34255.255.255.0真实服务器2
Client192.168.110.35255.255.255.0客户端

6.2 后端RS配置

  • 配置系统服务脚本

[root@LVS-RS1 ~]# vim /etc/init.d/LVS_RS
#!/bin/bash
​
# Startup script to handle the initialisation of LVS
# chkconfig: - 28 72
# description: Initialise the Linux Virtual Server for DR
# Provides: ipvsadm
# Required-Start: $local_fs $network $named
# Required-Stop: $local_fs $remote_fs $network
# Short-Description: Initialise the Linux Virtual Server
# Description: The Linux Virtual Server is a highly scalable and highly
# available server built on a cluster of real servers, with the load
# balancer running on Linux.LOCK=/var/lock/ipvsadm.lock
VIP=192.168.110.10
​
. /etc/rc.d/init.d/functions
​
start() {PID=`ifconfig | grep lo:20 | wc -l`if [ $PID -ne 0 ]; thenecho "The LVS-DR-RIP Server is already running !"else/sbin/ifconfig lo:20 $VIP netmask 255.255.255.255 broadcast $VIP up/sbin/route add -host $VIP dev lo:20echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignoreecho "2" >/proc/sys/net/ipv4/conf/lo/arp_announceecho "1" >/proc/sys/net/ipv4/conf/all/arp_ignoreecho "2" >/proc/sys/net/ipv4/conf/all/arp_announce/bin/touch $LOCKecho "starting LVS-DR-RIP server is ok !"fi
}
​
stop() {/sbin/route del -host $VIP dev lo:20/sbin/ifconfig lo:20 down >/dev/nullecho "0" >/proc/sys/net/ipv4/conf/lo/arp_ignoreecho "0" >/proc/sys/net/ipv4/conf/lo/arp_announceecho "0" >/proc/sys/net/ipv4/conf/all/arp_ignoreecho "0" >/proc/sys/net/ipv4/conf/all/arp_announcerm -rf $LOCKecho "stopping LVS-DR-RIP server is ok !"
}
​
status() {if [ -e $LOCK ]; thenecho "The LVS-DR-RIP Server is already running !"elseecho "The LVS-DR-RIP Server is not running !"fi
}
​
case "$1" instart)start;;stop)stop;;restart)stopstart;;status)status;;*)echo "Usage: $1 {start|stop|restart|status}"exit 1
esac
exit 0
​
[root@LVS-RS1 ~]# chmod +x /etc/init.d/LVS_RS 
[root@LVS-RS1 ~]# chkconfig --add LVS_RS 
[root@LVS-RS1 ~]# systemctl start LVS_RS.service 
[root@LVS-RS1 ~]# scp /etc/init.d/LVS_RS 192.168.110.34:/etc/init.d/   #发给另一台RS
​
[root@LVS-RS2 ~]# chmod +x /etc/init.d/LVS_RS 
[root@LVS-RS2 ~]# chkconfig --add LVS_RS 
[root@LVS-RS2 ~]# systemctl start LVS_RS.service 

6.3 Keepalived配置

6.3.1 基于TCP的健康检测

6.3.1.1 Keepalived-01配置
[root@Keepalived-01 ~]# cp /etc/keepalived/keepalived.conf{,.bak}
[root@Keepalived-01 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
​
global_defs {router_id LVS_node1
}
​
vrrp_instance LVS {state MASTERinterface ens160virtual_router_id 51priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.110.10}
}
​
virtual_server 192.168.110.10 80 {delay_loop 6  lb_algo rrlb_kind DRprotocol TCP
​real_server 192.168.110.33 80 {weight 1TCP_CHECK {connect_timeout 3retry 3delay_before_retry 3connect_port 80}}real_server 192.168.110.34 80 {weight 1TCP_CHECK {connect_timeout 3retry 3delay_before_retry 3connect_port 80}}
}
​
​
[root@Keepalived-01 ~]# systemctl start keepalived.service
[root@Keepalived-01 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.110.10:80 rr-> 192.168.110.33:80            Route   1      0          0         -> 192.168.110.34:80            Route   1      0          0 
6.3.1.2 Keepalived-02配置
[root@Keepalived-02 ~]# cp /etc/keepalived/keepalived.conf{,.bak}
[root@Keepalived-02 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
​
global_defs {router_id LVS_node2
}
​
vrrp_instance LVS {state MASTERinterface ens160virtual_router_id 51priority 80advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.110.10}
}
​
virtual_server 192.168.110.10 80 {delay_loop 6  lb_algo rrlb_kind DRprotocol TCP
​real_server 192.168.110.33 80 {weight 1TCP_CHECK {connect_timeout 3retry 3delay_before_retry 3connect_port 80}}real_server 192.168.110.34 80 {weight 1TCP_CHECK {connect_timeout 3retry 3delay_before_retry 3connect_port 80}}
}
​
[root@Keepalived-02 ~]# systemctl start keepalived.service
[root@Keepalived-02 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.110.10:80 rr-> 192.168.110.33:80            Route   1      0          0         -> 192.168.110.34:80            Route   1      0          0         
6.3.1.3 访问测试
[root@Client ~]# for ((i=1;i<=6;i++)); do curl http://192.168.110.10; done
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.33  Host=LVS-RS1
6.3.1.4 模拟故障转移
[root@Keepalived-01 ~]# systemctl stop keepalived.service
​
[root@Keepalived-02 ~]# ip address show ens160   #VIP漂移到Keepalived-02
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000link/ether 00:0c:29:b0:0d:30 brd ff:ff:ff:ff:ff:ffaltname enp3s0inet 192.168.110.32/24 brd 192.168.110.255 scope global noprefixroute ens160valid_lft forever preferred_lft foreverinet 192.168.110.10/32 scope global ens160valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:feb0:d30/64 scope link noprefixroute valid_lft forever preferred_lft forever
​
[root@Client ~]# for ((i=1;i<=6;i++)); do curl http://192.168.110.10; done  #访问正常
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
​
[root@Keepalived-01 ~]# systemctl start keepalived.service
[root@Keepalived-01 ~]# ip address show ens160     #恢复后回来
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000link/ether 00:0c:29:d1:a9:eb brd ff:ff:ff:ff:ff:ffaltname enp3s0inet 192.168.110.31/24 brd 192.168.110.255 scope global noprefixroute ens160valid_lft forever preferred_lft foreverinet 192.168.110.10/32 scope global ens160valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:fed1:a9eb/64 scope link noprefixroute valid_lft forever preferred_lft forever
6.3.1.5 后端服务器故障
[root@LVS-RS1 ~]# systemctl stop nginx.service
​
[root@Keepalived-02 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.110.10:80 rr-> 192.168.110.34:80            Route   1      0          9   [root@Client ~]# for ((i=1;i<=6;i++)); do curl http://192.168.110.10; done    #访问正常
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2

6.3.2 基于HTTP的健康检测

6.3.2.1 生成远程网页的MD5哈希值
  • genhash 是一个命令行工具,用于生成远程网页的MD5哈希值。它可以用于监控HTTP和HTTPS服务,特别是在Keepalived配置中,用于健康检查。genhash 可以通过HTTP或HTTPS连接到网页,并生成页面数据的MD5哈希值,该哈希值可以在Keepalived配置文件中使用。

[root@Keepalived-01 ~]# genhash -s 192.168.110.33 -p 80 -u /index.html
MD5SUM = fd0508d1ccc6c66c14977e54ffc7faef
​
[root@Keepalived-01 ~]# genhash -s 192.168.110.34 -p 80 -u /index.html
MD5SUM = 0632aaa5fb77608b1a4736d47aacb62c
​
[root@Keepalived-02 ~]# genhash -s 192.168.110.33 -p 80 -u /index.html
MD5SUM = fd0508d1ccc6c66c14977e54ffc7faef
​
[root@Keepalived-02 ~]# genhash -s 192.168.110.34 -p 80 -u /index.html
MD5SUM = 0632aaa5fb77608b1a4736d47aacb62c
6.3.2.2 Keepalived-01配置
[root@Keepalived-01 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
​
global_defs {router_id LVS_node1
}
​
vrrp_instance LVS {state MASTERinterface ens160virtual_router_id 51priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.110.10}
}
virtual_server 192.168.110.10 80 {delay_loop 6  lb_algo rrlb_kind DRprotocol TCP
​real_server 192.168.110.33 80 {weight 1
​HTTP_GET {url {path /index.htmldigest fd0508d1ccc6c66c14977e54ffc7faef}connect_timeout 3nb_get_retry 3delay_before_retry 3}}real_server 192.168.110.34 80 {weight 1HTTP_GET {url {path /index.htmldigest 0632aaa5fb77608b1a4736d47aacb62c
​}connect_timeout 3nb_get_retry 3delay_before_retry 3}}
}
​
[root@Keepalived-01 ~]# systemctl start keepalived.service
[root@Keepalived-01 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.110.10:80 rr-> 192.168.110.33:80            Route   1      0          0         -> 192.168.110.34:80            Route   1      0          0     
6.3.2.3 Keepalived-02配置
[root@Keepalived-02 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
​
global_defs {router_id LVS_node2
}
​
vrrp_instance LVS {state MASTERinterface ens160virtual_router_id 51priority 80advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.110.10}
}
virtual_server 192.168.110.10 80 {delay_loop 6  lb_algo rrlb_kind DRprotocol TCP
​real_server 192.168.110.34 80 {weight 1
​HTTP_GET {url {path /index.htmldigest fd0508d1ccc6c66c14977e54ffc7faef}connect_timeout 3nb_get_retry 3delay_before_retry 3}}real_server 192.168.110.34 80 {weight 1HTTP_GET {url {path /index.htmldigest 0632aaa5fb77608b1a4736d47aacb62c
​}connect_timeout 3nb_get_retry 3delay_before_retry 3}}
}
​
​
[root@Keepalived-02 ~]# systemctl start keepalived.service
[root@Keepalived-02 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.110.10:80 rr-> 192.168.110.33:80            Route   1      0          0         -> 192.168.110.34:80            Route   1      0          0     
6.3.2.4 访问测试
[root@Client ~]# for ((i=1;i<=6;i++)); do curl http://192.168.110.10; done
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
6.3.2.5 模拟故障转移
[root@Keepalived-01 ~]# systemctl stop keepalived.service
​
[root@Keepalived-02 ~]# ip address show ens160   #VIP漂移到Keepalived-02
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000link/ether 00:0c:29:b0:0d:30 brd ff:ff:ff:ff:ff:ffaltname enp3s0inet 192.168.110.32/24 brd 192.168.110.255 scope global noprefixroute ens160valid_lft forever preferred_lft foreverinet 192.168.110.10/32 scope global ens160valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:feb0:d30/64 scope link noprefixroute valid_lft forever preferred_lft forever
​
[root@Client ~]# for ((i=1;i<=6;i++)); do curl http://192.168.110.10; done  #访问正常
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
​
[root@Keepalived-01 ~]# systemctl start keepalived.service
[root@Keepalived-01 ~]# ip address show ens160     #恢复后回来
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000link/ether 00:0c:29:d1:a9:eb brd ff:ff:ff:ff:ff:ffaltname enp3s0inet 192.168.110.31/24 brd 192.168.110.255 scope global noprefixroute ens160valid_lft forever preferred_lft foreverinet 192.168.110.10/32 scope global ens160valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:fed1:a9eb/64 scope link noprefixroute valid_lft forever preferred_lft forever
6.3.2.6 后端服务器故障
[root@LVS-RS1 ~]# systemctl stop nginx.service
​
[root@Keepalived-01 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.110.10:80 rr-> 192.168.110.34:80            Route   1      0          6  [root@Client ~]# for ((i=1;i<=6;i++)); do curl http://192.168.110.10; done
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2

6.3.3 Keepalived健康检查(MISC方式)

6.3.3.1 编写健康脚本
[root@Keepalived-01 ~]# vim /etc/keepalived/chk_web.sh
#!/bin/bash# 检查传入的参数数量是否正确
if [ $# -ne 2 ]; thenecho "Error, Parameter error"exit 1
else# 使用 nmap 进行端口扫描,获取端口状态n=$(nmap -Pn -p$2 -sS -vv $1 | grep "^$2" | awk '{print $2}')
​# 判断端口是否开放if [ "$n" = "open" ]; thenexit 0elseexit 1fi
fi
​
[root@Keepalived-01 ~]# chmod +x /etc/keepalived/chk_web.sh 
[root@Keepalived-01 ~]# scp /etc/keepalived/chk_web.sh 192.168.110.32:/etc/keepalived/
6.3.3.2 keepalived-01配置
[root@Keepalived-01 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
​
global_defs {router_id LVS_node1
}
​
vrrp_instance LVS {state MASTERinterface ens160virtual_router_id 51priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.110.10}
}
​
virtual_server  192.168.110.10  80 {delay_loop  6lb_algo rrlb_kind DRprotocol TCP
​real_server  192.168.110.33  80 {weight  1MISC_CHECK {misc_path "/etc/keepalived/chk_web.sh  192.168.110.33  80"misc_timeout  3}}
​real_server  192.168.110.34  80 {weight  1MISC_CHECK {misc_path "/etc/keepalived/chk_web.sh  192.168.110.34  80"misc_timeout  3}}
}
​
​
[root@Keepalived-01 ~]# systemctl start keepalived.service
[root@Keepalived-01 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.110.10:80 rr-> 192.168.110.33:80            Route   1      0          0         -> 192.168.110.34:80            Route   1      0          0  
6.3.3.3 keepalived-02配置
[root@Keepalived-02 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
​
global_defs {router_id LVS_node2
}
​
vrrp_instance LVS {state MASTERinterface ens160virtual_router_id 51priority 80advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.110.10}
}
​
virtual_server  192.168.110.10  80 {delay_loop  6lb_algo rrlb_kind DRprotocol TCP
​real_server  192.168.110.33  80 {weight  1MISC_CHECK {misc_path "/etc/keepalived/chk_web.sh  192.168.110.33  80"misc_timeout  3}}
​real_server  192.168.110.34  80 {weight  1MISC_CHECK {misc_path "/etc/keepalived/chk_web.sh  192.168.110.34  80"misc_timeout  3}}
}
​
[root@Keepalived-02 ~]# systemctl start keepalived.service 
6.3.3.4 访问测试
[root@Client ~]# for ((i=1;i<=6;i++)); do curl http://192.168.110.10; done
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
6.3.3.5 模拟故障转移
[root@Keepalived-01 ~]# systemctl stop keepalived.service
​
[root@Keepalived-02 ~]# ip address show ens160   #VIP漂移到Keepalived-02
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000link/ether 00:0c:29:b0:0d:30 brd ff:ff:ff:ff:ff:ffaltname enp3s0inet 192.168.110.32/24 brd 192.168.110.255 scope global noprefixroute ens160valid_lft forever preferred_lft foreverinet 192.168.110.10/32 scope global ens160valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:feb0:d30/64 scope link noprefixroute valid_lft forever preferred_lft forever
​
[root@Client ~]# for ((i=1;i<=6;i++)); do curl http://192.168.110.10; done  #访问正常
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.33  Host=LVS-RS1
This is LVS test IP=192.168.110.34  Host=LVS-RS2
​
[root@Keepalived-01 ~]# systemctl start keepalived.service
[root@Keepalived-01 ~]# ip address show ens160     #恢复后回来
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000link/ether 00:0c:29:d1:a9:eb brd ff:ff:ff:ff:ff:ffaltname enp3s0inet 192.168.110.31/24 brd 192.168.110.255 scope global noprefixroute ens160valid_lft forever preferred_lft foreverinet 192.168.110.10/32 scope global ens160valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:fed1:a9eb/64 scope link noprefixroute valid_lft forever preferred_lft forever
6.3.3.6 后端服务器故障
[root@LVS-RS1 ~]# systemctl stop nginx.service
​
[root@Keepalived-01 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.110.10:80 rr-> 192.168.110.34:80            Route   1      0          6  [root@Client ~]# for ((i=1;i<=6;i++)); do curl http://192.168.110.10; done
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2
This is LVS test IP=192.168.110.34  Host=LVS-RS2

相关文章:

Keepalived实现LVS高可用

6.1 KeepalivedLVS集群介绍 Keepalived和LVS共同构建了一个高效的负载均衡和高可用性解决方案&#xff1a;LVS作为负载均衡器&#xff0c;负责在集群中的多个服务器间分配流量&#xff0c;以其高性能和可扩展性确保应用程序能够处理大量的并发请求&#xff1b;而Keepalived则作…...

【力扣】1089.复写零

原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 给你一个长度固定的整数数组 arr &#xff0c;请你将该数组中出现的每个零都复写一遍&#xff0c;并将其余的元素向右平移。 注意&#xff1a;请不…...

Golang实践录:gin框架使用自定义日志模块

本文介绍在 Golang 的 gin 框架中使用自定义日志模块的一些方法。 背景 很早之前就实现并使用了自己封装的日志模块&#xff0c;但一直没有将gin框架内部的日志和日志模块结合。gin的日志都是在终端上打印的&#xff0c;排查问题不方便。趁五一假期&#xff0c;集中研究把此事…...

Django之配置数据库

一&#xff0c;创建项目 二&#xff0c;将项目的setting.py中的 DATABASES {default: {ENGINE: django.db.backends.sqlite3,NAME: BASE_DIR / db.sqlite3,} }替换成如下&#xff08;以mysql为例&#xff09; DATABASES {default: {ENGINE: django.db.backends.mysql,NAME: …...

Ajax 笔记02

01 jq中的ajax方法中的dataType属性 dataType属性的属性值有以下几种: xml 返回数据按照xml解析 json 返回的数据按照json代码解析 script 返回的数据按照js代码解析 text 把返回的数据按照普通文本解析 jsonp 跨域 json: javascript object notation(js对象简谱) json整体…...

【隧道篇 / WAN优化】(7.4) ❀ 03. WAN优化的原理 ❀ FortiGate 防火墙

【简介】相信对WAN优化感兴趣的人都会有疑问&#xff0c;WAN优化真的有作用吗&#xff1f;如果真的有作用&#xff0c;那是根据什么原理呢&#xff1f;让我们来更深入的了解一下。 客户端和服务器端 其实很多人在一开始看到WAN优化这个词&#xff0c;就自然的以为上网速度太慢&…...

网络爬虫概述与原理

网络爬虫概述与原理 网络爬虫简介狭义上理解功能上理解常见用途总结 网络爬虫分类通用网络爬虫聚焦网络爬虫增量网络爬虫深度网络爬虫 网络爬虫流程网络爬虫采集策略深度有限搜索策略广度优先搜索策略 网络爬虫简介 通过有效地获取网络资源的方式&#xff0c;便是网络爬虫。网…...

可视化实验三 Matplotlib库绘图及时变数据可视化

1.1 任务一 1.1.1 恢复默认配置 #绘图风格&#xff0c;恢复默认配置 plt.rcParams.update(plt.rcParamsDefault)#恢复默认配置 或者 plt.rcdefaults() 1.1.2 汉字和负号的设置 import matplotlib.pyplot as plt plt.rcParams["font.sans-serif"]"SimH…...

开启多线程下变量共享与私有问题

开启多线程下变量共享与私有问题 &#x1f335;ThreadLocal和Atomic是Java中用于多线程编程的两个重要工具。 ThreadLocal是一个线程局部变量&#xff0c;它为每个线程提供了独立的变量副本&#xff0c;确保每个线程都可以访问自己的变量副本而不会影响其他线程的变量。在多线…...

Qt模型视图代理之QTableView应用的简单介绍

往期回顾 Qt绘图与图形视图之绘制带三角形箭头的窗口的简单介绍-CSDN博客 Qt绘图与图形视图之Graphics View坐标系的简单介绍-CSDN博客 Qt模型视图代理之MVD(模型-视图-代理)概念的简单介绍-CSDN博客 Qt模型视图代理之QTableView应用的简单介绍 一、最终效果 二、设计思路 这里…...

第七届精武杯部分wp

第一部分&#xff1a;计算机和手机取证 1.请综合分析计算机和手机检材&#xff0c;计算机最近一次登录的账户名是 答案&#xff1a;admin 创建虚拟机时直接给出了用户名 2. 请综合分析计算机和手机检材&#xff0c;计算机最近一次插入的USB存储设备串号是 答案&#xff1a…...

3.2Java全栈开发前端+后端(全栈工程师进阶之路)-前端框架VUE3框架-企业级应用- Vuex

Vuex简介 Vuex概述 Vuex是一个专门为Vue.js应用程序开发的状态管理模式, 它采用集中式存储管理所有组件的公共状态, 并以相应的规 则保证状态以一种可预测的方式发生变化. 试想这样的场景, 比如一个Vue的根实例下面有一个根组件名为App.vue, 它下面有两个子组件A.vue和B.vu…...

整合 Java, Python 和 Scrapy 爬虫以传递和使用参数

这篇博客将详细说明如何从 Java 应用程序调用一个 Python 脚本&#xff0c;并在此过程中传递参数给一个 Scrapy 爬虫。最终目标是让 Java 控制爬虫的行为&#xff0c;如爬取数量和特定的运行参数。 一、Scrapy 爬虫的修改 首先&#xff0c;我们需要确保 Scrapy 爬虫能接收从命…...

Android 蓝牙实战——蓝牙音乐播放进度(二十)

对于蓝牙音乐的开发来说,播放进度是一个比较重要的数据参数,这里我们就来分析一下蓝牙音乐播放进度的相关回调。 一、回调流程 1、AvrcpControllerService 源码位置:/packages/apps/Bluetooth/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java /…...

SQL注入实例(sqli-labs/less-1)

初始网页 从网页可知传递的参数名为 id&#xff0c;并且为数字类型 1、得知数据表有多少列 1.1 使用联合查询查找列数&#xff08;效率低&#xff09; http://localhost/sqli-labs-master/Less-1/?id1 union select 1,2 -- 1.2 使用order by查找列数&#xff08;效率高&…...

Python中tkinter编程入门3

在使用tkinter创建了窗口之后&#xff0c;可以将一些控件“放置”到窗口中。这些控件包括标签、按键以及输入框等。 1 在窗口中“放置”标签 在窗口中“放置”标签主要有两个步骤&#xff0c;一是创建标签控件&#xff0c;二是将创建好的标签“放置”到窗口上。 1.1 创建标签…...

XMind 2023 v23.05.2660软件安装教程(附软件下载地址)

软件简介&#xff1a; 软件【下载地址】获取方式见文末。注&#xff1a;推荐使用&#xff0c;更贴合此安装方法&#xff01; XMind 2023 v23.05.2660被视为顶尖思维导图软件&#xff0c;其界面简洁清爽&#xff0c;功能布局直观简单&#xff0c;摒弃繁复不实。尽管体积小巧&a…...

docker compose kafka集群部署

kafka集群部署 目录 部署zookeeper准备工作2、部署kafka准备工作3、编辑docker-compose.yml文件4、启动服务5、测试kafka6、web监控管理 部署zookeeper准备工作 mkdir data/zookeeper-{1,2,3}/{data,datalog,logs,conf} -p cat >data/zookeeper-1/conf/zoo.cfg<<EOF…...

最新版在线客服系统源码

源码介绍 首发最新在线客服系统源码&#xff0c;优化更好并且重构源码布局UI 性能不吃cpu并发快,普通1H2G都能带动最新版只要是服务器都能带动 搭建即可使用,操作简单,易懂 修复了老版本bug 内附有搭建教程 gofly.v1kf.com 运行环境 Nginx 1.20 MySQL 5.7 演示截图...

【比邻智选】MR880A模组

&#x1f680;高性价比&#xff0c;5G/4G双模&#xff0c;稳定可靠 &#x1f310;功能丰富&#xff0c;5G特性一应俱全 &#x1f9e9;多封装兼容&#xff0c;适配性强&#xff0c;灵活升级智能设备...

Outfit字体全攻略:5大核心优势与零基础实战指南

Outfit字体全攻略&#xff1a;5大核心优势与零基础实战指南 【免费下载链接】Outfit-Fonts The most on-brand typeface 项目地址: https://gitcode.com/gh_mirrors/ou/Outfit-Fonts Outfit字体作为一款专业的开源无衬线字体&#xff0c;凭借其完整的9种字重体系和现代设…...

feishu2md:飞书文档转Markdown的技术实现与架构解析

feishu2md&#xff1a;飞书文档转Markdown的技术实现与架构解析 【免费下载链接】feishu2md 一键命令下载飞书文档为 Markdown 项目地址: https://gitcode.com/gh_mirrors/fe/feishu2md 飞书文档转Markdown工具feishu2md为技术团队提供了文档格式转换的标准化解决方案。…...

Java 从入门到精通(八):抽象类和接口到底怎么选?看懂之后,面向对象才算真的入门

Java 从入门到精通&#xff08;八&#xff09;&#xff1a;抽象类和接口到底怎么选&#xff1f;看懂之后&#xff0c;面向对象才算真的入门 学到封装、继承、多态之后&#xff0c;很多人会有一种“好像差不多懂了”的感觉。 会定义类&#xff0c;会 new 对象&#xff0c;也知道…...

你的产品过不了EMC测试?很可能是电源接口这3个PCB布局坑没避开

电源接口EMC设计避坑指南&#xff1a;PCB布局中的三个致命细节 当你的产品在EMC测试中屡屡碰壁时&#xff0c;问题往往不在于防护电路设计本身&#xff0c;而是隐藏在PCB布局的细微之处。许多工程师精心设计了符合规范的防护拓扑&#xff0c;却在传导骚扰测试中遭遇滑铁卢。本文…...

leetcode 困难题 1505. 最多 K 次交换相邻数位后得到的最小整数

Problem: 1505. 最多 K 次交换相邻数位后得到的最小整数 从左到右遍历字符串的每个索引&#xff0c;对每个索引i&#xff0c;向后查找k窗口内的最小数字&#xff0c;右边界是min(n, ik1)&#xff0c;删去这个最小数字&#xff0c;然后将这个最小数字插入到当前索引&#xff0c;…...

CH340系列芯片选型指南与外围电路设计实战

1. CH340系列芯片选型指南 第一次接触CH340系列芯片时&#xff0c;我被它丰富的型号搞得眼花缭乱。作为国内最常用的USB转串口芯片之一&#xff0c;CH340系列凭借稳定的性能和亲民的价格&#xff0c;在嵌入式开发领域占据重要地位。但面对十几种不同型号&#xff0c;新手往往会…...

从定时器到任务调度:用Qt QTimer和QThreadPool构建一个轻量级后台任务管理器

从定时器到任务调度&#xff1a;用Qt QTimer和QThreadPool构建轻量级后台任务管理器 在开发中型Qt应用时&#xff0c;后台任务管理往往成为架构设计的痛点。当简单的定时器无法满足复杂业务需求&#xff0c;当主线程被耗时任务拖累导致界面卡顿&#xff0c;开发者需要一套更优雅…...

次元画室+AI绘图工作流:从文字描述到精准提示词的无缝衔接

次元画室AI绘图工作流&#xff1a;从文字描述到精准提示词的无缝衔接 1. 为什么需要AI绘图工作流&#xff1f; 在动漫角色设计领域&#xff0c;创作者们长期面临一个核心矛盾&#xff1a;脑海中有丰富的创意&#xff0c;却难以准确转化为视觉形象。传统工作流程中&#xff0c…...

FlowState Lab少样本学习效果:仅用10条数据生成特定波动模式

FlowState Lab少样本学习效果&#xff1a;仅用10条数据生成特定波动模式 1. 引言&#xff1a;当数据稀缺遇上智能生成 想象一下这样的场景&#xff1a;你手里只有10条设备振动波形数据&#xff0c;却需要分析上千种可能的故障模式。传统方法可能需要收集数月甚至数年的运行数…...

第12课:从 SPI 环路、CAN 通信到 SD 与 eMMC 存储实战

本节路线图 先把三条主线分开:控制总 → SPI环路测试:先把时序 → CAN:换一条总线,世界 小猫提醒 这节有分区、烧录或删除类操作,先确认盘符和路径,再按回车。 如果说上一课的关键词是“事件、时间和系统能力”,那这一课的关键词就是“总线、协议和数据落地”。 我们要…...