Nginx、Keepalived

一、对常用I/O模型进行比较说明

I/O在计算机中指Input/Output, IOPS (Input/Output Per Second)即每秒的输入输出量(或读写次数),是衡量磁盘性能的主要指标之一。IOPS是指单位时间内系统能处理的I/O请求数量,一般以每秒处理的I/O请求数量为单位,I/O请求通常为读或写数据操作请求。

一次完整的I/O是用户空间的进程数据与内核空间的内核数据的报文的完整交换,但是由于内核空间与用户空间是严格隔离的,所以其数据交换过程中不能由用户空间的进程直接调用内核空间的内存数据,而是需要经历一次从内核空间中的内存数据copy到用户空间的进程内存当中,所以简单说I/O就是把数据从内核空间中的内存数据复制到用户空间中进程的内存当中。

1. I/O模型相关概念

同步/异步:关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状态的通知。

  • 同步:synchronous,被调用者并不提供事件的处理结果相关的通知消息,需要调用者主动询问事情是否处理完成。
  • 异步:asynchronous,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态
用户空间
程序进程
内核准备好数据后
是否提供通知机制
不提供:同步
提供:异步

阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态

  • 阻塞:blocking,指IO操作需要彻底完成后才能返回到用户空间,调用结果返回之前,调用者被挂起,干不了别的事情。
  • 非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,而无需等待IO操作彻底完成,在最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情。
Syntax error in textmermaid version 10.9.0

2. 网络I/O模型

