为保证各项服务正常运行,其中系统时间的准确性是至关重要的。在 CentOS-7 之后的版本默认使用 chrony
做系统时间同步服务,而 CentOS-6
版本中使用 ntp
服务来同步时间。
chrony
采用 Client-Server(C/S) 架构,对应服务端: chronyd
,客户端: chronyc
。
为保证各项服务正常运行,其中系统时间的准确性是至关重要的。在 CentOS-7 之后的版本默认使用 chrony
做系统时间同步服务,而 CentOS-6
版本中使用 ntp
服务来同步时间。
chrony
采用 Client-Server(C/S) 架构,对应服务端: chronyd
,客户端: chronyc
。
Nginx 采用 master-worker 进程模式,worker 进程数需与CPU核数量相同。多进程之间使用共享内存,父子进程之间是使用信号管理的。
1 | ps -ef | grep nginx |
Master 进程
Worker 进程
Nginx 命令行
正则表达式效验工具 pcretest
CentOS 8
1 | $ yum install -y pcre2-tools |
1 | mv nginx nginx.old |
1 | mv logs/access.log back.log |
GoAccess
可视化实时监控 access 日志。
1 | yum install python2-certbot-nginx |
握手缓存:session
支持的安全套件:
gzip
error_page 404 =200 /404.html
error_page 500 502 503 504 /50x.html
return 200 “Hello world”
rewrite
在 server
块中可通过配置 rewrite_log on
参数,将 rewrite
请求记录到 nginx access
日志中。
if
~*
、!~*
location [=||*|^~] uri {…}
Syntax: location [=||*|^~] uri {…}
Context: server, location
合并连续的 /
符号,Default: merg_slashes on
匹配规则
匹配顺序
无顺序匹配全部前缀字符串 location
使用匹配上的 = 精确匹配 location: 匹配 = 字符串
。
使用匹配上的 ^~ 字符串 location:匹配 ^~ 字符串
。
多个匹配项,记住最长匹配的前缀字符串 location
按照 nginx.conf 中的顺序依次匹配正则表达式 location。
auth_basic
auth_basic “test auth_basic”
auth_basic_user_file file
生成工具: htpasswd
,可通过执行 yum install -y httpd-tools
命令安装。
1 | htpasswd -c -b file user pass |
try_files
默认安装、无法禁用
mirror
实时拷贝流量:precontent 阶段的 mirror 模块,默认编译进 Nginx,编译时可通过 --without-http_mirror_module
参数移除。
处理请求时,生成子请求访问其他服务,对子请求的返回值不做处理。
Syntax: mirror uri | off;
Default: mirror off;
Context: http, server, location
Syntax: mirror_request_body on | off;
Default: mirror_request_body on;
Context: http, server, location
content阶段
static: root 和 alias 指令
功能:将 url 映射为文件路径,以返回静态文件内容
区别:
关闭未找到文件时的错误日志:log_not_found off;
展示目录:autoindex on;
将多个小文件合并到一个http请求,最终将所有文件内容合并进行响应:ngx_http_concat_module
。
access_log path 可使用变量,但会造成频繁开关文件。可通过 open_log_file_cache
参数进行优化。
变量
防盗链 valid_referers none blocked server_names *.codezm.com $invalid_referer
keepalive
提升链接效率
1 | # nginx 向客户端返回的 keepalive |
http
块中增加 server_tokens off;
关闭 Response Headers
中 Server
对应 nginx
版本号,以提升安全性。7层应用反向代理:
uwsgi
fastcgi
scgi
http
memcached
websocket http://www.websocket.org/echo.html
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “upgrade”;
stream 4层反向代理:
名称 | 释义 |
---|---|
$upstream_addr | 上游服务器的IP地址,格式为可读的字符串,例如:127.0.0.1:8080 |
$upstream_connect_time | 与上游服务建立连接消耗的时间,单位为秒,精确到毫秒 |
$upstream_header_time | 接收上游服务发回响应中http头部所消耗的时间,单位为秒,精确到毫秒 |
$upstream_response_time | 接收完整的上游服务响应所消耗的时间,单位为秒,精确到毫秒 |
$upstream_http_名称 | 从上游服务返回的响应头部的值 |
$upstream_bytes_received | 从上游服务接收到的响应长度,单位为字节 |
$upstream_response_length | 从上游服务返回的响应包体长度,单位为字节 |
$upstream_status | 上游服务返回的HTTP响应中的状态码,如果未连接上,该变量值为502 |
$upstream_cookie_名称 | 从上游服务返回发回的 Set-Cookie 中取出的 cookie 值 |
$upstream_trailer_名称 | 从上游服务的响应尾部取到的值 |
$upstream_http_server | 上游服务 |
$upstream_cache_status | 缓存状态 |
client_max_body_size 1m;
仅对请求头部中含有 Content-Length
有效超出最大长度后,返回 413
错误。
client_body_temp_path path [level1 [level2 [level3]]]
,默认 client_body_temp_path client_body_temp;
。
client_body_in_file_only on|clean|off
,默认 client_body_in_file_only off;
。
client_body_timeout time;
,默认 client_body_timeout 60s;
。读取包体时超时,则返回 408 错误。
Syntax: proxy_connect_timeout time;
Default: proxy_connect_timeout 60s;
Context: http,server,location
超时后,会向客户端生成 http 响应,响应码为:502。
Syntax: proxy_next_upstream http_502|…;
Default: proxy_next_upstream error timeout;
Context: http,server,location
当上游连接返回 502
错误码后,可以再设置另一个上游服务提供处理。
Syntax: proxy_socket_keepalive on|off;
Default: proxy_socket_keepalive off;
Context: http,server,location
Syntax: keepalive connections;
Default: -;
Context: upstream
一个 tcp 连接最多处理多少个http请求。
Syntax: keepalive_requests number;
Default: keepalive_requests 100;
Context: upstream
Syntax: proxy_send_timeout time;
Default: proxy_send_timeout 60s;
Context: http,server,location
Syntax: proxy_buffer_size size;
Default: proxy_buffer_size 4k|8k;
Context: http,server,location
error_log: upstream sent too big header
Syntax: proxy_buffer number size;
Default: proxy_buffer 8 4k|8k;
Context: http,server,location
Syntax: proxy_buffering on|off;
Default: proxy_buffering on;
Context: http,server,location
使用上游服务设置的 Server
header 头配置。
proxy_pass_header server;
当上游响应的响应码 >= 300 时,应将响应返回客户端还是按 error_page 指令处理
error_page 500 /500.html;
proxy_intercept_errors on;
proxy_cache_path
LRU淘汰算法:末位淘汰。
查看上下文切换次数
惊群
reuseport
linux > 3.9,centos >= 7.0。listen 80 reuseport;
提升 cpu 缓存命中率
work_cpu_affinity: auto [cpumask];
1 | # cpu L1级指令缓存 |
netstat -nap | grep tcp
主动建立连接时,发 SYN 的重试次数:net.ipv4.tcp_syn_retries = 6
。
建立连接时的本地端口可用范围:net.ipv4.ip_local_port_range = 32768 60999
。
主动建立连接时,应用层超时时间:proxy_connect_timeout 60s;
。
(半链接)SYN Queue
SYN_RCVD 状态链接的最大个数:net.ipv4.tcp_max_syn_backlog
被动建立连接时,发 SYN/ACK 的重试次数:net.ipv4.tcp_synack_retries
。
(全连接)ACCEPT Queue
最大个数:backlog
net.core.netdev_max_backlog
。net.ipv4.tcp_max_syn_backlog
。net.ipv4.tcp_abort_on_overflow
。net.ipv4.tcp_syncookies=1
。操作系统全局
fs.file-max
,sysctl -a | grep file-max
。fs.file-nr
可以查看当前已分配、正使用、上限:fs.file-nr=21632 0 40000500
,sysctl -a | grep file-nr
限制用户
限制进程
worker_rlimit_nofile number;
Nginx 上游+下游间连接句柄数限制: worker_connections number;
SYN队列 - 未完成握手:net.ipv4.tcp_max_syn_backlog = 262144
。
ACCEPT 队列 - 已完成握手:net.core.somaxconn
,系统级最大 backlog
队列长度。
Nginx: listen address[:port] [backlog=number]
。限制已握手队列。
net.ipv4.tcp_fastopen
proxy_timeout: 1m;
当读、写超时指令生效引发连接关闭时,通过发送 RST
立刻释放端口、内存等资源来关闭链接: reset_timeout_connection on|off;默认:
off`。
ssl_session_cache off | none
1 | # 1m 大约提供 4000 个链接 |
https://ssl-config.mozilla.org/
Nginx 将会话 Session 中的信息作为 tickets 加密发给客户端,当客户端下次发起 TLS 链接时带上 tickets,由 nginx 解密验证后复用会话 Session。
会话票证虽然更易在 Nginx 集群中使用,但破坏了 TLS/SSL 的安全机制,有安全风险,必须频繁更换 tickets 密钥。
是否开启会话票证服务:
Syntax: ssl_session_tickets on | off;
Default: ssl_session_tickets on;
Context: http,server
使用会话票证时加密 tickets 的密钥文件,未配置时会随机生成:
Syntax: ssl_session_ticket_key file;
Default: -
Context: http,server
1 | ssl_session_ticket_key ticket.key; |
1 | openssl rand 80> ticket.key |
优点
- 减少握手次数
- 通过减少并发连接数减少了服务器资源的消耗
- 降低 TCP 拥塞控制的影响
Syntax: keepalive_requests number;
Default: keepalive_requests 100;
Context: http,server,location
Syntax: keepalive_requests number;
Default: keepalive_requests 100;
Context: upstream
功能:
通过实时压缩 http 包体,提升网络传输效率
模块:ngx_http_gzip_module
,通过 --without-http_gzip_module
禁用模块
Syntax: gzip on | off;
Default: gzip off;
Context: http,server,location, if in location
1 | gzip on; |
指定压缩文件类型
Syntax: gzip_types mime-type …;
Default: gzip_types text/html;
Context: http,server,location
1 | gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml; |
指定压缩文件的最小字节数,当小于此字节数时不进行压缩。
Syntax: gzip_min_length length;
Default: gzip_min_length 20;
Context: http, server, location
1 | gzip_min_length 1k; |
通过设置正则规则,表明哪些 User-Agent
头不使用 gzip 压缩。
Syntax: gzip_disable regex …;
Default: —
Context: http, server, location
1 | # 禁用IE 1-6 gzip |
指定压缩的 http 版本,默认:http_version: 1.1 才启用压缩处理。
Syntax: gzip_http_version 1.0 | 1.1;
Default: gzip_http_version 1.1;
Context: http, server, location
是否压缩上游的响应
Syntax: gzip_proxied off | expired | no-cache | no-store | private | no_last_modified | no_etag | auth | any …;
Default: gzip_proxied off;
Context: http, server, location
Cache-Control
头部,且其值含有 no-cache
值,则压缩响应。Cache-Control
头部,且其值含有 private
值,则压缩响应Last-Modified
头部,则压缩响应ETag
头部,则压缩响应Authorization
头部,则压缩响应配置缓冲区大小
Syntax: gzip_buffers number size;
Default: gzip_buffers 32 4k|16 8k;
Context: http, server, location
压缩率等级,1-9,1:压缩速度最快,压缩率最低。
Syntax: gzip_comp_level level;
Default: gzip_comp_level 1;
Context: http, server, location
是否在响应中返回 Vary: Accept-Encoding
。
Syntax: gzip_vary on | off;
Default: gzip_vary off;
Context: http, server, location
变量
$gzip_ratio
1 | # 开启缓存 |
升级更高效的 http2 协议:向前兼容 http/1.x
协议
HTTP/2
是建立在 TLS/SSL
协议上的,所以必须有证书支持。
nginx >= 1.9.5。可通过 nginx -v
查看当前版本。
编译 nginx 时所使用的 openssl >= 1.0.2。可通过 openssl version
查看当前系统 openssl
版本,通过 nginx -v
可查看编译 nginx 时 openssl
版本。
1 | server { |
HTTP/2 and SPDY indicator
。适用于大文件:直接IO。- http://nginx.org/en/docs/http/ngx_http_core_module.html#directio
Syntax: directio size | off;
Default: directio off;
Context: http, server, location
1 | # 当文件 size 大于 10M 时,启用 directio。 |
当启用 directio
时,将自动禁用 sendfile
。
异步IO - http://nginx.org/en/docs/http/ngx_http_core_module.html#aio
Syntax: aio on | off | threads[=pool];
Default: aio off;
Context: http, server, location
sendfile on;
将使用零拷贝技术:通过获取对应文件的句柄发送给 socket 缓冲区。
模块:ngx_http_gzip_static_module
,通过 --with-http_gzip_static_module
启用模块。
功能:检测到同名 .gz
文件时,返回 .gz
文件内容。
Syntax: gzip_static on | off | always;
Default: gzip_static off;
Context: http, server, location
lua 防火墙 https://github.com/loveshell/ngx_lua_waf
1 | tcpdump -i lo port 514 -A -s 0 |
1 | ./configure --user=apache --group=apache --prefix=/data/nginx-debug \ |
HTTP请求11个阶段:
postread
阶段
在 X-Forward-For 的最左边才是真实用户的地址,右边都是代理地址,当我们把 real_ip_header 设置为 X-Forward-For 时,如果没有启用 环回地址 real_ip_recursive,我们取到的 $remote_addr 是 X-Forward-For 中最右边的 ip,无论是否设置了 set_real_ip_from;如果启用了环回地址 real_ip_recursive on,那么就获取最左边的 ip,也就是排除设置了 set_real_ip_from(可信地址外的)。不一定是最左边的IP,而是从右边开始数,第一个非可信地址的IP(set_real_ip_from 可信地址外的)
当 nginx 前存在 SLB、反向代理时,我们是无法直接通过 $remote_addr
得到客户端IP地址的,此时变量 $remote_addr
的值是 SLB
等服务器的IP,并非真实客户端请求IP。
进而无法通过 $remote_addr
变量来对客户端做限流、限速等策略。
可通过 --with-http_realip_module
模块来获取真实客户端IP,默认是没有编译到 nginx
中的,需要通过 ./configure
配置时手动添加,来启用此模块。
1 | curl -H 'X-Forwarded-For: 93.184.216.34, 192.168.96.3, 127.0.0.1' -H 'cdn-src-ip: 122.4.117.22' realip.codezm.com |
限制并发连接。
1 | location / { |
1 | curl "var.codezm.com?name=codezm&age=22" |
1 | location / { |
1 | curl -H 'cdn-src-ip: 93.184.216.34' realip.codezm.com |
MySQL使用技巧
linux 常用命令
利用 tcpdump
抓包,利用 tcpdump/wireshark
来分析网络数据。
对于阅读者来说,提供文章字数统计、阅读时长可以起到友好的提示作用。
在移动支付盛行时代,在国内最常见的就属微信支付和支付宝支付了。
在写文章时,常常需要图片来说明需求或表明释义。而对于图片的存放,本文将介绍两种方式:
以本文文章链接地址为例,默认URL地址:http://localhost:4000/2020/12/01/hexo-博客搭建之文章链接地址/
在浏览器中则是:http://localhost:4000/2020/12/01/hexo-%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA%E4%B9%8B%E6%96%87%E7%AB%A0%E9%93%BE%E6%8E%A5%E5%9C%B0%E5%9D%80/
而本文将介绍如何将其转换成简短的URL地址:http://localhost:4000/posts/3ace8d52.html