nginx
约 2362 字大约 8 分钟
2024-08-12
安装
# HomeBrew 快捷安装
brew install nginx
# 编译安装
...nginx 路径: /usr/local/etc/nginx/
brew 安装的 nginx 路径:/opt/homebrew/etc/nginx/nginx.conf
将 nginx.conf 的 user 改为和启动用户一致: user root;
常用命令
sudo nginx # 启动(管理员)
sudo nginx -s stop # 关闭(管理员)
sudo nginx -s reload # 重启(管理员)
sudo nginx -t # 检查语法
sudo nginx -s quit # 平滑关闭nginx
ps aux | grep nginx # 检查 nginx 进程
# 查看 nginx 的启动用户
ps aux | grep "nginx: worker process" | awk '{print $1}'内置变量
$args : 这个变量等于请求行中的参数,同$query_string
$content_length : 请求头中的Content-length字段。
$content_type : 请求头中的Content-Type字段。
$document_root : 当前请求在root指令中指定的值。
$host : 请求主机头字段,否则为服务器名称。
$http_user_agent : 客户端agent信息
$http_cookie : 客户端cookie信息
$limit_rate : 这个变量可以限制连接速率。
$request_method : 客户端请求的动作,通常为GET或POST。
$remote_addr : 客户端的IP地址。
$remote_port : 客户端的端口。
$remote_user : 已经经过Auth Basic Module验证的用户名。
$request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。
$scheme : HTTP方法(如http,https)。
$server_protocol : 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。
$server_name : 服务器名称。
$server_port : 请求到达服务器的端口号。
$request_uri : 包含请求参数的原始URI,不包含主机名,如: ”/foo/bar.php?arg=baz”。
$uri : 不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
$document_uri : 与$uri相同模块基本配置
监听端口 (port)
server {
listen 80; # 标准 HTTP 协议
listen 443 ssl; # 标准 HTTPS 协议
listen 443 ssl http2; # 对于 http2
listen [::]:80; # 使用 IPv6 在 80 上收听
# 仅收听使用 IPv6
listen [::]:80 ipv6only=on;
}域名 (server_name)
server {
# 监听 example.com
server_name example.com;
# 监听多个域
server_name example.com www.example.com;
# 监听所有子域
server_name *.example.com;
# 监听所有顶级域
server_name example.*;
# 监听未指定的主机名(监听 IP 地址本身)
server_name "";
}location
1. location 路径映射路径
= 进行普通字符精确匹配。也就是完全匹配。
^~ 前缀匹配。如果匹配成功,则不再匹配其他location。
~ 表示执行一个正则匹配,区分大小写
~* 表示执行一个正则匹配,不区分大小写
/xxx/ 常规字符串路径匹配
/ 通用匹配,任何请求都会匹配到location 优先级从高到底:
= > /a/b/c > ^~ path > ~,~* path > /a/b > /example:
location = / {
# 精确匹配/,主机名后面不能带任何字符串 /
[ configuration A ]
}
location / {
# 匹配所有以 / 开头的请求。
# 但是如果有更长的同类型的表达式,则选择更长的表达式。
# 如果有正则表达式可以匹配,则优先匹配正则表达式。
[ configuration B ]
}
location /documents/ {
# 匹配所有以 /documents/ 开头的请求,匹配符合以后,还要继续往下搜索。
# 但是如果有更长的同类型的表达式,则选择更长的表达式。
# 如果有正则表达式可以匹配,则优先匹配正则表达式。
[ configuration C ]
}
location ^~ /images/ {
# 匹配所有以 /images/ 开头的表达式,如果匹配成功,则停止匹配查找,停止搜索。
# 所以,即便有符合的正则表达式location,也不会被使用
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
# 匹配所有以 gif jpg jpeg结尾的请求。
# 但是 以 /images/开头的请求,将使用 Configuration D,D具有更高的优先级
[ configuration E ]
}
location /images/ {
# 字符匹配到 /images/,还会继续往下搜索
[ configuration F ]
}
location = /test.htm {
root /usr/local/var/www/htm;
index index.htm;
}2. 路径拼接问题
下面四种情况分别用 http://192.168.1.4/proxy/test.html 进行访问。
# 1 会被代理到http://127.0.0.1:81/test.html 这个url
location /proxy/ {
proxy_pass http://127.0.0.1:81/;
}
# 2 会被代理到http://127.0.0.1:81/proxy/test.html 这个url
location /proxy/ {
proxy_pass http://127.0.0.1:81;
}
# 3 会被代理到http://127.0.0.1:81/ftlynx/test.html 这个url。
location /proxy/ {
proxy_pass http://127.0.0.1:81/ftlynx/;
}
# 4 会被代理到http://127.0.0.1:81/ftlynxtest.html 这个url
location /proxy/ {
proxy_pass http://127.0.0.1:81/ftlynx;
}3. 本地文件代理 alias
location ^~ /asset/ {
alias /Users/Rain/code/Project/src/asset/ ;
autoindex on;
index index.html index.htm;
}rewrite
重写链接
rewrite regex replacement [flag];
flag
last:停止处理当前的 ngx_http_rewrite_module 的指令集,并开始搜索与更改后的 URI 相匹配的 location;
break:停止处理当前的 ngx_http_rewrite_module 指令集,就像上面说的 break 指令一样;
redirect:返回 302 临时重定向。
permanent:返回 301 永久重定向。
example:
rewrite ^/recommend/campus$ $scheme://nowpick.nowcoder.com/w/recommend/campus redirect ;
rewrite ^/school/schedule/(\d+)$ https://nowpick.nowcoder.com/w/school/schedule/$1 redirect ;
rewrite ^/activity/v2/special-activity/index/(\w+)$ $scheme://www.nowcoder.com/jobs/activity/v2/special-activity/index/$1 redirect ;负载均衡
简单实例
upstream node_js {
server 0.0.0.0:3000;
server 0.0.0.0:4000;
server 127.155.142.421;
}权重
upstream test {
server localhost:8080 weight=9;
server localhost:8081 weight=1;
}ip_hash
解决负载均衡 session 的问题
upstream test {
ip_hash;
server localhost:8080;
server localhost:8081;
}fair
响应时间短的优先分配
upstream backend {
fair;
server localhost:8080;
server localhost:8081;
}url_hash
按访问url的hash结果来分配请求
upstream backend {
hash $request_uri;
hash_method crc32;
server localhost:8080;
server localhost:8081;
}keepalive
激活缓存以连接到上游服务器
upstream memcached_backend {
server 127.0.0.1:11211;
server 10.0.0.2:11211;
keepalive 32;
}server 可选参数
| 参数名 | 说明 |
|---|---|
weight | 访问权重数值越高,收到请求越多 |
fail_timeout | 指定的时间内必须提供响应 |
max_fails | 尝试失败服务器连接的最大次数 |
down | 标记一个服务器不再接受任何请求 |
backup | 有服务器宕机,标记的机器接收请求 |
反向代理
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://0.0.0.0:3000;
# 其中 0.0.0.0:3000 是绑定在
# 0.0.0.0端口3000 列表上的 Node.js 服务器
}
}负载均衡 + 反向代理
upstream node_js {
server 0.0.0.0:3000;
# 其中 0.0.0.0:3000 是绑定在
# 0.0.0.0端口3000 列表上的 Node.js 服务器
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://node_js;
}
}升级连接(适用于支持 WebSockets 的应用程序)
upstream node_js {
server 0.0.0.0:3000;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://node_js;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}跨域
server {
listen 80;
server_name api.xxx.com;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET,POST,HEAD';
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
}重定向 URI
upstream test {
server 127.0.0.1:8080;
server localhost:8081;
}
server {
listen 80;
server_name api.xxx.com;
location / {
root html; # 去请求../html文件夹里的文件
index index.html index.htm; # 首页响应地址
}
# 用于拦截请求,匹配任何以 /api/开头的地址,
# 匹配符合以后,停止往下搜索正则。
location ^~/api/{
# 代表重写拦截进来的请求,并且只能对域名后边的除去传递的参数外的字符串起作用
# 例如www.a.com/api/msg?meth=1&par=2重写,只对/api/msg重写。
# rewrite后面的参数是一个简单的正则 ^/api/(.*)$,
# $1代表正则中的第一个(),$2代表第二个()的值,以此类推。
rewrite ^/api/(.*)$ /$1 break;
# 把请求代理到其他主机
# 其中 http://www.b.com/ 写法和 http://www.b.com写法的区别如下
# 如果你的请求地址是他 http://server/html/test.jsp
# 配置一: http://www.b.com/ 后面有“/”
# 将反向代理成 http://www.b.com/html/test.jsp 访问
# 配置一: http://www.b.com 后面没有有“/”
# 将反向代理成 http://www.b.com/test.jsp 访问
proxy_pass http://test;
# 如果 proxy_pass URL 是 http://a.xx.com/platform/ 这种情况
# proxy_cookie_path应该设置成 /platform/ / (注意两个斜杠之间有空格)。
proxy_cookie_path /platfrom/ /;
# 设置 Cookie 头通过
proxy_pass_header Set-Cookie;
}
}屏蔽 IP
可以放到 http, server, location, limit_except 语句块
include blockip.conf;
在 blockip.conf 里面输入内容,如:
deny 165.91.122.67;
deny IP; # 屏蔽单个 ip 访问
allow IP; # 允许单个 ip 访问
deny all; # 屏蔽所有 ip 访问
allow all; # 允许所有 ip 访问
deny 123.0.0.0/8; # 屏蔽整个段即从 123.0.0.1 到 123.255.255.254 访问的命令
deny 124.45.0.0/16; # 屏蔽IP段即从 123.45.0.1 到 123.45.255.254 访问的命令
deny 123.45.6.0/24; # 屏蔽IP段即从 123.45.6.1 到 123.45.6.254 访问的命令
# 如果你想实现这样的应用,除了几个IP外,其他全部拒绝
allow 1.1.1.1;
allow 1.1.1.2;
deny all;图片防盗链
location ~* \.(gif|jpg|png|swf|flv)$ {
root html;
valid_referers none blocked *.nginx.com;
if ($invalid_referer) {
rewrite ^/ www.nginx.cn;
# return 404;
}
}屏蔽文件目录
# 通用备份和归档文件
location ~* "\.(old|orig|original|php#|php~|php_bak|save|swo|aspx?|tpl|sh|bash|bak?|cfg|cgi|dll|exe|git|hg|ini|jsp|log|mdb|out|sql|svn|swp|tar|rdf)$" {
deny all;
}
#拒绝访问 .git 和 .svn 目录
location ~ (.git|.svn) {
deny all;
}
#拒绝访问隐藏文件和目录
location ~ /\.(?!well-known\/) {
deny all;
}Gzip 配置
gzip on;
gzip_buffers 16 8k;
gzip_comp_level 6;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_proxied any;
gzip_vary on;
gzip_types
text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml image/svg+xml
text/javascript application/javascript application/x-javascript
text/x-json application/json application/x-web-app-manifest+json
text/css text/plain text/x-component
font/opentype application/x-font-ttf application/vnd.ms-fontobject
image/x-icon;
gzip_disable "msie6";解决 history 路由访问不到的问题
location / {
root /usr/share/nginx/html;
index index.html index.htm;
# try_files 试着去访问一下当前浏览所请求的页面
# $uri 当前请求的路径 如果找到就返回
# $uri/ 去找当前请求的路径,去找下面的文件,如果找到了就返回
# /index.html 保底方案:如果上面两个都没有找到就直接返回 index.html
# root 指定了 / 对应的单页静态资源目录
try_files $uri $uri/ /index.html;
}