阻塞型、非阻塞型、复用型、信号驱动型、异步

  1. 阻塞I/O模型(blocking IO)

    阻塞IO模型是最简单的I/O模型,用户线程在内核进行IO操作被阻塞

    用户线程通过系统调用read发起I/O读操作,由用户空间传到内核空间。内核等到数据包到达后,然后将接收的数据拷贝到用户空间,完成read操作

    用户需要等待read将数据读取到buffer后,才继续处理接收的数据。整个I/O请求的过程中,用户线程是被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够

    优点:程序简单,在阻塞等待数据期间进程/线程挂起,基本不会占用 CPU 资源

    缺点:每个连接需要独立的进程/线程单独处理,当并发请求量大时为了维护程序,内存、线程切换开销较大,apache 的preforck使用的是这种模式。

    同步阻塞:程序向内核发送I/O请求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回,则进程将一直等待并不再接受新的请求,并由进程轮询查看I/O是否完成,完成后进程将I/O结果返回给Client,在IO没有返回期间进程不能接受其他客户的请求,而且是有进程自己去查看I/O是否完成,这种方式简单,但是比较慢,用的比较少。

  2. 非阻塞型 I/O 模型 (nonblocking IO)

    用户线程发起IO请求时立即返回。但并未读取到任何数据,用户线程需要不断地发起IO请求,直到数据到达后,才真正读取到数据,继续执行。即“轮询”机制存在两个问题:如果有大量文件描述符都要等,那么就得一个一个的read。这会带来大量的Context Switch(read是系统调用,每调用一次就得在用户态和核心态切换一次)。轮询的时间不好把握。这里是要猜多久之后数据才能到。等待时间设的太长,程序响应延迟就过大;设的太短,就会造成过于频繁的重试,干耗CPU而已,是比较浪费CPU的方式,一般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。

    非阻塞:程序向内核发送I/O请求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回IO结果,进程将不再等待,而且继续处理其他请求,但是仍然需要进程隔一段时间就要查看内核I/O是否完成。

    查看上图可知,在设置连接为非阻塞时,当应用进程系统调用 recvfrom 没有数据返回时,内核会立即返回一个 EWOULDBLOCK 错误,而不会一直阻塞到数据准备好。如上图在第四次调用时有一个数据报准备好了,所以这时数据会被复制到 应用进程缓冲区 ,于是 recvfrom 成功返回数据。

    当一个应用进程这样循环调用 recvfrom 时,称之为轮询 polling 。这么做往往会耗费大量CPU时间,实际使用很少。

  3. 多路复用 I/O 模型(I/O multiplexing)

    上面的模型中,每一个文件描述符对应的IO是由一个线程监控和处理多路复用IO指一个线程可以同时(实际是交替实现,即并发完成)监控和处理多个文件描述符对应各自的IO,即复用同一个线程

    一个线程之所以能实现同时处理多个IO,是因为这个线程调用了内核中的SELECT,POLL或EPOLL等系统调用,从而实现多路复用IO

    I/O multiplexing 主要包括:select,poll,epoll三种系统调用,select/poll/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select/poll/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。

    当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。

    Apache prefork是此模式的select,worker是poll模式。

    IO多路复用(IO Multiplexing) :是一种机制,程序注册一组socket文件描述符给操作系统,表示“我要监视这些fd是否有IO事件发生,有了就告诉程序处理”

    IO多路复用一般和NIO一起使用的。NIO和IO多路复用是相对独立的。NIO仅仅是指IO API总是能立刻返回,不会被Blocking;而IO多路复用仅仅是操作系统提供的一种便利的通知机制。操作系统并不会强制这俩必须得一起用,可以只用IO多路复用 + BIO,这时还是当前线程被卡住。IO多路复用和NIO是要配合一起使用才有实际意义
    IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,就通知该进程多个连接共用一个等待机制,本模型会阻塞进程,但是进程是阻塞在select或者poll这两个系统调用上,而不是阻塞在真正的IO操作上
    用户首先将需要进行IO操作添加到select中,同时等待select系统调用返回。当数据到达时,IO被激活,select函数返回。用户线程正式发起read请求,读取数据并继续执行
    从流程上来看,使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视IO,以及调用select函数的额外操作,效率更差。并且阻塞了两次,但是第一次阻塞在select上时,select可以监控多个IO上是否已有IO操作准备就绪,即可达到在同一个线程内同时处理多个IO请求的目的。而不像阻塞IO那种,一次只能监控一个IO
    虽然上述方式允许单线程内处理多个IO请求,但是每个IO请求的过程还是阻塞的(在select函数上阻塞),平均时间甚至比同步阻塞IO模型还要长。如果用户线程只是注册自己需要的IO请求,然后去做自己的事情,等到数据到来时再进行处理,则可以提高CPU的利用率
    IO多路复用是最常使用的IO模型,但是其异步程度还不够“彻底”,因它使用了会阻塞线程的select系统调用。因此IO多路复用只能称为异步阻塞IO模型,而非真正的异步IO

    优缺点

    • 优点:可以基于一个阻塞对象,同时在多个描述符上等待就绪,而不是使用多个线程(每个文件描述符一个线程),这样可以大大节省系统资源
    • 缺点:当连接数较少时效率相比多线程+阻塞 I/O 模型效率较低,可能延迟更大,因为单个连接处理需要 2 次系统调用,占用时间会有增加

    IO多路复用适用如下场合:

    • 当客户端处理多个描述符时(一般是交互式输入和网络套接口),必须使用I/O复用
    • 当一个客户端同时处理多个套接字时,此情况可能的但很少出现
    • 当一个服务器既要处理监听套接字,又要处理已连接套接字,一般也要用到I/O复用
    • 当一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用
    • 当一个服务器要处理多个服务或多个协议,一般要使用I/O复用
  4. 信号驱动式 I/O 模型 (signal-driven IO)

    信号驱动I/O的意思就是进程现在不用傻等着,也不用去轮询。而是让内核在数据就绪时,发送信号通知进程。调用的步骤是,通过系统调用 sigaction ,并注册一个信号处理的回调函数,该调用会立即返回,然后主程序可以继续向下执行,当有I/O操作准备就绪,即内核数据就绪时,内核会为该进程产生一个 SIGIO信号,并回调注册的信号回调函数,这样就可以在信号回调函数中系统调用 recvfrom 获取数据,将用户进程所需要的数据从内核空间拷贝到用户空间此模型的优势在于等待数据报到达期间进程不被阻塞。用户主程序可以继续执行,只要等待来自信号处理函数的通知。

    在信号驱动式 I/O 模型中,应用程序使用套接口进行信号驱动 I/O,并安装一个信号处理函数,进程继续运行并不阻塞,当数据准备好时,进程会收到一个 SIGIO 信号,可以在信号处理函数中调用 I/O 操作函数处理数据。

    优点:线程并没有在等待数据时被阻塞,内核直接返回调用接收信号,不影响进程继续处理其他请求因此可以提高资源的利用率。

    缺点:信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知。

    异步阻塞:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核收到进程请求后进行的IO如果不能立即返回,
    就由内核等待结果,直到IO完成后内核再通知进程。

  5. 异步 I/O 模型 (asynchronous IO)

    异步I/O 与 信号驱动I/O最大区别在于,信号驱动是内核通知用户进程何时开始一个I/O操作,而异步I/O是由内核通知用户进程I/O操作何时完成,两者有本质区别,相当于不用去饭店场吃饭,直接点个外卖,把等待上菜的时间也给省了。

    相对于同步I/O,异步I/O不是顺序执行。用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket数据准备好了,内核直接复制数据给进程,然后从内核向进程发送通知。IO两个阶段,进程都是非阻塞的。

    信号驱动IO当内核通知触发信号处理程序时,信号处理程序还需要阻塞在从内核空间缓冲区拷贝数据到用户空间缓冲区这个阶段,而异步IO直接是在第二个阶段完成后,内核直接通知用户线程可以进行后续操作了

    优点:异步 I/O 能够充分利用 DMA 特性,让 I/O 操作与计算重叠

    缺点:要实现真正的异步 I/O,操作系统需要做大量的工作。目前 Windows 下通过 IOCP 实现了真正的异步 I/O,在 Linux 系统下,Linux 2.6才引入,目前 AIO 并不完善,因此在 Linux 下实现高并发网络编程时以 IO 复用模型模式+多线程任务的架构基本可以满足需求。

    Linux提供了AIO库函数实现异步,但是用的很少。目前有很多开源的异步IO库,例如libevent、libev、libuv。

    异步非阻塞:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核调用的IO如果不能立即返回,内核会继续处理其他事物,直到IO完成后将结果通知给内核,内核在将IO完成的结果返回给进程,期间进程可以接受新的请求,内核也可以处理新的事物,因此相互不影响,可以实现较大的同时并实现较高的IO复用,因此异步非阻塞使用最多的一种通信方式。

3. 五种IO模型对比

这五种 I/O 模型中,越往后,阻塞越少,理论上效率也是最优前四种属于同步 I/O,因为其中真正的 I/O操作(recvfrom)将阻塞进程/线程,只有异步 I/O 模型才与 POSIX 定义的异步 I/O 相匹配。

二、nginx中的模块分类及常见核心模块有哪些

nginx模块主要分为核心模块、标准HTTP模块、可选HTTP模块、邮件服务模块、第三方模块等。

常见核心模块:ngx_core、ngx_errlog、ngx_conf、ngx_events、ngx_event、ngx_epoll、ngx_regex

核心模块:是Nginx服务器正常运行必不可少的模块,提供错误日志记录、配置文件解析、事件驱动机制、进程管理等核心功能
标准HTTP模块:提供HTTP协议解析相关的功能,比如:端口配置、网页编码设置、HTTP响应头设置等
可选HTTP模块:主要用于扩展标准的HTTP功能,让Nginx能处理一些特殊的服务,比如:Flash多媒体传输、解析GeoIP请求、网络传输压缩、安全协议SSL支持等
邮件服务模块:主要用于支持Nginx的邮件服务,包括对POP3协议、IMAP协议和SMTP协议的支持
Stream服务模块: 实现反向代理功能,包括TCP协议代理
第三方模块:是为了扩展 Nginx服务器应用,完成开发者自定义功能,比如:Json支持、Lua支持等

