第八周作业

目录

1. 总结 哨兵机制实现原理,并搭建主从哨兵集群。

2. 总结redis cluster工作原理,并搭建集群实现扩缩容。

3. 总结 LVS的NAT和DR模型工作原理,并完成DR模型实战。

4. 总结 http协议的通信过程详解

5. 总结  网络IO模型和nginx架构

6. 完成nginx编译安装脚本

7. 总结nginx核心配置,并实现nginx多虚拟主机

8. 总结nginx日志格式定制


1. 总结 哨兵机制实现原理,并搭建主从哨兵集群。

# 要先实现主从复制
[root@slave ~]# vim /apps/redis/etc/redis.conf
replicaof 10.0.0.130 6379
masterauth 123456
[root@slave ~]# systemctl restart redis.service
[root@slave ~]# 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> dbsize
(integer) 2
127.0.0.1:6379> get class
"m48"
127.0.0.1:6379> get course
"linux"
127.0.0.1:6379> info Replication
# Replication
role:slave
master_host:10.0.0.130
master_port:6379
master_link_status:up
master_last_io_seconds_ago:8
master_sync_in_progress:0
slave_repl_offset:745
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:c0d4677496ffdfc7a332b545319a66dca4fdddce
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:745
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:745

配置第二个节点
[root@localhost ~]# 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> set name xie
OK
127.0.0.1:6379> set class 123
OK
127.0.0.1:6379> dbsize
(integer) 2
127.0.0.1:6379> exit
[root@localhost ~]# vim /apps/redis/etc/redis.conf
replicaof 10.0.0.130 6379
masterauth 123456

主节点中修改
[root@localhost ~]# vim /apps/redis/etc/redis.conf
masterauth 123456
[root@master ~]# systemctl restart redis

# 配置哨兵
三个机子的配置都是一样的,但是不能直接复制过去
[root@master ~]# cp /usr/local/src/redis-6.2.5/sentinel.conf  /apps/redis/etc/
[root@master ~]# ll /apps/redis/etc/
total 108
-rw-r--r-- 1 redis redis 93807 Mar 17 21:17 redis.conf
-rw-r--r-- 1 root  root  13768 Mar 17 21:19 sentinel.conf
[root@master ~]# chown redis. /apps/redis/etc/*
[root@master ~]# vim /apps/redis/etc/sentinel.conf
bind 0.0.0.0
logfile "/apps/redis/log/sentinel.log"
sentinel monitor mymaster 10.0.0.130 6379 2
sentinel auth-pass mymaster 123456

[root@master ~]# chown redis. /apps/redis/log/*
[root@master ~]# chown redis. /apps/redis/etc/*
[root@master ~]# ll /apps/redis/etc/
total 108
-rw-r--r-- 1 redis redis 93807 Mar 17 21:17 redis.conf
-rw-r--r-- 1 redis redis 14174 Mar 17 21:37 sentinel.conf

# service文件·启动
[root@master ~]# 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
[root@master ~]# scp /lib/systemd/system/redis-sentinel.service 10.0.0.137:/lib/systemd/system/
[root@master ~]# scp /lib/systemd/system/redis-sentinel.service 10.0.0.131:/lib/systemd/system/
主从都执行
[root@master ~]# systemctl enable --now redis-sentinel.service
[root@master ~]# ss -ntl
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:26379                        0.0.0.0:*                            
LISTEN         0              511                           0.0.0.0:6379                         0.0.0.0:*                            
LISTEN         0              128                              [::]:22                              [::]:*                            
LISTEN         0              511                             [::1]:6379                            [::]:* 

# 连接
[root@master ~]# redis-cli -p 26379
127.0.0.1:26379> info
# Server
redis_version:6.2.5
redis_git_sha1:00000000


2. 总结redis cluster工作原理,并搭建集群实现扩缩容。

