nginx
安装Nginx
docker安装
docker run -d --restart=always \
--net host \
--name nginx \
-v ./nginx.conf:/etc/nginx/nginx.conf \
-v ./log:/var/log/nginx \ # log
-v ./cert:/etc/nginx/cert \ # SSL证书文件, 没有可以去掉
-v ./html:/usr/share/nginx/html \
nginx:1.24.0
net=host是因为懒得配端口了, 这样好一些
shell启动不够优雅, 建议使用docker compose
version: '3.8'
services:
nginx:
image: nginx:1.24.0
container_name: nginx
restart: always
network_mode: host
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./logs:/var/log/nginx:rw
- ./cert:/etc/nginx/cert:ro
- ./html:/usr/share/nginx/html:ro # 一些html或者error.json
注意:
- network_mode是linux专用, docker desktop没用
- host网络模式不是最佳实践, 如果有确定的后端编排还是一起编排比较合适
apt下载安装启动(不建议)
为了不找不自在, 还是用docker部署吧!
不建议使用apt安装, 因为会缺少很多模块, 而且版本较老
sudo apt install nginx
service nginx start # 启动nginx
然后打开80端口查看情况, 如果出现nginx主页说明成功
从源码编译安装并配置SSL模块
参考: https://developer.aliyun.com/article/766958
先安装好nginx
- 去官网下载源码: https://nginx.org/en/download.html
建议下载Stable version
- 解压安装包
tar -zxvf <包的名字>
- 安装SSL模块
到nginx目录下, 输入
./configure --prefix=/etc/nginx --with-http_ssl_module
/ect/nginx是你的nginx安装位置, 也可以是/usr/local/nginx
如果用apt安装的话, 为/etc/nginx
如果出现 the HTTP rewrite module requires the PCRE library, 则安装:
apt-get install libpcre3 libpcre3-dev
上面的命令是配置ssl模块
- 用make命令编译, 注意不要使用make install, 会重新安装nginx, 当然, 想重新安装也可以输入
make
这里面可能会出现errors, 不用管
如果出现了缺少包依赖的错误, 直接安装即可, 这里提供一些可能出现的:
sudo apt-get install libpcre3 libpcre3-dev # 缺少pcre
sudo apt-get install openssl libssl-dev # 缺少openssl
sudo apt-get install zlib1g-dev # 缺少zlib
-
将obj的文件复制到nginx上覆盖原来的文件
-
查看是否安装成功
nginx -V
如果出现**–with-http_ssl_module**则成功
nginx文件树
nginx配置文件在/etc/nginx中
nginx启动时加载nginx.conf
其中有两行:
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
意思是引用了这两个目录下的所有文件
其中, sites-enabled 是 sites-available的链接, 把想启动的配置放在这里即可, 同理当想临时关闭某个站点时, 把sites-enabled对应的链接删去即可
当然,也可以在conf.d中放配置文件, 不过不建议
注意: 由于 sites-enabled 有默认的nginx界面,所有访问均会导向默认界面 所以要使我们的配置生效, 需要把sites-enabled的链接删去
nginx架构
配置模板开箱即用
注意, 需要使用上面的docker-compose.yaml启动, 目录下放这个配置文件(nginx.conf)
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice; # notice级别
pid /var/run/nginx.pid; # nginx进程id
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# --------------------日志 配置---------------------
# 格式:
# remote_addr - remote_user [time_local] "request" status body_bytes_sent "http_referer" "http_user_agent" "http_x_forwarded_for"
# 远程地址 用户名 时间 请求 状态 响应大小 来源网址 用户UA 代理地址
# log_format debug '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
log_format debug ' $remote_user [$time_local] $http_x_Forwarded_for $remote_addr $request '
'$http_x_forwarded_for '
'$upstream_addr '
'ups_resp_time: $upstream_response_time '
'request_time: $request_time';
access_log /var/log/nginx/access.log debug; # debug级别
# --------------------网络 配置---------------------
sendfile on; # 零拷贝传输(内核和用户)
#tcp_nopush on; # 优化网络传输,减少网络报文, 把多个小包合并成一个大包发送
keepalive_timeout 65; # 保持长连接的时间, 如果有客户端在65s内没有任何请求, 则关闭连接
# --------------------压缩 配置---------------------
# 开启/关闭 压缩机制
gzip on;
# 根据文件类型选择 是否开启压缩机制
gzip_types text/plain application/javascript text/css application/xml text/javascript image/jpeg image/jpg image/gif image/png application/json;
# 设置压缩级别,越高资源消耗越大越耗时,但压缩效果越好
gzip_comp_level 5;
# 设置是否携带Vary:Accept-Encoding 的响应头
gzip_vary on;
# 处理压缩请求的 缓冲区数量和大小
gzip_buffers 32 64k;
# 对于不支持压缩功能的客户端请求 不开启压缩机制
gzip_disable "MSIE [1-6]\."; # 比如低版本的IE浏览器不支持压缩
# 设置压缩功能所支持的HTTP最低版本
gzip_http_version 1.1;
# 设置触发压缩的最小阈值
gzip_min_length 2k;
# off/any/expired/no-cache/no-store/private/no_last_modified/no_etag/auth 根据不同配置对后端服务器的响应结果进行压缩
gzip_proxied any;
# --------------------缓存 配置---------------------
# 指定缓存存放目录为/usr/local/nginx/test/nginx_cache_storage,并设置缓存名称为mycache,大小为64m, 1天未被访问过的缓存将自动清除,磁盘中缓存的最大容量为1gb
proxy_cache_path /usr/local/nginx/test/nginx_cache_storage levels=1:2 keys_zone=mycache:64m inactive=1d max_size=1g;
# --------------------限流 配置---------------------
# 对请求速率限流
#limit_req_zone $binary_remote_addr zone=myRateLimit:10m rate=5r/s;
# 对请求连接数限流
limit_conn_zone $binary_remote_addr zone=myConnLimit:10m;
# --------------------重定向 配置---------------------
server {
listen 80;
charset utf-8;
server_name www.example.com example.com;
return 301 https://$server_name$request_uri; # 301永久重定向到https
}
# --------------------负载均衡 配置---------------------
# upstream backendserver {
# server 172.30.128.64:8081 fail_timeout=60s max_fails=3; # 60秒内 如果请求某一个应用失败3次,则认为该应用宕机 时间到后再有请求进来继续尝试连接宕机应用且仅尝试 1 次,如果还是失败,则继续等待 60 秒...以此循环,直到恢复
# server 172.30.128.64:8082;
# server 172.30.128.64:8083 backup; # 设置8083位备机
# }
upstream backendserver {
server 127.0.0.1:9000;
}
# --------------------HTTPS 配置---------------------
server {
#SSL 默认访问端口号为 443
listen 443 ssl;
#填写绑定证书的域名
server_name www.example.com example.com;
#请填写证书文件的相对路径或绝对路径
ssl_certificate /etc/nginx/cert/xxx.pem;
#请填写私钥文件的相对路径或绝对路径
ssl_certificate_key /etc/nginx/cert/xxx.key;
#停止通信时,加密会话的有效期,在该时间段内不需要重新交换密钥
ssl_session_timeout 5m;
#服务器支持的TLS版本
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
#开启由服务器决定采用的密码套件
ssl_prefer_server_ciphers on;
# # 指定 username 参数中只要有字母 就不走nginx缓存
# if ($arg_username ~ [a-z]) {
# set $cache_name "no cache";
# }
# # 前端页面资源
# location /page {
# alias '/usr/local/nginx/test/static/';
# index index_page.html;
# allow all;
# }
# # 后端服务
# location /interface {
# proxy_pass http://backendserver/;
# # 指定哪些错误状态才执行 重试
# proxy_next_upstream error timeout http_500 http_502 http_503 http_504 http_404;
# # 使用名为 mycache 的缓存空间
# proxy_cache mycache;
# # 对于200 206 状态码的数据缓存2分钟
# proxy_cache_valid 200 206 1m;
# # 定义生成缓存键的规则(请求的url+参数作为缓存key)
# proxy_cache_key $host$uri$is_args$args;
# # 资源至少被重复访问2次后再加入缓存
# proxy_cache_min_uses 3;
# # 出现重复请求时,只让其中一个去后端读数据,其他的从缓存中读取
# proxy_cache_lock on;
# # 上面的锁 超时时间为4s,超过4s未获取数据,其他请求直接去后端
# proxy_cache_lock_timeout 4s;
# # 对于请求参数中有字母的 不走nginx缓存
# proxy_no_cache $cache_name; # 判断该变量是否有值,如果有值则不进行缓存,没有值则进行缓存
# # 在响应头中添加一个缓存是否命中的状态(便于调试)
# add_header Cache-status $upstream_cache_status;
# limit_conn myConnLimit 12;
# # limit_req zone=myRateLimit burst=5 nodelay;
# # limit_req_status 520;
# # limit_req_log_level info;
# }
# # 后端服务
# location /interface2 {
# proxy_pass http://backendserver;
# # 使用名为 mycache 的缓存空间
# proxy_cache mycache;
# # 对于200 206 状态码的数据缓存2分钟
# proxy_cache_valid 200 206 1m;
# # 定义生成缓存键的规则(请求的url+参数作为缓存key)
# proxy_cache_key $host$uri$is_args$args;
# # 资源至少被重复访问2次后再加入缓存
# proxy_cache_min_uses 3;
# # 出现重复请求时,只让其中一个去后端读数据,其他的从缓存中读取
# proxy_cache_lock on;
# # 上面的锁 超时时间为4s,超过4s未获取数据,其他请求直接去后端
# proxy_cache_lock_timeout 4s;
# # 对于请求参数中有字母的 不走nginx缓存
# proxy_no_cache $cache_name; # 判断该变量是否有值,如果有值则不进行缓存,没有值则进行缓存
# # 在响应头中添加一个缓存是否命中的状态(便于调试)
# add_header Cache-status $upstream_cache_status;
# limit_conn myConnLimit 12;
# # limit_req zone=myRateLimit burst=5 nodelay;
# # limit_req_status 520;
# # limit_req_log_level info;
# }
}
# include /etc/nginx/conf.d/*.conf;
}
配置示例
修改错误返回值
有些时候希望返回的不是service unavailable, 希望返回某段json, 可以这样设置
/50x.json是返回的json内容, 也可以返回其他网页
server {
...
error_page 5xx /5xx.json;
location = /5xx.json {
root /usr/share/nginx/html;
internal; # 保证这个路径只能内部请求
}
...
}
websocket配置
websocket比较特殊, 需要加入upgrade和connection
location /api/ws/ {
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://127.0.0.1:9000/api/ws/;
}
SSE配置
SSE配置需要去掉缓存, 不然SSE失效
location /api/sse {
proxy_redirect off;
proxy_pass http://127.0.0.1:9000/api/sse;
proxy_buffering off; # 去掉缓存
}
请求速率限流
http{
...
# 对请求速率限流
limit_req_zone $binary_remote_addr zone=myRateLimit:10m rate=5r/s;
server{
location /api {
...
limit_req zone=myRateLimit burst=5 nodelay;
limit_req_status 520; # 返回码
limit_req_log_level info;
}
}
}
-
$binary_remote_addr: 基于客户端IP做限流
zone=myRateLimit:10m 指myRateLimit作为内存区域, 大小10M(16万)IP地址
rate=5r/s 指相同IP每秒最多请求5次(200ms一个请求)
-
burst=5: 削峰, 如果峰值超过rate(比如说200ms来了两个), 则会用一个大小为burst的队列削峰, 然后慢慢根据rate速率处理, 多余的直接503
-
nodelay: 如果是nodelay, 则burst削峰会立即处理, 而不是每200ms取一个
nodelay立即处理, 那么nginx怎么控制并发? 是通过处理但不释放的方式控制. 后面的请求会阻塞
一般建议burst和nodelay一起用, 可以处理突发流量
请求连接数限流
http{
# 针对ip 对请求连接数限流
...
limit_conn_zone $binary_remote_addr zone=myConnLimit:10m;
...
server{
...
limit_conn myConnLimit 12;
}
}
https/SSL
注意需要http_ssl_module
server {
#SSL 默认访问端口号为 443
listen 443 ssl;
#填写绑定证书的域名
server_name www.hzznb-xzll.xyz hzznb-xzll.xyz;
#请填写证书文件的相对路径或绝对路径
ssl_certificate 证书路径;
#请填写私钥文件的相对路径或绝对路径
ssl_certificate_key 私钥路径;
#停止通信时,加密会话的有效期,在该时间段内不需要重新交换密钥
ssl_session_timeout 5m;
#服务器支持的TLS版本
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
#开启由服务器决定采用的密码套件
ssl_prefer_server_ciphers on;
}
ssl_certificate: .pem或者/csr文件
ssl_certificate_key: 一般是.key文件
80重定向到443
server_name www.hzznb-xzll.xyz hzznb-xzll.xyz;
# 重定向到目标地址
return 301 https://$server_name$request_uri;
压缩
http {
# 开启/关闭 压缩机制
gzip on;
# 根据文件类型选择 是否开启压缩机制
gzip_types text/plain application/javascript text/css application/xml text/javascript image/jpeg image/jpg image/gif image/png application/json;
# 设置压缩级别,一共9个级别 1-9 ,越高资源消耗越大 越耗时,但压缩效果越好,
gzip_comp_level 5;
# 设置是否携带Vary:Accept-Encoding 的响应头
gzip_vary on;
# 处理压缩请求的 缓冲区数量和大小
gzip_buffers 32 64k;
# 对于不支持压缩功能的客户端请求 不开启压缩机制
gzip_disable "MSIE [1-6]\."; # 比如低版本的IE浏览器不支持压缩
# 设置压缩功能所支持的HTTP最低版本
gzip_http_version 1.1;
# 设置触发压缩的最小阈值
gzip_min_length 2k;
# off/any/expired/no-cache/no-store/private/no_last_modified/no_etag/auth 根据不同配置对后端服务器的响应结果进行压缩
gzip_proxied any;
}
负载均衡
配置热备
upstream mysvr {
server 192.168.10.121:3333 max_fails=2 fail_timeout=2;
server 192.168.10.122:3333 backup;
}
- max_fails: 允许请求失败的最大次数, 超过时返回proxy_next_upstream模块定义的错误
- fail_timeout: 经历了max_fails失败后暂停服务的时间
轮询(round-robin)
upstream mysvr {
server 127.0.0.1:7878;
server 192.168.10.121:3333;
}
- 请求会分别发送到两个服务器, A-B-A-B……
upstream mysvr {
server 127.0.0.1:7878 weight=1;
server 192.168.10.121:3333 weight=2;
}
- 给不同服务器设置权重, 上面会变成A-B-B-A-B-B……
ip_hash
upstream mysvr {
server 127.0.0.1:7878;
server 192.168.10.121:3333;
ip_hash;
}
- 会让相同客户端请求相同的服务器, 实现session等的共享