三、描述nginx中worker_processes、worker_cpu_affinity、worker_rlimit_nofile、worker_connections配置项的含义

  • worker_processes [num | auto]

设置启动Nginx工作进程的数量,一般设为和CPU核心数相同。

  • worker_cpu_affinity

将Nginx工作进程绑定到指定的CPU核心,默认Nginx是不进行进程绑定的,绑定并不是意味着当前nginx进程独占以一核心CPU,但是可以保证此进程不会运行在其他核心上,这就极大减少了nginx的工作进程在不同的cpu核心上的来回跳转,减少了CPU对进程的资源分配与回收以及内存管理等,因此可以有效的提升nginx服务器的性能。

  • worker_rlimit_nofile

所有worker进程能打开的文件数量上限,包括:Nginx的所有连接(例如与代理服务器的连接等),而不仅仅是与客户端的连接,另一个考虑因素是实际的并发连接数不能超过系统级别的最大打开文件数的限制.最好与ulimit -n 或者limits.conf的值保持一致

  • worker_connections

events设置快,设置单个nginx工作进程可以接受的最大并发,作为web服务器的时候最大并发数为worker_connections * worker_processes,作为反向代理的时候为(worker_connections * worker_processes)/2

四、编译安装nginx,实现多域名 https

官方源码下载地址:https://nginx.org/en/download.html

1. 编译安装nginx

#! /bin/bash
# nginx版本
NGINX_version=nginx-1.18.0
# 下载网址
NGINX_Download_URL=http://nginx.org/download/${NGINX_version}.tar.gz
# nginx 安装路径
install_path=/apps/nginx
# nginx源码路径
SRC_DIR=/usr/local/src
# CPU数量
CPUS=`lscpu|grep "^CPU(s)"|awk '{print $2}'`
# 系统类型
os_type=`grep "^NAME" /etc/os-release |awk -F'"| ' '{print $2}'`
# 系统版本号
os_version=`awk -F'"' '/^VERSION_ID/{print $2}' /etc/os-release`
color (){
if [[ $2 -eq 0 ]];then
echo -e "\e[1;32m$1\t\t\t\t\t\t[ OK ]\e[0;m"
else
echo $2
echo -e "\e[1;31m$1\t\t\t\t\t\t[ FAILED ]\e[0;m"
fi
}
install_nginx () {
if [ -e ${NGINX_version}.tar.gz ];then
color "${NGINX_version}.tar.gz 源码包已存在" 0
else
color "开始下载源码包" 0
wget ${NGINX_Download_URL}
fi
if [ $? -ne 0 ];then
color "下载失败" 1
exit 1
fi
color "开始安装 nginx" 0
if id nginx &>/dev/null;then
color "nginx 用户已存在" 1
else
useradd -s /sbin/nologin nginx
color "创建nginx用户" 0
fi
color "开始安装nginx依赖包" 0
if [ ${os_type}=="CentOS" -a ${os_version}=="8" ];then
yum -y install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
elif [ ${os_type}=="CentOS" -a ${os_version}=="7" ];then
yum -y install make gcc pcre-devel openssl-devel zlib-devel perl-ExtUtils-Embed
else
color "系统不符,无法安装" 1
exit 1
fi
tar -xvf ${NGINX_version}.tar.gz -C ${SRC_DIR}
cd ${SRC_DIR}
ln -s ${NGINX_version} nginx
cd nginx
./configure --prefix=${install_path} \
--user=nginx \
--group=nginx \
--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_ssl_module
make -j ${CPUS} && make install
chown -R nginx:nginx /apps/nginx
ln -s ${install_path}/sbin/nginx /usr/sbin/nginx
cat > /usr/lib/systemd/system/nginx.service <<EOF
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=${install_path}/logs/nginx.pid
ExecStartPre=/bin/rm -f ${install_path}/logs/nginx.pid
ExecStartPre=${install_path}/sbin/nginx -t
ExecStart=${install_path}/sbin/nginx -c ${install_path}/conf/nginx.conf
ExecReload=/bin/kill -s HUP \$MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now nginx &>/dev/null
systemctl is-active nginx &>/dev/null
if [ $? -eq 0 ];then
color "nginx已安装完成!" 0
else
color "nginx 启动失败" 1
exit 1
fi
}
install_nginx
exit 0

2. 多域HTTPS

配置自签名证书

  • 创建证书
#! /bin/bash
/etc/init.d/functions
# 创建目录
mkdir -p /apps/nginx/certs
cd /apps/nginx/certs
#自签名CA证书
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 3650 -out ca.crt <<EOF
CN
Jiangsu
Nanjing
shi.Ltd
shi
ca.shi.org
EOF
# 自制key和csr文件
openssl req -newkey rsa:4096 -nodes -sha256 -keyout www.testshi.org.key -out www.testshi.org.csr <<EOF
CN
Jiangsu
Nanjing
testshi.org
testshi.org
www.testshi.org
719537389@qq.com
EOF
# 签发证书
openssl x509 -req -days 3650 -in www.testshi.org.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out www.testshi.org.crt
# 合并CA和服务器证书一个文件,注意服务器证书在前
cat www.testshi.org.crt ca.crt > www.testshi.org.pem
chown -R nginx:nginx *
exit 0
  • 验证证书内容
