1.介绍
Nginx的4大特征
- 反向代理
- 动静分离
- 负载均衡
- api服务
1. 反向代理
- 实现缓存
- 性能与访问效率提升
- 实现tcp udp http socket转发
- 可以转发内网服务器,以提供外部服务
2 动静分离
- 静态: 留给nginx
- 动态: 反向代理给动态服务,如tomcat
3 负载均衡
- 实现动态容灾与扩容
- 请求均衡或指定转发
4 api服务
- 提供openRestry lua定制化编程
优势
- 高并发和高性能: 支持同时100万请求,tomcat 500左右
- 高可靠性:用久了不会出现内存满问题
- 支持热部署: 无需重启
- 开源: 免费 5.可扩展性: 支持各种模块
发布历史版本
- 2004年 10月 0.1.0 第一版
- 2005年 重写http反向代理
- 2011年 0.7.52 支持 window系统
- 2011年 1.0 正式版 支持 keepalive http 长连接 成立公司
- 2013年 支持socket
- 2015年 支持http2 thread pool stream四层方向代理 reuseport 特征
- 2016年 支持动态模块
- 2018年 支持TLS v1.3
组成文件
- 二进制文件
- conf配置
- access访问日志
- error错误日志
开源版本
tengine
阿里巴巴定制的开源版本 github.com/alibaba/ten…
openRestry
支持lua 第三方语言编程的 开源nginx版本
源码文件夹分析
configure # 编译时使用命令,可以定制使用哪个模块
objs # 存放 编译后的nginx运行文件
contrib # 高亮文字使用
html # 静态资源文件夹
conf # nginx配置文件夹
下载 安装
# 下载源码
wget http://nginx.org/download/nginx-1.15.8.tar.gz
# 解压文件
tar -zxvf nginx-1.15.8.tar.gz
# 创建 /usr/local/download 文件夹
mkdir /usr/local/download
# 剪切文件夹到 /usr/local/download/ 下
mv nginx-1.15.8 /usr/local/download/
#切换到 /usr/local/download/nginx-1.15.8/下面
cd /usr/local/download/nginx-1.15.8/
# 覆盖高亮文字提示 ### 文字高亮
cp contrib/vim/indent/nginx.vim vimrc
cp -r vimrc /etc/vimrc
# 查看支持的模块命令
./configure --help
# 执行命令
./configure
make
make install
#查看nginx是否正常安装
whereis nginx
常用命令
#nginx常用命令
#先进入nginx目录
cd /usr/local/nginx/sbin
#启动服务
./nginx
#测试配置是否正常
./nginx -t
#重新加载
./nginx -s reload
#关闭服务
./nginx -s stop
# 查看nginx服务是否启动成功
ps -ef | grep nginx
conf配置语法
- 配置文件由指令与指令块构成
- 每条指令以;分号结尾,指令与参数间以空格符号分隔指令块以 {}大括号将多条指令组织在一起
- include语句允许组合多个配置文件以提升可维护性
- 使用#符号添加注释,提高可读性
- 使用$符号使用变量
- 部分指令的参数支持正则表达式
常用命令
nginx -h # 帮助
nginx -c # 指定配置文件
nginx -g # 指定配置指令
nginx -p prefix #设置 指定运行目录:(默认是:/usr/share/nginx/)
nginx -t # 检查语法
nginx -v # 打印版本
nginx -V # 编译时的模块信息
nginx -s # 发送命令
nginx -s reopen #重新开始记录日志文件
# 等价于
kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`
# 信号与 命令 对照表
nginx -s stop # TERM INT
nginx -s quit # QUIT 优雅地停止Nginx服务(即处理完所有请求后再停止服务)
nginx -s reload # HUP 等价于重新启动
nginx -s reopen # USR1
# 升级新的nginx二级制
kill -USR2 PID # 平滑升级nginx 等价于 kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
kill -WINCH PID # 平滑关闭worker工作进程
kill -QUIT PID # 杀死进程老的master
# 回滚老master操作
kill -HUP 老PID # 相当于执行 nginx -s reload 重新分派worker进程
kill -WINCH 新PID # 平滑关闭新master的 所有worker工作进程
kill -QUIT 新PID # 杀死 新master 需谨慎操作
ps -ef grep nginx # 查看进程
日志切割
方法1 直接备份+重新生成
# 备份
cp /usr/local/nginx/logs/access.log access.log.20230324
# 重新打开
nginx -s reopen # 重新打开日志 写入access.log
方法2 crontab 方案
vi /home/scripts/cut_del_nginx_logs.sh
#!/bin/bash
#初始化
LOGS_PATH=/usr/local/nginx/logs
YESTERDAY=$(date -d "yesterday" +%Y%m%d)
#按天切割日志 切割access 和 error
mv ${LOGS_PATH}/access.log ${LOGS_PATH}/access.log.${YESTERDAY}
mv ${LOGS_PATH}/error.log ${LOGS_PATH}/error.log.${YESTERDAY}
#向nginx主进程发送USR1信号,重新打开日志文件,否则会继续往mv后的文件写数据的。原因在于:linux系统中,内核是根据文件描述符来找文件的。如果不这样操作导致日志切割失败。
# grep -v grep是过滤掉不包含grep的内容
# awk '{print $2}' 找到最后匹配的 第二个参数 则为 pid
# root 11151 0.0 0.0 49772 948 ? Ss 2022 0:00 nginx: master process ./sbin/nginx
# root 114498 0.0 0.0 112816 976 pts/1 S+ 09:30 0:00 grep --color=auto nginx: master process
kill -USR1 `ps axu | grep "nginx: master process" | grep -v grep | awk '{print $2}'`
#删除2个月前的日志
cd ${LOGS_PATH}
find . -mtime +60 -name "*20[1-9][3-9]*" | xargs rm -f
exit 0
# 写入 crontab
#执行命令
crontab -e
#写入文件并保存
59 23 * * * /home/scripts/cut_del_nginx_logs.sh
# 查看配置
crontab -l
# 检测 crond
service crond status
# 检测 开机启动状态 图形界面
yum intall ntsysv
ntsysv
# 加入开机自动启动:
chkconfig –-level 35 crond on
# 重启服务
service crond restart #重启服务
# 其他命令
service crond start # 启动服务
service crond stop # 关闭服务
service crond restart # 重启服务
service crond reload # 重新载入配置
方法3 使用logrotate 备份和生成
logratate介绍
-d或--debug 详细显示指令执行过程,便于排错或了解程序执行的情况。
-f或--force 强行启动记录文件维护操作,纵使logrotate指令认为没有需要亦然。
-s<状态文件>或--state=<状态文件> 使用指定的状态文件。
-v或--version 显示指令执行过程。
-usage 显示指令基本用法。
常用命令
yum -y install logrotate anacron
vim /etc/logrotate.d/nginx
/var/log/nginx/*.log
{
daily #指定转储周期为每天
rotate 60 #保留总文件数,由于一天一个所以就是总天数
create
dateext #日志压缩文件以当天日期做后缀
dateformat -%Y%m%d_%S
missingok
copytruncate
nocompress
sharedscripts
}
logrotate -vf /etc/logrotate.d/nginx #测试语法
rm -rf /etc/cron.daily/logrotate # 删除系统默认规则,先检测有没有其他有用的配置
crontab -e
# 新增下面规则 这样每天凌晨0点0分就会执行nginx日志切割
59 23 * * * logrotate -f /etc/logrotate.d/nginx
# 检测是否生效 查看日志
tail -f 100 /var/log/cron
# 最终生成的记录地址 如果是root用户编辑 则保存为root
cat /var/spool/cron/crontabs/root
# 重启服务
service crond restart
调试是否生效与注意事项
# 注意点:
# 1. 使用-vf 如果有error 就是异常,没有生成文件
logrotate -vf /etc/logrotate.d/nginx #如果提示下面信息则有问题
Potentially dangerous mode on /etc/logrotate.d/nginx: 0777
error: Ignoring /etc/logrotate.d/nginx because it is writable by group or others.
Creating stub state file: /var/lib/logrotate.status
Reading state from file: /var/lib/logrotate.status
Allocating hash table for state file, size 64 entries
# 修复方法:
chmod -R 644 /etc/logrotate.d
# 1. 配置crontab -e 注意 不能使用/usr/sbin/logrotate 只能使用全局命令
# 2. 不能使用-vf 只能使用 -f
# 2. 使用-f 情况
logrotate -f /etc/logrotate.d/nginx #如果提示下面信息则其实已经生成 只打印了错误提示
error: /etc/logrotate.d/nginx:1 lines must begin with a keyword or a filename (possibly in double quotes)
error: /etc/logrotate.d/nginx:11, unexpected text after }
# 调试方法:
## 设置为每分钟执行一次
* * * * * logrotate -f /etc/logrotate.d/nginx
## 通过不断输入date查看是否跨分钟
date
date
date
## 查看日志是否生成
ls -l /usr/local/nginx/logs/
## 设置为每天晚上整点 执行一次
## 由于使用了 daily 指定转储周期为每天属性,所以当天生成一次后,需要修改系统时间才能查看后面其他天效果
## 注意调整系统时间必须提前1分钟左右,可能linux调度是按1分钟执行,第一次可以立马有效,后面都要一分钟。
## 当前已经生成的不能再重新设置,只能延后一天,不能往前设置。
# 修改为 第一次
date -s "2023-05-12 23:58:00"
# 修改为 第二次
date -s "2023-05-13 23:58:00"
# 还原系统时间
yum install ntpdate
ntpdate ntp.ubuntu.com
插件安装后 nginx二进制升级
# make生成
make #这里不要进行make install,否则就是覆盖安装
# 然后备份原有已安装好的nginx
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
# 再进行覆盖
cp ./objs/nginx /usr/local/nginx/sbin/
# 平滑升级 nginx ,此时 系统会有两个master
kill -USR2 13195
# 通过 WINCH 关闭老master上所有worker ,但master 依然保留,已被恢复使用
kill -WINCH 13195
2.日志分析 goacess
要注意参数 --log-format COMBINED
安装版
# 下载
wget https://tar.goaccess.io/goaccess-1.3.tar.gz
# 解压
tar -xzvf goaccess-1.3.tar.gz $ cd goaccess-1.3/
./configure --enable-utf8 --enable-geoip=legacy
make && make install
# 命令行显示
goaccess access.log
# 生成一个HTML报告:
goaccess -a -d -f /srv/logs/access.log --port=7891 -p /srv/data/goaccess.conf > /srv/report/report.html --real-time-html
docker版
allinurl/goaccess
tail -f /docker_workspace/docker-compose/docker_compose_ylzs/logs/nginx/access.log | docker run -p 7890:7890 --rm -i -e LANG=$LANG allinurl/goaccess -a -o html --log-format COMBINED --real-time-html - > /docker_workspace/docker-compose/docker_compose_ylzs/dist/html/report/index.html
启动一个nginx 读取report.html
server {
listen 8086;
server_name localhost;
location / {
root /usr/share/nginx/html/report;
try_files $uri $uri/ /report.html;
}
}
3.配置指令块
- upstream : 上游服务器配置
- http:本地全局的http配置
- server:单个server的服务配置
- location:单个请求的配置
4.单位
## 时间单位
y # 年
M # 月
w # 周
d # 天
h # 小时
m # 分钟
s # 秒
ms # 毫秒
## 传输单位
不写单位 # 字节 byte
k/K # kb
m/M # mb
g/G # gb
5. error_log 与 debug调试
5.1debug定位问题:出现错误时的应对方案
debug_points abort | stop;
功能: 某些Nginx模块可能存在代码Bug,在生产环境则忽略问题,打开debug points后则遇到问题后停止服务方便定位问题
工作方式
abort #生成核心转储coredump文件并结束进程
stop # 结束进程
生效时刻
- 任何Nginx模块调用ngx_debug_point()函数的位置,例如
- ssi模块中输出“the same bufwas used in ssi”日志后
- 共享内存分配出错,输出“ngx_slab_alloc(): page is busy”日志后
5.2控制debug级别error.log日志的输出
配置error错误日志格式
error_log级别分为debug、info、notice、warn、error、crit,
默认为error,crit记录的日志最少,而debug记录的日志最多,
debug级别需要 编译进入nginx ./configure --with-debug ...
支持范围配置
error_log logs/error.log notice; # 全局
http{
server {
error_log logs/error1.log notice; # 某个server
# 用于验证具体问题的 uri地址
location /app/mymodule/add {
error_log logs/error2.log debug; #只针对某个请求做debug处理
proxy_pass http://xx.xx.xx.xx:12091;
}
location /app {
proxy_pass http://172.17.0.1:12091;
}
}
}
限制指定ip debug
Syntax: debug_connection address | CIDR | unix:;
Default: —
Context: events
针对特定客户端打印DEBUG级别日志,其他日志仍然遵从error log指令后设置的日志级别
注意: configure中必须加--with-debug编译选项
events{
debug_connection 127.0.0.1;
}
DEBUG日志流程
- 建立连接
- SSL握手
- 接收请求的HTTP头部
- 请求行解析
- 请求头部解析
- 11个阶段的处理
- 寻找处理请求的location
- 反向代理构造上游请求
- 接收客户端请求包体
- 构造出的响应头部
- 发送响应:过滤模块
6.实战
文件夹目录访问
server {
server_name localhost;
listen 8001;
location / {
alias html/;
autoindex on;
index a.html; # 当与 autoindex 同时设置 index优先于autoindex
# set $limit_rate 1k; # 限制访问速度
autoindex_exact_size off;
autoindex_format html;
autoindex_localtime on;
}
error_page 500 502 503 504 /50x.html; # 当服务器异常返回50的错误页面
}
配置日志格式
http {
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 logs/access.log main; # 全局配置
server { # 支持不同代码块写入日志
listen 8888;
server_name localhost;
access_log logs/host.access.log main;
}
}
7.加密相关
TLS 与SSL 发展历史
- SSL:Secure Sockets Layer
- TLS:Transport Layer Security
- 1995 SSL3.0
- 1999 TLS1.0 微软重新命名
- 2006 TLS1.1
- 2008 TLS1.2
- 2018 TLS1.3
ssl 属于 表示层的内容。在http 与 tcp 应用层与传输层之间
TLS 安全密码套件
- 密钥交互算法
- 身份验证算法
- 对称加密算法,强度 分组模式
- 签名hash算法
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
对称与非对称
对称逻辑
明文 1110
密钥 0010
密文 1100
密文 = 明文 + 密钥 # 位运算求与
非对称
通过公钥进行加密,私钥进行解密。 即使暴露了 公钥也无法破解密文。
PKI 公钥基础设施
- CA机构颁发证书
- 服务配置证书
- 客户端访问拿到证书先去CA验证
- 每一个CA上都还有上一个CA 直到根的CA 也就是操作系统内置信任的CA
证书类型
- EV 证书 扩展验证 extended validated 收费 适合银行证券 地址栏有绿标和 文字描述
- OV 证书 组织验证 org validated 收费 适合政府机构 地址栏有绿标
- DV 证书 域名验证 domain validated 人业务 无绿标 型证书不包含企业名称信息
tls 通讯过程
- 验证身份
- 达成安全套件共识
- 传递秘钥
- 加密通讯
自动生成秘钥
使用 python2-certbot-nginx 生成配置
# 安装
yum -y install yum-utils
yum-config-manager --enable rhui-REGION-rhel-server-extras rhui-REGION-rhel-server-optional
# 获取证书
certbot --nginx
# 或者输入完整信息
certbot --nginx --nginx-server-root=/usr/local/nginx/conf/ -d www.test.pub
# conf文件自动生成秘钥配置
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
# 配置定时更新
1 1 * * 6 certbot renew --renew-hook "nginx -s reload"