[TOC]
一、redis搭建哨兵原理和集群实现 1.1、搭建哨兵的原理 ①专门的Sentinel 服务进程是用于监控redis集群中Master工作的状态,当Master主服务器发生故障的时候,可以实现Master和Slave的角色的自动切换,从而实现系统的高可用性
②Sentinel是一个分布式系统,即需要在多个节点上各自同时运行一个sentinel进程,Sentienl 进程通过流言协议(gossip protocols)来接收关于Master是否下线状态,并使用投票协议(Agreement Protocols)来决定是否执行自动故障转移,并选择合适的Slave作为新的Master
③每个Sentinel进程会向其它Sentinel、Master、Slave定时发送消息,来确认对方是否存活,如果发现某个节点在指定配置时间内未得到响应,则会认为此节点已离线,即为主观宕机Subjective Down,简称为 SDOWN
④如果哨兵集群中的多数Sentinel进程认为Master存在SDOWN,共同利用 is-master-down-by-addr 命令
互相通知后,则认为客观宕机Objectively Down, 简称 ODOWN
⑤接下来利用投票算法,从所有slave节点中,选一台合适的slave将之提升为新Master节点,然后自动修改其它slave相关配置,指向新的master节点,最终实现故障转移failover
注意:Redis Sentinel中的Sentinel节点个数应该为大于等于3且最好为奇数
1.2、搭建集群 1.2.1、集群架构
注意:①每个Redis 节点采用相同的相同的Redis版本、相同的密码、硬件配置
②所有Redis服务器必须没有任何数据
准备六台主机,地址如下:
10.0.0.184 10.0.0.185 10.0.0.186 10.0.0.187 10.0.0.188 10.0.0.216
1.2.2、启用redis cluster配置 ①每个节点修改redis配置,必须开启cluster功能的参数
1 2 [root@Rocky ~] [root@Rocky ~]
②验证当前Redis服务状态:
1 2 3 4 5 6 7 8 9 10 11 12 13 [root@Rocky ~] State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 511 0.0.0.0:16379 0.0.0.0:* LISTEN 0 511 0.0.0.0:6379 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:* LISTEN 0 511 [::1]:16379 [::]:* LISTEN 0 511 [::1]:6379 [::]:* LISTEN 0 128 *:80 *:* [root@Rocky ~] redis 33345 1 0 09:16 ? 00:00:00 /apps/redis/bin/redis-server 0.0.0.0:6379 [cluster]
1.2.3、创建集群 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 [root@Rocky ~] >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 10.0.0.188:6379 to 10.0.0.184:6379 Adding replica 10.0.0.216:6379 to 10.0.0.185:6379 Adding replica 10.0.0.187:6379 to 10.0.0.186:6379 M: cdf92d28ccbf42767778bf65cacb6eda1c406257 10.0.0.184:6379 slots:[0-5460] (5461 slots) master M: 2ca4e638bd3fa22ad94cc238907faf6b613d0b88 10.0.0.185:6379 slots:[5461-10922] (5462 slots) master M: 56efb05a636f587fd11775f702a427291d4c1cb6 10.0.0.186:6379 slots:[10923-16383] (5461 slots) master S: 40bbd63934b4201e370de7424b1a8317715c8207 10.0.0.187:6379 replicates 56efb05a636f587fd11775f702a427291d4c1cb6 S: c6ef7581a4752b8e786a4585778427502defd6d5 10.0.0.188:6379 replicates cdf92d28ccbf42767778bf65cacb6eda1c406257 S: 3c15e99e9430bde6184a65554127cd0669b41b05 10.0.0.216:6379 replicates 2ca4e638bd3fa22ad94cc238907faf6b613d0b88 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 10.0.0.184:6379) M: cdf92d28ccbf42767778bf65cacb6eda1c406257 10.0.0.184:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) M: 56efb05a636f587fd11775f702a427291d4c1cb6 10.0.0.186:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: 40bbd63934b4201e370de7424b1a8317715c8207 10.0.0.187:6379 slots: (0 slots) slave replicates 56efb05a636f587fd11775f702a427291d4c1cb6 S: 3c15e99e9430bde6184a65554127cd0669b41b05 10.0.0.216:6379 slots: (0 slots) slave replicates 2ca4e638bd3fa22ad94cc238907faf6b613d0b88 M: 2ca4e638bd3fa22ad94cc238907faf6b613d0b88 10.0.0.185:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: c6ef7581a4752b8e786a4585778427502defd6d5 10.0.0.188:6379 slots: (0 slots) slave replicates cdf92d28ccbf42767778bf65cacb6eda1c406257 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. master:10.0.0.184 slave:10.0.0.188 master:10.0.0.185 slave:10.0.0.216 master:10.0.0.186 slave:10.0.0.187 master1:10.0.0.184 slave1:10.0.0.188 master2:10.0.0.185 slave2:10.0.0.216 master3:10.0.0.186 slave3:10.0.0.187
1.2.4、验证集群 1.2.4.1、查看主从状态 1 2 3 4 5 6 7 8 9 10 11 12 13 [root@slave3 ~] 40bbd63934b4201e370de7424b1a8317715c8207 10.0.0.187:6379@16379 myself,slave 56efb05a636f587fd11775f702a427291d4c1cb6 0 1668131120000 3 connected c6ef7581a4752b8e786a4585778427502defd6d5 10.0.0.188:6379@16379 slave cdf92d28ccbf42767778bf65cacb6eda1c406257 0 1668131122687 1 connected 56efb05a636f587fd11775f702a427291d4c1cb6 10.0.0.186:6379@16379 master - 0 1668131121648 3 connected 10923-16383 2ca4e638bd3fa22ad94cc238907faf6b613d0b88 10.0.0.185:6379@16379 master - 0 1668131122000 2 connected 5461-10922 cdf92d28ccbf42767778bf65cacb6eda1c406257 10.0.0.184:6379@16379 master - 0 1668131122000 1 connected 0-5460 3c15e99e9430bde6184a65554127cd0669b41b05 10.0.0.216:6379@16379 slave 2ca4e638bd3fa22ad94cc238907faf6b613d0b88 0 1668131120000 2 connected
1.2.4.2、验证集群状态 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@master1 ~] 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:6 cluster_size:3 [root@master1 ~] 10.0.0.186:6379 (56efb05a...) -> 0 keys | 5461 slots | 1 slaves. 10.0.0.185:6379 (2ca4e638...) -> 0 keys | 5462 slots | 1 slaves. 10.0.0.184:6379 (cdf92d28...) -> 0 keys | 5461 slots | 1 slaves. [OK] 0 keys in 3 masters. 0.00 keys per slot on average.
1.2.4.3、查看对应关系 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 [root@master1 ~] Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 10.0.0.184:6379 (cdf92d28...) -> 0 keys | 5461 slots | 1 slaves. 10.0.0.185:6379 (2ca4e638...) -> 0 keys | 5462 slots | 1 slaves. 10.0.0.186:6379 (56efb05a...) -> 0 keys | 5461 slots | 1 slaves. [OK] 0 keys in 3 masters. 0.00 keys per slot on average. >>> Performing Cluster Check (using node 10.0.0.216:6379) S: 3c15e99e9430bde6184a65554127cd0669b41b05 10.0.0.216:6379 slots: (0 slots) slave replicates 2ca4e638bd3fa22ad94cc238907faf6b613d0b88 M: cdf92d28ccbf42767778bf65cacb6eda1c406257 10.0.0.184:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) M: 2ca4e638bd3fa22ad94cc238907faf6b613d0b88 10.0.0.185:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: c6ef7581a4752b8e786a4585778427502defd6d5 10.0.0.188:6379 slots: (0 slots) slave replicates cdf92d28ccbf42767778bf65cacb6eda1c406257 M: 56efb05a636f587fd11775f702a427291d4c1cb6 10.0.0.186:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: 40bbd63934b4201e370de7424b1a8317715c8207 10.0.0.187:6379 slots: (0 slots) slave replicates 56efb05a636f587fd11775f702a427291d4c1cb6
1.2.5测试集群写入数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [root@master1 ~] 127.0.0.1:6379> dbsize (integer ) 0 127.0.0.1:6379> set a b (error) MOVED 15495 10.0.0.186:6379 [root@master3 ~] 127.0.0.1:6379> dbsize (integer ) 0 127.0.0.1:6379> set a b OK [root@master1 ~] 127.0.0.1:6379> set a w -> Redirected to slot [15495] located at 10.0.0.186:6379 OK 10.0.0.186:6379>
1.2.6、模拟故障实现故障转移 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 [root@master2 ~] [root@slave1 ~] 2ca4e638bd3fa22ad94cc238907faf6b613d0b88 10.0.0.185:6379@16379 master,fail - 1668132519648 1668132516486 2 disconnected cdf92d28ccbf42767778bf65cacb6eda1c406257 10.0.0.184:6379@16379 master - 0 1668132534993 1 connected 0-5460 3c15e99e9430bde6184a65554127cd0669b41b05 10.0.0.216:6379@16379 master - 0 1668132536008 7 connected 5461-10922 40bbd63934b4201e370de7424b1a8317715c8207 10.0.0.187:6379@16379 slave 56efb05a636f587fd11775f702a427291d4c1cb6 0 1668132535000 3 connected c6ef7581a4752b8e786a4585778427502defd6d5 10.0.0.188:6379@16379 myself,slave cdf92d28ccbf42767778bf65cacb6eda1c406257 0 1668132534000 1 connected 56efb05a636f587fd11775f702a427291d4c1cb6 10.0.0.186:6379@16379 master - 0 1668132534000 3 connected 10923-16383 [root@master2 ~] [root@slave3 ~] 40bbd63934b4201e370de7424b1a8317715c8207 10.0.0.187:6379@16379 myself,slave 56efb05a636f587fd11775f702a427291d4c1cb6 0 1668132977000 3 connected c6ef7581a4752b8e786a4585778427502defd6d5 10.0.0.188:6379@16379 slave cdf92d28ccbf42767778bf65cacb6eda1c406257 0 1668132979881 1 connected 56efb05a636f587fd11775f702a427291d4c1cb6 10.0.0.186:6379@16379 master - 0 1668132978841 3 connected 10923-16383 2ca4e638bd3fa22ad94cc238907faf6b613d0b88 10.0.0.185:6379@16379 slave 3c15e99e9430bde6184a65554127cd0669b41b05 0 1668132977798 7 connected cdf92d28ccbf42767778bf65cacb6eda1c406257 10.0.0.184:6379@16379 master - 0 1668132978000 1 connected 0-5460 3c15e99e9430bde6184a65554127cd0669b41b05 10.0.0.216:6379@16379 master - 0 1668132979000 7 connected 5461-10922
1.2.7、验证数据是否同步 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@master1 ~] Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> dbsize (integer ) 0 127.0.0.1:6379> set a w -> Redirected to slot [15495] located at 10.0.0.186:6379 OK 10.0.0.186:6379> [root@slave3 ~] 127.0.0.1:6379> get a (error) MOVED 15495 10.0.0.186:6379 127.0.0.1:6379> dbsize (integer ) 1
二、LVS常用模型工作原理,及实现 2.1、LVS的工作原理 VS根据请求报文的目标IP和目标协议及端口将其调度转发至某RS,根据调度算法来挑选RS。LVS是内核级功能,工作在INPUT链的位置,将发往INPUT的流量进行“处理”
2.2、DR模型实现过程
LVS-DR:Direct Routing,直接路由,LVS默认模式,应用最广泛,通过为请求报文重新封装一个MAC首部进行转发,源MAC是DIP所在的接口的MAC,目标MAC是某挑选出的RS的RIP所在接口的MAC地址;源IP/PORT,以及目标IP/PORT均保持不变
①Director和各RS都配置有VIP
②确保前端路由器将目标IP为VIP的请求报文发往Director
——在前端网关做静态绑定VIP和Director的MAC地址
——在RS上使用arptables工具
1 2 arptables -A IN -d $VIP -j DROP arptables -A OUT -s $VIP -j mangle --mangle-ip-s $RIP
——在RS上修改内核参数以限制arp通告及应答级别
1 2 /proc/sys/net/ipv4/conf/all/arp_ignore /proc/sys/net/ipv4/conf/all/arp_announce
③ RS的RIP可以使用私网地址,也可以是公网地址;RIP与DIP在同一IP网络;RIP的网关不能指向DIP,以确保响应报文不会经由Director
④ RS和Director要在同一个物理网络
⑤请求报文要经由Director,但响应报文不经由Director,而由RS直接发往Client
⑥不支持端口映射(端口不能修改)
⑦无需开启 ip_forward
三、LVS的负载策略有哪些,各应用在什么场景,通过LVS DR任意实现1-2种场景 3.1、负载策略及应用场景 ①NAT模型:由于配置简单,请求和回应都涉及LVS服务器(LVS服务器压力大),所以应用于并发量不大的中小企业。Real server服务器数量控制在10-20
②DR模型:并发量非常大的企业(DR模型的并发处理量能达到硬件级别的能力)。Real server服务器数量可以达到100
③TUN模型:TUN模式常会用来负载调度缓存服务器组,这些缓存服务器一般放置在不同的网络环境,可以就近折返给客户端。在请求对象不在Cache服务器本地命中的情况下,Cache服务器要向源服务器发送请求,将结果取回,最后将结果返回给用户。Real server服务器数量可以达到100
④FULLNAT模型:此模型主要是阿里云的二次开发使用。
3.2、LVS-DR模式单网段案例 3.2.1、环境
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 环境:5 台主机 一台:客户端 (主机名:Internet) eth0:仅主机模式 192.168.10.184 /24 GW:192.168.10.185 一台:路由器(主机名:ROUTER) eth0:NAT 10.0.0.185 /24 eth1:仅主机模式 192.168.10.185 /24 一台:LVS(主机名LVS) eth0:NAT DIP:10.0.0.186 /24 GW:10.0.0.185 lo VIP:10.0.0.100 /32 两台:RS(主机名web1、web2) RS1: eth0:NAT RIP:10.0.0.187 /24 GW:10.0.0.185 lo VIP:10.0.0.100 /32 RS2: eth0:NAT RIP:10.0.0.188 /24 GW:10.0.0.185 lo VIP:10.0.0.100 /32
3.2.2、LVS的网络配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 [root@Rocky ~] IPADDR=192.168.10.184 NETMASK=255.255.255.0 GATEWAY=192.168.10.185 :wq [root@Rocky ~] [root@Rocky ~] [root@Rocky ~] [root@internet ~] 192.168.10.184 [root@Rocky ~] [root@ROUTER ~] [root@ROUTER ~] [root@ROUTER ~] [root@ROUTER network-scripts] backup ifcfg-eth0 [root@ROUTER network-scripts] [root@ROUTER network-scripts] backup ifcfg-eth0 ifcfg-eth1 [root@ROUTER network-scripts] PROXY_METHOD=none BOOTPROTO=none NAME=eth1 DEVICE=eth1 IPADDR=192.168.10.185 NETMASK=255.255.255.0 :wq [root@ROUTER network-scripts] NAME UUID TYPE DEVICE eth0 9aee0c40-97c5-361f-a1e6-9c0b37325423 ethernet eth0 Wired connection 1 32b154a4-7f4d-32f0-aa39-a0cc460bd562 ethernet eth1 eth1 9c92fad9-6ecb-3e6c-eb4d-8a47c6f50c04 ethernet -- [root@ROUTER network-scripts] Connection 'Wired connection 1' (32b154a4-7f4d-32f0-aa39-a0cc460bd562) successfully deleted. [root@ROUTER network-scripts] NAME UUID TYPE DEVICE eth0 9aee0c40-97c5-361f-a1e6-9c0b37325423 ethernet eth0 eth1 9c92fad9-6ecb-3e6c-eb4d-8a47c6f50c04 ethernet eth1 [root@ROUTER network-scripts] [root@ROUTER network-scripts] Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4) [root@ROUTER network-scripts] 10.0.0.185 192.168.10.185 [root@Rocky ~] [root@web1 ~] [root@web1 ~] [root@web1 ~] [root@web1 ~] web1 [root@web1 ~] GATEWAY=10.0.0.185 :wq [root@web1 ~] [root@web1 ~] [root@Rocky ~] [root@web2 ~] [root@web2 ~] [root@web2 ~] [root@web2 ~] web2 [root@web2 ~] GATEWAY=10.0.0.185 :wq [root@web2 ~] [root@web2 ~] [root@Rocky ~] [root@LVS ~] GATEWAY=10.0.0.185 :wq [root@LVS ~] [root@LVS ~]
3.2.3、后端RS的IPVS配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 [root@web1 ~] [root@web1 ~] [root@web1 ~] [root@web1 ~] net.ipv4.conf.all.arp_ignore=1 net.ipv4.conf.all.arp_announce=2 net.ipv4.conf.lo.arp_ignore=1 net.ipv4.conf.lo.arp_announce=2 0:默认值,表示可使用本地任意接口上配置的任意地址进行响应 1:仅在请求的目标IP配置在本地主机的接收到请求报文的接口上时,才给予响应 0:默认值,把本机所有接口的所有信息向每个接口的网络进行通告 1:尽量避免将接口信息向非直接连接网络进行通告 2:必须避免将接口信息向非本网络进行通告 [root@web1 ~] [root@web1 ~] 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 10.0.0.100/0 scope global lo:1 valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link /ether 00:50:56:2c:b4:3c brd ff:ff:ff:ff:ff:ff inet 10.0.0.187/24 brd 10.0.0.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever inet6 fe80::250:56ff:fe2c:b43c/64 scope link valid_lft forever preferred_lft forever [root@web2 ~] [root@web2 ~] [root@web2 ~] [root@web2 ~] [root@web2 ~] [root@web2 ~] 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 10.0.0.100/32 scope global lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link /ether 00:50:56:3c:10:b0 brd ff:ff:ff:ff:ff:ff inet 10.0.0.188/24 brd 10.0.0.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever inet6 fe80::250:56ff:fe3c:10b0/64 scope link valid_lft forever preferred_lft forever
3.2.4、LVS主机的配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 [root@LVS ~] [root@LVS ~] 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 10.0.0.100/32 scope global lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link /ether 00:50:56:3d:ba:4d brd ff:ff:ff:ff:ff:ff inet 10.0.0.186/24 brd 10.0.0.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever [root@LVS ~] [root@LVS ~] [root@LVS ~] [root@LVS ~] [root@LVS ~] IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 10.0.0.100:80 rr -> 10.0.0.187:80 Route 1 0 0 -> 10.0.0.188:80 Route 1 0 0
3.2.5、测试访问 1 2 3 4 [root@internet ~] web1 [root@internet ~] web2
四、web http协议通信过程,相关技术术语总结 4.1、http协议通信过程
4.2、相关技术术语总结 4.2.1、WEB开发语言 http:Hyper Text Transfer Protocol 应用层协议,默认端口: 80/tcp
①html :Hyper Text Markup Language 超文本标记语言,编程语言,主要负责实现页面的结构
②CSS :Cascading Style Sheet 层叠样式表, 定义了如何显示(装扮) HTML 元素,比如:字体大小和颜色属性等。样式通常保存在外部的 .css 文件中,用于存放一些HTML文件的公共属性,从而通过仅编辑一个简单的 CSS 文档,可以同时改变站点中所有页面的布局和外观。
③Js :javascript,实现网页的动画效果,但实属于静态资源
4.2.2、MIME MIME : Multipurpose Internet Mail Extensions 多用途互联网邮件扩展
文件 /etc/mime.types ,来自于mailcap包
MIME格式:type/subtype txt html jpg bmp
4.2.3、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仅用于命名,而不指定地址。
URL组成
1 2 3 4 5 6 7 8 9 scheme: 方案,访问服务器以获取资源时要使用哪种协议user: 用户,某些方案访问资源时需要的用户名password: 密码,用户对应的密码,中间用:分隔Host: 主机,资源宿主服务器的主机名或IP地址port: 端口,资源宿主服务器正在监听的端口号,很多方案有默认端口号path: 路径,服务器资源的本地名,由一个/将其与前面的URL组件分隔params: 参数,指定输入的参数,参数为名/值对,多个参数,用query: 查询,传递参数给程序,如数据库,用?分隔,多个查询用&分隔frag: 片段,一小片或一部分资源的名字,此组件在客户端使用,用#分隔
五、总结网络IO模型和nginx架构 5.1、网络IO模型 阻塞型、非阻塞型、复用型、信号驱动型、异步
5.1.1、阻塞型I/O模型(blocking IO)
①阻塞IO模型是最简单的I/O模型,用户线程在内核进行IO操作时被阻塞
②用户线程通过系统调用read发起I/O读操作,由用户空间转到内核空间。内核等到数据包到达后,然后将
接收的数据拷贝到用户空间,完成read操作
③用户需要等待read将数据读取到buffer后,才继续处理接收的数据。整个I/O请求的过程中,用户线程是
被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够
优点 :程序简单,在阻塞等待数据期间进程/线程挂起,基本不会占用 CPU 资源
缺点 :每个连接需要独立的进程/线程单独处理,当并发请求量大时为了维护程序,内存、线程切换开销
较大,apache 的prefork使用的是这种模式。
5.1.2、非阻塞型I/O模型(nonblocking IO)
用户线程发起IO请求时立即返回。但并未读取到任何数据,用户线程需要不断地发起IO请求,直到数据
到达后,才真正读取到数据,继续执行。即 “轮询”机制存在两个问题:如果有大量文件描述符都要等,
那么就得一个一个的read。这会带来大量的Context Switch(read是系统调用,每调用一次就得在用户
态和核心态切换一次)。轮询的时间不好把握。这里是要猜多久之后数据才能到。等待时间设的太长,
程序响应延迟就过大;设的太短,就会造成过于频繁的重试,干耗CPU而已,是比较浪费CPU的方式,一
般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。
5.1.3、I/O多路复用型(I/O multiplexing) ①多路复用IO指一个线程可以同时(实际是交替实现,即并发完成)监控和处理多个文件描述符对应各自
的IO,即复用同一个线程
②一个线程之所以能实现同时处理多个IO,是因为这个线程调用了内核中的SELECT,POLL或EPOLL等系统调
用,从而实现多路复用IO
③它的基本原理就是select/poll/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数
据到达了,就通知用户进程。
④当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,
当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从
kernel拷贝到用户进程。
优点 :可以基于一个阻塞对象,同时在多个描述符上等待就绪,而不是使用多个线程(每个文件描述
符一个线程),这样可以大大节省系统资源
缺点 :当连接数较少时效率相比多线程+阻塞 I/O 模型效率较低,可能延迟更大,因为单个连接处
理需要 2 次系统调用,占用时间会有增加
IO多路复用适用如下场合 :
当客户端处理多个描述符时(一般是交互式输入和网络套接口),必须使用I/O复用
当一个客户端同时处理多个套接字时,此情况可能的但很少出现
当一个服务器既要处理监听套接字,又要处理已连接套接字,一般也要用到I/O复用
当一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用
当一个服务器要处理多个服务或多个协议,一般要使用I/O复用
5.1.4、信号驱动式I/O模型(signal-driven IO)
信号驱动I/O的意思就是进程现在不用傻等着,也不用去轮询。而是让内核在数据就绪时,发送信号通知
进程。
调用的步骤 :通过系统调用 sigaction ,并注册一个信号处理的回调函数,该调用会立即返回,然后
主程序可以继续向下执行,当有I/O操作准备就绪,即内核数据就绪时,内核会为该进程产生一个 SIGIO
信号,并回调注册的信号回调函数,这样就可以在信号回调函数中系统调用 recvfrom 获取数据,将用户
进程所需要的数据从内核空间拷贝到用户空间
此模型的优势在于等待数据报到达期间进程不被阻塞。用户主程序可以继续执行,只要等待来自信号处
理函数的通知。
在信号驱动式 I/O 模型中,应用程序使用套接口进行信号驱动 I/O,并安装一个信号处理函数,进程继
续运行并不阻塞
当数据准备好时,进程会收到一个 SIGIO 信号,可以在信号处理函数中调用 I/O 操作函数处理数据。
优点 :线程并没有在等待数据时被阻塞,内核直接返回调用接收信号,不影响进程继续处理其他请求因此
可以提高资源的利用率
缺点 :信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知
5.1.5、异步I/O模型(asynchronous IO)
执行过程 :用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket数据准备好了,内核直接复制数据给进程,然后从内核向进程发送通知。IO两个阶段,进程都是非阻塞的。
信号驱动IO当内核通知触发信号处理程序时,信号处理程序还需要阻塞在从内核空间缓冲区拷贝数据到
用户空间缓冲区这个阶段,而异步IO直接是在第二个阶段完成后,内核直接通知用户线程可以进行后续
操作了
优点 :异步 I/O 能够充分利用 DMA 特性,让 I/O 操作与计算重叠
缺点 :要实现真正的异步 I/O,操作系统需要做大量的工作。目前 Windows 下通过 IOCP 实现了真正的
异步 I/O,在 Linux 系统下,Linux 2.6才引入,目前 AIO 并不完善,因此在 Linux 下实现高并发网络编
程时以 IO 复用模型模式+多线程任务的架构基本可以满足需求
5.2、Nginx架构
六、nginx总结核心配置和优化 6.1、Nginx的配置文件的组成部分 ①主配置文件:nginx.conf
②子配置文件: include conf.d/*.conf
③fastcgi, uwsgi,scgi 等协议相关的配置文件
④mime.types:支持的mime类型,MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型,MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据,是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
MIME参考文档:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_Types
6.2、nginx 配置文件格式说明 1 2 3 4 5 6 7 8 配置文件由指令与指令块构成 每条指令以;分号结尾,指令与值之间以空格符号分隔 可以将多条指令放在同一行,用分号分隔即可,但可读性差,不推荐 指令块以{ }大括号将多条指令组织在一起,且可以嵌套指令块 include语句允许组合多个配置文件以提升可维护性 使用#符号添加注释,提高可读性 使用$符号使用变量 部分指令的参数支持正则表达式
6.3、主配置文件结构:四部分 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 directive value [value2 ...]; 注意 (1) 指令必须以分号结尾 (2) 支持使用配置变量 内建变量:由Nginx模块引入,可直接引用 自定义变量:由用户使用set 命令定义,格式: set variable_name value; 引用变量:$variable_name 主配置文件结构:四部分 main block:主配置段,即全局配置段,对http,mail都有效 event { ... } http { ... } mail { ... } stream { ... }
6.4、全局配置中的必备配置和优化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 user nginx nginx; worker_processes [number | auto]; worker_cpu_affinity 00000001 00000010 00000100 00001000 | auto ; CPU MASK: 00000001:0号CPU 00000010:1号CPU 10000000:7号CPU worker_cpu_affinity 0001 0010 0100 1000;第0号---第3号CPU worker_cpu_affinity 0101 1010; error_log /apps/nginx/logs/error.log error; pid /apps/nginx/logs/nginx.pid; worker_priority 0; worker_rlimit_nofile 65536; daemon off; master_process off|on; events { worker_connections 65536; use epoll; accept_mutex on; multi_accept on; }
6.5、http 协议配置中的必备配置和优化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65 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; } location ~ /passwd.html { deny all; } } ngx_http_index_module模块提供
七、使用脚本完成一键编译安装nginx任意版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 #!/bin/bash SRC_DIR=/usr/local/src NGINX_URL=http://nginx.org/download/ NGINX_FILE=nginx-1.20 .2 TAR=.tar.gz NGINX_INSTALL_DIR=/apps/nginx CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}' ` . /etc/os-release 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
八、任意编译一个第3方nginx模块,并使用 nginx-module-vts模块实现流量监控
1 https://github.com/vozlt/nginx-module-vts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 [root@Rocky ~] [root@Rocky src] [root@Rocky src] [root@Rocky src] nginx-1.22.1 nginx-1.22.1.tar.gz nginx-module-vts-0.2.1 v0.2.1.tar.gz [root@Rocky src] [root@Rocky nginx-1.22.1] nginx version: nginx/1.23.2 built by gcc 8.5.0 20210514 (Red Hat 8.5.0-10) (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 [root@Rocky nginx-1.22.1] [root@Rocky nginx-1.22.1] http { ...... vhost_traffic_status_zone; ...... server { ...... location /status { vhost_traffic_status_display; vhost_traffic_status_display_format html; } ...... } } :wq [root@Rocky nginx-1.20.2]
添加监控模块前
添加监控模块后