一、简介
Nginx 是一个高性能的HTTP和反向代理服务器,特点是占用内存少,并发能力强
应用场景
- 静态资源服务 : 通过本地文件系统提供服务
- 反向代理服务 : 性能高、缓存、负载均衡
- API服务: OpenResty
二、安装
2.1 源码方式安装
依赖安装
gcc 编译套件 (一般默认有 ,gcc -v )
yum -y install gcc
pcre perl库 正则表达式
yum install -y pcre pcre-devel
zlib 压缩和解压缩
yum install -y zlib zlib-devel
openssl ssl通信安全
yum install -y openssl openssl-devel
下载
官网下载gz 文件, 比如用 https://nginx.org/download/nginx-1.26.2.tar.gz
解压 tar -zxvf nginx-1.26.2.tar.gz
进入解压的文件
执行./configure 生成编译配置文件Makefile
make 编译
make install 安装
编译及安装
编译参数
https://nginx.org/en/docs/configure.html
## 查看可选的配置参数
./configure --help
## 示例
./configure --prefix=/usr/share/nginx/ --sbin-path=/usr/sbin/nginx --modules-path=/usr/share/nginx/modules/ --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/run/nginx.pid --with-http_gzip_static_module --with-stream --with-http_ssl_module
## 编译的时候使用 dynamic , 会在objs 文件夹下生成对应的模块文件 xxx.so , 如 ngx_stream_module.so
## 复制 xxx.so 到 modules-path 对应文件夹 (make install 可以自动安装,手动更新时,自己复制 )
2.2 源安装
yum 安装
yum install -y nginx
yum install -y nginx-mod-stream
apt方式安装参照yum 方式即可
三、配置
http 代理
指令块: http 、upstream 、 server 、 location
http {
include mime.types ;
upstream logserver {
server 172.20.51.2:8083;
server 172.20.51.3:8083;
}
server {
listen 80 default_server;
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s ;
location /proxylog {
proxy_buffering off ;
proxy_read_timeout 60000;
proxy_pass http://logserver/ ;
}
#location ^~ /proxylog {
# proxy_buffering off ;
# proxy_read_timeout 60000;
# rewrite ~/proxylog/(.*)$ /$1 break;
# proxy_pass http://logserver/ ;
#}
}
}
ssl 配置
TSL/SSL
对称加密
非对称加密
PKI公钥基础设施
证书类型 : 域名验证、组织验证、扩展验证
stream 代理
## 选择预编译或者加载模块stream
load_module modules/ngx_stream_module.so;
stream {
upstream proxy_name {
server 127.0.0.1:9553;
}
server {
listen 8088;
proxy_pass proxy_name;
}
}
配置参数
时间单位
ms milliseconds ;
s seconds ; # 如果不指定 ,默认是秒
m minutes ;
h hours ;
d days ;
w weeks ;
M months , 30days ;
y years , 365 days ;
空间单位
bytes ,## 默认;
k/K kilobytes ;
m/M megabytes ;
g/G gigabytes ;
重要参数
#启动进程,通常设置成和cpu的数量相等
worker_processes 1; # auto 自动匹配cpu核数
#一个 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 模型。 #epoll 是多路复用 IO(I/O Multiplexing) 中的一种方式,但是仅用于 linux2.6 以上内核,可以大大提高 nginx 的性能
use epoll;
#单个后台 worker process 进程的最大并发链接数
#事件模块指令,定义 nginx 每个进程最大连接数,默认 1024。最大客户连接数由 worker_processes 和 worker_connections 决定
#即 max_client=worker_processes*worker_connections,
#在作为反向代理时:max_client=worker_processes*worker_connections / 4
worker_connections 65535;
#worker_connections 1024; #单个后台worker process进程的最大并发链接数
}
#sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用, #必须设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,以平衡磁盘与网络I/O处理速度,降低系统的uptime.
sendfile on;
tcp_nopush on; #防止网络阻塞
tcp_nodelay on; #防止网络阻塞
keepalive_timeout 120; #单位是秒,客户端连接时时间,超时之后服务器端自动关闭该连接 如果 nginx 守护进程在这个等待的时间里,一直没有收到浏览发过来 http 请求,则关闭这个 http 连接 client_header_timeout 10; #客户端请求头的超时时间
gzip on;
gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/javascript image/jpeg image/gif image/png;
gzip_vary on;
#nginx 默认没有开启利用多核 CPU, 通过增加 worker_cpu_affinity 配置参数来充分利用多核 CPU 以下是 8 核的配置参数
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
日志格式
Access Format :
Access log :
Go access :
Realtime websocket :
log_format main '[$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/access.log access;
`$remote_addr`, `$http_x_forwarded_for` 记录客户端IP地址
`$remote_user`记录客户端用户名称
`$request`记录请求的URL和HTTP协议(GET,POST,DEL,等)
`$status`记录请求状态
`$body_bytes_sent`发送给客户端的字节数,不包括响应头的大小;该变量与Apache模块mod_log_config里的“%B”参数兼容。
`$bytes_sent`发送给客户端的总字节数。
`$connection`连接的序列号。
`$connection_requests` 当前通过一个连接获得的请求数量。
`$msec` 日志写入时间。单位为秒,精度是毫秒。
`$pipe`如果请求是通过HTTP流水线(pipelined)发送,pipe值为“p”,否则为“.”。
`$http_referer` 记录从哪个页面链接访问过来的
`$http_user_agent`记录客户端浏览器相关信息
`$request_length`请求的长度(包括请求行,请求头和请求正文)。
`$request_time` 请求处理时间,单位为秒,精度毫秒;从读入客户端的第一个字节开始,直到把最后一个字符发送给客户端后进行日志写入为止。
`$time_iso8601 ISO8601`标准格式下的本地时间。
`$time_local`通用日志格式下的本地时间。
upstream_addr
upstream_connect_time
upstream_header_time
upstream_response_time
## 负载均衡
### 轮询
```nginx
upstream bck_testing_01 {
# 默认所有服务器权重为 1
server 192.168.250.220:8080 ;
server 192.168.250.221:8080 ;
server 192.168.250.222:8080 ;
}
upstream bck_testing_01 {
server 192.168.250.220:8080 weight=3
server 192.168.250.221:8080 # default weight=1
server 192.168.250.222:8080 # default weight=1
}
最少连接
upstream bck_testing_01 {
least_conn; # with default weight for all (weight=1)
server 192.168.250.220:8080
server 192.168.250.221:8080
server 192.168.250.222:8080
}
upstream bck_testing_01 {
least_conn;
server 192.168.250.220:8080 weight=3
server 192.168.250.221:8080 # default weight=1
server 192.168.250.222:8080 # default weight=1
}
哈希
upstream bck_testing_01 {
ip_hash;
# with default weight for all (weight=1)
server 192.168.250.220:8080
server 192.168.250.221:8080
server 192.168.250.222:8080
}
upstream bck_testing_01 {
hash $request_uri;
# with default weight for all (weight=1)
server 192.168.250.220:8080
server 192.168.250.221:8080
server 192.168.250.222:8080
}
反向代理
#虚拟主机的配置
server {
#监听端口
listen 80;
#对 "/" 启用反向代理
location / {
proxy_pass http://127.0.0.1:8080;
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; #缓冲区代理缓冲用户端请求的最大字节数,
##代理设置 以下设置是 nginx 和后端服务器之间通讯的设置##
proxy_connect_timeout 90; #nginx 跟后端服务器连接超时时间(代理连接超时)
proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时)
proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时)
proxy_buffering on; #该指令开启从后端被代理服务器的响应内容缓冲 此参数开启后 proxy_buffers 和 proxy_busy_buffers_size 参数才会起作用
proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 4 32k; #proxy_buffers 缓冲区,网页平均在 32k 以下的设置
proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
proxy_max_temp_file_size 2048m; #默认 1024m, 该指令用于设置当网页内容大于 proxy_buffers 时,临时文件大小的最大值。如果文件大于这个值,它将从 upstream 服务器同步地传递请求,而不是缓冲到磁盘
proxy_temp_file_write_size 512k; 这是当被代理服务器的响应过大时 nginx 一次性写入临时文件的数据量。
proxy_temp_path /var/tmp/nginx/proxy_temp; ##定义缓冲存储目录,之前必须要先手动创建此目录
proxy_headers_hash_max_size 51200;
proxy_headers_hash_bucket_size 6400;
#######################################################
}
}
四、应用
命令操作
-? -h : 帮助
-c :使用指定的配置文件
-g : 指定配置指令
-p : 指定运行目录
-s : 发送信号 , stop 立刻停止服务,quit 优雅的停止服务 ,reload 重载配置文件 , reopen 重新开始记录日志文件
-t -T : 测试配置文件是否有语法错误
-v -V : 打印版本及编译信息
nginx -s reload
搭建文件服务器
有时候,团队需要归档一些数据或资料,那么文件服务器必不可少。使用 Nginx 可以非常快速便捷的搭建一个简易的文件服务。
Nginx 中的配置要点:
- 将 autoindex 开启可以显示目录,默认不开启。
- 将 autoindex_exact_size 开启可以显示文件的大小。
- 将 autoindex_localtime 开启可以显示文件的修改时间。
- root 用来设置开放为文件服务的根路径。
- charset 设置为
charset utf-8,gbk;
,可以避免中文乱码问题(windows 服务器下设置后,依然乱码,本人暂时没有找到解决方法)。
一个最简化的配置如下:
autoindex on;# 显示目录
autoindex_exact_size on;# 显示文件大小
autoindex_localtime on;# 显示文件时间
server {
charset utf-8,gbk; # windows 服务器下设置后,依然乱码,暂时无解
listen 9050 default_server;
listen [::]:9050 default_server;
server_name _;
root /share/fs;
}
高可用
nginx +keepalived
跨域
参考资料2 的配置
五、原理
1、master 进程 : i.加载配置;ii.启动workers;iii.非停重启即./nginx -s reload
2、worker 进程 :只有一个主线程,采用的是异步非阻塞的方式处理请求
3、nginx的异步非阻塞事件驱动模型:
nginx 使用了有限的单线程进程(workers),节省了CPU周期,因为减少了很多线程的创建和销毁和切换同时监控很多事件,单线程在请求之间不断地切换而已,切换也是因为异步事件未准备好,而主动让出的。这里的切换是没有任何代价,因为实际上是循环处理多个准备好的事件,好处是:不用创建很多线程占用内存资源,不用线程间上下文切换,并发再多也不用担心切换问题,只是会多占用一点内存而已;
4、更新配置升级时 主线程指挥worker做两件事:
i.重新加载配置文件,并配置一组新的worker(进程号跟之前的完全不同),新的worker会马上开始工作
ii.指示旧的工作进程正常退出 ,工作进程停止接受新连接,但是会直到http发送数据完毕,一旦所有连接都关闭,则工作进程就退出
六 、问题
链接数异常
检测TIME_WAIT状态的语句
$ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
SYN_RECV 7
ESTABLISHED 756
FIN_WAIT1 21
SYN_SENT 3
TIME_WAIT 2000
状态解析:
CLOSED
- 无连接是活动的或正在进行LISTEN
- 服务器在等待进入呼叫SYN_RECV
- 一个连接请求已经到达,等待确认SYN_SENT
- 应用已经开始,打开一个连接ESTABLISHED
- 正常数据传输状态FIN_WAIT1
- 应用说它已经完成FIN_WAIT2
- 另一边已同意释放ITMED_WAIT
- 等待所有分组死掉CLOSING
- 两边同时尝试关闭TIME_WAIT
- 另一边已初始化一个释放LAST_ACK
- 等待所有分组死掉
解决方法
执行 vim /etc/sysctl.conf
,并添加下面字段
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
执行 /sbin/sysctl -p
让修改生效。