[root@R9-129 ~]# vim /apps/redis/etc/redis.conf
masterauth 123456
requirepass 123456
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-require-full-coverage no
[root@R9-129 ~]# systemctl restart redis
[root@R9-129 ~]# ps aux|grep redis
redis       1463  0.1  0.3  57680  6792 ?        Ssl  17:56   0:00 /apps/redis/bin/redis-server 0.0.0.0:6379 [cluster]
root        1471  0.0  0.1   6636  2172 pts/1    S+   18:00   0:00 grep --color=auto redis
[root@Rocky2 ~]# cat /apps/redis/data/nodes-6379.conf
29cdc75a983d0ca02b350d8d4f45c332acf9d3b7 :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0
#创建集群
[root@R9-129 ~]# redis-cli -a 123456 --cluster create 10.0.0.129:6379 10.0.0.130:6379 10.0.0.131:6379 10.0.0.135:6379 10.0.0.137:6379 10.0.0.139:6379 --cluster-replicas 1
[root@Rocky2 ~]# cat /apps/redis/data/nodes-6379.conf 
acf19c56585ebdfdc02333f366e25da2f9ebfd54 10.0.0.129:6379@16379 master - 0 1679310586000 1 connected 0-5460
edfe77c65617d55232b896b4346a5e8aebed0182 10.0.0.135:6379@16379 slave a300a618fadf30c857e407134c3bd4bbf7d60755 0 1679310586288 3 connected
b9bf0fc7400045183d9d30cdbbe97683d5fe4a29 10.0.0.137:6379@16379 slave acf19c56585ebdfdc02333f366e25da2f9ebfd54 0 1679310586391 1 connected
025ac37084e48dda0cd26fba40880c1e015e1bfd 10.0.0.139:6379@16379 slave 29cdc75a983d0ca02b350d8d4f45c332acf9d3b7 0 1679310587311 2 connected
29cdc75a983d0ca02b350d8d4f45c332acf9d3b7 10.0.0.130:6379@16379 myself,master - 0 1679310585000 2 connected 5461-10922
a300a618fadf30c857e407134c3bd4bbf7d60755 10.0.0.131:6379@16379 master - 0 1679310585473 3 connected 10923-16383
vars currentEpoch 6 lastVoteEpoch 0

查看集群状态
[root@Rocky2 ~]# redis-cli -a 123456 cluster help
查看主从关系
[root@R9-129 ~]# redis-cli -a 123456 -c info replication
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Replication
role:master
connected_slaves:1
slave0:ip=10.0.0.137,port=6379,state=online,offset=308,lag=1
master_failover_state:no-failover
master_replid:a5515bcd55ea3378ea0515c3d2ab21838220aff2
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:308
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:308

查看任何节点的信息
[root@R9-129 ~]# redis-cli -a 123456 --cluster info 10.0.0.135:6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
10.0.0.129:6379 (acf19c56...) -> 0 keys | 5461 slots | 1 slaves.
10.0.0.131:6379 (a300a618...) -> 0 keys | 5461 slots | 1 slaves.
10.0.0.130:6379 (29cdc75a...) -> 0 keys | 5462 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
启用集群模式
[root@R9-129 ~]# redis-cli -a 123456 -c
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> set k1 v1
-> Redirected to slot [12706] located at 10.0.0.131:6379
OK
10.0.0.131:6379>
计算槽位
10.0.0.131:6379> cluster keyslot k1
(integer) 12706

