一、Keepalived 介绍 Keepalived 是 Linux 下一个轻量级别的高可用解决方案，通过虚拟路由冗余协议来实现服务或者网络的高可用。 起初是为 LVS 设计的，专门用来监控集群系统中各个服务节点的状态。 如果某个服务器节点出现故障，Keepalived 将检测到后自动将节点从集群系统中剔除。 而在故障节点恢复正常后，Keepalived 又可以自动将此节点重新加入集群中。 这些工作自动完成，不需要人工干预，需要人工完成的只是修复出现故障的节点。 1.1、特点： 1、部署简单，只需要配置一个配置文件即可。 2、加入了虚拟路由冗余协议，可以保证业务或网络不间断稳定运行。 1.2、核心功能： 1.2.1、健康检查 采用 tcp 三次握手，icmp 请求，http 请求，udp、echo 请求等方式对负载均衡器后面的实际的服务器 (通常是承载真实业务的服务器) 进行保活。 1.2.2、故障切换 主要应用在配置了主备的服务器上，使用虚拟路由冗余协议维持主备之间的心跳。 当主服务器出现问题时，由备服务器承载对应的业务，从而在最大限度上减少损失，并提供服务的稳定性。 1.3、VRRP 协议 在现实的网络环境中，主机之间的通信都是通过配置静态路由（默认网关）来完成的。 而主机之间的路由器一旦出现故障，就会通信失败。 因此在这种通信模式下，路由器就会有单点瓶颈问题，为了解决这个问题，引入了 VRRP 协议（虚拟路由冗余协议）。 通过 VRRP 可以在网络发生故障时透明的进行设备切换而不影响主机之间的数据通信。 VRRP 可以将两台或多台物理路由器设备虚拟成一个虚拟路由器，这个虚拟路由器通过虚拟 IP（一个或多个）对外提供服务，而在虚拟路由器内部是多个物理路由器协同工作，VRRP 角色如下： 1.3.1、角色 虚拟路由器：VRRP 组中所有的路由器，拥有虚拟的 IP+MAC (00-00-5e-00-01-VRID) 地址。 主路由器（master）：虚拟路由器内部通常只有一台物理路由器对外提供服务，主路由器是由选举算法产生，对外提供各种网络功能。 备份路由器（backup）：VRRP 组中除主路由器之外的所有路由器，不对外提供任何服务，只接受主路由的通告，当主路由器挂掉之后，重新进行选举算法接替 master 路由器。 master 路由器由选举算法产生，它拥有对外服务的 VIP，提供各种网络服务，如 ARP 请求、数据转发、ICMP 等等，而 backup 路由器不拥有 VIP，也不对外提供网络服务。 当 master 发生故障时，backup 将重新进行选举，产生一个新的 master 继续对外提供服务。 1.3.2、VRRP 工作模式 VRRP 有三种工作状态，分别是： Initialize 状态 Master 状态 Backup 状态 选举机制: 抢占模式：一旦有优先级高的路由器加入，立即成为 Master。 非抢占模式：只要 Master 不挂掉，优先级高的路由器只能等待。 二、Keepalived 原理 keepalived 工作在 TCP/IP 参考模型的第三、四和第五层，也就是网络层、传输层和应用层。 网络层：通过 ICMP 协议向集群每个节点发送一个 ICMP 数据包（类似于 ping 功能），如果某个节点没有返回响应数据包，那么认定此节点发生了故障，Keepalived 将报告此节点失效，并从集群中剔除故障节点。 传输层：通过 TCP 协议的端口连接和扫描技术来判断集群节点是否正常，keepalived 一旦在传输层探测到这些端口没有响应数据返回，就认为这些端口所对应的节点发生故障，从集群中剔除故障节点。 应用层：用户可以通过编写程序脚本来运行 keepalived，keepalived 根据脚本来检测各种程序或者服务是否正常，如果检测到有故障，则把对应的服务从服务器中删除。 2.1、组件架构 我们将整个体系结构分层用户层和内核层： Scheduler I/O Multiplexer I/O 复用分发调用器，负责安排 Keepalived 所有的内部的任务请求 Memory Management 内存管理机制，提供了访问内存的一下通用方法 Keepalived Control Plane 控制面板，实现对配置文件的编译和解析，Keepalived 的配置文件解析比较特殊，它并不是一次解析所有模块的配置，而是只有在用到某模块时才解析相应的配置 Core components Keepalived 的核心组件，包含了一系列功能模块，主要有 watch dog、Checkers、VRRP Stack、IPVS wrapper、Netlink Reflector。 watch dog 一个极为简单又非常有效的检测工具，针对被监视目标设置一个计数器和阈值，watch dog 会自己增加此计数值，然后等待被监视目标周期性的重置该数值，一旦被监控目标发生错误，就无法重置该数值，watch dog 就会检测到。Keepalived 是通过它来监控 Checkers 和 VRRP 进程。 Checkers 实现对服务器运行状态检测和故障隔离。 VRRP Stack 实现 HA 集群中失败切换功能，通过 VRRP 功能再结合 LVS 负载均衡软件即可部署一个高性能的负载均衡集群。 IPVS wrapper 实现 IPVS 功能，该模块可以将设置好的 IPVS 规则发送到内核空间并提交给 IPVS 模块，最终实现负载均衡功能。 Netlink Reflector 实现 VIP 的设置和切换。 三、安装 & 配置 yum install -y keepalived 配置文件都是以块（block）的形式组成，每一个块的内容都包含在 { } 中。 手动安装： tar -zxvf keepalived-2.2.8.tar.gz cd keepalived-2.2.8 ./configure --prefix=/usr/local/keepalived make install 复制 Keepalived 到系统服务目录： cp /root/tool/keepalived-2.2.8/keepalived/etc/init.d/keepalived /etc/rc.d/init.d 设置开机自启动： chkconfig --add keepalived chkconfig keepalived on 3.1、全局配置 ! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } 其中： global_defs 全局配置标识。 notification_email 用于设置报警的邮件地址，可以设置多个，每行一个。如果要开启邮件报警，需要开启本机的 sendmail 服务。 notification_email_from 邮件的发送地址。 smtp_server 设置邮件的 smtp server 地址。 smtp_connect_timeout 设置连接 smtp server 的超时时间。 router_id 运行 keepalived 的一个标识，唯一。 vrrp_skip_check_adv_addr 对所有通告报文都检查，会比较消耗性能，启用此配置后，如果收到的通告报文和上一个报文是同一个路由器，则跳过检查，默认值为全检查。 vrrp_strict 严格遵守 VRRP 协议，启用此项后以下状况将无法启动服务：1. 无 VIP 地址 2. 配置了单播邻居 3. 在 VRRP 版本 2 中有 IPv6 地址，开启动此项并且没有配置 vrrp_iptables 时会自动开启 iptables 防火墙规则，默认导致 VIP 无法访问，建议不加此项配置。 vrrp_iptables 此项和 vrrp_strict 同时开启时，则不会添加防火墙规则，如果无配置 vrrp_strict 项，则无需启用此项配置。 vrrp_garp_interval 0 gratuitous ARP messages 报文发送延迟，0 表示不延迟。 vrrp_gna_interval 0 unsolicited NA messages （不请自来）消息发送延迟。 3.2、VRRP 实例配置 vrrp_script nginx_check { script"/tools/nginx_check.sh" interval 1 } vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 52 mcast_src_ip 192.168.10.102 # 填写本机ip priority 100 advert_int 1 authentication { auth_type PASS auth_pass test } virtual_ipaddress { 192.168.149.100 } track_script { nginx_check } notify_master /tools/master.sh notify_backup /tools/backup.sh notify_fault /tools/fault.sh notify_stop /tools/stop.sh } 其中： vrrp_instance VI_1 VRRP 实例开始的标识 VI_1 为实例名称。 state 指定 keepalived 的角色，MASTER 表示此主机是主服务器，BACKUP 表示此主机是备服务器。 interface 指定检测网络的网卡接口。 virtual_router_id 虚拟路由标识，数字形式，同一个 VRRP 实例使用唯一的标识，即在同一个 vrrp_instance 下，master 和 backup 必须一致。 mcast_src_ip 填写本机ip priority 节点优先级，数字越大表示节点的优先级越高，在一个 VRRP 实例下，MASTER 的优先级必须要比 BACKUP 高，不然就会切换角色。 advert_int 用于设定 MASTER 与 BACKUP 之间同步检查的时间间隔，单位为秒。 auth_type PASS 预共享密钥认证，同一个虚拟路由器的 keepalived 节点必须一样。 auth_pass 设置密钥。 virtual_ipaddress 设置虚拟 IP 地址，可以设置多种形式：10.0.0.100 不指定网卡，默认为 eth0, 注意：不指定 /prefix, 默认为 / 32；10.0.0.101/24 dev eth1 指定 VIP 的网卡；10.0.0.102/24 dev eth2 label eth2:1 #指定 VIP 的网卡 label。 nopreempt 设置为非抢占模式，同一实例下主备设置必须一样。 preemtp_delay 设置抢占模式的延时时间，单位为秒。 3.3、脚本相关配置 vrrp_script 自定义资源监控脚本，vrrp 实例根据脚本返回值进行下一步操作，脚本可被多个实例调用。 track_script 调用 vrrp_script 定义的脚本去监控资源，定义在实例之内，调用事先定义的 vrrp_script。实现主备切换，保证服务高可用。 vrrp_script 仅仅通过监控脚本返回的状态码来识别集群服务是否正常，如果返回状态码是 0，那么就认为服务正常，反之亦然。 notify_master 当前节点成为主节点时触发的脚本。 notify_backup 当前节点转为备节点时触发的脚本。 notify_fault 当前节点转为 “失败” 状态时触发的脚本。 notify_stop 当停止 VRRP 时触发的脚本。 四、Nginx+Keepalived 案例 4.1、Nginx 配置 使用 Nginx + Keepalived 实现一个 web 服务高可用方案。 架构图如下： 首先安装 Nginx：参照 Nginx 安装。 安装完 Nginx 之后接着配置 web 站点。 nginx1： [root@nginx1 ~]# vim /etc/nginx/conf.d/web.conf server { listen 8080; root /usr/share/nginx/html; index test.html; } [root@nginx1 ~]# echo " This is web1 " > /usr/share/nginx/html/test.html nginx2： #web2 [root@nginx2 ~]# vim /etc/nginx/conf.d/web.conf server { listen 8080; root /usr/share/nginx/html; index test.html; } [root@nginx2 ~]# echo " This is web2 " > /usr/share/nginx/html/test.html 接着启动 Nginx： ./nginx -t 和 ./nginx 4.2、Keepalived 配置 配置 Keepalived（不同角色有些选项不一样）。 web1:master： vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL vrrp_skip_check_adv_addr vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_script nginx_check { script "/tools/nginx_check.sh" interval 1 } vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 52 priority 100 mcast_src_ip 192.168.10.102 # 填写本机ip advert_int 1 authentication { auth_type PASS auth_pass test } virtual_ipaddress { 192.168.149.100 } track_script { nginx_check } notify_master /tools/master.sh notify_backup /tools/backup.sh notify_fault /tools/fault.sh notify_stop /tools/stop.sh } web2:slave： vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL vrrp_skip_check_adv_addr vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_script nginx_check { script "/tools/nginx_check.sh" interval 1 } vrrp_instance VI_1 { state BACKUP interface ens33 virtual_router_id 52 priority 99 mcast_src_ip 192.168.10.103 # 填写本机ip advert_int 1 authentication { auth_type PASS auth_pass test } virtual_ipaddress { 192.168.149.100 } track_script { nginx_check } notify_master /tools/master.sh notify_backup /tools/backup.sh notify_fault /tools/fault.sh notify_stop /tools/stop.sh } 将所有脚本放在同一个目录下，方便集中管理。 mkdir /tools 首先是编写 Keepalived 日志脚本 (将每次工作过程输出到日志上)。 vim master.sh #!/bin/bash ip=`hostname -I | awk '{print $1}'` dt=$(date +'%Y%m%d %H:%M:%S') echo "$0--${ip}--${dt}--master" >> /tmp/kp.log vim backup.sh #!/bin/bash ip=$(hostname -I | awk '{print $1}') dt=$(date +'%Y%m%d %H:%M:%S') echo "$0--${ip}--${dt}--backup" >> /tmp/kp.log vim fault.sh #!/bin/bash ip=$(ip addr|grep inet| grep 192.168 |awk '{print $2}') dt=$(date +'%Y%m%d %H:%M:%S') echo "$0--${ip}--${dt}--fault" >> /tmp/kp.log vim stop.sh #!/bin/bash ip=$(ip addr|grep inet| grep 192.168| awk '{print $2}') dt=$(date +'%Y%m%d %H:%M:%S') echo "$0--${ip}--${dt}--stop" >> /tmp/kp.log 编写健康检查脚本 nginx_check.sh。 该脚本对 Nginx 进程进行检测，如果发现 Nginx 进程没了则返回失败（1）。 cat nginx_check.sh #!/bin/bash result=`pidof nginx` if [ ! -z "${result}" ]; then exit 0 else exit 1 fi 添加执行权限，并启动 Keepalived。 cd /tools/ && chmod +x *.sh systemctl restart keepalived.service 五、Keepalived 常用命令 1、启动 keepalived sudo systemctl start keepalived 2、停止 keepalived sudo systemctl stop keepalived 3、重启 keepalived sudo systemctl restart keepalived 4、查看 keepalived 状态 sudo systemctl status keepalived 5、查看 keepalived 运行日志 sudo journalctl -u keepalived 6、设置 keepalived 开机自启 sudo systemctl enable keepalived 7、取消 keepalived 开机自启 sudo systemctl disable keepalived 8、检查 keepalived 配置文件语法（部分发行版支持） sudo keepalived -t -f /etc/keepalived/keepalived.conf 9、查看 keepalived 进程 ps -ef | grep keepalived 10、重新加载配置（有些系统支持 reload） sudo systemctl reload keepalived
一、nginx 之 tcp_nopush、tcp_nodelay、sendfile 1.1、TCP_NODELAY 你怎么可以强制 socket 在它的缓冲区里发送数据？ 一个解决方案是 TCP 堆栈的 tcp_nodelay 选项。这样就可以使缓冲区中的数据立即发送出去。 Nginx 的 tcp_nodelay 选项使得在打开一个新的 socket 时增加了 tcp_nodelay 选项。但这时会造成一种情况： 终端应用程序每产生一次操作就会发送一个包，而典型情况下一个包会拥有一个字节的数据以及 40 个字节长的包头，于是产生 4000% 的过载，很轻易地就能令网络发生拥塞。为了避免这种情况，TCP 堆栈实现了等待数据 0.2 秒钟，因此操作后它不会发送一个数据包，而是将这段时间内的数据打成一个大的包。这一机制是由 Nagle 算法保证。 Nagle 化后来成了一种标准并且立即在因特网上得以实现。它现在已经成为默认配置了，但有些场合下把这一选项关掉也是合乎需要的。现在假设某个应用程序发出了一个请求，希望发送小块数据。我们可以选择立即发送数据或者等待产生更多的数据然后再一次发送两种策略。 如果我们马上发送数据，那么交互性的以及客户 / 服务器型的应用程序将极大地受益。如果请求立即发出那么响应时间也会快一些。以上操作可以通过设置套接字的 TCP_NODELAY = on 选项来完成，这样就禁用了 Nagle 算法。（不需要等待 0.2s） 1.2、TCP_NOPUSH 在 nginx 中，tcp_nopush 配置和 tcp_nodelay “互斥”。它可以配置一次发送数据的包大小。也就是说，它不是按时间累计 0.2 秒后发送包，而是当包累计到一定大小后就发送。 注：在 nginx 中，tcp_nopush 必须和 sendfile 搭配使用。 1.3、sendfile 现在流行的 web 服务器里面都提供 sendfile 选项用来提高服务器性能，那到底 sendfile 是什么，怎么影响性能的呢？ sendfile 实际上是 Linux2.0 + 以后的推出的一个系统调用，web 服务器可以通过调整自身的配置来决定是否利用 sendfile 这个系统调用。先来看一下不用 sendfile 的传统网络传输过程： read (file,tmp_buf, len); write (socket,tmp_buf, len); 硬盘 >> kernel buffer >> user buffer>> kernel socket buffer >> 协议栈 一般来说一个网络应用是通过读硬盘数据，然后写数据到 socket 来完成网络传输的。上面 2 行用代码解释了这一点，不过上面 2 行简单的代码掩盖了底层的很多操作。来看看底层是怎么执行上面 2 行代码的： 系统调用 read () 产生一个上下文切换：从 user mode 切换到 kernel mode，然后 DMA 执行拷贝，把文件数据从硬盘读到一个 kernel buffer 里。 数据从 kernel buffer 拷贝到 user buffer，然后系统调用 read () 返回，这时又产生一个上下文切换：从 kernel mode 切换到 user mode。 系统调用 write () 产生一个上下文切换：从 user mode 切换到 kernel mode，然后把步骤 2 读到 user buffer 的数据拷贝到 kernel buffer（数据第 2 次拷贝到 kernel buffer），不过这次是个不同的 kernel buffer，这个 buffer 和 socket 相关联。 系统调用 write () 返回，产生一个上下文切换：从 kernel mode 切换到 user mode（第 4 次切换了），然后 DMA 从 kernel buffer 拷贝数据到协议栈（第 4 次拷贝了）。 上面 4 个步骤有 4 次上下文切换，有 4 次拷贝，我们发现如果能减少切换次数和拷贝次数将会有效提升性能。在 kernel2.0+ 版本中，系统调用 sendfile () 就是用来简化上面步骤提升性能的。sendfile () 不但能减少切换次数而且还能减少拷贝次数。 再来看一下用 sendfile () 来进行网络传输的过程： sendfile (socket,file, len); 硬盘 >> kernel buffer (快速拷贝到 kernelsocket buffer) >> 协议栈 系统调用 sendfile () 通过 DMA 把硬盘数据拷贝到 kernel buffer，然后数据被 kernel 直接拷贝到另外一个与 socket 相关的 kernel buffer。这里没有 user mode 和 kernel mode 之间的切换，在 kernel 中直接完成了从一个 buffer 到另一个 buffer 的拷贝。 DMA 把数据从 kernelbuffer 直接拷贝给协议栈，没有切换，也不需要数据从 user mode 拷贝到 kernel mode，因为数据就在 kernel 里。 步骤减少了，切换减少了，拷贝减少了，自然性能就提升了。这就是为什么说在 Nginx 配置文件里打开 sendfile on 选项能提高 web server 性能的原因。 综上，这三个参数都应该配置成 on：sendfile on; tcp_nopush on; tcp_nodelay on; 二、nginx 长连接--keepalive 当使用 nginx 作为反向代理时，为了支持长连接，需要做到两点： 从 client 到 nginx 的连接是长连接。 从 nginx 到 server 的连接是长连接。 2.1、保持和 client 的长连接 默认情况下，nginx 已经自动开启了对 client 连接的 keep alive 支持（同时 client 发送的 HTTP 请求要求 keep alive）。一般场景可以直接使用，但是对于一些比较特殊的场景，还是有必要调整个别参数（keepalive_timeout 和 keepalive_requests）。 http { keepalive_timeout 120s 120s; keepalive_requests 10000; } 2.1.1、keepalive_timeout 语法: keepalive_timeout timeout [header_timeout]; 第一个参数：设置 keep-alive 客户端连接在服务器端保持开启的超时值（默认 75s）；值为 0 会禁用 keep-alive 客户端连接； 第二个参数：可选、在响应的 header 域中设置一个值 “Keep-Alive: timeout=time”；通常可以不用设置； 注：keepalive_timeout 默认 75s，一般情况下也够用，对于一些请求比较大的内部服务器通讯的场景，适当加大为 120s 或者 300s； 2.1.2、keepalive_requests keepalive_requests 指令用于设置一个 keep-alive 连接上可以服务的请求的最大数量，当最大请求数量达到时，连接被关闭。默认是 100。这个参数的真实含义，是指一个 keep alive 建立之后，nginx 就会为这个连接设置一个计数器，记录这个 keep alive 的长连接上已经接收并处理的客户端请求的数量。如果达到这个参数设置的最大值时，则 nginx 会强行关闭这个长连接，逼迫客户端不得不重新建立新的长连接。 大多数情况下当 QPS (每秒请求数) 不是很高时，默认值 100 凑合够用。但是，对于一些 QPS 比较高（比如超过 10000QPS，甚至达到 30000,50000 甚至更高) 的场景，默认的 100 就显得太低。 简单计算一下，QPS=10000 时，客户端每秒发送 10000 个请求 (通常建立有多个长连接)，每个连接只能最多跑 100 次请求，意味着平均每秒钟就会有 100 个长连接因此被 nginx 关闭。同样意味着为了保持 QPS，客户端不得不每秒中重新新建 100 个连接。因此，就会发现有大量的 TIME_WAIT 的 socket 连接 (即使此时 keep alive 已经在 client 和 nginx 之间生效)。因此对于 QPS 较高的场景，非常有必要加大这个参数，以避免出现大量连接被生成再抛弃的情况，减少 TIME_WAIT。 2.2、保持和 server 的长连接 为了让 nginx 和后端 server（nginx 称为 upstream）之间保持长连接，典型设置如下：（默认 nginx 访问后端都是用的短连接 (HTTP1.0)，一个请求来了，Nginx 新开一个端口和后端建立连接，后端执行完毕后主动关闭该链接） http { upstream BACKEND { server 192.168.0.1：8080 weight=1 max_fails=2 fail_timeout=30s; server 192.168.0.2：8080 weight=1 max_fails=2 fail_timeout=30s; keepalive 300; // 这个很重要！ } server { listen 8080 default_server; server_name ""; location / { proxy_pass http://BACKEND; proxy_set_header Host $Host; proxy_set_header x-forwarded-for $remote_addr; proxy_set_header X-Real-IP $remote_addr; add_header Cache-Control no-store; add_header Pragma no-cache; proxy_http_version 1.1; // 这两个最好也设置 proxy_set_header Connection ""; } } } 2.2.1、location 中有两个参数需要设置： http { server { location / { proxy_http_version 1.1; // 这两个最好也设置 proxy_set_header Connection ""; } } } HTTP 协议中对长连接的支持是从 1.1 版本之后才有的，因此最好通过 proxy_http_version 指令设置为”1.1”； 而”Connection” header 应该被清理。清理从 client 过来的 http header，因为即使是 client 和 nginx 之间是短连接，nginx 和 upstream 之间也是可以开启长连接的。这种情况下必须清理来自 client 请求中的”Connection” header。 2.2.2、upstream 中的 keepalive 设置 此处 keepalive 的含义不是开启、关闭长连接的开关；也不是用来设置超时的 timeout；更不是设置长连接池最大连接数。官方解释： The connections parameter sets the maximum number of idle keepalive connections to upstream servers connections（设置到 upstream 服务器的空闲 keepalive 连接的最大数量） When this number is exceeded, the least recently used connections are closed. （当这个数量被突破时，最近使用最少的连接将被关闭） It should be particularly noted that the keepalive directive does not limit the total number of connections to upstream servers that an nginx worker process can open.（特别提醒：keepalive 指令不会限制一个 nginx worker 进程到 upstream 服务器连接的总数量） 先假设一个场景： 有一个 HTTP 服务，作为 upstream 服务器接收请求，响应时间为 100 毫秒。如果要达到 10000 QPS 的性能，就需要在 nginx 和 upstream 服务器之间建立大约 1000 条 HTTP 连接。nginx 为此建立连接池，然后请求过来时为每个请求分配一个连接，请求结束时回收连接放入连接池中，连接的状态也就更改为 idle。我们再假设这个 upstream 服务器的 keepalive 参数设置比较小，比如常见的 10。 A、假设请求和响应是均匀而平稳的，那么这 1000 条连接应该都是一放回连接池就立即被后续请求申请使用，线程池中的 idle 线程会非常的少，趋进于零，不会造成连接数量反复震荡。 B、显示中请求和响应不可能平稳，我们以 10 毫秒为一个单位，来看连接的情况 (注意场景是 1000 个线程 + 100 毫秒响应时间，每秒有 10000 个请求完成)，我们假设应答始终都是平稳的，只是请求不平稳，第一个 10 毫秒只有 50, 第二个 10 毫秒有 150： 1、下一个 10 毫秒，有 100 个连接结束请求回收连接到连接池，但是假设此时请求不均匀 10 毫秒内没有预计的 100 个请求进来，而是只有 50 个请求。注意此时连接池回收了 100 个连接又分配出去 50 个连接，因此连接池内有 50 个空闲连接。 2、然后注意看 keepalive=10 的设置，这意味着连接池中最多容许保留有 10 个空闲连接。因此 nginx 不得不将这 50 个空闲连接中的 40 个关闭，只留下 10 个。 3、再下一个 10 个毫秒，有 150 个请求进来，有 100 个请求结束任务释放连接。150 - 100 = 50, 空缺了 50 个连接，减掉前面连接池保留的 10 个空闲连接，nginx 不得不新建 40 个新连接来满足要求。 C、同样，如果假设相应不均衡也会出现上面的连接数波动情况。 造成连接数量反复震荡的一个推手，就是这个 keepalive 这个最大空闲连接数。毕竟连接池中的 1000 个连接在频繁利用时，出现短时间内多余 10 个空闲连接的概率实在太高。因此为了避免出现上面的连接震荡，必须考虑加大这个参数，比如上面的场景如果将 keepalive 设置为 100 或者 200, 就可以非常有效的缓冲请求和应答不均匀。 总结： keepalive 这个参数一定要小心设置，尤其对于 QPS 比较高的场景，推荐先做一下估算，根据 QPS 和平均响应时间大体能计算出需要的长连接的数量。比如前面 10000 QPS 和 100 毫秒响应时间就可以推算出需要的长连接数量大概是 1000. 然后将 keepalive 设置为这个长连接数量的 10% 到 30%。或者可以直接设置为 keepalive=1000 之类的，一般都 OK 的了。 2.3、综上，出现大量 TIME_WAIT 的情况 2.3.1、导致 nginx 端出现大量 TIME_WAIT 的情况有两种 keepalive_requests 设置比较小，高并发下超过此值后 nginx 会强制关闭和客户端保持的 keepalive 长连接；（主动关闭连接后导致 nginx 出现 TIME_WAIT）。 keepalive 设置的比较小（空闲数太小），导致高并发下 nginx 会频繁出现连接数震荡（超过该值会关闭连接），不停的关闭、开启和后端 server 保持的 keepalive 长连接。 2.3.2、导致后端 server 端出现大量 TIME_WAIT 的情况 nginx 没有打开和后端的长连接，即：没有设置 proxy_http_version 1.1; 和 proxy_set_header Connection “”; 从而导致后端 server 每次关闭连接，高并发下就会出现 server 端出现大量 TIME_WAIT。
一、Nginx 安装 1、从官网 nginx.org 下载对应的 nginx 包。 2、安装依赖环境。 # 安装 gcc 环境 yum install gcc-c++ # 安装 PCRE 库，用于解析正则表达式 yum install -y pcre pcre-devel # 安装 zlib 库压缩和解压缩依赖 yum install -y zlib zlib-devel # 安装 SSL 安全的加密的套接字协议层，用于 HTTP 安全传输，也就是 https yum install -y openssl openssl-devel 3、解压，需要注意，解压后得到的是源码，源码需要编译后才能安装。 tar -zxvf nginx-1.16.1.tar.gz 4、编译之前，先创建 nginx 临时目录，如果不创建，在启动 nginx 的过程中会报错。 mkdir /var/temp/nginx -p 5、在 nginx 目录，输入如下命令进行配置，目的是为了创建 makefile 文件。 ./configure --prefix=/usr/local/nginx --pid-path=/var/run/nginx/nginx.pid --lock-path=/var/lock/nginx.lock --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --with-http_gzip_static_module --http-client-body-temp-path=/var/temp/nginx/client --http-proxy-temp-path=/var/temp/nginx/proxy --http-fastcgi-temp-path=/var/temp/nginx/fastcgi --http-uwsgi-temp-path=/var/temp/nginx/uwsgi --http-scgi-temp-path=/var/temp/nginx/scgi 注：代表在命令行中换行，用于提高可读性配置命令： 6、make 编译 & 安装 make make install 7、进入 sbin 目录启动 nginx 启动：nginx ，停止：./nginx -s stop，重新加载：./nginx -s reload。 二、配置反向代理 2.1、配置 upstream upstream [proxyName] { server 192.168.1.173:8080; server 192.168.1.174:8080; server 192.168.1.175:8080; } 2.2、配置 server server { listem 80; server_name www.tomcats.com; location / { proxy_pass http://tomcats; } } 三、配置负载均衡 3.1、使用加权轮询 nginx 默认采用轮询的方式进行负载均衡。 upstream [proxyName] { server 192.168.1.173:8080 weight=1; server 192.168.1.174:8080 weight=5; server 192.168.1.175:8080 weight=2; } 3.2、hash 负载均衡 upstream [proxyName] { ip_hash server 192.168.1.173:8080; server 192.168.1.174:8080; server 192.168.1.175:8080; } 使用 ip_hash 的注意点：不能把后台服务器直接移除，只能标记 down。 3.3、url hash 负载均衡 upstream [proxyName] { hash $request_url; server 192.168.1.173:8080; server 192.168.1.174:8080; server 192.168.1.175:8080; } 3.4、最小连接负载均衡 upstream [proxyName] { least_conn; server 192.168.1.173:8080; server 192.168.1.174:8080; server 192.168.1.175:8080; } 四、upstream 指令参数 max_conns：限制最大同时连接数 1.11.5 之前只能用于商业版。 slow_start：单位秒，权重在指定时间内从 1 上升到指定值，不适用与 hash 负载均衡、随机负载均衡 如果在 upstream 中只有一台 server，则该参数失效（商业版才有）。 down：禁止访问。 backup：备用机 只有在其他服务器无法访问的时候才能访问到 不适用与 hash 负载均衡、随机负载均衡。 max_fails：表示失败几次，则标记 server 已宕机，剔出上游服务 默认值 1。 fail_timeout：表示失败的重试时间默认值 10。 4.1、keepalive 设置与后端服务器的长连接数 upstream [proxyName] { server 192.168.1.173:8080 weight=1; server 192.168.1.174:8080 weight=5; server 192.168.1.175:8080 weight=2; keepalive 32; #Nginx 与每台后端服务器之间最多保持 32 个空闲的长连接。 } server { listem 80; server_name www.tomcats.com; location / { proxy_pass http://tomcats; proxy_http_version 1.1; #连接的协议版本 proxy_set_header Connection ""; 清空连接请求头 } } 4.2、控制浏览器缓存 server { listem 80; server_name www.tomcats.com; location / { proxy_pass http://tomcats; expires 10s; #浏览器缓存 10 秒钟 #expires @22h30m #在晚上 10 点 30 的时候过期 #expires -1h #缓存在一小时前时效 #expires epoch #不设置缓存 #expires off #缓存关闭，浏览器自己控制缓存 #expires max #最大过期时间 } } 4.3、反向代理缓存 upstream [proxyName] { server 192.168.1.173:8080 weight=1; server 192.168.1.174:8080 weight=5; server 192.168.1.175:8080 weight=2; } #proxy_cache_path 设置缓存保存的目录的位置 #keys_zone 设置共享内以及占用的空间大小 #mas_size 设置缓存最大空间 #inactive 缓存过期时间，错过此时间自动清理 #use_temp_path 关闭零时目录 proxy_cache_path /usr/local/nginx/upsteam_cache keys_zone=mycache:5m max_size=1g inactive=8h use_temp_path=off; server { listem 80; server_name www.tomcats.com; #开启并使用缓存 proxy_cache mycache; #针对 200 和 304 响应码的缓存过期时间 proxy_cache_valid 200 304 8h; location / { proxy_pass http://tomcats; } } 五、配置 ssl 证书提供 https 访问 5.1、安装 SSL 模块 要在 nginx 中配置 https，就必须安装 ssl 模块，也就是: http_ssl_module。 进入到 nginx 的解压目录：/home/software/nginx-1.16.1。 新增 ssl 模块 (原来的那些模块需要保留) ./configure \ --prefix=/usr/local/nginx \ --pid-path=/var/run/nginx/nginx.pid \ --lock-path=/var/lock/nginx.lock \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --with-http_gzip_static_module \ --http-client-body-temp-path=/var/temp/nginx/client \ --http-proxy-temp-path=/var/temp/nginx/proxy \ --http-fastcgi-temp-path=/var/temp/nginx/fastcgi \ --http-uwsgi-temp-path=/var/temp/nginx/uwsgi \ --http-scgi-temp-path=/var/temp/nginx/scgi \ --with-http_ssl_module 编译和安装： make make install 5.2、配置 HTTPS 把 ssl 证书 *.crt 和 私钥 *.key 拷贝到 /usr/local/nginx/conf 目录中。 新增 server 监听 443 端口： server { listen 443; server_name www.imoocdsp.com; # 开启 ssl ssl on; # 配置 ssl 证书 ssl_certificate 1_www.imoocdsp.com_bundle.crt; # 配置证书秘钥 ssl_certificate_key 2_www.imoocdsp.com.key; # ssl 会话 cache ssl_session_cache shared:SSL:1m; # ssl 会话超时时间 ssl_session_timeout 5m; # 配置加密套件，写法遵循 openssl 标准 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; location / { proxy_pass http://tomcats/; index index.html index.htm; } } 六、配置 ha nginx 6.1、安装 keepalived 1、下载 keepalived download 2、解压：tar -zxvf keepalived-2.0.18.tar.gz 3、使用 configure 命令配置安装目录与核心配置文件所在位置： ./configure --prefix=/usr/local/keepalived --sysconf=/etc prefix：keepalived 安装的位置。 sysconf：keepalived 核心配置文件所在位置，固定位置，改成其他位置则 keepalived 启动不了，/var/log/messages 中会报错。 配置过程中可能会出现警告信息，如下所示： *** WARNING - this build will not support IPVS with IPv6. Please install libnl/libnl-3 dev libraries to support IPv6 with IPVS. # 安装 libnl/libnl-3 依赖 yum -y install libnl libnl-devel 4、安装 keepalived：make && make install 5、配置文件在：/etc/keepalived/keepalived.conf 6、忘记安装配置的目录，则通过如下命令找到：whereis keepalived 7、进入 sbin 目录，启动 keepalived：./keepalived 6.2、配置 keepalived 主机 1、通过命令 vim keepalived.conf 打开配置文件 global_defs { # 路由 id：当前安装 keepalived 的节点主机标识符，保证全局唯一 router_id keep_171 } vrrp_instance VI_1 { # 表示状态是 MASTER 主机还是备用机 BACKUP state MASTER # 该实例绑定的网卡 interface ens33 # 保证主备节点一致即可 virtual_router_id 51 mcast_src_ip 192.168.1.171 # 填写本机ip # 权重，master 权重一般高于 backup，如果有多个，那就是选举，谁的权重高，谁就当选 priority 100 # 主备之间同步检查时间间隔，单位秒 advert_int 2 # 认证权限密码，防止非法节点进入 authentication { auth_type PASS auth_pass 1111 } # 虚拟出来的 ip，可以有多个（vip） virtual_ipaddress { 192.168.1.161 } } 附：查看网卡信息命令：ip addr 2、启动 keepalived 3、查看进程：ps -ef|grep keepalived (4) 查看 vip (虚拟 ip) 在网卡 ens33 下，多了一个 192.168.1.161，这个就是虚拟 ip。 6.3、把 keepalived 注册为系统服务 1、拷贝配置文件 将 keepalived 目录下 etc/init.d/keepalived 拷贝到 /etc/init.d/ 下。 将 keepalived 目录下 etc/sysconfig/keepalived 拷贝到 /etc/sysconfig/ 下。 2、刷新 systemctl：systemctl daemon-reload 3、启动、停止、重启 keepalived # 启动 systemctl start keepalived.service # 停止 systemctl stop keepalived.service # 重启 systemctl restart keepalived.service 6.4、实现双机主备高可用 1、修改备机配置： global_defs { router_id keep_172 } vrrp_instance VI_1 { # 备用机设置为 BACKUP state BACKUP interface ens33 virtual_router_id 51 # 权重低于 MASTER priority 80 mcast_src_ip 192.168.1.171 # 填写本机ip advert_int 2 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { # 注意：主备两台的 vip 都是一样的，绑定到同一个 vip 192.168.1.161 } } 2、启动 Keepalived。 3、访问 vip 即可访问主机，当主机失效时访问 vip 就会访问到备机。 6.5、keepalived 配置 nginx 自动重启 1、编写脚本 在 /etc/keepalived/ 下创建脚本 check_nginx_alive_or_not.sh。 #!/bin/bash A=`ps -C nginx --no-header |wc -l` # 判断 nginx 是否宕机，如果宕机了，尝试重启 if [ $A -eq 0 ];then /usr/local/nginx/sbin/nginx # 等待一小会再次检查 nginx，如果没有启动成功，则停止 keepalived，使其启动备用机 sleep 3 if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then killall keepalived fi fi 2、添加运行权限：chmod +x /etc/keepalived/check_nginx_alive_or_not.sh。 3、配置 keepalived 监听 nginx 脚本。 vrrp_script check_nginx_alive { script "/etc/keepalived/check_nginx_alive_or_not.sh" interval 2 # 每隔两秒运行上一行脚本 weight 10 # 如果脚本运行失败，则升级权重 + 10 } 4、在 vrrp_instance 中新增监控的脚本： track_script { check_nginx_alive # 追踪 nginx 脚本 } 5、重启 Keepalived 使得配置文件生效 systemctl restart keepalived 6.6、keepalived 双主热备 1、配置 DNS 轮询：在同一个域名下配置两个 ip，自行百度。 2、配置第一台主机： global_defs { router_id keep_171 } vrrp_instance VI_1 { state MASTER i nterface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.161 } } vrrp_instance VI_2 { state BACKUP interface ens33 virtual_router_id 52 priority 80 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.162 } } 3、配置第二台主机： global_defs { router_id keep_172 } vrrp_instance VI_1 { state BACKUP interface ens33 virtual_router_id 51 priority 80 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.161 } } vrrp_instance VI_2 { state MASTER interface ens33 virtual_router_id 52 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.162 } } 4、重启两台 Keepalived： systemctl restart keepalived 七、LVS（Linux Virtual Server）实现高可用负载均衡 7.1、为什么要使用 LVS+Nginx LVS 基于四层负载均衡，工作效率较 Nginx 的七层负载更高，使用 LVS 搭建 Nginx 集群，可以提高性能。 四层负载均衡无法对信息处理，只能通过 ip + 端口的形式转发，所以需要七成负载进行数据的处理。 Nginx 接收请求来回，LVS 可以只接受不响应。 7.2、LVS 的三种模式 7.2.1、NAT 模式 客户端将请求发往 LVS，LVS 会选择一台服务器响应请求，服务器将结果返回给 LVS，LVS 再返回给客户端。 在 NAT 模式中，服务器的网关必须指向 LVS，否则报文无法送达客户端。 NAT 技术将请求的报文和响应的报文都需要通过 LVS 进行地址改写，因此网站访问量比较大的时候负载均衡调度器有比较大的瓶颈，一般要求最多之能 10-20 台节点。 NAT 模式支持对 IP 地址和端口进行转换。即用户请求的端口和真实服务器的端口可以不一致。 7.2.2、TUN 模式 客户端将请求发往 LVS，LVS 会选择一台服务器响应请求，在客户端与服务器之间建立隧道，返回结果的时候直接由服务器返回响应，不在经过 LVS。 TUN 模式必须所有的服务器上都绑定 VIP 的 IP 地址，所有的服务器都必须有网卡。 TUN 模式走隧道运维难度大，并且会直接暴露服务器地址 服务器将应答包直接发给用户。所以，减少了负载均衡器的大量数据流动，负载均衡器不再是系统的瓶颈，就能处理很巨大的请求量，这种方式，一台负载均衡器能够为很多服务器进行分发。而且跑在公网上就能进行不同地域的分发 7.2.3、DR 模式 客户端将请求发往 LVS，LVS 会选择一台服务器响应请求，返回结果的时候通过统一的路由进行返回，不在经过 LVS。 和 TUN 模式一样，LVS 只是分发请求，应答包通过单独的路由返回给客户端，与 TUN 相比这种方式不需要隧道结构，可以兼容大多数的操作系统，同时统一路由可以隐藏真实的物理服务器。DR 模式效率更高，但配置更复杂. 所有服务器节点和 LVS 只能在一个局域网里面。 7.3、搭建 LVS-DR 模式 先关闭掉服务器上网络配置管理器，避免网络接口冲突。 systemctl stop NetworkManager systemctl disable NetworkManager 7.3.1、创建子接口（创建 LVS 的虚拟 ip） 进入网卡配置目录 /etc/sysconfig/network-scripts/, 找到网卡配置文件，这里以 ifcfg-ens33 为例，拷贝并创建子接口。 cp ifcfg-ens33 ifcfg-ens33:1 修改子接口配置如下： 配置中的 192.168.1.150 就是 vip，是提供给外网用户访问的 ip 地址。 DEVICE="ens33:1" ONBOOT="yes" IPADDR=192.168.1.150 NETMASK=255.255.255.0 BOOTPROTO=static 重启网络服务：service network restart 重启成功后，ip addr 查看一下，你会发现多了一个 ip，也就是虚拟 ip（vip）。 注意：阿里云不支持配置网卡，需要购买相应的负载均衡服务，腾讯云支持配置网卡，但需要购买网卡支持，一个网卡支持 10 个虚拟 ip 配置。 7.3.2、安装 ipvsadm 如今的 centos 都集成了 LVS，所以 ipvs 是自带的，我们只需要安装 ipvsadm 即可（ipvsadm 是管理集群的工具，通过 ipvs 可以管理集群，查看集群等操作）。 yum install ipvsadm 7.3.3、配置服务器（RS）的虚拟 ip 进入网卡配置目录 /etc/sysconfig/network-scripts/, 找到 ifcfg-lo，拷贝并创建子接口。 cp ifcfg-lo ifcfg-lo:1 修改子接口配置如下： DEVICE="lo:1" IPADDR=192.168.1.150 NETMASK=255.255.255.255 NETWORK=127.0.0.0 BROADCAST=127.255.255.255 ONBOOT="yes" NAME=loopback 重启网络服务成功后，ip addr 查看一下，你会发现多了一个 ip，也就是虚拟 ip（vip）。 7.3.4、为服务器（RS）配置 arp ARP 响应级别与通告行为参数说明： arp-ignore：ARP 响应级别（处理请求） 0：只要本机配置了 ip，就能响应请求 1：请求的目标地址到达对应的网络接口，才会响应请求 arp-announce：ARP 通告行为（返回响应） 0：本机上任何网络接口都向外通告，所有的网卡都能接受到通告 1：尽可能避免本网卡与不匹配的目标进行通告 2：只在本网卡通告 打开 sysctl.conf:vim /etc/sysctl.conf 配置所有网卡、默认网卡以及虚拟网卡的 arp 响应级别和通告行为，分别对应：all，default，lo。 # configration for lvs net.ipv4.conf.all.arp_ignore = 1 net.ipv4.conf.default.arp_ignore = 1 net.ipv4.conf.lo.arp_ignore = 1 net.ipv4.conf.all.arp_announce = 2 net.ipv4.conf.default.arp_announce = 2 net.ipv4.conf.lo.arp_announce = 2 刷新配置文件：sysctl -p 增加一个网关，用于接收数据报文，当有请求到本机后，会交给 lo 去处理： route add -host 192.168.1.150 dev lo:1 将网关添加至开机启动： echo "route add -host 192.168.1.150 dev lo:1" >> /etc/rc.local 7.3.5、使用 ipvsadm 配置集群规则 创建 LVS 节点，用户访问的集群调度者： ipvsadm -A -t 192.168.1.150:80 -s rr -p 5 其中： -A：添加集群 -t：tcp 协议 ip 地址：设定集群的访问 ip：也就是 LVS 的虚拟 ip -s：设置负载均衡的算法， rr：表示轮询 -p：设置连接持久化的时间，在指定时间内同一个用户的请求会访问到同一个服务器中 创建多台 RS 真实服务器： ipvsadm -a -t 192.168.1.150:80 -r 192.168.1.171:80 -g ipvsadm -a -t 192.168.1.150:80 -r 192.168.1.172:80 -g 其中： -a：添加真实服务器 -t：tcp 协议 -r：真实服务器的 ip 地址 -g：设定 DR 模式 检查集群： # 查看集群列表 ipvsadm -Ln # 查看集群状态 ipvsadm -Ln --stats 一些其他命令： # 重启 ipvsadm，重启后需要重新配置 service ipvsadm restart # 查看持久化连接 ipvsadm -Ln --persistent-conn # 查看连接请求过期时间以及请求源 ip 和目标 ip ipvsadm -Lnc # 设置 tcp tcpfin udp 的过期时间（一般保持默认） ipvsadm --set 1 1 1 # 查看过期时间 ipvsadm -Ln --timeout 访问虚拟 ip，完成 LVS 搭建。 7.4、LVS 的负载均衡算法 7.4.1、静态算法 静态：根据 LVS 本身自由的固定的算法分发用户请求。 轮询（Round Robin 简写’rr’）：轮询算法假设所有的服务器处理请求的能力都一样的，调度器会把所有的请求平均分配给每个真实服务器。（同 Nginx 的轮询） 加权轮询（Weight Round Robin 简写’wrr’）：安装权重比例分配用户请求。权重越高，被分配到处理的请求越多。（同 Nginx 的权重） 源地址散列（Source Hash 简写’sh’）：同一个用户 ip 的请求，会由同一个 RS 来处理。（同 Nginx 的 ip_hash） 目标地址散列（Destination Hash 简写’dh’）：根据 url 的不同，请求到不同的 RS。（同 Nginx 的 url_hash） 7.4.2、动态算法 动态：会根据流量的不同，或者服务器的压力不同来分配用户请求，这是动态计算的。 最小连接数（Least Connections 简写’lc’）：把新的连接请求分配到当前连接数最小的服务器。 加权最少连接数（Weight Least Connections 简写’wlc’）：服务器的处理性能用数值来代表，权重越大处理的请求越多。Real Server 有可能会存在性能上的差异，wlc 动态获取不同服务器的负载状况，把请求分发到性能好并且比较空闲的服务器。 最短期望延迟（Shortest Expected Delay 简写’sed’）：特殊的 wlc 算法。举例阐述，假设有 ABC 三台服务器，权重分别为 1、2、3 。如果使用 wlc 算法的话，当一个新请求进来，它可能会分给 ABC 中的任意一个。使用 sed 算法后会进行如下运算： A：（1+1）/1=2 B：（1+2）/2=3/2 C：（1+3）/3=4/3 最终结果，会把这个请求交给得出运算结果最小的服务器。最少队列调度（Never Queue 简写’nq’）：永不使用队列。如果有 Real Server 的连接数等于 0，则直接把这个请求分配过去，不需要在排队等待运算了（sed 运算）。 八、搭建 Keepalived+Lvs+Nginx 高可用集群负载均衡 如果原先服务器上配置了 LVS+nginx 需要清空 ipvsadm 中的配置： ipvsadm -C 如果配置了 Keepalived+Nginx 双主集群也需要去除掉 Keepalived 中原先的配置，按照的后文进行配置。 8.1、使用 keepalived 配置 Master LVS 在 LVS 的机器上安装 keepalived，安装过程参考上文。 (1) 修改 keepalived 的配置 global_defs { router_id keep_151 } vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 41 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.150 } } # 配置集群访问的 ip + 端口，端口和 nginx 保持一致 virtual_server 192.168.1.150 80 { #健康检查的时间，单位：秒 delay_loop 6 #配置负载均衡的算法，默认的轮询 lb_algo rr #设置 LVS 的模式 NAT|TUN|DR lb-kind DR #设置会话持久化的时间 persistence_timeout 5 #协议 protocol TCP #配置负载均衡的真实服务器，也就是 nginx 节点的具体的 ip 地址 real_server 192.168.1.171 80 { #轮询权重配比 weight 1 #设置健康检查 TCP_CHECK { #检查 80 端口 connect_port 80 #超时时间 connect_timeout 2 #重试次数 nb_get_retry 2 #重试间隔时间 delay_before_retry 3 } } real_server 192.168.1.171 80 { weight 1 TCP_CHECK { connect_port 80 connect_timeout 2 nb_get_retry 2 delay_before_retry 3 } } } (2) 启动 / 重启 keepalived systemctl restart keepalived 8.2、使用 keepalived 配置 Backup LVS 配置在备用机上： global_defs { router_id keep_152 } vrrp_instance VI_1 { state BACKUP interface ens33 virtual_router_id 41 priority 50 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.150 } } # 配置集群访问的 ip + 端口，端口和 nginx 保持一致 virtual_server 192.168.1.150 80 { #健康检查的时间，单位：秒 delay_loop 6 #配置负载均衡的算法，默认的轮询 lb_algo rr #设置 LVS 的模式 NAT|TUN|DR lb-kind DR #设置会话持久化的时间 persistence_timeout 5 #协议 protocol TCP #配置负载均衡的真实服务器，也就是 nginx 节点的具体的 ip 地址 real_server 192.168.1.171 80 { #轮询权重配比 weight 1 #设置健康检查 TCP_CHECK { #检查 80 端口 connect_port 80 #超时时间 connect_timeout 2 #重试次数 nb_get_retry 2 #重试间隔时间 delay_before_retry 3 } } real_server 192.168.1.171 80 { weight 1 TCP_CHECK { connect_port 80 connect_timeout 2 nb_get_retry 2 delay_before_retry 3 } } }
配置示例 #定义Nginx运行的用户和用户组 user www www; #nginx进程数，建议设置为等于CPU总核心数。 worker_processes 8; #全局错误日志定义类型，[ debug | info | notice | warn | error | crit ] error_log /var/log/nginx/error.log info; #进程文件 pid /var/run/nginx.pid; #一个nginx进程打开的最多文件描述符数目，理论值应该是最多打开文件数（系统的值ulimit -n）与nginx进程数相除，但是nginx分配请求并不均匀，所以建议与ulimit -n的值保持一致。 worker_rlimit_nofile 65535; #工作模式与连接数上限 events { #参考事件模型，use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型，如果跑在FreeBSD上面，就用kqueue模型。 use epoll; #单个进程最大连接数（最大连接数=连接数*进程数） worker_connections 65535; } #设定http服务器 http { include mime.types; #文件扩展名与文件类型映射表 default_type application/octet-stream; #默认文件类型 #charset utf-8; #默认编码 server_names_hash_bucket_size 128; #服务器名字的hash表大小 client_header_buffer_size 32k; #上传文件大小限制 large_client_header_buffers 4 64k; #设定请求缓 client_max_body_size 8m; #设定请求缓 sendfile on; #开启高效文件传输模式，sendfile指令指定nginx是否调用sendfile函数来输出文件，对于普通应用设为 on，如果用来进行下载等应用磁盘IO重负载应用，可设置为off，以平衡磁盘与网络I/O处理速度，降低系统的负载。注意：如果图片显示不正常把这个改成off。 autoindex on; #开启目录列表访问，合适下载服务器，默认关闭。 tcp_nopush on; #防止网络阻塞 tcp_nodelay on; #防止网络阻塞 keepalive_timeout 120; #长连接超时时间，单位是秒 #FastCGI相关参数是为了改善网站的性能：减少资源占用，提高访问速度。下面参数看字面意思都能理解。 fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 128k; #gzip模块设置 gzip on; #开启gzip压缩输出 gzip_min_length 1k; #最小压缩文件大小 gzip_buffers 4 16k; #压缩缓冲区 gzip_http_version 1.0; #压缩版本（默认1.1，前端如果是squid2.5请使用1.0）开始压缩的http协议版本(可以不设置,目前几乎全是1.1协议) gzip_comp_level 2; #推荐6压缩级别(级别越高,压的越小,越浪费CPU计算资源) gzip_types text/plain application/x-javascript text/css application/xml; #压缩类型，默认就已经包含text/html，所以下面就不用再写了，写上去也不会有问题，但是会有一个warn。 gzip_vary on; # 是否传输gzip压缩标志 #limit_zone crawler $binary_remote_addr 10m; #开启限制IP连接数的时候需要使用 upstream blog.ha97.com { #upstream的负载均衡，weight是权重，可以根据机器配置定义权重。weigth参数表示权值，权值越高被分配到的几率越大。 server 192.168.80.121:80 weight=3; server 192.168.80.122:80 weight=2; server 192.168.80.123:80 weight=3; } #虚拟主机的配置 server { #监听端口 listen 80; #域名可以有多个，用空格隔开 server_name www.ha97.com ha97.com; index index.html index.htm index.php; root /data/www/ha97; location ~ .*\.(php|php5)?$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; } #图片缓存时间设置 location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 10d; } #JS和CSS缓存时间设置 location ~ .*\.(js|css)?$ { expires 1h; } #日志格式设定 log_format access '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" $http_x_forwarded_for'; #定义本虚拟主机的访问日志 access_log /var/log/nginx/ha97access.log access; #对 "/" 启用反向代理 location / { proxy_pass http://127.0.0.1:88; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #以下是一些反向代理的配置，可选。 proxy_set_header Host $host; client_max_body_size 10m; #允许客户端请求的最大单文件字节数 client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数， proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时) proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时) proxy_read_timeout 90; #连接成功后，后端服务器响应时间(代理接收超时) proxy_buffer_size 4k; #设置代理服务器（nginx）保存用户头信息的缓冲区大小 proxy_buffers 4 32k; #proxy_buffers缓冲区，网页平均在32k以下的设置 proxy_busy_buffers_size 64k; #高负荷下缓冲大小（proxy_buffers*2） proxy_temp_file_write_size 64k; #设定缓存文件夹大小，大于这个值，将从upstream服务器传 } #设定查看Nginx状态的地址 location /NginxStatus { stub_status on; access_log on; auth_basic "NginxStatus"; auth_basic_user_file conf/htpasswd; #htpasswd文件的内容可以用apache提供的htpasswd工具来产生。 } #本地动静分离反向代理配置 #所有jsp的页面均交由tomcat或resin处理 location ~ .(jsp|jspx|do)?$ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:8080; } #所有静态文件由nginx直接读取不经过tomcat或resin location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$ { expires 15d; } location ~ .*.(js|css)?$ { expires 1h; } } }
一、目录结构 # tree nginx/ nginx/ ├── client_body_temp ├── conf │ ├── fastcgi.conf │ ├── fastcgi.conf.default │ ├── fastcgi_params │ ├── fastcgi_params.default │ ├── include │ │ ├── xxx.conf │ ├── koi-utf │ ├── koi-win │ ├── mime.types │ ├── mime.types.default │ ├── nginx.conf │ ├── nginx.conf.default │ ├── scgi_params │ ├── scgi_params.default │ ├── uwsgi_params │ ├── uwsgi_params.default │ └── win-utf ├── fastcgi_temp ├── html │ ├── 50x.html │ └── index.html ├── logs │ ├── access.log │ ├── error.log │ └── nginx.pid ├── proxy_temp ├── sbin │ └── nginx ├── scgi_temp └── uwsgi_temp 其中这几个文件夹client_body_temp、fastcgi_temp、proxy_temp、scgi_temp在刚安装后是没有的，主要用来存放运行过程中的临时文件。 conf：用来存放配置文件相关。 html：用来存放静态文件的默认目录 html、css 等。 sbin：nginx 的主程序。 Nginx 依赖于 3 个库：PCRE，zlib 和 OpenSSL： 如果通过操作系统的包管理器安装 Nginx (例如，在 Ubuntu/Debian 上使用 apt，在 CentOS/RHEL 上使用 yum 或 dnf)，那么这些依赖库通常会作为 Nginx 包的依赖项自动安装。 如果选择从源代码编译安装 Nginx，那么就需要手动下载并编译 PCRE、zlib 和 OpenSSL 的源代码。 # PCRE version 4.4 - 8.40 wget https://ftp.pcre.org/pub/pcre/pcre-8.40.tar.gz && tar xzvf pcre-8.40.tar.gz # zlib version 1.1.3 - 1.2.11 wget http://www.zlib.net/zlib-1.2.11.tar.gz && tar xzvf zlib-1.2.11.tar.gz # OpenSSL version 1.0.2 - 1.1.0 wget https://www.openssl.org/source/openssl-1.1.0f.tar.gz && tar xzvf openssl-1.1.0f.tar.gz 安装 tree 命令： yum update yum install -y tree 二、基本运行原理 2.1、基本配置 最小配置： worker_processes 1; // 默认为1，表示开启一个业务进程，启动多少work进程，对应服务器物理cpu的内核数。 events { //事件驱动模块 worker_connections 1024; // 表示单个业务进程可接受的连接数 } http { include mime.types; // 把其他配置引入到当前配置当中。引入http mime 类型，服务器端（nginx）发给客户端，告诉客户端是什么格式的东西（http协议头中） default_type application/octet-stream; // 如果mime类型没有匹配上，默认使用二进制流的方式传输 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; } } } 未开启 sendfile： 开启 sendfile： server： 2.2、servername 匹配规则 需要注意的是 servername 匹配分先后顺序，写在前面的匹配上就不会继续往下匹配了。 2.2.1、完整匹配 可以在同一 servername 中匹配多个域名 server_name vod.mmban.com www1.mmban.com; 2.2.2、通配符匹配 server_name *.mmban.com 2.2.3、通配符结束匹配 server_name vod.*; 2.2.4、正则匹配 server_name ~^[0-9]+\.mmban\.com$; 三、反向代理 proxy_pass http://baidu.com; location / { proxy_pass http://atguigu.com/; --> 转发到目标主机 } 四、基于反向代理的负载均衡 upstream httpd { server 192.168.44.102:80; server 192.168.43.103:80; } 4.1、负载均衡策略 4.1.1、轮询 默认情况下使用轮询方式，逐一转发，这种方式适用于无状态请求。 4.1.2、weight (权重) 指定轮询几率，weight 和访问比率成正比，用于后端服务器性能不均的情况。 upstream httpd { server 127.0.0.1:8050 weight=10 down; server 127.0.0.1:8060 weight=1; server 127.0.0.1:8060 weight=1 backup; } down：表示当前的 server 暂时不参与负载 weight：默认为 1. weight 越大，负载的权重就越大。 backup： 其它所有的非 backup 机器 down 或者忙的时候，请求 backup 机器。 4.1.3、ip_hash 根据客户端的 ip 地址转发同一台服务器，可以保持回话。 4.1.4、least_conn 少连接访问。 4.1.5、url_hash 根据用户访问的 url 定向转发请求。 4.1.2、fair 根据后端服务器响应时间转发请求。 4.2、动静分离 配置反向代理： location / { proxy_pass http://127.0.0.1:8080; root html; index index.html index.htm; } 增加每一个 location： location /css { root /usr/local/nginx/static; index index.html index.htm; } location /images { root /usr/local/nginx/static; index index.html index.htm; } location /js { root /usr/local/nginx/static; index index.html index.htm; } 使用正则，location 前缀 / 通用匹配，任何请求都会匹配到。 = 精准匹配，不是以指定模式开头。 ~ 正则匹配，区分大小写。 ~* 正则匹配，不区分大小写。 ^~ 非正则匹配，匹配以指定模式开头的 location。 location 匹配顺序 多个正则 location 直接按书写顺序匹配，成功后就不会继续往后面匹配。 普通（非正则）location 会一直往下，直到找到匹配度高的（大前缀匹配）。 当普通 location 与正则 location。同时存在，如果正则匹配成功，则不会再执行普通匹配。 所有类型 location 存在时，= 匹配 > ^~ 匹配 > 正则匹配 > 普通（大前缀匹配）。 location ~*/(css|img|js) { root /usr/local/nginx/static; index index.html index.htm; } root 用来设置根目录，而 alias 在接受请求的时候在路径上不会加上 location。 1、alias 指定的目录是准确的，即 location 匹配访问的 path 目录下的文件直接是在 alias 目录下查找的； 2、root 指定 的目录是 location 匹配访问的 path 目录的上一级目录，这个 path 目录一定要是真实存在 root 指定目录下的； 3、使用 alias 标签的目录块中不能使用 rewrite 的 break（具体原因不明）；另外，alias 指定的目录后面必须要加上 "/" 符号！！ 4、alias 虚拟目录配置中，location 匹配的 path 目录如果后面不带 "/"，那么访问的 url 地址中这个 path 目录后 面加不加 "/" 不影响访问，访问时它会自动加上 "/"； 但是如果 location 匹配的 path 目录后面加上 "/"，那么访问的 url 地址中这个 path 目录必须要加上 "/"，访问时它不会自动加上 "/"。如果不加上 "/"，访问就会失败！ 5、root 目录配置 中，location 匹配的 path 目录后面带不带 "/"，都不会影响访问。 4.3、UrlRewrite 4.3.1、rewrite 语法格式及参数语法： rewrite 是实现 URL 重写的关键指令，根据 regex (正则表达式) 部分内容， 重定向到 replacement，结尾是 flag 标记。 rewrite <regex> <replacement> [flag]; 关键字 正则 替代内容 flag 标记 关键字：其中关键字 rewrite 不能改变。rewrite 参数的标签段位置：server,location,if 正则：perl 兼容正则表达式语句进行规则匹配。 替代内容：将正则匹配的内容替换成 replacement。 flag 标记：rewrite 支持的 flag 标记。 flag 标记说明： last：本条规则匹配完成后，继续向下匹配新的 location URI 规则。 break：本条规则匹配完成即终止，不再匹配后面的任何规则。 redirect：返回 302 临时重定向，浏览器地址会显示跳转后的 URL 地址。 permanent：返回 301 永久重定向，浏览器地址栏会显示跳转后的 URL 地址。 实例： rewrite ^/([0-9]+).html$ /index.jsp?pageNum=$1 break; 4.3.2、同时使用负载均衡 应用服务器防火墙配置： 开启防火墙：systemctl start firewalld 重启防火墙：systemctl restart firewalld 重载规则：firewall-cmd --reload 查看已配置规则：firewall-cmd --list-all 指定端口和 ip 访问： firewall-cmd --permanent --add-rich-rule="rule family="ipv4"source address="192.168.44.101"port protocol="tcp"port="8080"accept" 移除规则： firewall-cmd --permanent --remove-rich-rule="rule family="ipv4"source address="192.168.44.101"port port="8080"protocol="tcp"accept" 网关配置： upstream httpds { server 192.168.44.102 weight=8 down; server 192.168.44.103:8080 weight=2; server 192.168.44.104:8080 weight=1 backup; } location / { rewrite ^/([0-9]+).html$ /index.jsp?pageNum=$1 redirect; proxy_pass http://httpds ; } 4.4、防盗链配置 valid_referers none | blocked | server_names | strings ....; none：检测 Referer 头域不存在的情况。 blocked：检测 Referer 头域的值被防火墙或者代理服务器删除或伪装的情况。这种情况该头域的值不以 http:// 或 https:// 开头。 server_names：设置一个或多个 URL ，检测 Referer 头域的值是否是这些 URL 中的某一个。 在需要防盗链的 location 中配置： valid_referers 192.168.44.101; if ($invalid_referer) { return 403; } 使用 curl 测试： curl -I http://192.168.44.101/img/logo.png 带引用： curl -e "http://baidu.com" -I http://192.168.44.101/img/logo.png 五、高可用配置 5.1、安装 Keepalived 1、编译安装 下载地址：keepalived 下载 使用 ./configure 编译安装 如遇报错提示： configure: error: !!! OpenSSL is not properly installed on your system. !!! !!! Can not include OpenSSL headers files. !!! 安装依赖： yum install openssl-devel yum 安装： yum install keepalived 2、配置 使用 yum 安装后配置文件在 /etc/keepalived/keepalived.conf 3、最小配置 第一台机器： ! Configuration File for keepalived global_defs { router_id lb111 } vrrp_instance atguigu { state MASTER interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.44.200 } } 第二台机器： ! Configuration File for keepalived global_defs { router_id lb110 } vrrp_instance atguigu { state BACKUP interface ens33 virtual_router_id 51 priority 50 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.44.200 } } 启动服务： systemctl start keepalived 六、Https 证书配置 6.1、不安全的 http 协议 6.2、腾讯云申请免费 SSL 证书 https://console.cloud.tencent.com/ssl 下载证书： 解压缩，存在如下文件: wordplay.work.csr wordplay.work.key wordplay.work_bundle.crt wordplay.work_bundle.pem 6.3、SSL 证书 6.3.1、wordplay.work.csr (Certificate Signing Request - 证书签名请求) 作用：这是一个证书签名请求文件。当你需要从证书颁发机构 (CA) 获取 SSL 证书时，你首先需要在你的服务器上生成一个 CSR 文件。 内容：它包含了你的公钥以及你希望包含在证书中的信息，例如： 通用名称 (Common Name - CN): 你的域名（例如 wordplay.work）。 组织 (Organization - O): 你的公司或组织的法定名称。 城市/地区 (Locality - L)、省/州 (State - S)、国家 (Country - C): 你组织所在的地理位置。 电子邮件地址 (Email Address): 用于联系的邮箱。 特点：CSR 文件本身并不是证书，它只是向 CA 申请证书的“申请表”。你将此文件提交给 CA，CA 会使用你的公钥和这些信息来签发你的 SSL 证书。 6.3.2、wordplay.work.key (Private Key - 私钥) 作用：这是与你的 SSL 证书配对的私钥文件。私钥和公钥是非对称加密的关键组成部分。 内容：包含一个长串的加密数据，只有你的服务器拥有。 特点： 保密性：私钥是绝对不能泄露的。如果私钥泄露，你的 SSL 证书将不再安全，恶意用户可以解密你的加密通信。 解密：服务器使用私钥来解密由客户端使用相应公钥加密的数据（例如客户端发送的 HTTPS 请求）。 签名：服务器也使用私钥对数据进行数字签名，以证明其身份。 生成：私钥通常在生成 CSR 文件时同时生成。 6.3.3、wordplay.work_bundle.crt (Certificate - 证书) 作用：这是一个SSL/TLS 证书文件，由证书颁发机构 (CA) 签发。 内容： 你的公钥。 你的域名和其他身份信息。 CA 的数字签名，用于验证证书的真实性和未被篡改。 证书的有效期。 其他扩展信息。 特点： 信任：浏览器或客户端通过验证这个证书（检查 CA 签名）来确认你的网站是可信的。 加密：客户端使用证书中的公钥来加密与服务器的通信数据。 链式信任：_bundle.crt 通常表示这是一个证书链文件，可能包含了你的服务器证书以及一个或多个中间 CA 证书。这些中间证书是必要的，因为它们将你的服务器证书链接到受浏览器信任的根 CA 证书，从而形成一个完整的信任链。 6.3.4、wordplay.work_bundle.pem (PEM Encoded File - PEM 编码文件) 作用：PEM (Privacy-Enhanced Mail) 是一种非常常见的文件格式或编码方式，用于存储加密数据，包括 SSL 证书、私钥、CSR 等。它是一种 Base64 编码的文本文件，这意味着你可以用文本编辑器打开它，看到“-----BEGIN xxx-----”和“-----END xxx-----”这样的标记。 内容： 在这个例子中，wordplay.work_bundle.pem 很可能是一个组合文件，将 wordplay.work.crt (服务器证书和中间证书链) 和 wordplay.work.key (私钥) 合并到同一个文件中。 它可能包含一个或多个-----BEGIN CERTIFICATE-----和-----END CERTIFICATE-----块，以及一个-----BEGIN RSA PRIVATE KEY-----（或类似的）和-----END RSA PRIVATE KEY-----块。 特点： 灵活性：PEM 格式非常灵活，可以包含不同类型的数据。 兼容性：许多服务器软件（如 Apache）和工具都支持 PEM 格式，因为它易于处理。 打包：将证书链和私钥打包到一个 .pem 文件中，简化了某些服务器的配置过程。 6.3.5、总结： 首先生成一个私钥 (.key) 和一个证书签名请求 (.csr)。 你将 .csr 文件提交给证书颁发机构 (CA)。 CA 使用你的 .csr 中的公钥和信息，并用自己的私钥对你的证书进行签名，然后将签发的证书（通常是 .crt 或 .cer 格式，可能还包含中间证书）返回给你。 在你的服务器上，你需要将获得的证书 (.crt 或其中的服务器证书部分) 和你最初生成的私钥 (.key) 配对使用，才能启用 HTTPS。 有时，为了方便管理或兼容性，你会将证书链 (.crt 的内容) 和私钥 (.key 的内容) 合并到一个 .pem 文件中进行配置。 6.4、配置示例 server { listen 80; server_name wordplay.work; rewrite ^(.*)$ https://$host$1 permanent; } server { listen 443 ssl; server_name wordplay.work; server_tokens off; keepalive_timeout 5; # 添加以下两行以指定 SSL 证书位置 ssl_certificate /path/to/wordplay.work_bundle.pem; ssl_certificate_key /path/to/wordplay.work.key; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; root /usr/local/lighthouse/softwares/typecho; index index.php index.html; access_log logs/typecho.log combinediox; error_log logs/typecho.error.log; if (!-e $request_filename) { rewrite ^(.*)$ /index.php$1 last; } location ~ .*\.php(\/.*)*$ { include fastcgi.conf; fastcgi_pass 127.0.0.1:9000; } } 6.5、Nginx 中配置 SSL/TLS 所需文件 私钥文件 (.key): wordplay.work.key 文件。这个文件包含服务器的私钥，Nginx 需要它来解密传入的加密流量。务必保护好这个文件的安全，因为它绝不能泄露。 证书文件 (.crt 或 .pem): wordplay.work_bundle.crt 或 wordplay.work_bundle.pem 文件。 wordplay.work_bundle.crt 应该包含你的服务器证书以及所有中间 CA 证书。这是一个完整的证书链，浏览器需要它来验证你的服务器证书的可信性。 如果 wordplay.work_bundle.pem 是一个合并文件，既包含证书链又包含私钥，那么你也可以直接使用它。不过，通常建议将私钥和证书文件分开，以提高安全性和清晰度。 需要在 Nginx 的 server 块中配置 SSL/TLS。下面是一个典型的配置示例： server { listen 80; # 监听 HTTP 请求，用于自动重定向到 HTTPS server_name wordplay.work www.wordplay.work; # 将所有 HTTP 请求重定向到 HTTPS return 301 https://$host$request_uri; } server { listen 443 ssl http2; # 监听 HTTPS 请求，启用 HTTP/2 server_name wordplay.work www.wordplay.work; # SSL/TLS 证书路径 ssl_certificate /etc/nginx/ssl/wordplay.work_bundle.crt; # 指向你的证书链文件 ssl_certificate_key /etc/nginx/ssl/wordplay.work.key; # 指向你的私钥文件 # 以下是推荐的 SSL/TLS 安全配置，可以根据需要进行调整： # 启用强大的加密协议，禁用不安全的版本 ssl_protocols TLSv1.2 TLSv1.3; # 优先使用服务器的密码套件顺序 ssl_prefer_server_ciphers on; # 定义安全的密码套件 ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384'; # 启用 Strict-Transport-Security (HSTS) 头，强制浏览器在指定时间内只通过 HTTPS 访问 add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"; # 启用 OCSP Stapling (可选，但推荐用于提高性能和安全性) ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/nginx/ssl/wordplay.work_bundle.crt; # 通常与 ssl_certificate 指向同一个文件 resolver 8.8.8.8 8.8.4.4 valid=300s; # 配置 DNS 解析器，用于 OCSP 查询 resolver_timeout 5s; # SSL 会话缓存，提高性能 ssl_session_cache shared:SSL:10m; ssl_session_timeout 1h; # gzip 配置 (如果需要) # gzip on; # gzip_proxied any; # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; # 你的网站根目录和索引文件 root /var/www/wordplay.work; # 根据你的实际路径修改 index index.html index.htm; location / { try_files $uri $uri/ =404; } # 其他可能的 location 块，例如 PHP-FPM 配置等 # location ~ \.php$ { # include snippets/fastcgi-php.conf; # fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # } } 七、Windows 环境 E:\SOFTWARE\nginx-1.20.2>nginx.exe -h nginx version: nginx/1.20.2 Usage: nginx [-?hvVtTq] [-s signal] [-p prefix] [-e filename] [-c filename] [-g directives] Options: -?,-h : this help -v : show version and exit -V : show version and configure options then exit -t : test configuration and exit -T : test configuration, dump it and exit -q : suppress non-error messages during configuration testing -s signal : send signal to a master process: stop, quit, reopen, reload -p prefix : set prefix path (default: NONE) -e filename : set error log file (default: logs/error.log) -c filename : set configuration file (default: conf/nginx.conf) -g directives : set global directives out of configuration file 1、启动 start nginx 或 nginx.exe 注：建议使用第一种，第二种会使你的 cmd 窗口一直处于执行中，不能进行其他命令操作。 如果需要特殊设置 nginx 的配置文件路径，可以这样执行： start nginx -c conf/nginx.conf 2、停止： nginx.exe -s stop 或 bnginx.exe -s quit 注：stop 是快速停止 nginx，可能并不保存相关信息；quit 是完整有序的停止 nginx，并保存相关信息。 执行 nginx.exe -s stop 或者 quit 命令是不是不能删除进程？查看进程开了一堆 nignx.exe。 还有 80 端口在 Listening，并且浏览器 F5 刷新还能访问页面，可能 nginx.exe 版本或系统的原因，用taskkill /f/im nginx.exe > null 杀死 nginx 进程。 3、重新载入 Nginx nginx.exe -s reload 当配置信息修改，需要重新载入这些配置时使用此命令。 4、重新打开日志文件 nginx.exe -s reopen 5、查看 Nginx 版本 nginx -v / nginx -V 注：v 只是简单显示版本信息，V 不但显示版本信息，还显示配置参数信息。 6、测试或载入指定配置文件 注意，修改了配置文件后最好先检查一下修改过的配置文件是否正确，以免重启后 Nginx 出现错误影响服务器稳定运行。判断 Nginx 配置是否正确命令如下： nginx.exe -t -c conf/default.conf 载入指定配置文件： start nginx.exe -c conf/default.conf 参考： 腾讯云如何申请免费ssl证书以及如何使用 typecho 全站开启Https证书访问