目录
3. LVS的负载策略有哪些,各应用在什么场景,通过LVS DR任意实现1-2种场景。
完成作业:
1. redis搭建哨兵原理和集群实现。
2. LVS常用模型工作原理,及实现。
3. LVS的负载策略有哪些,各应用在什么场景,通过LVS DR任意实现1-2种场景。
4. web http协议通信过程,相关技术术语总结。
5. 总结网络IO模型和nginx架构。
6. nginx总结核心配置和优化。
7. 使用脚本完成一键编译安装nginx任意版本。
8. 任意编译一个第3方nginx模块,并使用。
1. redis搭建哨兵原理和集群实现。
1.1哨兵原理
哨兵,英文名 Sentinel,是一个分布式系统,用于对主从结构中的每一台服务器进行监控,当主节点出现故障后通过投票机制来挑选新的主节点,并且将所有的从节点连接到新的主节点上。
哨兵的三个作用:
监控:监控谁?支持主从结构的工作一个是主节点一个是从节点,那肯定就是监控这俩个了。监控主节点和从节点是否正常运行;检测主节点是否存活,主节点和从节点运行情况。
通知:哨兵检测的服务器出现问题时,会向其他的哨兵发送通知,哨兵之间就相当于一个微信群,每个哨兵发现的问题都会发在这个群里。
自动转移故障:当检测到主节点宕机后,断开与宕机主节点连接的所有从节点,在从节点中选取一个作为主节点,然后将其他的从节点连接到这个最新主节点的上。并且告知客户端最新的服务器地址。这里有一个注意点,哨兵也是一台 Redis 服务器,只是不对外提供任何服务。配置哨兵时配置为单数。
1.2搭建哨兵原理
#准备:哨兵配置文件默认存放位置:
/usr/local/src/redis-6.2.6/sentinel.conf
cp /usr/local/src/redis-6.2.6/sentinel.conf /apps/redis/etc/
chown redis. /apps/redis/etc/*#修改sentinel配置文件
vim /apps/redis/etc/sentinel.conf
# protected-mode no
bind 0.0.0.0
# port <sentinel-port>
# The port that this sentinel instance will run on
port 26379
# By default Redis Sentinel does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis-sentinel.pid when
# daemonized.
daemonize no
# When running daemonized, Redis Sentinel writes a pid file in
# /var/run/redis-sentinel.pid by default. You can specify a custom pid file
# location here.
pidfile /var/run/redis-sentinel.pid
# Specify the log file name. Also the empty string can be used to force
# Sentinel to log on the standard output. Note that if you use standard
# output for logging but daemonize, logs will be sent to /dev/null
logfile "/apps/redis/log/sentinel.log"
# Note: master name should not include special characters or spaces.
# The valid charset is A-z 0-9 and the three characters ".-_".
sentinel monitor mymaster 192.168.72.142 6379 2
sentinel auth-pass mymaster 123456
# Default is 30 seconds.
sentinel down-after-milliseconds mymaster 3000
chown redis. /apps/redis/etc/*
#把主节点修改好的哨兵配置文件带属性复制到另外两台从节点上
[root@Rocky8 ~]# ll /apps/redis/etc
total 108
-rw-r--r-- 1 redis redis 93834 Nov 30 21:48 redis.conf
-rw-r--r-- 1 redis redis 13768 Nov 30 21:51 sentinel.conf
[root@Rocky8 ~]# rsync -a /apps/redis/etc/sentinel.conf 192.168.72.151:/apps/redis/etc/
[root@Rocky8 ~]# rsync -a /apps/redis/etc/sentinel.conf 192.168.72.155:/apps/redis/etc/
#三台机器分别在前台启动哨兵
[root@Rocky8 ~]#/apps/redis/bin/redis-sentinel /apps/redis/etc/sentinel.conf
验证启动后自动改动的哨兵配置文件vim /apps/redis/etc/sentinel.conf
#主节点验证
# Generated by CONFIG REWRITE
protected-mode no
user default on nopass ~* &* +@all
sentinel myid 3285e24f38bec229c1ae6f6e7c9040b67633e313
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
sentinel current-epoch 0
sentinel known-replica mymaster 192.168.72.151 6379
sentinel known-replica mymaster 192.168.72.155 6379
#第一个从节点验证:
# Generated by CONFIG REWRITE
protected-mode no
user default on nopass ~* &* +@all
sentinel myid 9bd9b2a20176cdba2c102071710e9da821e18051
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
sentinel current-epoch 0
sentinel known-replica mymaster 192.168.72.151 6379
sentinel known-replica mymaster 192.168.72.155 6379
sentinel known-sentinel mymaster 192.168.72.142 26379 3285e24f38bec229c1ae6f6e7c9040b67633e313
#第二个从节点验证:
# Generated by CONFIG REWRITE
protected-mode no
user default on nopass ~* &* +@all
sentinel myid d398f9beb74e52d518bf9fdf021a4c660ba369a6
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
sentinel current-epoch 0
sentinel known-replica mymaster 192.168.72.155 6379
sentinel known-replica mymaster 192.168.72.151 6379
sentinel known-sentinel mymaster 192.168.72.142 26379 3285e24f38bec229c1ae6f6e7c9040b67633e313
sentinel known-sentinel mymaster 192.168.72.151 26379 9bd9b2a20176cdba2c102071710e9da821e18051
注:此处生成的三台服务器的sentinel myid 必须唯一,否则就是失败
#三台服务器一起创建service服务文件
[root@Rocky8 ~]# cat /lib/systemd/system/redis-sentinel.service
cat: /lib/systemd/system/redis-sentinel.service: No such file or directory
[root@Rocky8 ~]# vim /lib/systemd/system/redis-sentinel.service
[Unit]
Description=Redis Sentinel
After=network.target
[Service]
ExecStart=/apps/redis/bin/redis-sentinel /apps/redis/etc/sentinel.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
#修改文件属性,把创建好的service文件复制到另外两台节点上
[root@Rocky8 ~]# chown -R redis.redis /apps/redis/
[root@Rocky8 ~]# scp /lib/systemd/system/redis-sentinel.service 192.168.72.151:/lib/systemd/system
root@192.168.72.151's password:
redis-sentinel.service 100% 303 266.0KB/s 00:00
[root@Rocky8 ~]# scp /lib/systemd/system/redis-sentinel.service 192.168.72.155:/lib/systemd/system
root@192.168.72.155's password:
redis-sentinel.service
#三台服务器都设置为开机自启动且立即启动
[root@Rocky8 ~]# systemctl enable --now redis-sentinel.service
#进行端口验证
[root@Rocky8 ~]# ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 1 511 0.0.0.0:26379 0.0.0.0:*
LISTEN 0 511 0.0.0.0:6379 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 244 0.0.0.0:5432 0.0.0.0:*
LISTEN 0 128 *:9090 *:*
LISTEN 0 511 [::1]:6379 [::]:*
LISTEN 0 128 [::]:22 [::]:*
#登陆sentinel的专用端口验证:
[root@Rocky8 ~]# redis-cli -p 26379
127.0.0.1:26379> info
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.72.142:6379,slaves=2,sentinels=3
#通过日志验证
[root@Rocky8 ~]# cat /apps/redis/log/sentinel.log
2356:X 30 Nov 2022 22:32:17.122 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
2356:X 30 Nov 2022 22:32:17.122 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=2356, just started
2356:X 30 Nov 2022 22:32:17.122 # Configuration loaded
2356:X 30 Nov 2022 22:32:17.142 * Increased maximum number of open files to 10032 (it was originally set to 1024).
2356:X 30 Nov 2022 22:32:17.142 * monotonic clock: POSIX clock_gettime
2356:X 30 Nov 2022 22:32:17.208 * Running mode=sentinel, port=26379.
2356:X 30 Nov 2022 22:32:17.678 # Sentinel ID is 3285e24f38bec229c1ae6f6e7c9040b67633e313
2356:X 30 Nov 2022 22:32:17.678 # +monitor master mymaster 192.168.72.142 6379 quorum 2
2356:X 30 Nov 2022 22:32:18.019 * +slave slave 192.168.72.151:6379 192.168.72.151 6379 @ mymaster 192.168.72.142 6379
2356:X 30 Nov 2022 22:32:18.035 * +slave slave 192.168.72.155:6379 192.168.72.155 6379 @ mymaster 192.168.72.142 6379
2356:X 30 Nov 2022 22:33:19.935 # +tilt #tilt mode entered
2356:X 30 Nov 2022 22:33:50.010 # -tilt #tilt mode exited
2356:X 30 Nov 2022 22:38:43.490 * +sentinel sentinel 9bd9b2a20176cdba2c102071710e9da821e18051 192.168.72.151 26379 @ mymaster 192.168.72.142 6379
2356:X 30 Nov 2022 22:40:26.216 * +sentinel sentinel d398f9beb74e52d518bf9fdf021a4c660ba369a6 192.168.72.155 26379 @ mymaster 192.168.72.142 6379
#停掉主节点142服务器后,哨兵投票自动随机决定了155成为新的主节点,而151和被停掉的142服务器已变为新的从节点。
[root@Rocky8 ~]# tail -f /apps/redis/log/sentinel.log
1694:X 01 Dec 2022 22:35:31.239 # +sdown master mymaster 192.168.72.142 6379
1694:X 01 Dec 2022 22:35:31.328 # +new-epoch 1
1694:X 01 Dec 2022 22:35:31.332 # +vote-for-leader 3285e24f38bec229c1ae6f6e7c9040b67633e313 1
1694:X 01 Dec 2022 22:35:32.305 # +odown master mymaster 192.168.72.142 6379 #quorum 3/2
1694:X 01 Dec 2022 22:35:32.306 # Next failover delay: I will not start a failover before Thu Dec 1 22:41:31 2022
1694:X 01 Dec 2022 22:35:32.442 # +config-update-from sentinel 3285e24f38bec229c1ae6f6e7c9040b67633e313 192.168.72.142 26379 @ mymaster 192.168.72.142 6379
1694:X 01 Dec 2022 22:35:32.442 # +switch-master mymaster 192.168.72.142 6379 192.168.72.155 6379
1694:X 01 Dec 2022 22:35:32.442 * +slave slave 192.168.72.151:6379 192.168.72.151 6379 @ mymaster 192.168.72.155 6379
1694:X 01 Dec 2022 22:35:32.442 * +slave slave 192.168.72.142:6379 192.168.72.142 6379 @ mymaster 192.168.72.155 6379
1694:X 01 Dec 2022 22:35:35.475 # +sdown slave 192.168.72.142:6379 192.168.72.142 6379 @ mymaster 192.168.72.155 6379
#手动让主节点下线
[root@centos8 ~]#vim /etc/redis.conf
replica-priority 10 #指定优先级,值越小sentinel会优先将之选为新的master,默为值为100
[root@centos8 ~]#systemctl restart redis
127.0.0.1:26379> sentinel failover <masterName>
1.3redis集群功能实现
#可以用一条sed命令修改下列6项redis配置文件以实现cluster功能
敲入命令sed -i.bak -e '/masterauth/a masterauth 123456' -e '/# cluster-enabled yes/a cluster-enabled yes' -e '/# cluster-config-filenodes-6379.conf/a cluster-config-file nodes-6379.conf' -e '/cluster-require-full-coverage yes/c cluster-require-full-coverage no' /apps/redis/etc/redis.conf
#开启cluster集群后重启redis服务
[root@Rocky8 ~]# systemctl restart redis [root@Rocky8 ~]# ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 511 0.0.0.0:6379 0.0.0.0:* LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 244 0.0.0.0:5432 0.0.0.0:* LISTEN 0 511 0.0.0.0:16379 0.0.0.0:* LISTEN 0 128 *:9090 *:* LISTEN 0 511 [::1]:6379 [::]:* LISTEN 0 128 [::]:22 [::]:* LISTEN 0 511 [::1]:16379 [::]:*
#在6台服务器中的任意一台输入创建集群的命令(注:开启集群前要确保所有节点redis的数据为空且互相没有主从复制关系或哨兵服务关系,有的话则必须清除掉配置文件里相关的复制关系)
redis-cli -a 123456 --cluster create 192.168.72.142:6379 192.168.72.151:6379 192.168.72.155:6379 192.168.72.152:6379 192.168.72.153:6379 192.168.72.150:6379 --cluster-replicas 1
#具体执行验证结果如下[root@Rocky8 ~]# ls /apps/redis/data/ nodes-6379.conf [root@Rocky8 ~]# redis-cli -a 123456 --cluster create 192.168.72.142:6379 192.168.72.151:6379 192.168.72.155:6379 192.168.72.152:6379 192.168.72.153:6379 192.168.72.150:6379 --cluster-replicas 1 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 192.168.72.150:6379 to 192.168.72.142:6379 Adding replica 192.168.72.153:6379 to 192.168.72.151:6379 Adding replica 192.168.72.152:6379 to 192.168.72.155:6379 M: 1c10f642637b8e997fca9c1e8f9e73699bc60b15 192.168.72.142:6379 slots:[0-5460] (5461 slots) master M: accd85afbe7c1d9bded991f045703974a1931ad4 192.168.72.151:6379 slots:[5461-10922] (5462 slots) master M: ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 192.168.72.155:6379 slots:[10923-16383] (5461 slots) master S: b86eced539971413958b34d4e320556d2482f4bd 192.168.72.152:6379 replicates ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 S: cb965245d3d9836de27b483dd861b24c8969aae2 192.168.72.150:6379 replicates 1c10f642637b8e997fca9c1e8f9e73699bc60b15 S: c200aab6263548b949a44bb1754a461c7038b418 192.168.72.153:6379 replicates accd85afbe7c1d9bded991f045703974a1931ad4 Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join . >>> Performing Cluster Check (using node 192.168.72.142:6379) M: 1c10f642637b8e997fca9c1e8f9e73699bc60b15 192.168.72.142:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) M: accd85afbe7c1d9bded991f045703974a1931ad4 192.168.72.151:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: b86eced539971413958b34d4e320556d2482f4bd 192.168.72.152:6379 slots: (0 slots) slave replicates ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 S: c200aab6263548b949a44bb1754a461c7038b418 192.168.72.153:6379 slots: (0 slots) slave replicates accd85afbe7c1d9bded991f045703974a1931ad4 S: cb965245d3d9836de27b483dd861b24c8969aae2 192.168.72.150:6379 slots: (0 slots) slave replicates 1c10f642637b8e997fca9c1e8f9e73699bc60b15 M: ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 192.168.72.155:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
#查看cluster集群主从节点关系的命令
[root@Rocky8 ~]# cat /apps/redis/data/nodes-6379.conf
b86eced539971413958b34d4e320556d2482f4bd 192.168.72.152:6379@16379 slave ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 0 1670085679813 10 connected
c200aab6263548b949a44bb1754a461c7038b418 192.168.72.153:6379@16379 slave accd85afbe7c1d9bded991f045703974a1931ad4 0 1670085678000 2 connected
cb965245d3d9836de27b483dd861b24c8969aae2 192.168.72.150:6379@16379 myself,slave 1c10f642637b8e997fca9c1e8f9e73699bc60b15 0 1670085678000 1 connected
accd85afbe7c1d9bded991f045703974a1931ad4 192.168.72.151:6379@16379 master - 0 1670085679224 2 connected 5461-10922
ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 192.168.72.155:6379@16379 master - 0 1670085677000 10 connected 10923-16383
1c10f642637b8e997fca9c1e8f9e73699bc60b15 192.168.72.142:6379@16379 master - 0 1670085678217 1 connected 0-5460
vars currentEpoch 10 lastVoteEpoch 0
[root@Rocky8 ~]# redis-cli -a 123456 -c INFO replication
[root@Rocky8 ~]# redis-cli -a 123456 cluster nodes
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
b86eced539971413958b34d4e320556d2482f4bd 192.168.72.152:6379@16379 slave,fail ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 1670085453518 1670085453333 10 connected
c200aab6263548b949a44bb1754a461c7038b418 192.168.72.153:6379@16379 slave,fail accd85afbe7c1d9bded991f045703974a1931ad4 1670085453518 1670085453333 2 connected
cb965245d3d9836de27b483dd861b24c8969aae2 192.168.72.150:6379@16379 myself,slave 1c10f642637b8e997fca9c1e8f9e73699bc60b15 0 1670085620000 1 connected
accd85afbe7c1d9bded991f045703974a1931ad4 192.168.72.151:6379@16379 master - 0 1670085622876 2 connected 5461-10922
ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 192.168.72.155:6379@16379 master - 0 1670085621871 10 connected 10923-16383
1c10f642637b8e997fca9c1e8f9e73699bc60b15 192.168.72.142:6379@16379 master - 0 1670085619000 1 connected 0-5460
#扩容:添加一个节点到集群中
[root@Rocky8 ~]# redis-cli -a 123456 --cluster add-node 192.168.72.157:6379 192.168.72.151:6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Adding node 192.168.72.157:6379 to cluster 192.168.72.151:6379
>>> Performing Cluster Check (using node 192.168.72.151:6379)
M: accd85afbe7c1d9bded991f045703974a1931ad4 192.168.72.151:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: cb965245d3d9836de27b483dd861b24c8969aae2 192.168.72.150:6379
slots: (0 slots) slave
replicates 1c10f642637b8e997fca9c1e8f9e73699bc60b15
M: ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 192.168.72.155:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: b86eced539971413958b34d4e320556d2482f4bd 192.168.72.152:6379
slots: (0 slots) slave
replicates ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13
S: c200aab6263548b949a44bb1754a461c7038b418 192.168.72.153:6379
slots: (0 slots) slave
replicates accd85afbe7c1d9bded991f045703974a1931ad4
M: 1c10f642637b8e997fca9c1e8f9e73699bc60b15 192.168.72.142:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Send CLUSTER MEET to node 192.168.72.157:6379 to make it join the cluster.
[OK] New node added correctly.
#在另一台服务器192.168.72.150上确认新添加节点之后的集群状态
[root@Rocky8 ~]# redis-cli -a 123456 --cluster info 192.168.72.150:6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.72.155:6379 (ddbc2de4...) -> 0 keys | 5461 slots | 1 slaves.
192.168.72.151:6379 (accd85af...) -> 0 keys | 5462 slots | 1 slaves.
192.168.72.157:6379 (480577a4...) -> 0 keys | 0 slots | 0 slaves.
192.168.72.142:6379 (1c10f642...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 0 keys in 4 masters.
0.00 keys per slot on average.
[root@Rocky8 ~]# redis-cli -a 123456 CLUSTER INFO
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:7
cluster_size:3
cluster_current_epoch:10
cluster_my_epoch:1
cluster_stats_messages_ping_sent:2564
cluster_stats_messages_pong_sent:2444
cluster_stats_messages_sent:5008
cluster_stats_messages_ping_received:2444
cluster_stats_messages_pong_received:2564
cluster_stats_messages_received:5008
#在新的master上重新分配槽位
(注:重新分配槽位需要清空数据,所以需要先备份数据,扩展后再恢复数据)
[root@Rocky8 ~]#redis-cli -a 123456 --cluster reshard 192.168.72.157:6379
Warning: Using a password with '-a' or '-u' option on the command line interface
may not be safe.
>>> Performing Cluster Check (using node 192.168.72.157:6379)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)?4096 #新分配多少个槽位
=16384/master个数
What is the receiving node ID? d6e2eca6b338b717923f64866bd31d42e52edc98 #新的master的ID
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1: all #输入all,将哪些源主机的槽位分配给新的节点,all是自动在所有的redis
node选择划分,如果是从redis cluster删除某个主机可以使用此方式将指定主机上的槽位全部移动到别的
redis主机
......
Do you want to proceed with the proposed reshard plan (yes/no)? yes #确认分配
Moving slot 317 from 192.168.72.142:6379 to 192.168.72.157:6379:
Moving slot 318 from 192.168.72.142:6379 to 192.168.72.157:6379:
Moving slot 319 from 192.168.72.142:6379 to 192.168.72.157:6379:
Moving slot 320 from 192.168.72.142:6379 to 192.168.72.157:6379:
Moving slot 321 from 192.168.72.142:6379 to 192.168.72.157:6379:
Moving slot 322 from 192.168.72.142:6379 to 192.168.72.157:6379:
Moving slot 323 from 192.168.72.142:6379 to 192.168.72.157:6379:
Moving slot 324 from 192.168.72.142:6379 to 192.168.72.157:6379:
Moving slot 325 from 192.168.72.142:6379 to 192.168.72.157:6379:
.......
#确认slot分配成功
[root@Rocky8 ~]# redis-cli -a 123456 cluster nodes
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 192.168.72.155:6379@16379 master - 0 1670133312733 10 connected 12288-16383
accd85afbe7c1d9bded991f045703974a1931ad4 192.168.72.151:6379@16379 master - 0 1670133314745 2 connected 6827-10922
1c10f642637b8e997fca9c1e8f9e73699bc60b15 192.168.72.142:6379@16379 master - 0 1670133315000 1 connected 1365-5460
480577a4e5260efab5cadd4216cdec30125a5a88 192.168.72.157:6379@16379 master - 0 1670133315750 11 connected 0-1364 5461-6826 10923-12287
b86eced539971413958b34d4e320556d2482f4bd 192.168.72.152:6379@16379 myself,slave ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 0 1670133311000 10 connected
cb965245d3d9836de27b483dd861b24c8969aae2 192.168.72.150:6379@16379 slave 1c10f642637b8e997fca9c1e8f9e73699bc60b15 0 1670133313739 1 connected
c200aab6263548b949a44bb1754a461c7038b418 192.168.72.153:6379@16379 slave accd85afbe7c1d9bded991f045703974a1931ad4 0 1670133314000 2 connected
#再新加一个节点到集群中并同时设置它为192.168.72.157的从节点,这样话目前构建好的此集群中两两相配,刚好形成了4主4从的格局
[root@Rocky8 ~]# redis-cli -a 123456 --cluster add-node 192.168.72.154:6379 192.168.72.155:6379 --cluster-slave --cluster-master-id 480577a4e5260efab5cadd4216cdec30125a5a88
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Adding node 192.168.72.154:6379 to cluster 192.168.72.155:6379
>>> Performing Cluster Check (using node 192.168.72.155:6379)
M: ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 192.168.72.155:6379
slots:[12288-16383] (4096 slots) master
1 additional replica(s)
M: accd85afbe7c1d9bded991f045703974a1931ad4 192.168.72.151:6379
slots:[6827-10922] (4096 slots) master
1 additional replica(s)
M: 1c10f642637b8e997fca9c1e8f9e73699bc60b15 192.168.72.142:6379
slots:[1365-5460] (4096 slots) master
1 additional replica(s)
S: b86eced539971413958b34d4e320556d2482f4bd 192.168.72.152:6379
slots: (0 slots) slave
replicates ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13
M: 480577a4e5260efab5cadd4216cdec30125a5a88 192.168.72.157:6379
slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
S: cb965245d3d9836de27b483dd861b24c8969aae2 192.168.72.150:6379
slots: (0 slots) slave
replicates 1c10f642637b8e997fca9c1e8f9e73699bc60b15
S: c200aab6263548b949a44bb1754a461c7038b418 192.168.72.153:6379
slots: (0 slots) slave
replicates accd85afbe7c1d9bded991f045703974a1931ad4
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Send CLUSTER MEET to node 192.168.72.154:6379 to make it join the cluster.
Waiting for the cluster to join
>>> Configure node as replica of 192.168.72.157:6379.
[OK] New node added correctly.
#验证一下新添加两个节点后的cluster状态
[root@Rocky8 ~]# redis-cli -a 123456 CLUSTER nodes
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
accd85afbe7c1d9bded991f045703974a1931ad4 192.168.72.151:6379@16379 master - 0 1670135188000 2 connected 6827-10922
1c10f642637b8e997fca9c1e8f9e73699bc60b15 192.168.72.142:6379@16379 master - 0 1670135189898 1 connected 1365-5460
354be8dc095454717325a4793163daaec4391204 192.168.72.154:6379@16379 slave 480577a4e5260efab5cadd4216cdec30125a5a88 0 1670135188892 11 connected
b86eced539971413958b34d4e320556d2482f4bd 192.168.72.152:6379@16379 slave ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 0 1670135187000 10 connected
480577a4e5260efab5cadd4216cdec30125a5a88 192.168.72.157:6379@16379 master - 0 1670135188000 11 connected 0-1364 5461-6826 10923-12287
cb965245d3d9836de27b483dd861b24c8969aae2 192.168.72.150:6379@16379 slave 1c10f642637b8e997fca9c1e8f9e73699bc60b15 0 1670135187000 1 connected
c200aab6263548b949a44bb1754a461c7038b418 192.168.72.153:6379@16379 slave accd85afbe7c1d9bded991f045703974a1931ad4 0 1670135187886 2 connected
ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 192.168.72.155:6379@16379 myself,master - 0 1670135190000 10 connected 12288-16383
#缩容之前在集群中任意一台服务器上确认槽位的分配信息
[root@Rocky8 ~]# cat /apps/redis/data/nodes-6379.conf
ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 192.168.72.155:6379@16379 master - 0 1670134889891 10 connected 12288-16383
accd85afbe7c1d9bded991f045703974a1931ad4 192.168.72.151:6379@16379 master - 0 1670134887877 2 connected 6827-10922
1c10f642637b8e997fca9c1e8f9e73699bc60b15 192.168.72.142:6379@16379 master - 0 1670134888885 1 connected 1365-5460
480577a4e5260efab5cadd4216cdec30125a5a88 192.168.72.157:6379@16379 master - 0 1670134889000 11 connected 0-1364 5461-6826 10923-12287
354be8dc095454717325a4793163daaec4391204 192.168.72.154:6379@16379 slave 480577a4e5260efab5cadd4216cdec30125a5a88 0 1670134889994 11 connected
b86eced539971413958b34d4e320556d2482f4bd 192.168.72.152:6379@16379 myself,slave ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 0 1670134888000 10 connected
cb965245d3d9836de27b483dd861b24c8969aae2 192.168.72.150:6379@16379 slave 1c10f642637b8e997fca9c1e8f9e73699bc60b15 0 1670134888000 1 connected
c200aab6263548b949a44bb1754a461c7038b418 192.168.72.153:6379@16379 slave accd85afbe7c1d9bded991f045703974a1931ad4 0 1670134886000 2 connected
vars currentEpoch 11 lastVoteEpoch 0
#启动缩容
[root@Rocky8 ~]# redis-cli -a 123456 --cluster reshard 192.168.72.152:6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing Cluster Check (using node 192.168.72.152:6379)
S: b86eced539971413958b34d4e320556d2482f4bd 192.168.72.152:6379
slots: (0 slots) slave
replicates ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13
M: ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 192.168.72.155:6379
slots:[12288-16383] (4096 slots) master
1 additional replica(s)
M: accd85afbe7c1d9bded991f045703974a1931ad4 192.168.72.151:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
M: 1c10f642637b8e997fca9c1e8f9e73699bc60b15 192.168.72.142:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: 480577a4e5260efab5cadd4216cdec30125a5a88 192.168.72.157:6379
slots:[10923-12287] (1365 slots) master
1 additional replica(s)
S: 354be8dc095454717325a4793163daaec4391204 192.168.72.154:6379
slots: (0 slots) slave
replicates 480577a4e5260efab5cadd4216cdec30125a5a88
S: cb965245d3d9836de27b483dd861b24c8969aae2 192.168.72.150:6379
slots: (0 slots) slave
replicates 1c10f642637b8e997fca9c1e8f9e73699bc60b15
S: c200aab6263548b949a44bb1754a461c7038b418 192.168.72.153:6379
slots: (0 slots) slave
replicates accd85afbe7c1d9bded991f045703974a1931ad4
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)? 1365
What is the receiving node ID? accd85afbe7c1d9bded991f045703974a1931ad4
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1: 480577a4e5260efab5cadd4216cdec30125a5a88
Source node #2: done
Moving slot 12276 from 192.168.72.157:6379 to 192.168.72.151:6379:
Moving slot 12277 from 192.168.72.157:6379 to 192.168.72.151:6379:
Moving slot 12278 from 192.168.72.157:6379 to 192.168.72.151:6379:
Moving slot 12279 from 192.168.72.157:6379 to 192.168.72.151:6379:
Moving slot 12280 from 192.168.72.157:6379 to 192.168.72.151:6379:
Moving slot 12281 from 192.168.72.157:6379 to 192.168.72.151:6379:
Moving slot 12282 from 192.168.72.157:6379 to 192.168.72.151:6379:
Moving slot 12283 from 192.168.72.157:6379 to 192.168.72.151:6379:
Moving slot 12284 from 192.168.72.157:6379 to 192.168.72.151:6379:
Moving slot 12285 from 192.168.72.157:6379 to 192.168.72.151:6379:
Moving slot 12286 from 192.168.72.157:6379 to 192.168.72.151:6379:
Moving slot 12287 from 192.168.72.157:6379 to 192.168.72.151:6379:
.......
#缩容后可以安全删除这个已经没了槽位的节点
[root@Rocky8 ~]# redis-cli -a 123456 --cluster del-node 192.168.72.157:6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
[ERR] Wrong number of arguments for specified --cluster sub command
[root@Rocky8 ~]# redis-cli -a 123456 --cluster del-node 192.168.72.157:6379 480577a4e5260efab5cadd4216cdec30125a5a88
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Removing node 480577a4e5260efab5cadd4216cdec30125a5a88 from cluster 192.168.72.157:6379
>>> Sending CLUSTER FORGET messages to the cluster...
>>> Sending CLUSTER RESET SOFT to the deleted node.
#删除157服务器后发现它原来的从节点154已自动变为151的从节点
[root@Rocky8 ~]# cat /apps/redis/data/nodes-6379.conf ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 192.168.72.155:6379@16379 master - 0 1670136567477 10 connected 12288-16383 accd85afbe7c1d9bded991f045703974a1931ad4 192.168.72.151:6379@16379 master - 0 1670136565464 13 connected 5461-12287 1c10f642637b8e997fca9c1e8f9e73699bc60b15 192.168.72.142:6379@16379 master - 0 1670136564000 12 connected 0-5460 354be8dc095454717325a4793163daaec4391204 192.168.72.154:6379@16379 slave accd85afbe7c1d9bded991f045703974a1931ad4 0 1670136565000 13 connected b86eced539971413958b34d4e320556d2482f4bd 192.168.72.152:6379@16379 myself,slave ddbc2de4bc11c18ac85b024b17f6f5812e9d0c13 0 1670136563000 10 connected cb965245d3d9836de27b483dd861b24c8969aae2 192.168.72.150:6379@16379 slave 1c10f642637b8e997fca9c1e8f9e73699bc60b15 0 1670136564457 12 connected c200aab6263548b949a44bb1754a461c7038b418 192.168.72.153:6379@16379 slave accd85afbe7c1d9bded991f045703974a1931ad4 0 1670136564000 13 connected vars currentEpoch 13 lastVoteEpoch 0
#现在可以把154这个多余的从节点也剔除掉
[root@Rocky8 ~]# redis-cli -a 123456 --cluster del-node 192.168.72.154:6379 354be8dc095454717325a4793163daaec4391204 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Removing node 354be8dc095454717325a4793163daaec4391204 from cluster 192.168.72.154:6379 >>> Sending CLUSTER FORGET messages to the cluster... >>> Sending CLUSTER RESET SOFT to the deleted node.
#清除集群关系的命令
[root@Rocky8 ~]# redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> cluster reset
OK
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> exit
2. LVS常用模型工作原理,及实现。
工作原理:
a、当用户向负载均衡调度器(Director Server)发起请求,调度器将请求发往至内核空间
b、PREROUTING链首先会接收到用户请求,判断目标IP确定是本机IP,将数据包发往INPUT链
c、IPVS是工作在INPUT链上的,当用户请求到达INPUT时,IPVS会将用户请求和自己已定义好的集群服务进行比对,如果用户请求的就是定义的集群服务,那么此时IPVS会强行修改数据包里的目标IP地址及端口,并将新的数据包发往POSTROUTING链
d、POSTROUTING链接收数据包后发现目标IP地址刚好是自己的后端服务器,那么此时通过选路,将数据包最终发送给后端的服务器。
LVS常用模型分类
3. LVS的负载策略有哪些,各应用在什么场景,通过LVS DR任意实现1-2种场景。
lvs-nat
:本质是多目标IP的DNAT
,通过将请求报文中的目标地址和目标端口修改为某挑出的RS
的RIP
和PORT
实现转发lvs-dr
:Direct Routing
,直接路由,LVS默认模式,应用最广泛,通过为请求报文重新封装一个MAC
首部进行转发,源MAC
是DIP
所在的接口的MAC
,目标MAC
是某挑选出的RS
的RIP
所在接口的MAC地址;源IP/PORT
,以及目标IP/PORT
均保持不变lvs-tun
:不修改请求报文的IP首部(源IP为CIP,目标IP为VIP),而在原IP报文之外再封装一个IP首部(源IP是DIP,目标IP是RIP),将报文发往挑选出的目标RS;RS直接响应给客户端(源IP是VIP,目标IP是CIP)lvs-fullnat
:修改请求报文的源和目标IP,默认内核不支持。
3.1 负载策略
3.1.1 静态方法
仅根据算法本身进行调度
RR
:roundrobin
,轮询,较常用,
WRR
:Weighted RR
,加权轮询,较常用
SH
:Source Hashing
,实现session sticky
,源IP地址hash;将来自于同一个IP地址的请求始终发往第一次挑中的RS,从而实现会话绑定
3.1.2 动态方法
主要根据每RS当前的负载状态及调度算法进行调度Overhead=value
较小的RS将被调度
-
LC
:least connections
适用于长连接应用Overhead=activeconns*256+inactiveconns
-
WLC
:Weighted LC
,默认调度方法,较常用Overhead=(activeconns*256+inactiveconns)/weight
-
SED
:Shortest Expection Delay
,初始连接高权重优先,只检查活动连接,而不考虑非活动连接Overhead=(activeconns+1)*256/weight
-
NQ
:Never Queue
,第一轮均匀分配,后续SED
-
LBLC
:Locality-Based LC
,动态的DH
算法,使用场景:根据负载状态实现正向代理,实现Web Cache等 -
LBLCR
:LBLC with Replication
,带复制功能的LBLC
,解决LBLC
负载不均衡问题,从负载重的复制到负载轻的RS,实现Web Cache等 DH
:Destination Hashing
;目标地址哈希,第一次轮询调度至RS,后续将发往同一个目标地址的请求始终转发至第一次挑中的RS,典型使用场景是正向代理缓存场景中的负载均衡,如: Web缓存
#LVS-DR模式单网段案例:
总共需要5台服务器:
两台rs服务器:192.168.72.7
192.168.72.17
一台lvs服务器:192.168.72.8
一台模拟路由器的服务器:192.168.72.200,配一块仅主机模式的网卡10.0.0.200
一台internet客户端服务器:10.0.0.101
安装依赖的RPM包
yum -y install httpd mod_ssl redis
yum -y install net-tools(用来使用ifconfig命令)
修改RS1的网卡配置:
[root@web1 ~]vim /etc/sysconfig/network-scripts/ifcfg-ens33
web1设置:
BOOTPROTO="static"
NAME="ens33"
IPADDR=192.168.72.7
PREFIX=24
GATEWAY=192.168.72.200
DNS1=192.168.72.2
DNS2=180.76.76.76
UUID="9fbe9de5-7a33-4469-92c4-89f6557ef712"
DEVICE="ens33"
ONBOOT="yes"
[root@web1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::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 1000
link/ether 00:0c:29:b4:ef:9e brd ff:ff:ff:ff:ff:ff
inet 192.168.72.7/24 brd 192.168.72.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:feb4:ef9e/64 scope link
valid_lft forever preferred_lft forever
[root@web1 ~]# ip route
default via 192.168.72.200 dev ens33 proto static metric 100
192.168.72.0/24 dev ens33 proto kernel scope link src 192.168.72.7 metric 100
[root@web1 ~]vi /etc/redis.conf
bind 0.0.0.0
[root@web1 ~]# redis-cli
127.0.0.1:6379> set host 192.168.72.7
OK
127.0.0.1:6379> get host
"192.168.72.7"
127.0.0.1:6379> exit
[root@web1 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@web1 ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@web1 ~]# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@web1 ~]# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
#配置VIP的回环网卡
[root@web1 ~]# ip a a 192.168.72.100/32 dev lo label lo:1
[root@web1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 192.168.72.100/32 scope global lo:1
valid_lft forever preferred_lft forever
inet6 ::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 1000
link/ether 00:0c:29:b4:ef:9e brd ff:ff:ff:ff:ff:ff
inet 192.168.72.7/24 brd 192.168.72.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:feb4:ef9e/64 scope link
valid_lft forever preferred_lft forever
#修改RS2的网卡配置
[root@web2 ~]# vi /etc/sysconfig/network-scripts/ifcfg-ens33
NAME="ens33"
BOOTPROTO="static"
UUID="9bb65852-ed90-49f2-99d7-4853e4dd03fa"
IPADDR=192.168.72.17
PREFIX=24
GATEWAY=192.168.72.200
DNS1=192.168.72.2
DNS2=180.76.76.76
DEVICE="ens33"
ONBOOT="yes"
[root@web2 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::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 1000
link/ether 00:0c:29:aa:bb:3b brd ff:ff:ff:ff:ff:ff
inet 192.168.72.17/24 brd 192.168.72.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:feaa:bb3b/64 scope link
valid_lft forever preferred_lft forever
[root@web2 ~]# ip route
default via 192.168.72.200 dev ens33 proto static metric 100
192.168.72.0/24 dev ens33 proto kernel scope link src 192.168.72.17 metric 100
[root@web2 ~]# hostname > /var/www/html/index.html
[root@web2 ~]# redis-cli
127.0.0.1:6379> set host 192.168.72.17
OK
127.0.0.1:6379> get host
"192.168.72.17"
127.0.0.1:6379> exit
[root@web2 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@web2 ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@web2 ~]# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@web2 ~]# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
#配置VIP的回环网卡
[root@web2 ~]# ip a a 192.168.72.100/32 dev lo label lo:1
[root@web2 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 192.168.72.100/32 scope global lo:1
valid_lft forever preferred_lft forever
inet6 ::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 1000
link/ether 00:0c:29:aa:bb:3b brd ff:ff:ff:ff:ff:ff
inet 192.168.72.17/24 brd 192.168.72.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:feaa:bb3b/64 scope link
valid_lft forever preferred_lft forever
#设置LVS服务器的网络配置
[root@lvs ~]vim /etc/sysconfig/network-scripts/ifcfg-ens160
NAME=ens160
UUID=e37367ad-c466-4366-a071-5c9152d529ef
DEVICE=ens160
BOOTPROTO=static
ONBOOT=yes
IPADDR=192.168.72.8
PREFIX=24
GATEWAY=192.168.72.200
DNS1=192.168.72.2
DNS2=180.76.76.76
[root@lvs ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:a5:6a:fd brd ff:ff:ff:ff:ff:ff
inet 192.168.72.8/24 brd 192.168.72.255 scope global noprefixroute ens160
valid_lft forever preferred_lft forever
[root@lvs ~]# redis-cli
127.0.0.1:6379> info
NOAUTH Authentication required.
127.0.0.1:6379> exit
#查看路由设置
[root@lvs ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.72.200 0.0.0.0 UG 100 0 0 ens160
192.168.72.0 0.0.0.0 255.255.255.0 U 100 0 0 ens160
#配置VIP的回环网卡
[root@lvs ~]# ip a a 192.168.72.100/32 dev lo label lo:1
[root@lvs ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 192.168.72.100/32 scope global lo:1
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:a5:6a:fd brd ff:ff:ff:ff:ff:ff
inet 192.168.72.8/24 brd 192.168.72.255 scope global noprefixroute ens160
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fea5:6afd/64 scope link
valid_lft forever preferred_lft forever
#设置LVS服务器的ipvs策略
[root@LVS ~]#ipvsadm -A -t 192.168.72.100:80 -s wrr
[root@LVS ~]#ipvsadm -a -t 192.168.72.100:80 -r 192.168.72.7 -g -w 3
[root@LVS ~]#ipvsadm -a -t 192.168.72.100:80 -r 192.168.72.17 -g
#修改192.168.72.200路由器的网络配置文件,并给它配一块仅主机模式的网卡10.0.0.200
root@router:~# vim /etc/netplan/00-installer-config.yaml
network:
version: 2
renderer: networkd
ethernets:
ens33:
addresses:
- 192.168.72.200/24
gateway4: 192.168.72.2
nameservers:
search: [magedu.com, magedu.org]
addresses: [192.168.72.2, 180.76.76.76]
ens37:
addresses:
- 10.0.0.200/24
#在两台RS服务器防火墙关闭的前提下,试着ping通这两台RS服务器
root@router:~# curl 192.168.72.7
web1
root@router:~# curl 192.168.72.17
web2
#开启路由器ip转发功能
root@router:~# echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
root@router:~# sysctl -p
net.ipv4.ip_forward = 1
#互联网客户端机器配置(新的网络ip:10.0.0.101)
[root@internet ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens160
BOOTPROTO=static
NAME=ens160
UUID=e37367ad-c466-4366-a071-5c9152d529ef
DEVICE=ens160
ONBOOT=yes
IPADDR=10.0.0.101
PREFIX=24
GATEWAY=10.0.0.200
DNS1=192.168.72.2
DNS2=180.76.76.76
#验证结果看看通不通
root@router:~# curl 192.168.72.7
web1
root@router:~# curl 192.168.72.17
web2
#LVS-DR模式多网段案例:
路由器加配ip:
root@router:~# ip a a 172.16.0.200/24 dev ens33 label ens33:1
root@router:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:53:69:75 brd ff:ff:ff:ff:ff:ff
inet 192.168.72.200/24 brd 192.168.72.255 scope global ens33
valid_lft forever preferred_lft forever
inet 172.16.0.200/24 scope global ens33:1
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe53:6975/64 scope link
valid_lft forever preferred_lft forever
3: ens37: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:53:69:7f brd ff:ff:ff:ff:ff:ff
inet 10.0.0.200/24 brd 10.0.0.255 scope global ens37
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe53:697f/64 scope link
valid_lft forever preferred_lft forever
#验证添加ip后的路由表
root@router:~# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.72.2 0.0.0.0 UG 0 0 0 ens33
10.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0 ens37
172.16.0.0 0.0.0.0 255.255.255.0 U 0 0 0 ens33
192.168.72.0 0.0.0.0 255.255.255.0 U 0 0 0 ens33
#修改RS1和RS2的网络配置和内核参数
[root@web1 ~]# vim lvs_dr_rs.sh
#!/bin/bash
vip=172.16.0.100
mask='255.255.255.255'
dev=lo:1
case $1 in
start)
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
ifconfig $dev $vip netmask $mask
echo "The RS Server is Ready!"
;;
stop)
ifconfig $dev down
echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo "The RS Server is Canceled!"
;;
*)
echo "Usage: $(basename $0) start|stop"
exit 1
;;
esac
[root@web1 ~]# chmod +x lvs_dr_rs.sh
[root@web1 ~]# ./lvs_dr_rs.sh
Usage: lvs_dr_rs.sh start|stop
[root@web1 ~]# ./lvs_dr_rs.sh start
./lvs_dr_rs.sh: line 13: ifconfig: command not found
The RS Server is Ready!
[root@web1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 172.16.0.100/32 scope global lo:1
valid_lft forever preferred_lft forever
inet6 ::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 1000
link/ether 00:0c:29:b4:ef:9e brd ff:ff:ff:ff:ff:ff
inet 192.168.72.7/24 brd 192.168.72.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:feb4:ef9e/64 scope link
valid_lft forever preferred_lft forever
#拷贝修改参数的脚本到另一台RS服务器上
[root@web1 ~]# scp lvs_dr_rs.sh 192.168.72.17:
The authenticity of host '192.168.72.17 (192.168.72.17)' can't be established.
ECDSA key fingerprint is SHA256:TUB7ojU2RTw4bWUMS/jYAZB+9LXP820dVIPnxEVZiPk.
ECDSA key fingerprint is MD5:f5:90:35:79:11:53:ab:4a:c1:96:c5:7b:53:60:2e:9d.
Are you sure you want to continue connecting (yes/no)? y
Please type 'yes' or 'no': yes
Warning: Permanently added '192.168.72.17' (ECDSA) to the list of known hosts.
root@192.168.72.17's password:
lvs_dr_rs.sh
100% 751 458.0KB/s 00:00
[root@web2 ~]# bash lvs_dr_rs.sh start
The RS Server is Ready!
[root@web2 ~]# ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.72.17 netmask 255.255.255.0 broadcast 192.168.72.255
inet6 fe80::20c:29ff:feaa:bb3b prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:aa:bb:3b txqueuelen 1000 (Ethernet)
RX packets 24052 bytes 10212945 (9.7 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3063 bytes 388482 (379.3 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 16 bytes 1405 (1.3 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 16 bytes 1405 (1.3 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo:1: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 172.16.0.100 netmask 255.255.255.255
loop txqueuelen 1000 (Local Loopback)
#用脚本修改lvs的网卡配置和内核参数
[root@lvs ~]# vim lvs_dr_vs.sh.sh
#!/bin/bash
#Author:wangxiaochun
#Date:2017-08-13
vip='172.16.0.100'
iface='lo:1'
mask='255.255.255.255'
port='80'
rs1='192.168.72.7'
rs2='192.168.72.17'
scheduler='wrr'
type='-g'
rpm -q ipvsadm &> /dev/null || yum -y install ipvsadm &> /dev/null
case $1 in
start)
ifconfig $iface $vip netmask $mask #broadcast $vip up
iptables -F
ipvsadm -A -t ${vip}:${port} -s $scheduler
ipvsadm -a -t ${vip}:${port} -r ${rs1} $type -w 1
ipvsadm -a -t ${vip}:${port} -r ${rs2} $type -w 1
echo "The VS Server is Ready!"
;;
stop)
ipvsadm -C
ifconfig $iface down
echo "The VS Server is Canceled!"
;;
*)
echo "Usage: $(basename $0) start|stop"
exit 1
;;
esac
[root@lvs ~]# chmod +x lvs_dr_vs.sh.sh
[root@lvs ~]# bash lvs_dr_vs.sh.sh
Usage: lvs_dr_vs.sh.sh start|stop
[root@lvs ~]# bash lvs_dr_vs.sh.sh start
The VS Server is Ready!
[root@lvs ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 172.16.0.100/32 scope global lo:1
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:a5:6a:fd brd ff:ff:ff:ff:ff:ff
inet 192.168.72.8/24 brd 192.168.72.255 scope global noprefixroute ens160
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fea5:6afd/64 scope link
valid_lft forever preferred_lft forever
[root@lvs ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.16.0.100:80 wrr
-> 192.168.72.7:80 Route 1 0 0
-> 192.168.72.17:80 Route 1 0 0
#用客户端机器验证
[root@internet~]while true; do curl 172.16.0.100;sleep 0.5;done
web2
web1
web2
web1
web2
web1
4. web http协议通信过程,相关技术术语总结。
4.1 传输数据过程:
http1.0 连接—>传输–>断开 在连接—>传输–>断开 每一个请求都要经过连接然后传输然后断开
每一个请求 表示 请求的每一个URL
http1.1 一次连接多次请求(建立一次三次握手 后面直接按照顺序请求所有的url)
http2.0 一次连接多次请求(并发请求)
4.2 HTTP工作原理
在用户点击URL为http://www.magedu.org/index.html的链接后,浏览器和Web服务器执行以下动作:
a.浏览器分析超链接中的URL
b.浏览器向DNS请求解析www.magedu.org的IP地址
c.DNS将解析出的IP地址192.168.72.150:80返回浏览器
d.浏览器与服务器建立TCP连接(80端口)
e.浏览器请求文档:GET /index.html
f.服务器给出响应,将文档 index.html发送给浏览器
g.释放TCP连接
h.浏览器显示index.html
i.web服务器关闭连接:一般情况下,一旦web服务器向浏览器发送了请求的数据,就会关闭TCP连接。若浏览器或者服务器在头信息中加入了Connection:keep-alive
,TCP连接在发送后仍将以打开状态,于是,浏览器可以继续通过相同的连接发送请求。
4.3 相关技术术语
4.3.1 WEB开发语言
html
:Hyper Text Markup Language
超文本标记语言,编程语言,主要负责实现页面的结构css
:Cascading Style Sheet
层叠样式表, 定义了如何显示(装扮) HTML 元素,比如:字体大小和颜色属性等。样式通常保存在外部的 .css 文件中,用于存放一些HTML文件的公共属性,从而通过仅编辑一个简单的 CSS 文档,可以同时改变站点中所有页面的布局和外观。javascript
:实现网页的动画效果,但是属于静态资源
4.3.2 HTTP响应
响应头部信息:
Connection: keep-alive # 响应长连接
Date: Tue, 14 Jun 2022 03:21:07 GMT # 响应时间
ETag: "53762af0-12e1" # 和浏览器缓存相关
Last-Modified: Fri, 16 May 2014 15:12:48 GMT# 最后内容修改时间
Server: nginx/1.20.1 # 服务器WEB版本信息Request URL: http://10.0.0.8/ # 请求的URL 链接
Request Method: GET # 请求方法
Status Code: 304 OK # 服务状态码
Remote Address: 10.0.0.8:80 # 服务器的IP地址
响应报文中的状态码
状态码(Status-Code)是响应报文状态行中包含的一个3位数字,指明特定的请求是否被满足,如果没有满足,原因是什么。
通过状态码知道服务器状况:
200: 表示成功访问网站
301: 表示访问一个网站会跳转到另外一个网站 简称永久跳转
302: 表示访问一个网站会跳转到另外一个网站 简称临时跳转
304: 表示访问网站走的是浏览器的缓存
401: 表示访问网站会弹出让我们输入用户名和密码的对话框 权限认证
403: 访问页面 具体的资源不存在 但是存放资源的目录存在
404: 表示访问的内容页面不存在 用户访问了一个不存在的页面
500: 服务器内部错误 代码配置错误 服务端网络问题 无法访问到后端数据库
502: 有代理代理服务器不正常 或者 没有开启服务
503: 后端数据库服务器压力较大或者服务器暂时无法响应客户端请求的数据
504: 访问超时
2 开头表示 网站没问题
3 开头表示 网站跳转
4 开头表示 访问不了页面 服务器没有配置这个页面 用户访问了一个不存在的页面
5 表示服务器端问题 数据问题
4.3.3 MIME 消息
MIME
: Multipurpose Internet Mail Extensions
多用途互联网邮件扩展
MIME 消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。
4.3.4 URI和URL
-
URI
:Uniform Resource Identifier
统一资源标识,分为URL
和URN
-
URN
:Uniform Resource Naming
,统一资源命名 -
示例: P2P下载使用的磁力链接是URN的一种实现magnet:?xt=urn:btih:660557A6890EF888666
-
URL
:Uniform Resorce Locator
,统一资源定位符,用于描述某服务器某特定资源位置
两者区别:URN
如同一个人的名称,而URL
代表一个人的住址。换言之,URN
定义某事物的身份,而URL
提供查找该事物的方法。URN
仅用于命名,而不指定地址
4.3.5 PV,UV和IP
PV: 用户访问一个页面称为一个PV 刷新1次+1
UV: 表示用户真实独立的设备 笔记本算一个UV 手机算一个UV 平板算一个UV
IP: 表示公网IP 表示通过哪个公网IP访问的网站
家里一个IP 手机 平台 电视 通过路由器上网 NAT—>转换成了一个公网IP地址
公司算一个IP 所有员工通过NAT上网
4.3.6 网站访问量
网站访问量统计的重要指标
- IP(独立IP):即
Internet Protocol
,指独立IP数。一天内来自相同客户机IP 地址只计算一次,记录远程客户机IP地址的计算机访问网站的次数,是衡量网站流量的重要指标 - PV(访问量): 即
Page View
, 页面浏览量或点击量,用户每次刷新即被计算一次,PV反映的是浏览某网站的页面数,PV与来访者的数量成正比,PV并不是页面的来访者数量,而是网站被访问的页面数量 - UV(独立访客):即
Unique Visitor
,访问网站的一台电脑为一个访客。一天内相同的客户端只被计算一次。可以理解成访问某网站的电脑的数量。网站判断来访电脑的身份是通过cookies实现的。如果更换了IP后但不清除cookies,再访问相同网站,该网站的统计中UV数是不变的
网站访问量的计算方式
QPS
:request per second
,每秒请求数PV
,QPS
和并发连接数换算公式QPS
=PV
*
页面衍生连接次数/ 统计时间(86400)- 并发连接数 =QPS * http平均响应时间
- 峰值时间:每天80%的访问集中在20%的时间里,这20%时间为峰值时间
- 峰值时间每秒请求数(QPS)=( 总PV数 页面衍生连接次数)80% ) / ( 每天秒数 * 20% )
5. 总结网络IO模型和nginx架构。
网络I/O
I/O介绍
网络I/O:本质是socket文件读取
磁盘I/O:本质是磁盘数据文件读取
每次I/O,都要经由两个阶段:
第一步:将数据从文件先加载至内核内存空间(缓冲区),等待数据准备完成,时间较长
第二步:将数据从内核缓冲区复制到用户空间的进程的内存中,时间较短
I/O模型
同步/异步:关注的是消息通信机制
- 同步:synchronous,调用者等待被调用者返回消息,才能继续执行
- 异步:asynchronous,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态
阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态
- 阻塞:blocking,指IO操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂起
- 非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成,最终的调用结果返回之前,调用者不会被挂起
Unix 有五种 I/O 模型:
- 阻塞IO(bloking IO)
- 非阻塞IO(non-blocking IO)
- 多路复用IO(multiplexing IO)
- 信号驱动式IO(signal-driven IO)
- 异步IO(asynchronous IO)
同步阻塞IO模型
阻塞原理:
1、阻塞IO模型是最简单的IO模型,用户线程在内核进行IO操作时被阻塞。
2、用户线程通过系统调用read发起IO读操作,由用户空间转到内核空间。内核等到数据包到达后,然后将接收的数据拷贝到用户空间,完成read操作。
3、用户需要等待read将数据读取到buffer后,才继续处理接收的数据。整个IO请求的过程中,用户线程是被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够。
优缺点:
- 优点:程序简单,在阻塞等待数据期间进程/线程挂起,基本不会占用 CPU 资源。
- 缺点:每个连接需要独立的进程/线程单独处理,当并发请求量大时为了维护程序,内存、线程切换开销较大,这种模型在实际生产中很少使用,apache的preforck使用的是这种模式。
同步阻塞原理:
程序向内核发送IO请求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回,则进程将一直等待并不再接受新的请求,并由进程轮训查看IO是否完成,完成后进程将IO结果返回给Client,在IO没有返回期间进程不能接受其他客户的请求,而且是有进程自己去查看IO是否完成,这种方式简单,但是比较慢,用的比较少。
同步非阻塞IO模型
非阻塞原理:
用户线程发起IO请求时立即返回。但并未读取到任何数据,用户线程需要不断地发起IO请求,直到数据到达后,才真正读取到数据,继续执行。即 “轮询”机制存在两个问题:如果有大量文件描述符都要等,那么就得一个一个的read。这会带来大量的ContextSwitch(read是系统调用,每调用一次就得在用户态和核心态切换一次)。轮询的时间不好把握。这里是要猜多久之后数据才能到。等待时间设的太长,程序响应延迟就过大;设的太短,就会造成过于频繁的重试,干耗CPU而已,是比较浪费CPU的方式,一般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。
同步非阻塞原理:
程序向内核发送请IO求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回IO结果,进程将不再等待,而且继续处理其他请求,但是仍然需要进程隔一段时间就要查看内核IO是否完成。
IO多路复用模型
IO多路复用原理:
1、IO多路复用(IO Multiplexing) :是一种机制,程序注册一组socket文件描述符给操作系统,表示“我要监视这些fd是否有IO事件发生,有了就告诉程序处理”。对于监视的方式,又可以分为 select, poll, epoll三种方式。
2、IO多路复用是要和NIO一起使用的。NIO和IO多路复用是相对独立的。NIO仅仅是指IO API总是能立刻返回,不会被Blocking;而IO多路复用仅仅是操作系统提供的一种便利的通知机制。操作系统并不会强制这俩必须得一起用,可以只用IO多路复用 + BIO,这时还是当前线程被卡住。IO多路复用和NIO是要配合一起使用才有实际意义。
3、IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,就通知该进程。
4、多个连接共用一个等待机制,本模型会阻塞进程,但是进程是阻塞在select或者poll这样的系统调用上,而不是阻塞在真正的IO操作如recvfrom上。
5、用户首先将需要进行IO操作添加到select中,同时等待select系统调用返回。当数据到达时,IO被激活,select函数返回。用户线程正式发起read请求,读取数据并继续执行。
注意:Apache prefork是select模式,work是poll模式。
1、从流程上来看,使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视IO,以及调用select函数的额外操作,效率更差。并且阻塞了两次,但是第一次阻塞在select上时,select可以监控多个IO上是否已有IO操作准备就绪,即可达到在同一个线程内同时处理多个IO请求的目的。而不像阻塞IO那种,一次只能监控一个IO。
2、虽然上述方式允许单线程内处理多个IO请求,但是每个IO请求的过程还是阻塞的(在select函数上阻塞),平均时间甚至比同步阻塞IO模型还要长。如果用户线程只是注册自己需要的IO请求,然后去做自己的事情,等到数据到来时再进行处理,则可以提高CPU的利用率。
3、IO多路复用是最常使用的IO模型,但是其异步程度还不够“彻底”,因它使用了会阻塞线程的select系统调用。因此IO多路复用只能称为异步阻塞IO模型,而非真正的异步IO。
NIO&epoll:
可以这么理解NIO是JAVA的IO模型,而epoll是Linux内核的IO模型。它们之间有很深的因缘,因为从实现方式来看,它们其实是很相似的,都是基于“通道”和缓冲区的,也有selector,只是在epoll中,通道实际上是操作系统的“管道”。和NIO不同的是,NIO中,解放了线程,但是需要由selector阻塞式地轮询IO事件的就绪;而epoll中,IO事件就绪后,会自动发送消息,通知selector:“我已经就绪了。”可以认为,Linux的epoll是一种效率更高的NIO。
信号驱动IO模型
信号驱动IO模型原理:
1、用户进程可以通过sigaction系统调用注册一个信号处理程序,然后主程序可以继续向下执行,当有IO操作准备就绪时,由内核通知触发一个SIGIO信号处理程序执行,然后将用户进程所需要的数据从内核空间拷贝到用户空间。
2、此模型的优势在于等待数据报到达期间进程不被阻塞。用户主程序可以继续执行,只要等待来自信号处理函数的通知。
3、对于 TCP 而言,信号驱动的 I/O 方式近乎无用,因为导致这种通知的条件为数众多,每一个来进行判别会消耗很大资源,与前几种方式相比优势尽失。
优缺点:
- 优点:线程并没有在等待数据时被阻塞,可以提高资源的利用率。
- 缺点:信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知。
异步阻塞原理:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核收到进程请求后进行的IO如果不能立即返回,就由内核等待结果,直到IO完成后内核再通知进程,apache event是此模式。
异步IO(非阻塞)模型
异步IO原理:
1、异步IO与信号驱动IO最主要的区别是信号驱动IO是由内核通知应用程序何时可以进行IO操作,而异步IO则是由内核告诉用户线程IO操作何时完成。信号驱动IO当内核通知触发信号处理程序时,信号处理程序还需要阻塞在从内核空间缓冲区拷贝数据到用户空间缓冲区这个阶段,而异步IO直接是在第二个阶段完成后,内核直接通知用户线程可以进行后续操作了。
2、由 POSIX 规范定义,应用程序告知内核启动某个操作,并让内核在整个操作(包括将数据从内核拷贝到应用程序的缓冲区)完成后通知应用程序。
优缺点:
- 优点:异步 I/O 能够充分利用 DMA 特性,让 I/O 操作与计算重叠。
- 缺点:要实现真正的异步 I/O,操作系统需要做大量的工作。目前 Windows 下通过 IOCP 实现了真正的异步 I/O,在 Linux 系统下,Linux 2.6才引入,目前 AIO 并不完善,因此在 Linux 下实现高并发网络编程时以 IO 复用模型模式+多线程任务的架构基本可以满足需求。
异步非阻塞原理:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核调用的IO如果不能立即返回,内核会继续处理其他事物,直到IO完成后将结果通知给内核,内核在将IO完成的结果返回给进程,期间进程可以接受新的请求,内核也可以处理新的事物,因此相互不影响,可以实现较大的同时并实现较高的IO复用,因此异步非阻塞是使用最多的一种通信方式。
I/O模型对比
这五种 I/O 模型中,越往后,阻塞越少,理论上效率也是最优,前四种属于同步 I/O,因为其中真正的 I/O 操作(recvfrom)将阻塞进程/线程,只有异步 I/O 模型才与 POSIX 定义的异步 I/O 相匹配。
I/O模型实现方式
Nginx支持在多种不同的操作系统实现不同的事件驱动模型,但是其在不同的操作系统甚至是不同的系统版本上面的实现方式不尽相同,主要有以下实现方式:
1、select:
select库是在linux和windows平台都基本支持的事件驱动模型库,并且在接口的定义也基本相同,只是部分
参数的含义略有差异,最大并发限制1024,是最早期的事件驱动模型。
2、poll:
在Linux 的基本驱动模型,windows不支持此驱动模型,是select的升级版,取消了最大的并发限制,在编译
nginx的时候可以使用--with-poll_module和--without-poll_module这两个指定是否编译select库。
3、epoll:
epoll是库是Nginx服务器支持的最高性能的事件驱动库之一,是公认的非常优秀的事件驱动模型,它和select
和poll有很大的区别,epoll是poll的升级版,但是与poll的效率有很大的区别.
epoll的处理方式是创建一个待处理的事件列表,然后把这个列表发给内核,返回的时候在去轮训检查这个表,
以判断事件是否发生,epoll支持一个进程打开的最大事件描述符的上限是系统可以打开的文件的最大数,同时
epoll库的IO效率不随描述符数目增加而线性下降,因为它只会对内核上报的“活跃”的描述符进行操作。
Nginx架构
模块化结构的思想是一个很久的概念,但也正是这个概念造就了Nginx现在的领先优越性。
我们知道Nginx从总体上来讲是有许多个模块构成的。习惯将Nginx分为5大模块分别为:核心模块,标准HTTP模块,可选HTTP模块,邮件服务模块和第三方模块。
这5个模块由上到下重要性一次递减。
(1)核心模块;
核心模块是Nginx服务器正常运行必不可少的模块,如同操作系统的内核。它提供了Nginx最基本的核心服务。像进程管理、权限控制、错误日志记录等;
(2)标准HTTP模块;
标准HTTP模块支持标准的HTTP的功能;
(3)可选HTTP模块;
可选HTTP模块主要用于扩展标准的HTTP功能,让Nginx能处理一些特殊的服务;
(4)邮件服务模块;
邮件服务模块主要用于支持Nginx的邮件服务;
(5)第三方模块;
第三方模块是为了扩展Nginx服务器应用,完成开发者想要的功能;
*******Nginx中的模块命名有自己的习惯*********
一般以Ngx_作为前缀,——module作为后缀,中间使用一个或者多个英文单词描述模块的工能,例如Ngx_core_module表示该模块提供Nginx的核心功能等;
Nginx的大致架构就是遵循一个这样的逻辑:
1.Nginx启动后,会产生一个主进程,主进程执行一系列的工作后会产生一个或者多个工作进程;
2.在客户端请求动态站点的过程中,Nginx服务器还涉及和后端服务器的通信。Nginx将接收到的Web请求通过代理转发到后端服务器,由后端服务器进行数据处理和组织;
3.Nginx为了提高对请求的响应效率,降低网络压力,采用了缓存机制,将历史应答数据缓存到本地。保障对缓存文件的快速访问;
6. nginx总结核心配置和优化。
Nginx核心配置
在学习 Nginx之前,要熟知它的配置文件,毕竟,下面需要做的所有配置(反向代理、负载均衡、动静分离等),都是基于它的配置文件。
Nginx默认的配置文件是在安装目录下的 conf目录下,后续对 Nginx的使用基本上都是对此配置文件进行相应的修改。完整的配置文件,可以看一下文章最后。修改过nginx.conf配置文件,记得要重启Nginx服务(☆☆☆☆☆)
配置文件中有很多#号,该符号表示注释内容,去掉所有以 #开头的段落,精简之后的配置文件内容如下(PS:其实注释掉的地方,都是一些功能的使用代码,需要用到的时候,取消注释即可):
# 主进程叫master,负责管理子进程,子进程叫worker
# worker_processes配置项表示开启几个业务进程,一般和cpu核数有关
worker_processes 1;
events {
worker_connections 1024;
}
http {
# include表示可以引入其他文件,此处表示引入http mime类型
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 虚拟主机,可以配置多个
server {
listen 80;
server_name localhost;
location / {
# 路径匹配之后,哪个目录下去匹配相应的网页,html是相对路径
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
- 去掉注释信息后,可以将
nginx.conf
配置文件分为三部分:
第一部分:全局块
worker_processes 1;
从配置文件开始到events
块之间的内容,主要会设置一些影响Nginx服务器整体运行的配置指令,主要包括:配置运行Nginx服务器的用户(组)、允许生成的 worker process 数,进程PID存放路径、日志存放路径和类型以及配置文件的引入等。
上面这行 worker_processes
配置,是 Nginx 服务器并发处理服务的关键配置,该值越大,可以支持的并发处理量也越多,但是会受到硬件、软件等设备的约束。
第二部分:events 块
events {
worker_connections 1024;
}
events
块涉及的指令主要影响Nginx服务器与用户的网络连接,常用的设置包括:是否开启对多 work process下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 work process 可以同时支持的最大连接数等
上述例子就表示每个 work process 支持的最大连接数为 1024。这部分的配置对Nginx的性能影响较大,在实际中应该灵活配置。
第三部分:http 块
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
这部分是 Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。需要注意的是:http 块也可以包括 http 全局块、server 块。下面的反向代理、动静分离、负载均衡都是在这部分中配置
1)http 全局块:http 全局块配置的指令包括:文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。
2)server 块:这块和虚拟主机有密切关系,从用户角度看,虚拟主机和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本。
每个http块可以包括多个server块,而每个server块就相当于一个虚拟主机。而每个server块也分为全局server块,以及可以同时包含多个locaton块。
全局 server 块
最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或IP配置。
location 块
一个 server 块可以配置多个 location 块。
这块的主要作用是:基于 Nginx 服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称(也可以是 IP 别名)之外的字符串(例如 前面的 /uri-string)进行匹配,对特定的请求进行处理。地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
# 若请求路径像这样:www.xxxx/img/example.png
# 则访问/img/目录下的文件时,nginx会去/var/www/image/img/目录下找文件
location /img/ {
root /var/www/image;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
以上就是Nginx核心配置文件详解的全部内容。
Nginx优化实战
[root@nginx1 ~]# cd /data/nginx/html/pc
[root@nginx1 pc]# ls
about download index.html
vim /apps/nginx/conf/conf.d/pc.conf
server {
listen 80;
server_name www.magedu.org;
root /data/nginx/html/pc;
location /download {
autoindex on; #自动索引功能
autoindex_exact_size off; #计算文件确切大小(单位bytes),此为默认值,off只显示大概大小(单位kb、mb、gb)
autoindex_localtime on; #on表示显示本机时间而非GMT(格林威治)时间,默为为off显示GMT时间
limit_rate 1024k; #限速,默认不限速
客户端限速1M的下载测试
[root@client ~]# wget http://www.magedu.org/download/isoyum/CentOS-8.5.2111-x86_64-boot.iso%3Fspm%3Da2c6h.25603864.0.0.733353bavi8tw4
--2022-12-12 14:57:28-- http://www.magedu.org/download/isoyum/CentOS-8.5.2111-x86_64-boot.iso%3Fspm%3Da2c6h.25603864.0.0.733353bavi8tw4
Resolving www.magedu.org (www.magedu.org)... 192.168.72.152
Connecting to www.magedu.org (www.magedu.org)|192.168.72.152|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 91189010 (87M) [application/octet-stream]
Saving to: ‘CentOS-8.5.2111-x86_64-boot.iso?spm=a2c6h.25603864.0.0.733353bavi8tw4’
-x86_64-boot.iso?spm=a2c6h.256038 20%[===========>
] 17.75M 1023KB/s eta 69s
#nginx账户认证的优化
[root@nginx1 pc]# cd /usr/local/src/nginx-1.20.0/
[root@nginx1 nginx-1.20.0]# ls
auto CHANGES CHANGES.ru conf configure contrib html LICENSE Makefile man objs README src
[root@nginx1 nginx-1.20.0]# ./configure --help |grep access
--without-http_access_module disable ngx_http_access_module
--http-log-path=PATH set http access log pathname
--without-stream_access_module disable ngx_stream_access_module
[root@nginx1 nginx-1.20.0]# yum -y install httpd-tools
Last metadata expiration check: 4:40:15 ago on Mon 12 Dec 2022 10:22:52 AM CST.
Dependencies resolved.
======================================================================================================================================
Package Architecture Version Repository Size
======================================================================================================================================
Installing:
httpd-tools x86_64 2.4.37-51.module+el8.7.0+1059+126e9251 appstream 108 k
Installing dependencies:
apr x86_64 1.6.3-12.el8 appstream 128 k
apr-util x86_64 1.6.1-6.el8.1 appstream 104 k
Installing weak dependencies:
apr-util-bdb x86_64 1.6.1-6.el8.1 appstream 23 k
apr-util-openssl x86_64 1.6.1-6.el8.1 appstream 26 k
Enabling module streams:
httpd 2.4
Transaction Summary
======================================================================================================================================
Install 5 Packages
Installed:
apr-1.6.3-12.el8.x86_64 apr-util-1.6.1-6.el8.1.x86_64 apr-util-bdb-1.6.1-6.el8.1.x86_64
apr-util-openssl-1.6.1-6.el8.1.x86_64 httpd-tools-2.4.37-51.module+el8.7.0+1059+126e9251.x86_64
Complete!
#查看包里是否有生成用户名密码的工具htpasswd
[root@nginx1 nginx-1.20.0]# rpm -ql httpd-tools
/usr/bin/ab
/usr/bin/htdbm
/usr/bin/htdigest
/usr/bin/htpasswd
/usr/bin/httxt2dbm
/usr/bin/logresolve
[root@nginx1 ~]# ls /apps/nginx/conf/conf.d
mobile.conf pc.conf
#用htpasswd工具生成用户名账户和密码
[root@nginx1 ~]# htpasswd -bc /apps/nginx/conf/conf.d/.nginx-user wangwang 123456
[root@nginx1 ~]# cat /apps/nginx/conf/conf.d/.nginx-user
wangwang:$apr1$POFLor2M$Ue30eXc2ol9.gN01rnOO91
#注:第二次添加用户不要加-c的命令,否则之前创建的用户名密码文件会被直接覆盖
[root@nginx1 ~]# htpasswd -b /apps/nginx/conf/conf.d/.nginx-user doudou 123456
Adding password for user doudou
[root@nginx1 ~]# cat /apps/nginx/conf/conf.d/.nginx-user
wangwang:$apr1$POFLor2M$Ue30eXc2ol9.gN01rnOO91
doudou:$apr1$Q6nHzzRL$hi3tJiFIjorX2ZDvrPcoo.
#修改pc端配置文件以达到客户端查看系统特定目录需要密码验证的效果
vim /apps/nginx/conf/conf.d/pc.conf
server {
listen 80;
server_name www.magedu.org;
root /data/nginx/html/pc;
location /admin {
auth_basic "WARNING!!!";
auth_basic_user_file /apps/nginx/conf/conf.d/.nginx-user;
}
}
~
[root@nginx1 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@nginx1 ~]# nginx -s reload
#创建admin目录和网页index文件
[root@nginx1 ~]# mkdir /data/nginx/html/pc/admin/
[root@nginx1 ~]# echo /data/nginx/html/pc/admin/index.html > /data/nginx/html/pc/admin/index.html
#如果用户名密码输错日志文件就会出现401错误的提示
192.168.72.1 - zhuzhu [12/Dec/2022:15:31:50 +0800] "GET /admin HTTP/1.1" 401 581 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
#如果用户名密码输对日志文件就会出现200的正确提示
192.168.72.1 - wangwang [12/Dec/2022:15:32:26 +0800] "GET /admin/ HTTP/1.1" 200 37 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
#优化配置在访问网页时检测文件是否存在,如果不存在则直接跳转回默认的主页
vim /apps/nginx/conf/conf.d/pc.conf
server {
listen 80;
server_name www.magedu.org;
root /data/nginx/html/pc;
try_files $uri $uri.html $uri/index.html /index.html;
location /admin {
auth_basic "WARNING!!!";
auth_basic_user_file /apps/nginx/conf/conf.d/.nginx-user;
}
}
#重启nginx并测试,当访问到http://www.magedu.org/about/xx.html等不存在的uri会显示
index.html,如果是自定义的状态码则会显示在返回数据的状态码中
#nginx配置优化2-用户账号授权登录验证
# nginx配置优化3-错误页面自动跳转回主页结果验证
#nginx的优化之4-日志格式定制
#修改pc端的nginx子配置文件里的日志指引
[root@nginx1 ~]# vim /apps/nginx/conf/conf.d/pc.conf
vhost_traffic_status_zone;
server {
listen 80;
server_name www.magedu.org;
root /data/nginx/html/pc;
access_log /apps/nginx/logs/access_json.log access_json;
location /status {
vhost_traffic_status_display;
vhost_traffic_status_display_format html;
}
[root@nginx1 ~]# nginx -s reload
[root@nginx1 ~]# ls /apps/nginx/logs
access_json.log access.log error.log
#客户端访问www.magedu.org验证json日志是否已生成
[root@nginx1 ~]# tail /apps/nginx/logs/access_json.log -f
{"@timestamp":"2022-12-13T09:59:55+08:00","host":"192.168.72.152","clientip":"192.168.72.154","size":7,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-","http_host":"www.magedu.org","uri":"/index.html","xff":"-","referer":"-","tcp_xff":"-","http_user_agent":"curl/7.61.1","status":"200"}
{"@timestamp":"2022-12-13T10:00:58+08:00","host":"192.168.72.152","clientip":"192.168.72.150","size":7,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-","http_host":"www.magedu.org","uri":"/index.html","xff":"-","referer":"-","tcp_xff":"-","http_user_agent":"curl/7.61.1","status":"200"}
#查看access格式的日志
[root@nginx1 ~]# tail /apps/nginx/logs/access.log
192.168.72.1 - - [13/Dec/2022:00:08:02 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:04 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:06 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:08 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:10 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:12 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:14 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:16 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:18 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:20 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
#安装专门的jq工具来整理j_son日志
[root@nginx1 ~]# yum -y install jq
Last metadata expiration check: 0:29:53 ago on Tue 13 Dec 2022 09:44:14 AM CST.
Dependencies resolved.
======================================================================================================================================
Package Architecture Version Repository Size
======================================================================================================================================
Installing:
jq x86_64 1.6-3.el8 appstream 201 k
Installing dependencies:
oniguruma x86_64 6.8.2-2.el8 appstream 186 k
Transaction Summary
======================================================================================================================================
Install 2 Packages
Total download size: 387 k
Installed size: 1.1 M
Installed:
jq-1.6-3.el8.x86_64 oniguruma-6.8.2-2.el8.x86_64
#用安装好的jq工具把日志直接转化成j_son格式,方便又清晰,便于以后做专门的日志分析绘图
[root@nginx1 ~]# cat /apps/nginx/logs/access_json.log|jq
{
"@timestamp": "2022-12-13T09:59:55+08:00",
"host": "192.168.72.152",
"clientip": "192.168.72.154",
"size": 7,
"responsetime": 0.000,
"upstreamtime": "-",
"upstreamhost": "-",
"http_host": "www.magedu.org",
"uri": "/index.html",
"xff": "-",
"referer": "-",
"tcp_xff": "-",
"http_user_agent": "curl/7.61.1",
"status": "200"
}
{
"@timestamp": "2022-12-13T10:00:58+08:00",
"host": "192.168.72.152",
"clientip": "192.168.72.150",
"size": 7,
"responsetime": 0.000,
"upstreamtime": "-",
"upstreamhost": "-",
"http_host": "www.magedu.org",
"uri": "/index.html",
"xff": "-",
"referer": "-",
"tcp_xff": "-",
"http_user_agent": "curl/7.61.1",
"status": "200"
}
7 使用脚本完成一键编译安装nginx任意版本。
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2020-12-01
#FileName: install_nginx.sh
#URL: http://www.wangxiaochun.com
#Description: The test script
#Copyright (C): 2021 All rights reserved
#********************************************************************
SRC_DIR=/usr/local/src
NGINX_URL=http://nginx.org/download/
NGINX_FILE=nginx-1.20.2
#NGINX_FILE=nginx-1.18.0
TAR=.tar.gz
NGINX_INSTALL_DIR=/apps/nginx
CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'`
. /etc/os-release
color () {
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \E[0m"
echo -n "$1" && $MOVE_TO_COL
echo -n "["
if [ $2 = "success" -o $2 = "0" ] ;then
${SETCOLOR_SUCCESS}
echo -n $" OK "
elif [ $2 = "failure" -o $2 = "1" ] ;then
${SETCOLOR_FAILURE}
echo -n $"FAILED"
else
${SETCOLOR_WARNING}
echo -n $"WARNING"
fi
${SETCOLOR_NORMAL}
echo -n "]"
echo
}
os_type () {
awk -F'[ "]' '/^NAME/{print $2}' /etc/os-release
}
os_version () {
awk -F'"' '/^VERSION_ID/{print $2}' /etc/os-release
}
check () {
[ -e ${NGINX_INSTALL_DIR} ] && { color "nginx 已安装,请卸载后再安装" 1; exit; }
cd ${SRC_DIR}
if [ -e ${NGINX_FILE}${TAR} ];then
color "相关文件已准备好" 0
else
color '开始下载 nginx 源码包' 0
wget ${NGINX_URL}${NGINX_FILE}${TAR}
[ $? -ne 0 ] && { color "下载 ${NGINX_FILE}${TAR}文件失败" 1; exit; }
fi
}
install () {
color "开始安装 nginx" 0
if id nginx &> /dev/null;then
color "nginx 用户已存在" 1
else
useradd -s /sbin/nologin -r nginx
color "创建 nginx 用户" 0
fi
color "开始安装 nginx 依赖包" 0
if [ $ID == "centos" ] ;then
if [[ $VERSION_ID =~ ^7 ]];then
yum -y -q install make gcc pcre-devel openssl-devel zlib-devel perl-ExtUtils-Embed
elif [[ $VERSION_ID =~ ^8 ]];then
yum -y -q install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
else
color '不支持此系统!' 1
exit
fi
elif [ $ID == "rocky" ];then
yum -y -q install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
else
apt update &> /dev/null
apt -y install make gcc libpcre3 libpcre3-dev openssl libssl-dev zlib1g-dev &> /dev/null
fi
cd $SRC_DIR
tar xf ${NGINX_FILE}${TAR}
NGINX_DIR=`echo ${NGINX_FILE}${TAR}| sed -nr 's/^(.*[0-9]).*/\1/p'`
cd ${NGINX_DIR}
./configure --prefix=${NGINX_INSTALL_DIR} --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
make -j $CPUS && make install
[ $? -eq 0 ] && color "nginx 编译安装成功" 0 || { color "nginx 编译安装失败,退出!" 1 ;exit; }
echo "PATH=${NGINX_INSTALL_DIR}/sbin:${PATH}" > /etc/profile.d/nginx.sh
cat > /lib/systemd/system/nginx.service <<EOF
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=/bin/rm -f ${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=${NGINX_INSTALL_DIR}/sbin/nginx -t
ExecStart=${NGINX_INSTALL_DIR}/sbin/nginx
ExecReload=/bin/kill -s HUP \$MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now nginx &> /dev/null
systemctl is-active nginx &> /dev/null || { color "nginx 启动失败,退出!" 1 ; exit; }
color "nginx 安装完成" 0
}
check
install
8. 任意编译一个第3方nginx模块,并使用。
Nginx 第三方模块
第三模块是对nginx 的功能扩展,第三方模块需要在编译安装Nginx 的时候使用参数--add-
module=PATH指定路径添加,有的模块是由公司的开发人员针对业务需求定制开发的,有的模块是开源爱好者开发好之后上传到github进行开源的模块,nginx的第三方模块需要从源码重新编译进行支持
1.nginx-module-vts 模块实现流量监控,下载地址https://github.com/vozlt/nginx-module-vts
#加入第三方模块功能
#先下载nginx-module-vts 模块后重现编译nginx以实现流量监控
[root@nginx1 src]# wget https://github.com/vozlt/nginx-module-vts/archive/refs/tags/v0.2.0.tar.gz
--2022-12-12 22:48:40-- https://github.com/vozlt/nginx-module-vts/archive/refs/tags/v0.2.0.tar.gz
Resolving github.com (github.com)... 20.205.243.166
Connecting to github.com (github.com)|20.205.243.166|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/vozlt/nginx-module-vts/tar.gz/refs/tags/v0.2.0 [following]
--2022-12-12 22:48:41-- https://codeload.github.com/vozlt/nginx-module-vts/tar.gz/refs/tags/v0.2.0
Resolving codeload.github.com (codeload.github.com)... 20.205.243.165
Connecting to codeload.github.com (codeload.github.com)|20.205.243.165|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/x-gzip]
Saving to: ‘v0.2.0.tar.gz’
v0.2.0.tar.gz [ <=> ] 174.78K 166KB/s in 1.1s
2022-12-12 22:48:43 (166 KB/s) - ‘v0.2.0.tar.gz’ saved [178975]
[root@nginx1 src]# ls
nginx-1.20.0 nginx-1.20.0.tar.gz redis-6.2.6 v0.2.0.tar.gz
[root@nginx1 src]# tar xf v0.2.0.tar.gz
[root@nginx1 src]# ls
nginx-1.20.0 nginx-1.20.0.tar.gz nginx-module-vts-0.2.0 redis-6.2.6 v0.2.0.tar.gz
[root@nginx1 src]# cd nginx-module-vts-0.2.0/
[root@nginx1 nginx-module-vts-0.2.0]# ls
CHANGELOG.md config LICENSE README.md share src t util
[root@nginx1 nginx-module-vts-0.2.0]# cd /usr/local/src/nginx-1.20.0
[root@nginx1 nginx-1.20.0]# ls
auto CHANGES CHANGES.ru conf configure contrib html LICENSE Makefile man objs README src
[root@nginx1 nginx-1.20.0]# nginx -V
nginx version: nginx/1.20.0
built by gcc 8.5.0 20210514 (Red Hat 8.5.0-15) (GCC)
built with OpenSSL 1.1.1k FIPS 25 Mar 2021
TLS SNI support enabled
configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
#加入Nginx virtual host traffic status module功能,重新编译nginx
[root@nginx1 nginx-1.20.0]# ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/usr/local/src/nginx-module-vts-0.2.0
[root@nginx1 nginx-1.20.0]# make -j 2 && make install
[root@nginx1 nginx-1.20.0]# ll /apps/nginx/sbin
total 15864
-rwxr-xr-x 1 root root 8513104 Dec 12 23:10 nginx
-rwxr-xr-x 1 nginx nginx 7725280 Dec 8 14:22 nginx.old
#编译完成后需要重启nginx服务
[root@nginx1 nginx-1.20.0]# systemctl restart nginx
[root@nginx1 nginx-1.20.0]# vim /apps/nginx/conf/conf.d/pc.conf
vhost_traffic_status_zone;
server {
listen 80;
server_name www.magedu.org;
root /data/nginx/html/pc;
location /status {
vhost_traffic_status_display;
vhost_traffic_status_display_format html;
}
}
#改完配置文件后进行语法检查
[root@nginx1 nginx-1.20.0]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
#浏览器访问验证:http://www.magedu.org/status 可以看到下面显示:
2.#利用下载好的echo模块再次编译nginx以实现特定信息的状态显示 --下载地址https://github.com/openresty/echo-nginx-module
[root@nginx1 src]# wget https://github.com/openresty/echo-nginx-module/archive/refs/tags/v0.63.tar.gz
--2022-12-12 23:27:10-- https://github.com/openresty/echo-nginx-module/archive/refs/tags/v0.63.tar.gz
Resolving github.com (github.com)... 20.205.243.166
Connecting to github.com (github.com)|20.205.243.166|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/openresty/echo-nginx-module/tar.gz/refs/tags/v0.63 [following]
--2022-12-12 23:27:26-- https://codeload.github.com/openresty/echo-nginx-module/tar.gz/refs/tags/v0.63
Resolving codeload.github.com (codeload.github.com)... 20.205.243.165
Connecting to codeload.github.com (codeload.github.com)|20.205.243.165|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 53421 (52K) [application/x-gzip]
Saving to: ‘v0.63.tar.gz’
v0.63.tar.gz 100%[===========================================================>] 52.17K 51.1KB/s in 1.0s
2022-12-12 23:27:28 (51.1 KB/s) - ‘v0.63.tar.gz’ saved [53421/53421]
[root@nginx1 src]# ls
nginx-1.20.0 nginx-1.20.0.tar.gz nginx-module-vts-0.2.0 redis-6.2.6 v0.2.0.tar.gz v0.63.tar.gz
[root@nginx1 src]# tar xf v0.63.tar.gz
[root@nginx1 src]# ls
echo-nginx-module-0.63 nginx-1.20.0 nginx-1.20.0.tar.gz nginx-module-vts-0.2.0 redis-6.2.6 v0.2.0.tar.gz v0.63.tar.gz
#再加入Github上开源的echo模块重新进行编译(可以用来打印信息,变量等)
[root@nginx1 nginx-1.20.0]# ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/usr/local/src/nginx-module-vts-0.2.0
--add-module=/usr/local/src/echo-nginx-module-0.63
[root@nginx1 nginx-1.20.0]#make -j 2 && make install
[root@nginx1 nginx-1.20.0]# systemctl restart nginx
[root@nginx1 nginx-1.20.0]# vim /apps/nginx/conf/conf.d/pc.conf
location /echo {
echo $scheme;
echo "Hello,M68";
echo $remote_addr;
echo $remote_port;
echo $request_method;
echo_reset_timer;
echo_location /sub1;
echo_location /sub2;
echo "took $echo_timer_elapsed sec for total.";
}
}
#客户端验证
[root@Rocky8 ~]# curl www.magedu.org/echo
http
Hello,M68
192.168.72.154
58110
GET
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.20.0</center>
</body>
</html>
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.20.0</center>
</body>
</html>
took 0.000 sec for total.
日志格式自定义:
#自定义json日志格式(Nginx 的默认访问日志记录内容相对比较单一,默认的格式也不方便后期做日志统计分析,生产环境中
通常将nginx日志转换为json日志,然后配合使用ELK做日志收集,统计和分析。)
#修改nginx核心配置文件
[root@nginx1 ~]# vim /apps/nginx/conf/nginx.conf
http {
include mime.types;
default_type application/octet-stream;
log_format nginx_format1 '$remote_addr - $remote_user [$time_local] "$request"';
log_format access_json '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"uri":"$uri",'
'"xff":"$http_x_forwarded_for",'
'"referer":"$http_referer",'
'"tcp_xff":"$proxy_protocol_addr",'
'"http_user_agent":"$http_user_agent",'
'"status":"$status"}';
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
#修改pc端的nginx子配置文件里的日志指引
[root@nginx1 ~]# vim /apps/nginx/conf/conf.d/pc.conf
vhost_traffic_status_zone;
server {
listen 80;
server_name www.magedu.org;
root /data/nginx/html/pc;
access_log /apps/nginx/logs/access_json.log access_json;
location /status {
vhost_traffic_status_display;
vhost_traffic_status_display_format html;
}
[root@nginx1 ~]# nginx -s reload
[root@nginx1 ~]# ls /apps/nginx/logs
access_json.log access.log error.log
#客户端访问www.magedu.org验证json日志是否已生成
[root@nginx1 ~]# tail /apps/nginx/logs/access_json.log -f
{"@timestamp":"2022-12-13T09:59:55+08:00","host":"192.168.72.152","clientip":"192.168.72.154","size":7,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-","http_host":"www.magedu.org","uri":"/index.html","xff":"-","referer":"-","tcp_xff":"-","http_user_agent":"curl/7.61.1","status":"200"}
{"@timestamp":"2022-12-13T10:00:58+08:00","host":"192.168.72.152","clientip":"192.168.72.150","size":7,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-","http_host":"www.magedu.org","uri":"/index.html","xff":"-","referer":"-","tcp_xff":"-","http_user_agent":"curl/7.61.1","status":"200"}
[root@nginx1 ~]# tail /apps/nginx/logs/access.log
192.168.72.1 - - [13/Dec/2022:00:08:02 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:04 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:06 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:08 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:10 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:12 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:14 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:16 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:18 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
192.168.72.1 - - [13/Dec/2022:00:08:20 +0800] "GET /status/format/json HTTP/1.1" 200 3523 "http://www.magedu.org/status" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36"
#安装专门的jq工具来整理j_son日志
[root@nginx1 ~]# yum -y install jq
Last metadata expiration check: 0:29:53 ago on Tue 13 Dec 2022 09:44:14 AM CST.
Dependencies resolved.
======================================================================================================================================
Package Architecture Version Repository Size
======================================================================================================================================
Installing:
jq x86_64 1.6-3.el8 appstream 201 k
Installing dependencies:
oniguruma x86_64 6.8.2-2.el8 appstream 186 k
Transaction Summary
======================================================================================================================================
Install 2 Packages
Total download size: 387 k
Installed size: 1.1 M
Installed:
jq-1.6-3.el8.x86_64 oniguruma-6.8.2-2.el8.x86_64
[root@nginx1 ~]# cat /apps/nginx/logs/access_json.log|jq
{
"@timestamp": "2022-12-13T09:59:55+08:00",
"host": "192.168.72.152",
"clientip": "192.168.72.154",
"size": 7,
"responsetime": 0.000,
"upstreamtime": "-",
"upstreamhost": "-",
"http_host": "www.magedu.org",
"uri": "/index.html",
"xff": "-",
"referer": "-",
"tcp_xff": "-",
"http_user_agent": "curl/7.61.1",
"status": "200"
}
{
"@timestamp": "2022-12-13T10:00:58+08:00",
"host": "192.168.72.152",
"clientip": "192.168.72.150",
"size": 7,
"responsetime": 0.000,
"upstreamtime": "-",
"upstreamhost": "-",
"http_host": "www.magedu.org",
"uri": "/index.html",
"xff": "-",
"referer": "-",
"tcp_xff": "-",
"http_user_agent": "curl/7.61.1",
"status": "200"
}