# 当一个主节点出现故障时:
暂停10.0.0.130机器
[root@Rocky2 ~]# systemctl stop redis
[root@Rocky2 ~]# ss -ntl
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              128                               [::]:22                             [::]:* 
139变成了主节点
[root@R9-129 ~]# cat /apps/redis/data/nodes-6379.conf 
a300a618fadf30c857e407134c3bd4bbf7d60755 10.0.0.131:6379@16379 master - 0 1679311436118 3 connected 10923-16383
b9bf0fc7400045183d9d30cdbbe97683d5fe4a29 10.0.0.137:6379@16379 slave acf19c56585ebdfdc02333f366e25da2f9ebfd54 0 1679311435000 1 connected
29cdc75a983d0ca02b350d8d4f45c332acf9d3b7 10.0.0.130:6379@16379 master,fail - 1679311419632 1679311413000 2 disconnected
acf19c56585ebdfdc02333f366e25da2f9ebfd54 10.0.0.129:6379@16379 myself,master - 0 1679311433000 1 connected 0-5460
025ac37084e48dda0cd26fba40880c1e015e1bfd 10.0.0.139:6379@16379 master - 0 1679311434060 7 connected 5461-10922
edfe77c65617d55232b896b4346a5e8aebed0182 10.0.0.135:6379@16379 slave a300a618fadf30c857e407134c3bd4bbf7d60755 0 1679311435091 3 connected
vars currentEpoch 7 lastVoteEpoch 7
将130重新开启了
[root@Rocky2 ~]# systemctl start redis
130变成了139的从节点
[root@R9-139 ~]# redis-cli -a 123456 info replication
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Replication
role:master
connected_slaves:1
slave0:ip=10.0.0.130,port=6379,state=online,offset=1218,lag=0
master_failover_state:no-failover
master_replid:0a055d5fa6e18410382dc15cff59b6f243ce4060
master_replid2:ffe025cb4e99f758cd9999e010af1b5bdad2e385
master_repl_offset:1218
second_repl_offset:1135
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1218

将139关闭
127.0.0.1:6379> shutdown
not connected>
130则将变成主节点
[root@Rocky2 ~]# redis-cli -a 123456 info replication
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:c78dc8fb5e055718bf27cfed0633974e0de6f170
master_replid2:0a055d5fa6e18410382dc15cff59b6f243ce4060
master_repl_offset:1330
second_repl_offset:1331
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1135
repl_backlog_histlen:196
启动139
[root@R9-139 ~]# systemctl start redis
在130中可以看到,139变成了130的从节点
[root@Rocky2 ~]# redis-cli -a 123456 info replication
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Replication
role:master
connected_slaves:1
slave0:ip=10.0.0.139,port=6379,state=online,offset=1400,lag=0
master_failover_state:no-failover
master_replid:c78dc8fb5e055718bf27cfed0633974e0de6f170
master_replid2:0a055d5fa6e18410382dc15cff59b6f243ce4060
master_repl_offset:1414
second_repl_offset:1331
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1135
repl_backlog_histlen:280

# 扩容
修改配置
[root@R9-140 ~]# vim /apps/redis/etc/redis.conf
masterauth 123456
requirepass 123456
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-require-full-coverage no
[root@R9-140 ~]# systemctl restart redis

调用加入指令
[root@R9-140 ~]# redis-cli -a 123456 --cluster add-node 10.0.0.140:6379  10.0.0.130:6379
分槽位
[root@R9-140 ~]# redis-cli -a 123456 --cluster reshard 10.0.0.130:6379
16384/4=4096
将上面的长条id抄下来
all
yes
查看全部节点的id
[root@R9-140 ~]# redis-cli -a 1123456 cluster nodes
给140加上从节点
[root@R9-140 ~]# redis-cli -a 123456 --cluster add-node 10.0.0.141:6379 10.0.0.130:6379 --cluster-slave --cluster-master-id  +刚刚查询到的140的id

# 缩容
查看140的槽位
[root@R9-140 ~]# redis-cli -a 1123456 cluster nodes
[root@R9-140 ~]# redis-cli -a 123456 --cluster reshard 10.0.0.130:6379
1365
写上129的id
done
yes
[root@R9-140 ~]# redis-cli -a 123456 --cluster reshard 10.0.0.130:6379
1366
写上130的id
done
yes
[root@R9-140 ~]# redis-cli -a 123456 --cluster reshard 10.0.0.130:6379
1365
写上131的id
done
yes
在集群中删除140
[root@R9-140 ~]# redis-cli -a 123456 --cluster del-node 10.0.0.130:6379 +140的id
[root@R9-140 ~]# redis-cli -a 123456 --cluster del-node 10.0.0.130:6379 +141的id


3. 总结 LVS的NAT和DR模型工作原理,并完成DR模型实战。

NAT:

