1. redis搭建哨兵原理和集群实现。
哨兵的结构如图:
哨兵的作用如下:
监控:Sentinel 会不断检查您的master和slave是否按预期工作
自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主
通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端
集群监控原理
Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:
- 主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线。
- 客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。
集群故障恢复原理
一旦发现master故障,sentinel需要在salve中选择一个作为新的master,选择依据是这样的:
- 首先会判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds * 10)则会排除该slave节点
- 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举
- 如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高
- 最后是判断slave节点的运行id大小,越小优先级越高。
当选出一个新的master后,该如何实现切换呢? 流程如下: - sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为master
- sentinel给所有其它slave发送slaveof 192.168.150.101 7002 命令,让这些slave成为新master的从节点,开始从新的master上同步数据。
- 最后,sentinel将故障节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点
结构如图所示:
Redis集群
集群由多组节点(Node)组成,Redis的数据分布在这些节点中。集群中的节点分为主节点和从节点:只有主节点负责读写请求和集群信息的维护;从节点只进行主节点数据和状态信息的复制。 集群实现 准备三台 CentOS 7 主机,已编译安装好Redis,各启动两个Redis实例,分别使用6379和6380端口,从 而模拟实现6台Redis实例
10.0.0.7:6379|6380
10.0.0.17:6379|6380
10.0.0.27:6379|638
准备6个实例:在三个主机上重复下面的操作 范例: 3个节点6个实例
#在三台主机上都编译安装redis
[root@redis-node1 ~]#yum -y install gcc jemalloc-devel
[root@redis-node1 ~]#cd /usr/local/src
[root@redis-node1 src]#wget http://download.redis.io/releases/redis4.0.14.tar.gz
[root@redis-node1 src]#tar xf redis-4.0.14.tar.gz
[root@redis-node1 src]#cd redis-4.0.14
[root@redis-node1 redis-4.0.14]#make PREFIX=/apps/redis install
#准备相关文件和目录
[root@redis-node1 redis-4.0.14]#ln -s /apps/redis/bin/redis-* /usr/bin/
[root@redis-node1 redis-4.0.14]#mkdir -p /apps/redis/{etc,log,data,run}
[root@redis-node1 redis-4.0.14]#cp redis.conf /apps/redis/etc/
#准备用户
[root@redis-node1 ~]#useradd -r -s /sbin/nologin redis
#配置权限和相关优化配置
[root@redis-node1 ~]#chown -R redis.redis /apps/redis
[root@redis-node1 ~]#cat >> /etc/sysctl.conf <<EOF
net.core.somaxconn = 1024
vm.overcommit_memory = 1
EOF
[root@redis-node1 ~]#sysctl -p
[root@redis-node1 ~]#echo 'echo never >
/sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.d/rc.local
[root@redis-node1 ~]#chmod +x /etc/rc.d/rc.local
[root@redis-node1 ~]#/etc/rc.d/rc.local
#准备service文件
[root@redis-node1 ~]#cat > /usr/lib/systemd/system/redis.service <<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target
[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis.conf --supervised
systemd
ExecStop=/bin/kill -s QUIT \$MAINPID
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
EOF
[root@redis-node1 ~]#systemctl daemon-reload
[root@redis-node1 ~]#systemctl enable --now redis
#准备6379的实例配置文件
[root@redis-node1 ~]#systemctl stop redis
[root@redis-node1 ~]#cd /apps/redis/etc/
[root@redis-node1 etc]#sed -i -e 's/bind 127.0.0.1/bind 0.0.0.0/' -e '/^#
masterauth/a masterauth 123456' -e '/# requirepass/a requirepass 123456' -e '/#
cluster-enabled yes/a cluster-enabled yes' -e '/# cluster-config-file nodes-6379.conf/a cluster-config-file nodes-6379.conf' -e 's/^dir .*/dir
\/apps\/redis\/data/' -e '/appendonly no/c appendonly yes' -e '/logfile ""/c
logfile "/apps/redis/log/redis-6379.log"' -e '/^pidfile .*/c pidfile
/apps/redis/run/redis_6379.pid' /apps/redis/etc/redis.conf
#准备6380端口的实例的配置文件
[root@redis-node1 etc]#cp -p redis.conf redis6380.conf
[root@redis-node1 etc]#sed -i -e 's/6379/6380/' -e 's/dbfilename
dump\.rdb/dbfilename dump6380.rdb/' -e 's/appendfilename
"appendonly\.aof"/appendfilename "appendonly6380.aof"/'
/apps/redis/etc/redis6380.conf
#准备服务文件
[root@redis-node1 ~]#cp /lib/systemd/system/redis.service
/lib/systemd/system/redis6380.service
[root@redis-node1 ~]#sed -i 's/redis.conf/redis6380.conf/'
/lib/systemd/system/redis6380.service
#启动服务,查看到端口都打开
[root@redis-node1 ~]#systemctl daemon-reload
[root@redis-node1 ~]#systemctl enable --now redis redis6380
2. LVS常用模型工作原理,及实现。
LVS是Linux Virtual Server的简写,也就是Linux虚拟服务器,是一个虚拟的服务器集群系统,本项目在1998年5月由章文嵩博士成立,是中国国内最早出现的自由软件项目之一。
LVS集群体系架构
LVS的工作模式
原生只有3种模式(Nat、DR、TUN),fullnat工作模式默认不支持。
LVS基本工作原理
1.当用户向负载均衡器(Director Server)发起请求,调度器将请求发送至内核空间。
2.Prerouting链首先会接收到用户请求,判断目标IP确定是本机IP,将数据包发送到INPUT链。
3.IPVS是工作在INPUT链上的,当用户请求到达INPUT时,IPVS会将用户请求和自己已经定义好的集群服务进行对比,如果用户请求的就是定义的集群服务,那么此时IPVS会强行修改数据包里的目标IP地址及端口,并将新的数据包发送到POSTROUTING链。
4.POSTROUTING链接收数据包后发现目标IP地址刚好是自己的后端服务器,那么此时通过选路,将数据包最终发送到后端的服务器。
3. LVS的负载策略有哪些,各应用在什么场景,通过LVS DR任意实现1-2种场景。
LVS的负载策略有两种,分别为静态方法和动态方法。
静态方法
1、RR:roundrobin,轮询,较常用,雨露均沾,大锅饭
2、WRR:Weighted RR,加权轮询,较常用
3、SH:Source Hashing,实现session sticky,源IP地址hash;将来自于同一个IP地址的请求始终发往第一次挑中的RS,从而实现会话绑定
4、DH:Destination Hashing;目标地址哈希,第一次轮询调度至RS,后续将发往同一个目标地址的请求始终转发至第一次挑中的RS,典型使用场景是正向代理缓存场景中的负载均衡,如: Web缓存
动态方法
1、LC:least connections 适用于长连接应用
2、WLC:Weighted LC,默认调度方法,较常用
3、SED:Shortest Expection Delay,初始连接高权重优先,只检查活动连接,而不考虑非活动连接
4、NQ:Never Queue,第一轮均匀分配,后续SED
5、LBLC:Locality-Based LC,动态的DH算法,使用场景:根据负载状态实现正向代理,实现Web Cache等
6、LBLCR:LBLC with Replication,带复制功能的LBLC,解决LBLC负载不均衡问题,从负载重的复制 到负载轻的 RS,,实现Web Cache等
LVS-DR模式单网段案例
环境:五台主机
一台:客户端 eth0:仅主机 192.168.10.6/24 GW:192.168.10.200
一台:ROUTER
eth0 :NAT 10.0.0.200/24
eth1: 仅主机 192.168.10.200/24
启用 IP_FORWARD
一台:LVS
eth0:NAT:DIP:10.0.0.8/24 GW:10.0.0.200
两台RS:
RS1:eth0:NAT:10.0.0.7/24 GW:10.0.0.200
RS2:eth0:NAT:10.0.0.17/24 GW:10.0.0.200
LVS的网络配置
[root@internet ~]#hostname
internet
[root@internet ~]#hostname -I
192.168.10.6
[root@internet ~]#route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.10.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0
0.0.0.0 192.168.10.200 0.0.0.0 UG 0 0 0 eth0
[root@internet ~]#ping 10.0.0.7 -c1
PING 10.0.0.7 (10.0.0.7) 56(84) bytes of data.
64 bytes from 10.0.0.7: icmp_seq=1 ttl=63 time=0.565 ms
[root@internet ~]#ping 10.0.0.17 -c1
PING 10.0.0.7 (10.0.0.17) 56(84) bytes of data.
64 bytes from 10.0.0.17: icmp_seq=1 ttl=63 time=0.565 ms
[root@router ~]#echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
[root@router ~]#sysctl -p
[root@router network-scripts]#pwd
/etc/sysconfig/network-scripts
[root@router network-scripts]#cat ifcfg-eth0
DEVICE=eth0
NAME=eth0
BOOTPROTO=static
IPADDR=10.0.0.200
PREFIX=24
ONBOOT=yes
[root@router network-scripts]#cat ifcfg-eth1
DEVICE=eth1
NAME=eth1
BOOTPROTO=static
IPADDR=192.168.10.200
PREFIX=24
ONBOOT=yes
#RS1的网络配置
[root@rs1 ~]#hostname
rs1.magedu.org
[root@rs1 ~]#hostname -I
10.0.0.7
[root@rs1 ~]#cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
NAME=eth0
BOOTPROTO=static
IPADDR=10.0.0.7
PREFIX=24
GATEWAY=10.0.0.200
ONBOOT=yes
[root@rs1 ~]#route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.0.200 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
[root@rs1 ~]#yum -y install httpd
[root@rs1 ~]#systemctl enable --now httpd
[root@rs1 ~]#hostname -I > /var/www/html/index.html
[root@rs1 ~]#ping 192.168.10.6 -c1
PING 192.168.10.6 (192.168.10.6) 56(84) bytes of data.
64 bytes from 192.168.10.6: icmp_seq=1 ttl=63 time=1.14 ms
[root@rs1 ~]#curl 10.0.0.7
10.0.0.7
[root@rs2 ~]#cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
NAME=eth0
BOOTPROTO=static
IPADDR=10.0.0.17
PREFIX=24
GATEWAY=10.0.0.200
ONBOOT=yes
[root@rs2 ~]#route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.0.200 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
[root@rs2 ~]#yum -y install httpd
[root@rs2 ~]#systemctl enable --now httpd
[root@rs2 ~]#hostname -I > /var/www/html/index.html
[root@rs2 ~]#curl 10.0.0.17
10.0.0.17
[root@rs1 ~]#ping 192.168.10.6 -c1
PING 192.168.10.6 (192.168.10.6) 56(84) bytes of data.
64 bytes from 192.168.10.6: icmp_seq=1 ttl=63 time=1.14 ms
[root@rs2 ~]#curl 10.0.0.17
10.0.0.17
#LVS的网络配置
[root@lvs ~]#hostname
lvs.magedu.org
[root@lvs ~]#hostname -I
10.0.0.8
[root@lvs ~]#cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
NAME=eth0
BOOTPROTO=static
IPADDR=10.0.0.8
PREFIX=24
GATEWAY=10.0.0.200
ONBOOT=yes
[root@lvs ~]#route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.0.200 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
[root@lvs ~]#ping 192.168.10.6 -c1
后端RS的IPVS配置
#RS1的IPVS配置
[root@rs1 ~]#echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@rs1 ~]#echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@rs1 ~]#echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@rs1 ~]#echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
[root@rs1 ~]#ifconfig lo:1 10.0.0.100/32
#RS2的IPVS配置
[root@rs2 ~]#echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@rs2 ~]#echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@rs2 ~]#echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@rs2 ~]#echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
[root@rs2 ~]#ifconfig lo:1 10.0.0.100/32
LVS主机的配置
#在LVS上添加VIP
[root@lvs ~]#ifconfig lo:1 10.0.0.100/32
#实现LVS 规则
[root@lvs ~]#dnf -y install ipvsadm
[root@lvs ~]#ipvsadm -A -t 10.0.0.100:80 -s rr
[root@lvs ~]#ipvsadm -a -t 10.0.0.100:80 -r 10.0.0.7:80 -g
[root@lvs ~]#ipvsadm -a -t 10.0.0.100:80 -r 10.0.0.17:80 -g
[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 10.0.0.100:80 rr
-> 10.0.0.7:80 Route 1 0 0
-> 10.0.0.17:80 Route 1 0 0
测试访问
[root@internet ~]#curl 10.0.0.100
10.0.0.17
[root@internet ~]#curl 10.0.0.100
10.0.0.7
[root@rs1 ~]#tail -f /var/log/httpd/access_log -n0
192.168.10.6 - - [12/Jul/2020:10:36:21 +0800] "GET / HTTP/1.1" 200 10 "-"
"curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3
libidn/1.18 libssh2/1.4.2"
4. web http协议通信过程,相关技术术语总结。
HTTP服务通信过程
1. 客户端发送请求:
- URL(Uniform Resource Locator): 客户端通过URL指定要访问的资源的地址。
- HTTP请求方法: 常见的HTTP请求方法包括GET(获取资源)、POST(提交数据创建资源)、PUT(更新资源)、DELETE(删除资源)等。
- 请求头(Headers): 包含关于请求的附加信息,如User-Agent(标识客户端类型)、Accept(指定客户端可接受的响应数据类型)等。
- 请求体(Body): 仅在使用POST、PUT等方法时出现,用于传输客户端要发送给服务器的数据。
2. 服务器处理请求:
- Web服务器: 接收并处理客户端请求的软件,如Apache、Nginx等。
- 后端处理: Web服务器将请求发送到适当的后端应用程序,可能是应用服务器或API服务器。
- 路由解析: 服务器根据请求的URL将其路由到正确的处理程序。
3. 服务器发送响应:
- 状态码(Status Code): 表示服务器对请求的处理结果,如200 OK(成功)、404 Not Found(未找到资源)、500 Internal Server Error(服务器错误)等。
- 响应头(Headers): 包含有关响应的附加信息,如Content-Type(指定响应数据类型)、Content-Length(响应体长度)等。
- 响应体(Body): 包含实际的响应数据,如HTML文档、JSON数据等。
4. 客户端处理响应:
- 状态码解析: 客户端根据收到的状态码确定请求是否成功,并采取适当的操作。
- 响应数据处理: 客户端解析响应体中的数据,如呈现HTML页面、处理JSON数据等。
常见技术术语总结:
- URL(Uniform Resource Locator): 统一资源定位符,用于标识Web上的资源。
- HTTP(Hypertext Transfer Protocol): 用于在客户端和服务器之间传输数据的协议。
- 请求方法(HTTP Request Methods): 定义HTTP请求的操作类型,如GET、POST、PUT、DELETE等。
- 请求头(HTTP Request Headers): 包含关于请求的元信息,如User-Agent、Accept等。
- 请求体(HTTP Request Body): 仅在包含数据的请求中出现,如POST请求。
- 状态码(HTTP Status Codes): 表示服务器对请求的处理结果,如200 OK、404 Not Found等。
- 响应头(HTTP Response Headers): 包含关于响应的元信息,如Content-Type、Content-Length等。
- 响应体(HTTP Response Body): 包含服务器返回的实际数据。
- Web服务器(Web Server): 接受并处理客户端请求的软件,如Apache、Nginx等。
- API(Application Programming Interface): 用于不同软件组件之间交换数据的接口。
- 后端(Backend): 服务器端的应用程序部分,用于处理业务逻辑和数据存储。
- 前端(Frontend): 客户端(通常是浏览器)中负责用户界面呈现和交互的部分。
5. 总结网络IO模型和nginx架构。
阻塞型 I/O 模型(blocking IO)
阻塞IO模型是最简单的I/O模型,用户线程在内核进行IO操作时被阻塞
用户线程通过系统调用read发起I/O读操作,由用户空间转到内核空间。内核等到数据包到达后,然后将 接收的数据拷贝到用户空间,完成read操作
用户需要等待read将数据读取到buffer后,才继续处理接收的数据。整个I/O请求的过程中,用户线程是 被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够
优点:程序简单,在阻塞等待数据期间进程/线程挂起,基本不会占用 CPU 资源
缺点:每个连接需要独立的进程/线程单独处理,当并发请求量大时为了维护程序,内存、线程切换开销 较大,apache 的prefork使用的是这种模式。
非阻塞型 I/O 模型 (nonblocking IO)
用户线程发起IO请求时立即返回。但并未读取到任何数据,用户线程需要不断地发起IO请求,直到数据 到达后,才真正读取到数据,继续执行。即 “轮询”机制存在两个问题:如果有大量文件描述符都要等, 那么就得一个一个的read。这会带来大量的Context Switch(read是系统调用,每调用一次就得在用户 态和核心态切换一次)。轮询的时间不好把握。这里是要猜多久之后数据才能到。等待时间设的太长, 程序响应延迟就过大;设的太短,就会造成过于频繁的重试,干耗CPU而已,是比较浪费CPU的方式,一 般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。
I/O 多路复用型 (I/O multiplexing)
信号驱动式 I/O 模型 (signal-driven IO)
异步 I/O 模型 (asynchronous IO)
Nginx 架构
- 主进程
nginx启动的时候,是会产生一个主进程的。其实其他软件也是这样。主进程就相当于领导。它能干什么呢?领导一般都比较重要,总揽全局,所以ngnix的主进程也是一样的,它主要负责与外界通信,把命令传达给工作进程,让工作进程执行。工作进程怎么来的?也是主进程创建的,不光创建还管理呢。除了这些,主进程还负责读取配置文件,当然配置文件有效性的验证也是它的活儿。你可还记得,配置文件不对,启动nginx的时候,nginx是会报错的。主进程还有别的活,以后再说。
- 工作进程
工作进程是由主进程创建的,它相当于员工,需要的时候,创建一个来使用,当工作进程没用的时候,主进程就会结束这个工作进程,释放资源。员工就是个干活的,工作进程也是。有需要则招之,用完后,你给我滚犊子,不养闲人。看到了吧,主进程像不像个领导。工作进程具体干什么,比如:接收主进程的指令,去执行,与后端服务器通信,接收后端服务器处理的结果,发送结果给客户端,数据缓存,访问缓存索引、查询和调用缓存数据等等。
- 通信
主进程和工作进程是如何通信的呢?其实主进程在创建工作进程的时候,它会维护一个工作进程表,把创建的这个工作进程的相关信息都记录下来,同时建立一个单向的通道用来发号指令。主进程和工作进程的交互,英文叫:master-worker交互。
工作进程之间能通信吗?能,不过费点劲,因为工作进程之间是隔离的,不能直接通信。这就要靠领导了,也就是靠主进程来协助了。比如:工作进程A1想跟工作进程A2搞对象,不是,是进行通信,A1是不知道A2的相关信息的,A1就去找主进程这个领导。主进程告诉它A2的相关信息,比如家庭住址啥的,A1就能找到A2,并和A2进行通信了。工作进程之间的交互英文叫:worker-worker交互。
6. nginx总结核心配置和优化。
默认的Linux内核参数考虑的是最通用场景,不符合用于支持高并发访问的Web服务器的定义,根据业 务特点来进行调整,当Nginx作为静态web内容服务器、反向代理或者提供压缩服务器的服务器时,内 核参数的调整都是不同的,此处针对最通用的、使Nginx支持更多并发请求的TCP网络参数做简单的配置
fs.file-max = 1000000
#表示单个进程较大可以打开的句柄数
net.ipv4.tcp_tw_reuse = 1
#参数设置为 1 ,表示允许将TIME_WAIT状态的socket重新用于新的TCP链接,这对于服务器来说意义重大,因为总有大量TIME_WAIT状态的链接存在
net.ipv4.tcp_keepalive_time = 600
#当keepalive启动时,TCP发送keepalive消息的频度;默认是2小时,将其设置为10分钟,可更快的清理无效链接
net.ipv4.tcp_fin_timeout = 30
#当服务器主动关闭链接时,socket保持在FIN_WAIT_2状态的较大时间
net.ipv4.tcp_max_tw_buckets = 5000
#表示操作系统允许TIME_WAIT套接字数量的较大值,如超过此值,TIME_WAIT套接字将立刻被清除并打印警告信息,默认为8000,过多的TIME_WAIT套接字会使Web服务器变慢
net.ipv4.ip_local_port_range = 1024 65000
#定义UDP和TCP链接的本地端口的取值范围
net.ipv4.tcp_rmem = 10240 87380 12582912
#定义了TCP接受缓存的最小值、默认值、较大值
net.ipv4.tcp_wmem = 10240 87380 12582912
#定义TCP发送缓存的最小值、默认值、较大值
net.core.netdev_max_backlog = 8096
#当网卡接收数据包的速度大于内核处理速度时,会有一个列队保存这些数据包。这个参数表示该列队的较大值
net.core.rmem_default = 6291456
#表示内核套接字接受缓存区默认大小
net.core.wmem_default = 6291456
#表示内核套接字发送缓存区默认大小
net.core.rmem_max = 12582912
#表示内核套接字接受缓存区较大大小
net.core.wmem_max = 12582912
#表示内核套接字发送缓存区较大大小
注意:以上的四个参数,需要根据业务逻辑和实际的硬件成本来综合考虑
net.ipv4.tcp_syncookies = 1
#与性能无关。用于解决TCP的SYN攻击
net.ipv4.tcp_max_syn_backlog = 8192
#这个参数表示TCP三次握手建立阶段接受SYN请求列队的较大长度,默认1024,将其设置的大一些可使出现Nginx繁忙来不及accept新连接时,Linux不至于丢失客户端发起的链接请求
net.ipv4.tcp_tw_recycle = 1
#这个参数用于设置启用timewait快速回收
net.core.somaxconn=262114
#选项默认值是128,这个参数用于调节系统同时发起的TCP连接数,在高并发的请求中,默认的值可能会导致链接超时或者重传,因此需要结合高并发请求数来调节此值。
net.ipv4.tcp_max_orphans=262114
#选项用于设定系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤立链接将立即被复位并输出警告信息。这个限制指示为了防止简单的DOS攻击,不用过分依靠这个限制甚至认为的减小这个值,更多的情况是增加这个值
7. 使用脚本完成一键编译安装nginx任意版本。
bash install_nginx.sh
#!/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
8. 任意编译一个第3方nginx模块,并使用。
echo 模块实现信息显示
[root@centos8 ~]# systemctl stop nginx
[root@centos8 ~]# vim /apps/nginx/conf/conf.d/pc.conf
location /main {
index index.html;
default_type text/html;
echo "hello world,main-->";
echo $remote_addr ;
echo_reset_timer; #将计时器开始时间重置为当前时间
echo_location /sub1;
echo_location /sub2;
echo "took $echo_timer_elapsed sec for total.";
}
location /sub1 {
echo_sleep 1;
echo sub1;
}
location /sub2 {
echo_sleep 1;
echo sub2;
}
[root@centos8 ~]# /apps/nginx/sbin/nginx -t
nginx: [emerg] unknown directive "echo_reset_timer" in
/apps/nginx/conf/conf.d/pc.conf:86
nginx: configuration file /apps/nginx/conf/nginx.conf test failed
#解决以上报错问题
[root@centos8 ~]# cd /usr/local/src
[root@centos8 src]# yum install git -y
#github网站国内访问不稳定,可能无法下载
[root@centos8 src]# git clone https://github.com/openresty/echo-nginx-module.git
#如果上面链接无法下载,可以用下面链接
[root@centos8 src]# git clone https://github.com.cnpmjs.org/openresty/echonginx-module.git
[root@centos8 src]# cd nginx-1.18.0/
[root@centos8 src]# ./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 \
--with-http_perl_module \
--add-module=/usr/local/src/echo-nginx-module #指定模块源代码路径
[root@centos8 src]# make && make install
#确认语法检测通过
[root@centos8 ~]# /apps/nginx/sbin/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
#重启nginx访问测试
[root@centos8 ~]# systemctl restart nginx
[root@centos8 ~]#nginx -V
nginx version: wanginx/1.68.9
built by gcc 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC)
built with OpenSSL 1.1.1c FIPS 28 May 2019
TLS SNI support enabled
configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --withhttp_ssl_module --with-http_v2_module --with-http_realip_module --withhttp_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream
--with-stream_ssl_module --with-stream_realip_module --addmodule=/usr/local/src/echo-nginx-module
#测试查看结果
[root@centos7 ~]#curl http://www.magedu.org/main
hello world,main-->
10.0.0.7
sub1
sub2
took 2.003 sec for total.
.