openssl x509 -in www.testshi.org.crt -noout -text
[root@shichu certs]# openssl x509 -in www.testshi.org.crt -noout -text
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
af:62:40:d6:42:e4:16:ab
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=Jiangsu, L=Nanjing, O=shi.Ltd, OU=shi, CN=ca.shi.org
Validity
Not Before: Jun 29 17:01:40 2022 GMT
Not After : Jun 26 17:01:40 2032 GMT
Subject: C=CN, ST=Jiangsu, L=Nanjing, O=testshi.org, OU=testshi.org, CN=www.testshi.org/emailAddress=719537389@qq.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:b8:1f:7e:09:86:4a:d6:05:b9:39:63:b3:ba:44:
...
6e:08:53:49:3d:79:fe:ee:13:4c:32:61:42:e4:f6:
f4:aa:6f
Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
6b:56:3e:8f:66:c7:47:4a:38:93:90:e8:d2:15:6a:d5:57:86:
...
85:aa:db:e1:3d:19:46:76:49:a7:e3:e6:f3:01:ff:75:b2:ad:
27:d4:2f:a6:cd:dc:d9:e5

配置https

  • 准备配置文件
#修改nginx.conf配置
vim /apps/nginx/conf/nginx.conf
http {
......
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;
}
}
#在配置文件的最后面添加此行,注意不要放在最前面,会导致前面的命令无法生效
include /apps/nginx/conf/conf.d/*.conf;
}
#修改默认网页
hostname -I > /apps/nginx/conf/nginx.conf
#准备www.testshi.org网页
mkdir -p /data/nginx/html/pc
cat > /data/nginx/html/pc/index.html <<EOF
`hostname -I`
www.testshi.org
EOF
#准备www.testshi.org配置文件
cat > /apps/nginx/conf/conf.d/pc.conf <<EOF
server {
listen 80;
listen 443 ssl;
server_name www.testshi.org;
ssl_certificate /apps/nginx/certs/www.testshi.org.pem;
ssl_certificate_key /apps/nginx/certs/www.testshi.org.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
location / {
root "/data/nginx/html/pc";
}
}
EOF
  • 重启服务
#语法检查
nginx -t
#重启服务
nginx -s reload #或者 systemctl restart nginx
  • 浏览器验证

实现多域HTTPS

Nginx 支持基于单个IP实现多域名的功能,并且还支持单IP多域名的基础之上实现HTTPS,其实是基于Nginx的 SNI(Server Name Indication)功能实现,SNI是为了解决一个Nginx服务器内使用一个IP绑定多个域名和证书的功能,其具体功能是客户端在连接到服务器建立SSL链接之前先发送要访问站点的域名(Hostname),这样服务器再根据这个域名返回给客户端一个合适的证书。

  • 创建证书
#! /bin/bash
. /etc/init.d/functions
cd /apps/nginx/certs
# 自制key和csr文件
openssl req -newkey rsa:4096 -nodes -sha256 -keyout m.testshi.org.key -out m.testshi.org.csr <<EOF
CN
Jiangsu
Nanjing
testshi.org
testshi.org
m.testshi.org
719537389@qq.com
EOF
# 签发证书
openssl x509 -req -days 3650 -in m.testshi.org.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out m.testshi.org.crt
# 合并CA和服务器证书
cat m.testshi.org.crt ca.crt > m.testshi.org.pem
chown nginx:nginx *
exit 0
  • 配置nginx

    #准备m.testshi.org网页
    mkdir -p /data/nginx/html/mobile
    cat > /data/nginx/html/mobile/index.html <<EOF
    `hostname -I`
    m.testshi.org
    EOF
    #准备m.testshi.org配置文件
    cat > /apps/nginx/conf/conf.d/mobile.conf <<EOF
    #http跳转至https
    #server {
    # #listen 80 default_server;
    # listen 80 ;
    # server_name m.testshi.org;
    # rewrite ^(.*)$ https://${server_name}$1 permanent;#
    #}
    server {
    listen 80;
    listen 443 ssl;
    server_name m.testshi.org;
    ssl_certificate /apps/nginx/certs/m.testshi.org.pem;
    ssl_certificate_key /apps/nginx/certs/m.testshi.org.key;
    ssl_session_cache shared:sslcache:20m;
    ssl_session_timeout 10m;
    location / {
    root "/data/nginx/html/mobile";
    }
    }
    EOF
  • 浏览器验证

五、nginx七层负载均衡中常见的算法及原理

官方文档:http://nginx.org/en/docs/http/ngx_http_upstream_module.html

  1. 轮询(默认)

    rr轮询算法为nginx默认调度算法,按客户端请求顺序把客户端的请求逐一分配到不同的后端节点服务器,这相当于LVS中的rr轮询算法。如果后端节点服务器宕机,宕机的服务器会被自动从节点服务器池中剔除,以使客户端的用户访问不受影响。新的请求会分配给正常的服务器。

    适用业务场景:后端服务器硬件性能配置完全一致,业务无特殊要求时使用。

  2. 加权轮询(weight)

    在轮询算法的基础上加上权重,即为权重轮询算法。权重越高,在被访问的概率越大 。可以根据服务器的配置和性能指定权重值大小,达到合理有效的地利用主机资源 。

    适用业务场景:用于后端服务器硬件性处理能力不平均的情形。

  3. ip_hash(源地址hash)

    源地址hash调度算法,基于的客户端的remote_addr(源地址IPv4的前24位或整个IPv6地址)做hash计算,以实现会话保持。该方法确保来自同一客户端的请求将始终传递到同一服务器,除非该服务器不可用。在该服务器不可用的情况下,客户端请求将被传递到另一台服务器。很可能,它也将始终是同一台服务器。

    适用业务场景:适用于需要账号登录的系统,会话连接保持的业务。

    注意:当负载均衡算法为ip_hash时,后端服务器在负载均衡调度中的状态不能有weight和backup。

  4. least_conn(最少连接调度算法)

    最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器,相当于LVS中的WLC。

    适用业务场景:适用于客户端与后端服务器需要保持长连接的业务。

  5. least_time(最小响应时间算法)

    最小响应时间, 计算节点平均响应时间,然后取响应最快的那个,分配更高权重。

    适用业务场景:对访问响应速度有一定要求的业务。

    注意:需编译安装第三方模块 ngx_http_upstream_fair_module

  6. hash KEY [consistent] 一致性hash算法

    基于指定请求报文中首部字段或者URI等key做hash计算,使用consistent参数,将使用ketama一致性hash算法,适用于后端是Cache服务器(如varnish)时使用,consistent定义使用一致性hash运算,一致性hash基于取模运算

    hash $request_uri consistent 基于用户请求的uri做hash

    hash $cookie_sessionid 基于cookie中的sessionid这个key进行hash调度,实现会话绑定

    适用业务场景:适用于后端服务器为缓存服务器时比较有效。

    注意:需编译安装第三方模块 ngx_http_upstream_hash_module

六、使用rewrite规则实现将所有到a域名的访问rewrite到b域名

rewrite说明

rewrite 格式

Syntax: rewrite regex replacement [flag]; #通过正则表达式处理用户请求并返回替换后的数据包。
Default: —
Context: server, location, if

flag 使用介绍

redirect;
#临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302
permanent;
#重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求,状态码:301
break;
#重写完成后,停止对当前URL在当前location中后续的其它重写操作,而后直接跳转至重写规则配置块之后
的其它配置;结束循环,建议在location中使用
#适用于一个URL一次重写
last;
#重写完成后,停止对当前URI在当前location中后续的其它重写操作,而后对新的URL启动新一轮重写检查,
不建议在location中使用
#适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户

实现步骤

  1. 配置www.a.com
# 配置a.conf
cat > /etc/nginx/conf.d/a.conf <<EOF
server {
listen 80;
server_name www.a.com;
location / {
root /apps/nginx/html/a;
index index.html index.htm;
rewrite / $scheme://www.b.com redirect;
}
}
EOF
# 准备网页
echo www.a.com > /apps/nginx/html/a/index.html
  1. 配置www.b.com
# 配置b.conf
cat > /etc/nginx/conf.d/b.conf <<EOF
server {
listen 80;
server_name www.b.com;
location / {
root /apps/nginx/html/b;
index index.html index.htm;
}
}
EOF
# 准备网页
echo www.b.com > /apps/nginx/html/b/index.html
  1. 重启服务
# nginx -t
nginx -s reload
  1. 验证,访问www.a.com将跳转至www.b.com

七、实现反向代理客户端IP透传

架构

http
10.0.0.7
Client
10.0.0.17
Proxy
10.0.0.27
Web
  1. Proxy配置
#添加conf.d/web.conf配置文件
cat > /etc/nginx/conf.d/web.conf <<EOF
server {
listen 80;
server_name www.web.com;
location / {
root /apps/nginx/html/web;
index index.html index.htm;
proxy_pass http://10.0.0.27;
#proxy_set_header X-Real-IP $remote_addr; #只添加客户端IP到请求报文头部,转发至后端服务器
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #添加客户端IP和反向代理服务器IP到请求报文头部
}
}
EOF
#重新加载nginx
nginx -s reload
  1. Web服务器配置
#检查nginx.conf配置文件
cat /etc/nginx/nginx.conf
http {
......
# 检查$http_x_forwarded_for日志格式,默认有此日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
......
}
#重新加载nginx
nginx -s reload
  1. Client访问web界面并验证日志格式

    echo '10.0.0.17 www.web.com' >> /etc/hosts

    [root@client ~]# curl www.web.com
    web

    查看Web服务器日志,可看到客户端IP和Proxy反向代理服务器IP

    [root@web nginx]# tail -f /var/log/nginx/access.log
    10.0.0.17 - - [30/Jun/2022:21:17:54 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) \
    AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "10.0.0.1"
    10.0.0.17 - - [30/Jun/2022:21:18:00 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.29.0" "10.0.0.7"

八、利用LNMP实现wordpress站点搭建

架构

L:Linux(CentOS7)https://mirrors.aliyun.com/centos/7/isos/x86_64/
N:Nginx(1.18.0) https://nginx.org/en/download.html
M:MySQL(8.0.19) https://dev.mysql.com/downloads/mysql/
P:PHP(7.4.10) http://php.net/downloads.php
Wordpress(6.0) https://cn.wordpress.org/download/releases/
#部署规划
10.0.0.7 nginx+php-fpm
10.0.0.17 MySQL
Client
Linux
Nginx
PHP
Wordpress
10.0.0.7
Linux
MySQL
10.0.0.17

部署MySQL

  • 二进制安装MySQL8.0,主机:10.0.017
#!/bin/bash
# 二进制安装mysql
. /etc/init.d/functions
#mysql版本
MYSQL_version=mysql-8.0.19-linux-glibc2.12-x86_64
TAR=tar.xz
MYSQL=${MYSQL_version}.${TAR}
# mysql安装包解压路径
SRC_DIR=/usr/local
#mysql root用户密码
MYSQL_ROOT_PASSWORD=123456
# CPU数量
CPUS=`lscpu|grep "^CPU(s)"|awk '{print $2}'`
# 系统类型
os_type=`grep "^NAME" /etc/os-release |awk -F'"| ' '{print $2}'`
# 系统版本号
os_version=`awk -F'"' '/^VERSION_ID/{print $2}' /etc/os-release`
color () {
if [[ $2 -eq 0 ]];then
echo -e "\e[1;32m$1\t\t\t\t\t\t[ OK ]\e[0;m"
else
echo $2
echo -e "\e[1;31m$1\t\t\t\t\t\t[ FAILED ]\e[0;m"
fi
}
check () {
if [ $UID -ne 0 ];then
color "当前用户不是root,安装失败" 1
exit 1
fi
if [ ! -e /opt/${MYSQL} ];then
color "${MYSQL}安装包不存在" 1
echo "请将安装包放在/opt目录下,退出!"
exit 1
fi
}
install_mysql () {
color "开始安装mysql数据库" 0
yum -y install libaio numactl-libs libaio &>/dev/null
tar -xvf ${MYSQL} -C ${SRC_DIR}
cd ${SRC_DIR}
ln -s ${MYSQL_version} mysql
chown -R root:root mysql
useradd -s /sbin/nologin -r mysql
color "创建mysql用户" 0
echo "PATH=${SRC_DIR}/mysql/bin:\$PATH" >/etc/profile.d/mysql.sh
. /etc/profile.d/mysql.sh
ln -s ${SRC_DIR}/mysql/bin/* /usr/bin/
if [ ! -d /apps/mysql ];then
mkdir -p /apps/mysql
fi
cat > /etc/my.cnf <<EOF
[mysqld]
#bind地址设置为0.0.0.0,否则默认监听IPV6的3306端口
bind-address=0.0.0.0
server-id=`hostname -I|awk -F. '{print $4}'`
datadir=/apps/mysql
#skip_host_cache
skip_name_resolve
socket=/apps/mysql/mysql.sock
log-error=/apps/mysql/mysql.log
pid-file=/apps/mysql/mysql.pid
#default_authentication_plugin=mysql_native_password
#mysqlx=1 # 默认开启,0为关闭,多实例时必须关闭
#mysqlx_port=33060 # 端口号为33060
#mysqlx_bind_address=0.0.0.0 #默认监听IPV6
[client]
socket=/apps/mysql/mysql.sock
EOF
# 生成随机密码
mysqld --initialize --user=mysql --datadir=/apps/mysql
cp ${SRC_DIR}/mysql/support-files/mysql.server /etc/init.d/mysqld
chkconfig --add mysqld
chkconfig mysqld on
systemctl start mysqld
systemctl is-active mysqld
if [ $? -ne 0 ];then
color "mysql服务启动失败" 1
exit 1
fi
# 修改root密码
mysqladmin -uroot -p`awk '/temporary password/{print $NF}' /apps/mysql/mysql.log` password ${MYSQL_ROOT_PASSWORD}
color "mysql数据库安装完成" 0
}
grant_wordpress(){
# 创建WordPress用户,并授权
mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "create database wordpress"
mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "create user wordpress@'10.0.0.%' identified by '123456'"
mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "grant all on wordpress.* to wordpress@'10.0.0.%'"
}
check
install_mysql
grant_wordpress
exit 0
  • 远程登录验证
[root@shichu opt]# hostname -I
10.0.0.27
[root@shichu opt]# mysql -uwordpress -p123456 -h10.0.0.17
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 8.0.19 MySQL Community Server - GPL
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| wordpress |
+--------------------+
2 rows in set (0.01 sec)
mysql>

部署PHP

  • 编译安装php7.4,主机:10.0.0.7
#!/bin/bash
# 编译安装php
. /etc/init.d/functions
#PHP版本
PHP_version=php-7.4.11
TAR=tar.xz
PHP=${PHP_version}.${TAR}
# php安装路径
PHP_DIR=/apps/php
# CPU数量
CPUS=`lscpu|grep "^CPU(s)"|awk '{print $2}'`
# 系统类型
os_type=`grep "^NAME" /etc/os-release |awk -F'"| ' '{print $2}'`
# 系统版本号
os_version=`awk -F'"' '/^VERSION_ID/{print $2}' /etc/os-release`
color () {
if [[ $2 -eq 0 ]];then
echo -e "\e[1;32m$1\t\t\t\t\t\t[ OK ]\e[0;m"
else
echo $2
echo -e "\e[1;31m$1\t\t\t\t\t\t[ FAILED ]\e[0;m"
fi
}
download_php (){
cd /opt
if [ -e ${PHP} ];then
color "php安装包已存在" 0
else
color "开始下载php" 0
wget https://www.php.net/distributions/${PHP}
if [ $? -ne 0 ];then
color "下载失败!" 1
color "请检查网络是否正常" 1
exit 1
fi
fi
}
install_php () {
color "----------------开始安装php-----------" 0
color "开始安装依赖包" 0
yum -y install gcc openssl-devel libxml2-devel bzip2-devel libmcrypt-devel sqlite-devel \
oniguruma-devel bison re2c &>/dev/null
download_php
tar -xvf ${PHP} -C /usr/local/src
cd /usr/local/src
ln -s ${PHP_version} php
cd php
color "开始编译" 0
./configure --prefix=${PHP_DIR} \
--enable-mysqlnd \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-openssl \
--with-zlib \
--with-config-file-path=/etc \
--with-config-file-scan-dir=/etc/php.d \
--enable-mbstring \
--enable-xml \
--enable-sockets \
--enable-fpm \
--enable-maintainer-zts \
--disable-fileinfo
sleep 1
make -j ${CPUS} && make install
if [ $? -eq 0 ];then
color "编译完成" 0
else
color "退出,编译失败!" 1
exit 1
fi
# 生成配置文件
cp php.ini-production /etc/php.ini
cd ${PHP_DIR}/etc
cp php-fpm.conf.default php-fpm.conf
cd php-fpm.d
cp www.conf.default www.conf
cat > www.conf <<EOF
[www]
user = www
group = www
listen = 127.0.0.1:9000
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.status_path = /pm_status
ping.path = /ping
access.log = log/\$pool.access.log
slowlog = log/\$pool.log.slow
EOF
useradd -r -s /sbin/nologin www
color "创建www用户" 0
mkdir -pv ${PHP_DIR}/log
cp /usr/local/src/php/sapi/fpm/php-fpm.service /usr/lib/systemd/system/php-fpm.service
systemctl daemon-reload
systemctl enable --now php-fpm
systemctl is-active php-fpm
if [ $? -ne 0 ];then
color "php-fpm服务启动失败" 1
exit 1
fi
color "php安装完成!" 0
}
install_php
exit 0
  • 安装后验证

部署Nginx

1. 编译安装Nginx1.18,主机:10.0.0.7

#! /bin/bash
# 编译安装nginx
# nginx版本
NGINX_version=nginx-1.18.0
# 下载网址
NGINX_Download_URL=http://nginx.org/download/${NGINX_version}.tar.gz
# nginx 安装路径
install_path=/apps/nginx
# nginx源码路径
SRC_DIR=/usr/local/src
# CPU数量
CPUS=`lscpu|grep "^CPU(s)"|awk '{print $2}'`
# 系统类型
os_type=`grep "^NAME" /etc/os-release |awk -F'"| ' '{print $2}'`
# 系统版本号
os_version=`awk -F'"' '/^VERSION_ID/{print $2}' /etc/os-release`
color (){
if [[ $2 -eq 0 ]];then
echo -e "\e[1;32m$1\t\t\t\t\t\t[ OK ]\e[0;m"
else
echo $2
echo -e "\e[1;31m$1\t\t\t\t\t\t[ FAILED ]\e[0;m"
fi
}
install_nginx () {
if [ -e ${NGINX_version}.tar.gz ];then
color "${NGINX_version}.tar.gz 源码包已存在" 0
else
color "开始下载源码包" 0
wget ${NGINX_Download_URL}
fi
if [ $? -nq 0 ];then
color "下载失败" 1
exit 1
fi
color "开始安装 nginx" 0
if id nginx &>/dev/null;then
color "nginx 用户已存在" 1
else
useradd -s /sbin/nologin nginx
color "创建nginx用户" 0
fi
color "开始安装nginx依赖包" 0
if [ ${os_type}=="CentOS" -a ${os_version}=="8" ];then
yum -y install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
elif [ ${os_type}=="CentOS" -a ${os_version}=="7" ];then
yum -y install make gcc pcre-devel openssl-devel zlib-devel perl-ExtUtils-Embed
else
color "系统不符,无法安装" 1
exit 1
fi
tar -xvf ${NGINX_version}.tar.gz -C ${SRC_DIR}
cd ${SRC_DIR}
ln -s ${NGINX_version} nginx
cd nginx
./configure --prefix=${install_path} \
--user=nginx \
--group=nginx \
--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_ssl_module
make -j ${CPUS} && make install
chown -R nginx:nginx /apps/nginx
ln -s ${install_path}/sbin/nginx /usr/sbin/nginx
cat > /usr/lib/systemd/system/nginx.service <<EOF
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=${install_path}/logs/nginx.pid
ExecStartPre=/bin/rm -f ${install_path}/logs/nginx.pid
ExecStartPre=${install_path}/sbin/nginx -t
ExecStart=${install_path}/sbin/nginx -c ${install_path}/conf/nginx.conf
ExecReload=/bin/kill -s HUP \$MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now nginx &>/dev/null
systemctl is-active nginx &>/dev/null
if [ $? -eq 0 ];then
color "nginx已安装完成!" 0
else
color "nginx 启动失败" 1
exit 1
fi
}
install_nginx
exit 0

2. Nginx登录验证

3. 配置nginx支持fastcgi

修改/apps/nginx/conf/nginx.conf配置文件

worker_processes 1;
pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name www.testshi.org; #指定主机名
server_tokens off; #隐藏nginx版本信息
location / {
root /data/nginx/wordpress; #指定数据目录
index index.php index.html index.htm; #指定默认主页
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location ~ \.php$ { #实现php-fpm
root /data/nginx/wordpress;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By; #隐藏php版本信息
}
location ~ ^/(ping|pm_status)$ { #实现状态页
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;
}
}
}

准备php页面

mkdir -p /data/nginx/wordpress
cat > /data/nginx/wordpress/test.php <<EOF
<?php
phpinfo();
?>
EOF
#重启nginx
systemctl reload nginx

验证php页面

www.test.org/ping

www.test.org/pm_status

www.test.org/test.php

部署WordPress

主机:10.0.0.7

安装WordPress

tar -xvf wordpress-6.0-zh_CN.tar.gz
cp -r wordpress/* /data/nginx/wordpress
chown -R www:www /data/nginx/wordpress

初始化web页面

登录www.testshi.org网页,按以下步骤填写执行

完成安装,发表文章

[root@php wordpress]# tree wp-content/uploads/
wp-content/uploads/
└── 2022
└── 07
├── 2021101112482223.jpeg
└── 2.png
2 directories, 2 files

配置允许上传文件大小

默认只支持上传1M以下文件,直接上传大于1M文件,会出现413错误

[root@php wordpress]# tail -f /apps/nginx/logs/access.log
10.0.0.1 - - [01/Jul/2022:19:13:03 +0800] "POST /index.php?rest_route=%2Fwp%2Fv2%2Fmedia&_locale=user HTTP/1.1" 413 585
"http://www.testshi.org/wp-admin/post.php?post=8&action=edit" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36"

注意:要利用php程序上传大图片,还需要修改下面三项配置,最大上传由三项值的最小值决定

# 修改nginx配置文件/apps/nginx/conf/nginx.conf
server {
client_max_body_size 10m; #默认值为1M
.....
# 修改php配置文件/etc/php.ini
post_max_size = 30M #默认值为8M
upload_max_filesize = 20M #默认值为2M

重启服务

systemctl restart nginx php-fpm

可正常上传大于1M文件

[root@php opt]# ll -h /data/nginx/wordpress/wp-content/uploads/2022/07/
total 2.7M
-rw-r--r-- 1 www www 485K Jul 1 18:52 2021101112482223.jpeg
-rw-r--r-- 1 www www 467K Jul 1 18:48 2.png
-rw-r--r-- 1 www www 1.8M Jul 1 19:16 4.jpg

配置 php 开启 opcache 加速

#修改/etc/php.ini配置文件
[opcache]
; Determines if Zend OPCache is enabled
opcache.enable=1
zend_extension=opcache.so
sed -i.bak 's/;opcache.enable=1/opcache.enable=1\nzend_extension=opcache.so/' /etc/php.ini

重启服务

systemctl restart php-fpm

访问测试页确认开启opcache加速

九、简述keepalived工作原理

官网:https://keepalived.org/

工作原理

基于vrrp协议完成地址流动
为vip地址所在的节点生成ipvs规则(在配置文件中预先定义)
为ipvs集群的各RS做健康状态检测
基于脚本调用接口完成脚本中定义的功能,进而影响集群事务,以此支持nginx、haproxy等服务

Keepalived高可用对之间是通过VRRP进行通信的,VRRP是通过竞选机制来确定主备的,主的优先级高于备,因此,工作时主会优先获得所有的资源,备节点处于等待状态,当主挂了的时候,备节点就会接管主节点的资源,然后顶替主节点对外提供服务。

在Keepalived服务对之间,只有作为主的服务器会一直发送VRRP广播包,告诉备它还活着,此时备不会抢占主,当主不可用时,即备监听不到主发送的广播包时,就会启动相关服务接管资源,保证业务的连续性。接管速度最快可以小于1秒。

组件功能

https://keepalived.org/doc/software_design.html#atomic-elements

User Space(用户空间)组件

  • Control Plane(控制平面):提供keepalived.conf 的解析器,完成Keepalived配置

  • Scheduler - I/O Multiplexer(IO复用器):针对网络目的而优化的自己的线程抽象

  • Memory Management(内存管理组件):为某些通用的内存管理功能(例如分配,重新分配,释放等)提供访问权限

  • Core Components(核心组件)

WatchDog:监控子进程
Checkers:监测real server
VRRP Stack:VIP消息通告
System Call:实现 vrrp 协议状态转换时调用脚本的功能
Netlink Reflector:网络接口
SMTP:邮件组件
IPVS Wrapper:生成IPVS规则
  • IPVS:实现传输层负载平衡
  • NETLINK:用于在内核和用户空间进程之间传输信息

Kernel Space(内核空间)组件

Keepalived进程树

PID 111 Keepalived <-- Parent process monitoring children
112 \_ Keepalived <-- VRRP child
113 \_ Keepalived <-- Healthchecking child

十、编译安装haproxy

源码包下载地址:http://www.haproxy.org/download/

升级lua版本

默认lua版本低于5.3

[root@shichu haproxy]# lua -v
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio

升级lua版本至5.3

# 安装依赖包
yum -y install gcc readline-devel
# 下载并解压源码包
cd /opt
wget http://www.lua.org/ftp/lua-5.3.5.tar.gz
tar -xvf lua-5.3.5.tar.gz -C /usr/local/src
ln -s /usr/local/src/lua-5.3.5 /usr/local/src/lua
# 编译安装
cd /usr/local/src/lua
make linux test
# 查看lua版本
[root@shichu haproxy]# /usr/local/src/lua/src/lua -v
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio

编译安装HAProxy

  • 安装
# 安装依赖包
yum -y install gcc openssl-devel pcre-devel systemd-devel
# 下载并解压源码包
cd /opt
wget http://www.haproxy.org/download/2.6/src/haproxy-2.6.1.tar.gz
tar xvf haproxy-2.6.1.tar.gz -C /usr/local/src
ln -s /usr/local/src/haproxy-2.6.1 /usr/local/src/haproxy
# 编译安装
cd /usr/local/src/haproxy
make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_LUA=1 LUA_INC=/usr/local/src/lua/src/ LUA_LIB=/usr/local/src/lua/src/
make install PREFIX=/apps/haproxy
ln -s /apps/haproxy/sbin/haproxy /usr/sbin/
# 准备服务启动配置文件
## 添加用户
useradd -r -s /sbin/nologin -d /var/lib/haproxy haproxy
mkdir -p /etc/haproxy
mkdir -p /var/lib/haproxy
## 准备service服务
cat > /usr/lib/systemd/system/haproxy.service <<EOF
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target
[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /var/lib/haproxy/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
EOF
###准备haproxy配置文件
cat > /etc/haproxy/haproxy.cfg <<EOF
global
maxconn 100000
chroot /apps/haproxy
stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
#uid 99
#gid 99
user haproxy
group haproxy
daemon
#nbproc 4
#cpu-map 1 0
#cpu-map 2 1
#cpu-map 3 2
#cpu-map 4 3
pidfile /var/lib/haproxy/haproxy.pid
log 127.0.0.1 local2 info
defaults
option http-keep-alive
option forwardfor
maxconn 100000
mode http
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms
listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global
stats uri /haproxy-status
stats auth haadmin:123456
listen web_port
bind 10.0.0.7:80
mode http
log global
server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5
EOF
systemctl daemon-reload
systemctl enable --now haproxy
# systemctl is-active haproxy
  • 查看版本、端口
[root@shichu haproxy]# haproxy -v
HAProxy version 2.6.1-f6ca66d 2022/06/21 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2027.
Known bugs: http://www.haproxy.org/bugs/bugs-2.6.1.html
Running on: Linux 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64
[root@shichu haproxy]# netstat -ntlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:9999 0.0.0.0:* LISTEN 22196/haproxy
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 635/rpcbind
tcp 0 0 10.0.0.7:80 0.0.0.0:* LISTEN 22196/haproxy
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 898/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1073/master
tcp6 0 0 :::111 :::* LISTEN 635/rpcbind
tcp6 0 0 :::22 :::* LISTEN 898/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1073/master
  • 查看状态页

访问http://10.0.0.7:9999/haproxy-status验证

用户名、密码可在haproxy.cfg配置文件中设置

posted @   areke  阅读(346)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示