原理:就是把客户端发来的数据包的IP头的目的地址,在负载均衡器上换成其中一台RS的IP地址,并发至此RS来处理,RS处理完成后把数据交给经过负载均衡器,负载均衡器再把数据包的原IP地址改为自己的IP,将目的地址改为客户端IP地址即可。

优点:集群中的物理服务器可以使用任何支持TCP/IP操作系统它只需要一个 IP 地址配置在调度器上,服务器组可以用私有的 IP 地址。

缺点:扩展性有限。当服务器节点(普通PC服务器)增长过多时,负载均衡器将成为整个系统的瓶颈,因为所有的请求包和应答包的流向都经过负载均衡器。当服务器节点过多时,大量的数据包都交汇在负载均衡器那,速度就会变慢。

DR:

原理:负载均衡器和RS都使用同一个IP对外服务,但只有DR对ARP请求进行响应,所有RS对本身这个IP的ARP请求保持静默,也就是说,网关会把对这个服务IP的请求全部定向给DR,而DR收到数据包后根据调度算法,找出对应的RS,把目的MAC地址改为RS的MAC(因为IP一致)并将请求分发给这台RS,这时RS收到这个数据包,处理完成之后,由于IP一致,可以直接将数据返给客户,则等于直接从客户端收到这个数据包无异,处理后直接返回给客户端。由于负载均衡器要对二层包头进行改换,所以负载均衡器和RS之间必须在一个广播域,也可以简单的理解为在同一台交换机上。

优点:VS/DR跟 VS/TUN 方法相同,负载调度器中只负责调度请求,而服务器直接将响应返回给客户,可以极大地提高整个集群系统的吞吐量。

缺点:要求负载均衡器的网卡必须与物理网卡在一个物理段上

[root@route ~]# ip a a 172.16.0.200/24 dev eth0 label eth0:1
[root@route ~]# 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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:1d:35:83 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.137/24 brd 10.0.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet 172.16.0.200/24 scope global eth0:1
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe1d:3583/64 scope link 
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:1d:35:8d brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.200/24 brd 192.168.10.255 scope global noprefixroute eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe1d:358d/64 scope link 
       valid_lft forever preferred_lft forever

[root@route ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.2        0.0.0.0         UG    100    0        0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     100    0        0 eth0
172.16.0.0      0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.10.0    0.0.0.0         255.255.255.0   U     101    0        0 eth1

[root@Web1 ~]# vim lvs_dr_rs.sh
#!/bin/bash
#Author:wangxiaochun
#Date:2017-08-13
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 start
The RS Server is Ready!
[root@Web1 ~]# scp lvs_dr_rs.sh 10.0.0.139:
[root@Web2 ~]# bash lvs_dr_rs.sh 
Usage: lvs_dr_rs.sh start|stop
[root@Web2 ~]# bash lvs_dr_rs.sh start
The RS Server is Ready!

[root@LVS ~]# vim lvs_dr_vs.sh 
[root@LVS ~]# cat lvs_dr_vs.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='10.0.0.129'
rs2='10.0.0.139'
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 ~]# ipvsadm -C
[root@LVS ~]# bash lvs_dr_vs.sh start
The VS Server is Ready!
[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
  -> 10.0.0.129:80                Route   1      0          0         
  -> 10.0.0.139:80                Route   1      0          0         


4. 总结 http协议的通信过程详解

1 建立TCP连接
在HTTP工作开始之前,Web浏览器首先要通过网络与Web服务器建立连接,该连接是通过TCP来完成的,该协议与IP协议共同构建Internet,即著名的TCP/IP协议族,因此Internet又被称作是TCP/IP网络。HTTP是比TCP更高层次的应用层协议,根据规则,只有低层协议建立之后才能进行更深层协议的连接,因此,首先要建立TCP连接,一般TCP连接的端口号是80。

2 Web浏览器向Web服务器发送请求命令
一旦建立了TCP连接,Web浏览器就会向Web服务器发送请求命令

例如:GET/sample/hello.jsp HTTP/1.1。

3 Web浏览器发送请求头信息
浏览器发送其请求命令之后,还要以头信息的形式向Web服务器发送一些别的信息,之后浏览器发送了一空白行来通知服务器,它已经结束了该头信息的发送。

4 Web服务器应答
客户机向服务器发出请求后,服务器会客户机回送应答,

HTTP/1.1 200 OK

应答的第一部分是协议的版本号和应答状态码。

5 Web服务器发送应答头信息
正如客户端会随同请求发送关于自身的信息一样,服务器也会随同应答向用户发送关于它自己的数据及被请求的文档。

6 Web服务器向浏览器发送数据
Web服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此为结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据。

7 Web服务器关闭TCP连接
一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码

Connection:keep-alive

TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。
 


5. 总结  网络IO模型和nginx架构

网络IO模型:

四种IO模型

  • 同步阻塞IO(Blocking IO):
  • 同步非阻塞IO(Non-Blocking IO)
  • IO多路复用(IO Multiplexing)
  • 异步IO(Asynchronous IO)

同步阻塞IO(Blocking IO)
在同步阻塞IO模型中,程序用IO调用开始,直到系统调用返回,在这段时间内,进程是阻塞的。直到返回成功后,应用程序开始处理用户空间的缓存区数据.主要分为两个阶段:

等待数据就绪:网络IO就是等待远端数据陆续到达;磁盘IO就是等到磁盘数据从磁盘读取到内核缓冲区。
数据复制: 用户空间的程序没有权限直接读取内核缓冲区的数据(操作系统处于安全的考虑),因此内核与需要把内核缓冲区的数据复制一份到进程缓冲区。

阻塞IO的特点是:在内核进行IO执行的两个阶段用户线程都被阻塞了。

同步非阻塞IO(None Blocking IO)
将Socket设置为non-blocking,当前连接就变成了非阻塞IO。使用非阻塞模式的IO读写,叫做同步非阻塞IO(None Blocking IO),简称NIO模型。

在同步非阻塞IO模型中,会出现下面几种情况:

在内核缓冲区没有数据的情况下,系统调用会立即返回,返回一个调用失败的信息。这样请求就不会阻塞。
用户线程需要不断的发起IO系统调用,测试内核数据是否准备好。
在内核缓冲区有数据的情况下,是阻塞的。直到内核缓冲区的数据全部复制到进程缓冲区,系统调用成功。

同步非阻塞IO特点:程序需要不断的进行IO系统调用轮询数据是否准备好,如果没有准备好,就继续轮询

IO多路复用模型(IO Multiplexing)
在IO多路复用模型中,引入了一种新的系统调用select/epoll,查询IO的就绪状态。通过该系统调用可以监视多个文件描述符,一旦某个描述符就绪(一般是内核缓存区可读/可写),内核能够将就绪的状态返回给应用程序。随后,应用程序根据就绪的状态,进行相应的IO系统调用。

在IO多路复用模型中通过select/epoll系统调用,单个应用程序的线程,可以不断轮询成百上千的socket连接,当某个或者某些socket网络连接有IO就绪的状态,就返回对应的可以执行的读写操作。

IO多路复用模型的特点:IO多路复用模型涉及两种系统调用,一种是就绪查询(select/epoll),一种是IO操作。

多路复用IO也需要轮询。负责就绪状态查询系统调用的线程,需要不断的进行select/epoll轮询,查找出达到IO操作就绪的socket连接

异步IO模型(Asynchronous IO)
异步IO模型(Asynchronous IO)简称AIO,其基本流程为:用户线程通过系统调用,向内核注册某个IO操作。内核在整个IO操作(包括数据准备、数据复制)完成后,通知用户程序,执行后续的业务操作。

在异步IO模型中,整个内核的数据处理过程中,包括内核将数据从网络物理设备(网卡)读取到内核缓存区、将内核缓冲区的数据复制到用户缓冲区,用户程序都不需要阻塞。

异步IO模型的特点:在内核等待数据复制数据的两个阶段,用户线程都不是阻塞的。当内核的IO操作(等待数据和复制数据)全部完成后,内核会通知应用程序读数据

四种IO模型的优缺点
3.1 同步阻塞IO
优点:程序开发简单;在阻塞等待数据期间,用户线程挂起,不占用CPU资源。
缺点:一个线程维护一个IO流的读写,在高并发应用场景下,需要大量的线程来维护大量的网络连接,内存、线程切换开销会十分巨大,BIO模型在高并发场景下是不可用的。
3.2 同步非阻塞IO
优点:内核缓冲区没有数据的情况下,发起的系统调用不会阻塞,用户程序不会阻塞,实时性较好。
缺点:需要不断地重复地发起IO调用,这种不断轮询,不断询问内核的方式,会占用CPU大量的时间,资源利用率比较低;在内核缓冲区有数据的情况下,也是阻塞的。NIO模型在高并发场景下是不可用的。
3.3 IO多路复用
优点:select/epoll可以同时处理成百上千的连接,与之前的一个线程维护一个连接相比,IO多路复用则不需要创建线程,也就不需要维护,从而减少系统开销.
缺点: select/epoll系统调用,属于阻塞的模式。读写事件就绪之后,用户自己进行读写,这个读写过程也是阻塞的。
3.4 异步IO
优点:在内核等待数据和复制数据的两个阶段,用户线程都不是阻塞的。
缺点:需要事件的注册,就需要操作系统。

nginx框架:

Nginx功能

  • 静态的web资源服务器html,图片、js、css、txt等静态资源
  • http/https协议的方向代理
  • 结合FastCGI/uWSGI/SCDI等协议方向代理动态资源请求
  • tcp/udp协议的请求转发(反向代理)
  • imap4/pop3协议的反向代理

基础特性

  • 模块化设计,较好的扩展性
  • 高可靠性
  • 支持热部署:不停机更新配置文件,升级版本,更新日志文件
  • 低内存消耗:10000个keep-aliva连接模式下的非活动连接,仅需要2.5M的内存

web服务想关的功能

  • 虚拟主机(server)
  • 支持keep-aliva和管道连接(利用一个连接做多次请求)
  • 访问日志(支持基于日志缓冲,提高其性能)
  • url rewirte
  • 路径别名
  • 基于IP及用户的访问控制
  • 支持速率限制及并发数限制
  • 重新配置和在线升级而无需终端客户的工作进程

Nginx模块

  • 核心模块:正常运行必不可少的
  • 标准http模块:提供http协议解析相关功能
  • 可选http模块:扩展标准的http功能
  • 邮件服务模块:支持Nginx的邮件服务
  • stream服务模块:是相反代理功能,包括TCP协议代理
  • 第三方模块:扩展Nginx的服务器应用,完成开发者自定义功能


6. 完成nginx编译安装脚本

#!/bin/bash
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


7. 总结nginx核心配置,并实现nginx多虚拟主机

# 事件驱动相关的配置
event {
	……
}

# http/https 协议相关的配置
http {
	……
}

# 默认配置文件不包括下面两个快
# mail 协议相关的配置
mail {
	……
}

# stream 服务器相关的配置
stream {
	……
}


# 自动实现相匹配的核数,实现多worker运作
[root@Rocky2 ~]# vim /apps/nginx/conf/nginx.conf
worker_processes  auto;
worker_cpu_affinity auto;
root@Rocky2 ~]# nginx -s reload
[root@Rocky2 ~]# ps auxf |grep nginx
root       17003  0.0  0.1   6408  2148 pts/0    S+   14:36   0:00  |           \_ grep --color=auto nginx
root       16768  0.0  0.3   9892  6640 ?        S    13:36   0:00 nginx: master process /apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf
nginx      16998  0.0  0.2  13720  4748 ?        S    14:34   0:00  \_ nginx: worker process
nginx      16999  0.0  0.2  13720  4756 ?        S    14:34   0:00  \_ nginx: worker process
# 调整工作进程优先级
[root@Rocky2 ~]# vim /apps/nginx/conf/nginx.conf
worker_priority 0;
worker_rlimit_nofile   1000000

events {
	worker_connections 10240;
	accept_mutex on;   # 轮流叫醒,避免惊群现象
}


8. 总结nginx日志格式定制

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"}';

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值