[nginx]常用配置 - 迁
配置
官网
基本配置
#edit by zgt user ecp; worker_processes 8; # 处理线程,根据CPU个数确定 worker_cpu_affinity auto; # 设置cpu自动亲和 error_log logs/error.log error; events { use epoll; worker_connections 65535; #最大线程数 } http { include mime.types; default_type application/octet-stream; sendfile on; tcp_nopush on; underscores_in_headers on; keepalive_timeout 10; send_timeout 60; charset utf-8; 设置字符集 include /usr/local/nginx/conf/vhost/*.conf; # vhost目录 upstream api_cdrs_server { server 172.23.4.43:8081 weight=10; server 172.23.4.33:8081 weight=10; } upstream manage_server { server 172.23.4.43:8082; server 172.23.4.33:8082; ip_hash; } if ($request_method !~* GET|HEAD|POST) { return 403; } location ~ ^/(api|cdrs) { proxy_pass http://api_cdrs_server; # proxy_set_header Host $host; #主机获取源IP proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { proxy_pass http://manage_server; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } }
tengine的安装
./configure --prefix=/usr/local/openresty --with-luajit --with-openssl=/home/ecp/nginx_install/openssl-1.0.1h/ --add-module=/home/ecp/nginx_install/nginx-sticky-module-1.1 make make install 不能加sticky; 加了报错;下次再增加一些模块试试看 ./configure --prefix=/usr/local/openresty --with-luajit --with-openssl=/usr/local/src/openssl-1.0.1h -j 2 直接安装就是一个打包的nginx web
session粘连模块
ngx_http_upstream_session_sticky_module 负载均衡模块,通过cookie实现客户端和后端服务器的会话保持 http://tengine.taobao.org/document_cn/http_upstream_session_sticky_cn.html https://www.cnblogs.com/tinywan/p/6534151.html
server_name
普通用法 server { listen 80; server_name howtocn.org www.howtocn.org; ... } *通配符 server { listen 80; server_name *.howtocn.org; ... } 正则表达式 server { listen 80; server_name ~^(?<www>.+)\.howtocn\.org$; ... }
location
# 匹配 user目录,优先级最高 location ^~ /user # 匹配 api或者 cdrs 目录 location ~ ^/(api|cdrs) # 做后缀过滤 location ~* (\/$)|\.(do|json|jsx|tile|resource|file|htm|checkcode|s)$ { .... }
正则表达式
很好理解,就是使用正则表达式去匹配URI,
而要使用正则表达式去匹配则需要用到了~和~*这两个通配符。
其中~表示大小写敏感,而~*表示大小写不敏感
location ~ \.(gif|jpg|png)$ { [configuration D] } location ~* \.(gif|jpg|png)$ { [configuration E] } location ~* /user/[0-9a-z]+\.(html|json) { //是不能直接写/user/info.html匹配的,需要改成[0-9a-z] return 200 "ok"; } location ~* (/group/|/user/[0-9a-z]+\.html) { return 200 "regexp"; }
优先级:
例如我们访问http://www.example.com/asset/img/icon.png (location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/)
Nginx首先会去匹配用前缀字符串定义的location配置,可能会匹配出多个,Nginx会记住最长那个配置,
上面的例子里都会匹配到,但是最后会被记住的则是[configuration C]
然后Nginx会去匹配用正则表达式定义的location配置,如果匹配的到,则这个配置作为最后采用的配置。
如果匹配不到或者没有正则表达式定义的location配置,则使用上面记住的那个匹配。跟匹配前缀字符串不同,
匹配正则表达式时,如果匹配到一个,就不会继续匹配下面的正则表达式配置了。
所以Nginx最终匹配到的配置是[configuration D]。如果配置使用了^~这个通配符,并且这个配置是匹配到的最长的那个配置。
则Nginx不会再去匹配正则表达式类型的location配置。如下面这个例子:
location ^~ /asset/img/ { [configuration F] } 请求地址 http://127.0.0.1/asset/img/favicon.pic 实际到服务器的request /favicon.pic
最后说下=这个通配符,使用了这个通配符后,表示这个配置是要完全匹配,
需要URI跟这个配置的前缀字符串完全一致才会匹配的到。它的优先级是最高的,
如果匹配到,则不会进行其他配置的匹配了。如:
location = /asset/img/icon.png { [configuration G] }
如果要访问一个静态文件
带url路径的访问 location ^~ /page/app/privacy/privacy.htm { root html/www/mapi_uires/; index privacy.htm; } 全部重定向到这个文件 location / { root html/www/mapi_uires/page/app/privacy/; index privacy.htm; } # curl http://36.27.209.70/page/app/privacy/privacy.htm -H "host:www.njgreat88.com"
if 判断语句
限制主机名访问
if ($host != "ecp.189.cn" ) { return 403; }
根据正则匹配提取关键参数
if ( $args ~ ";(\S+)$" ) { #proxy_pass http://www.baidu.com; #root html; #index /hello.html; set $servername $1; #return 200 $servername; ajp_pass 1-4.jchweb:8009; }
注意:if is evil ,注意不要滥用if语句而且是没有else的,只有lua里面有else,千万不要弄混了
以下写法是不可以的,因为nginx不支持多个正则匹配连接
if ($request_method = POST && $http_cookie ~* "CCCC=.+(?:;|$)")
代替方法:
if ($request_method = POST) { set $test P; } if ($http_cookie ~* "CCCC=.+(?:;|$)" ) { set $test "${test}C"; } if ($test = PC) { #rewrite rule goes here. }
if指令判断
==或者 = :等值比较; != : 不等于 ~:与指定正则表达式模式匹配时返回“真”,判断匹配与否时区分字符大小写; ~*:与指定正则表达式模式匹配时返回“真”,判断匹配与否时不区分字符大小写; !~:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时区分字符大小写; !~*:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时不区分字符大小写;
举例:
if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /msie/$1 break; } //如果UA包含"MSIE",rewrite请求到/msid/目录下 if ($http_cookie ~* "id=([^;]+)(?:;|$)") { set $id $1; } //如果cookie匹配正则,设置变量$id等于正则引用部分 if ($request_method = POST) { return 405; } //如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302 if ($slow) { limit_rate 10k; } //限速,$slow可以通过 set 指令设置 if (!-f $request_filename){ break; proxy_pass http://127.0.0.1; } //如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查 if ($args ~ post=140){ rewrite ^ http://example.com/ permanent; } //如果query string中包含"post=140",永久重定向到example.com location ~* \.(gif|jpg|png|swf|flv)$ { valid_referers none blocked www.jefflei.com www.leizhenfang.com; if ($invalid_referer) { return 404; } //防盗链 }
常用正则匹配
. : 匹配除换行符以外的任意字符 ? : 重复0次或1次 + : 重复1次或更多次 * : 重复0次或更多次 \d :匹配数字 ^ : 匹配字符串的开始 $ : 匹配字符串的介绍 {n} : 重复n次 {n,} : 重复n次或更多次 [c] : 匹配单个字符c [^/] : 匹配除了/之外的所有字符 [a-z] : 匹配a-z小写字母的任意一个
下面是可以用作if判断的全局变量
$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相同。 例:http://localhost:88/test1/test2/test.php $host:localhost $server_port:88 $request_uri:http://localhost:88/test1/test2/test.php $document_uri:/test1/test2/test.php $document_root:/var/www/html $request_filename:/var/www/html/test1/test2/test.php
rewrite
直接重新定访问,浏览器会改变URL地址
rewrite ^/(.*) http://ecp.189.cn/page/app/index.html redirect;
last – 本条规则匹配后,会继续向下匹配新的location规则,相当于Apache中的L
break – 中止所有匹配,不在继续匹配后面的任何规则
redirect – 返回临时重定向的HTTP状态302,浏览器地址栏会显示跳转后的URL地址,相当于Apache中的R
permanent – 返回永久重定向的HTTP状态301,浏览器地址栏会显示跳转后的URL地址,相当于Apache中的R=301
可以放在server, location 和 if 模块中
。 - last一般写在server和if中,而break一般使用在location中
- last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配
- break和last都能阻止继续执行后面的rewrite指令
域名跳转
实例1.
# 访问服务器请求全跳转到“server_name”定义的域名 server_name www.to-share.net; rewrite ^(.*)$ https://$server_name$1 permanent; rewrite为固定关键字,表示开始进行rewrite匹配规则 regex部分是 ^(.*)$ ,这是一个正则表达式,匹配完整的域名和后面的路径地址 replacement部分是https://$server_name/$1 $1,是取自regex部分()里的内容。匹配成功后跳转到的URL。 flag部分 permanent表示永久301重定向标记,即跳转到新的 http://www.czlun.com/$1 地址上
实例2.
if ($host != 'www.to-share.net' ) { rewrite ^/(.*)$ http://www.to-share.net/$1 permanent; }
# 请求重写 if ( $request_uri = "/" ) { rewrite "/" $uri/index.htm break; } index index.htm; # A服务匹配到后 302转到B服务(需要浏览器跳转) location ~ ^/MP_verify_vdxAFDed2dH3uq5c.txt$ { rewrite ^(.*)$ http://img-m.xjball.com/$1 last; }
全部做转发处理 location / { rewrite ^(.*) http://img-mapi.njgreat88.com/page/app/privacy/privacy.htm break; } # 无差别转发,重定向到某个网页(privacy.htm) server { server_name *.91caizhan.com 91caizhan.com; listen 80; location /91caizhan.com.html { root html/; } location / { # root html/; # index 91caizhan.com.html; rewrite "/*" http://$http_host/91caizhan.com.html permanent; } }
proxy_pass 以及 proxy_redirect
proxy_pass 是不能映射到目录的,所以:
server { listen 80; location ~ ^/oauth/ { proxy_pass http://192.168.21.2:8081; index /oauth/user/addSysUser; } }
使用proxy_pass代理到https的服务器
server { listen 80; server_name "info.sporttery.cn"; location / { proxy_pass https://info.sporttery.cn; proxy_set_header Host $host; } }
如果代理后出现502,403错误,因为https协议不支持改Host,默认也不会把server_name传到后端,所以需要强制指定!
server { listen 80; server_name hndj188.xxxxx; location / { proxy_ssl_server_name on; # 核心配置 proxy_ssl_name api.hndj188.com; # 核心配置 proxy_set_header Host api.hndj188.com; proxy_pass https://api.hndj188.com; } error_page 403 = /50x.html; location = /50x.html { root html; } }
当然proxy_pass和rewrite 可以结合起来用,达到一个效果:
访问 http://bops.jczj123.com/crossdomain.xml 的时候,是nginx代理到http://img-bops.jczj123.com/crossdomain_jczj123.xml ,客户端是看不到 img-bops.jczj123.com的,而index crossdomain_jczj123.xml 直接找:q
:文件貌似是没用的,他会跳转到 http://img-bops.jczj123.com/crossdomain.xml ,显然不是我想要的,所以再用rewrite break跳转出去
location ~ ^/crossdomain.xml$ { #rewrite ^(.*)$ http://img-bops.jczj123.com/crossdomain_jczj123.xml last; proxy_pass http://img-bops.jczj123.com; rewrite ^(.*)$ /crossdomain_jczj123.xml break; # index crossdomain_jczj123.xml; }
location ~ ^/crossdomain.xml$ { rewrite ^(.*)$ http://img.wenjieerp.com/$1 last; } 实际使用中,更能接受直接rewrite的做法,注意$1 = crossdomain.xml
proxy_redirect
可以做不同端口的转发,可以修改源请求的参数
# ssl 代理
server { listen 443; server_name jenkins.domain.com; ssl_certificate ssl/cert.crt; ssl_certificate_key ssl/cert.key; ssl on; ssl_session_cache builtin:1000 shared:SSL:10m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4; ssl_prefer_server_ciphers on; access_log /var/log/nginx/jenkins.access.log; location / { # Fix the “It appears that your reverse proxy set up is broken" error. proxy_pass http://localhost:8080; proxy_read_timeout 90; proxy_redirect http://localhost:8080 https://jenkins.domain.com; } }
proxy_redirect http://html.aslibra.com/css.aslibra.com/ http://css.aslibra.com/;
说道proxy_pass就必须要说下 proxy_set_header
proxy_set_header Host $host; -- 添加主机头 proxy_set_header X-Real-IP $remote_addr; -- X-Real-IP设置到源地址 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -- 增加X-Forwarded-For地址 proxy_set_header X-Forwarded-Proto $scheme; -- 协议类型
root 和 alias 匹配的区别
server { listen 8082; server_name yw_online; location /wiki { root html/wiki/; } location ^~ /servers/files/ { alias /usr/local/yw_online/files/; } location / { proxy_pass http://127.0.0.1:8083; } }
还需要注意一点的是 同一个location下,root proxy_pass两者不能共存,且proxy_pass优先级高,即root配置了没用
-- 去掉 /servers/files/ 去匹配:请求是 GET /servers/files/2016_01_08_14_41_07.xls
经过alias之后就变成
/usr/local/yw_online/files/2016_01_08_14_41_07.xls (实际文件所在)
alias会把location后面配置的路径丢弃掉,把当前匹配到的目录指向到指定的目录。
如果一个请求的URI是/binapp/a.ttlsa.com/favicon时,
web服务器将会返回服务器上的/data/statics/bin/apps/a.ttlsa.com/favicon.jgp的文件。
1. 使用alias时,目录名后面一定要加"/"。
2. alias可以指定任何名称。
3. alias在使用正则匹配时,必须捕捉要匹配的内容并在指定的内容处使用。
4. alias只能位于location块中
日志格式
配置http部
# http 日志格式,配置成json格式,直接输出到ELK
log_format main '{"remote_addr":"$remote_addr","remote_user":"$remote_user","time_local":"$time_iso8601","request":"$request","status":"$status","body_bytes_sent":"$body_bytes_sent","http_referer":"$http_referer","http_user_agent":"$http_user_agent","http_x_forwarded_for":"$http_x_forwarded_for"}';
其中,各个字段的含义如下:
1.$remote_addr 与$http_x_forwarded_for 用以记录客户端的ip地址; 2.$remote_user :用来记录客户端用户名称; 3.$time_local : 用来记录访问时间与时区;18/Apr/2016:23:00:58 +0800 $time_iso8601: 2016-04-19T09:38:04+08:00 4.$request : 用来记录请求的url与http协议; 5.$status : 用来记录请求状态;成功是200, 6.$body_bytes_s ent :记录发送给客户端文件主体内容大小; 7.$http_referer :用来记录从那个页面链接访问过来的; 8.$http_user_agent :记录客户端浏览器的相关信息;
upstream
1、轮询(weight=1)
默认选项,当weight不指定时,各服务器weight相同,
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除
2、weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
如果后端服务器down掉,能自动剔除。 比如下面配置,则1.11服务器的访问量为1.10服务器的两倍。
3、ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session不能跨服务器的问题。
如果后端服务器down掉,要手工down掉。
4、fair(第三方插件)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
5、url_hash(第三方插件)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存服务器时比较有效。
在upstream中加入hash语句,hash_method是使用的hash算法
设备的状态有:
- 1.down 表示单前的server暂时不参与负载
- 2.weight 权重,默认为1。 weight越大,负载的权重就越大。
- 3.max_fails 允许请求失败的次数默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误
- 4.fail_timeout max_fails次失败后,暂停的时间。
- 5.backup 备用服务器, 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
upstream backend { server 98-7.bops.base:80 ; } server { listen 80; server_name bopsbase.corphzinnovate.net; location ~* (\/$)|\.(do|json|jsx|tile|resource|file|htm|checkcode|s)$ { if ( $request_uri = "/" ) { rewrite "/" $uri/index.htm break; } proxy_set_header Host $host; #需要加上不然getRequestUrl会是代理的 backend proxy_set_header X-Real-Ip $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_pass http://backend; index index.htm; } }
vhost
vhost的意义:
可以将 80 端口 分成多个域名,进不同的项目
健康检测
以下都是tengine或者原生nginx的健康检查,openresty是需要自己添加健康检查模块
server { listen 8080; server_name 172.23.4.43; location /nginx_status { stub_status on; # 统计TCP连接状态,统计计数,而不是servers状态 access_log off; allow 127.0.0.1; deny all; } Active connections: 4 server accepts handled requests 394608907 394608907 2868853713 Reading: 0 Writing: 1 Waiting: 3
nginx_status 访问统计
curl http://127.0.0.1:8080/nginx_status Active connections: 1 server accepts handled requests 14236 14236 798 Reading: 0 Writing: 1 Waiting: 0
- Active connections: 对后端发起的活动连接数 1 .
- Server accepts handled requests: Nginx总共处理了14236个连接,成功创建14236次握手(证明中间没有失败的),总共处理了798个请求
- Reading: nginx 读取到客户端的 Header 信息数
- Writing: nginx 返回给客户端的 Header 信息数
- Waiting: nginx 已经处理完正在等候下一次请求指令的驻留连接.开启keep-alive的情况下这个值等于active–(reading + writing).
upstream test { server A:8081; server B:8081; check interval=3000 rise=2 fall=5 timeout=1000 type=tcp; } location /nstatus { check_status; # 探测upstream的状态 access_log off; allow 172.23.4.0/24; deny all; } curl https://naas.ecplive.cn/nstatus?format=json {"servers": { "total": 5, "generation": 216, "server": [ {"index": 0, "upstream": "api_cdrs_server", "name": "172.23.4.33:8081", "status": "up", "rise": 1843321, "fall": 0, "type": "tcp", "port": 0}, {"index": 1, "upstream": "api_cdrs_server", "name": "172.23.4.43:8081", "status": "up", "rise": 2415129, "fall": 0, "type": "tcp", "port": 0}, {"index": 2, "upstream": "api_manage_test", "name": "172.23.4.36:8111", "status": "up", "rise": 55616, "fall": 0, "type": "tcp", "port": 0}, {"index": 3, "upstream": "manage_server", "name": "172.23.4.33:8082", "status": "up", "rise": 24079, "fall": 0, "type": "http", "port": 0}, {"index": 4, "upstream": "manage_server", "name": "172.23.4.43:8082", "status": "up", "rise": 23807, "fall": 0, "type": "http", "port": 0} ] }}
注意: 只需要在一个conf下面设置location /nstatus 就可以了,比如都是监听80端口的10个服务,
只需要在server下面配置nstatus就能看到其他,但是要在upstream里面配置
check interval=3000 rise=2 fall=5 timeout=1000 type=tcp;
但是配置了这个之后,fail检测是不是就不用配置了,还待验证
server 1-1.kqweb:8009 max_fails=2 fail_timeout=10;
注意, 如果没有启用检测模块,通过设置连接超时时长,也可以通过这个参数来设置backends的超时重试
proxy_connect_timeout 10s;
开启跨域访问
add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Headers X-Requested-With; add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
一般后端都可以修改这个跨域请求头,并设置跨域资源共享(CORS)
ajp 转发
利用nginx ajp 模块可以实现ajp代理 ,一种比较古老的方式(apache原生支持)
{ ajp_keep_conn on; if ( $request_uri = "/" ) { rewrite "/" $uri/index.htm break; } ajp_pass liveweb; # ajp_pass 1-4.jchweb:8009 index index.htm; }
动态dns解析
ngx_http_upstream_dynamic_module
此模块提供了在运行时动态解析upstream中server域名的功能
http://tengine.taobao.org/document_cn/http_upstream_dynamic_cn.html
upstream weibo { # dns动态解析,缓存3s,解析不到失败 dynamic_resolve fallback=stale fail_timeout=3s; }
自定义cookie
配置虚拟主机
set $cookie_buriedData "-"; if ($http_cookie ~* "buriedData=(\S+)(?:;|$)") # 正则匹配,buriedData是关键字 { set $cookie_buriedData $1; }
在nginx.conf http里面配置日志with_cookie
log_format access_with_cookie '{"remote_addr":"$remote_addr","remote_user":"$remote_user","time_local":"$time_iso8601","request":"$request","status":"$status","body_bytes_sent":"$body_bytes_sent","http_referer":"$http_referer","http_user_agent":"$http_user_agent","http_x_forwarded_for":"$http_x_forwarded_for","server_name":"$server_name","cookie_buriedData":"$cookie_buriedData"}'; access_log logs/access.log access_with_cookie;
自定义header
比如我们自定义header为wx_unionid,获取该header时需要这样:$http_wx_unionid(一律采用小写,而且前面多了个http_)
如果需要把自定义header传递到下一个nginx:
1.如果是在nginx中自定义采用proxy_set_header X_CUSTOM_HEADER $http_host;
2.如果是在用户请求时自定义的header,例如curl –head -H “X_CUSTOM_HEADER: foo” http://domain.com/api/test,则需要通过proxy_pass_header X_CUSTOM_HEADER来传递
http { underscores_in_headers on; # nginx是不支持读取非nginx标准的用户自定义的,但是需要在http或者server下开启header的下划线支持 } 可以直接调用变量 "cookie_buriedData":"$cookie_buriedData","http_appUserAgent":"$http_appUserAgent","http_appVersion":"$http_appVersion","http_appName":"$http_appName"
default_server配置
如果找不到呢,那 Nginx 就会将请求送到指定了 default_server 的 节点来处理,如果没有指定为 default_server 的话,就跑到 localhost 的节点,如果没有 localhost 的节点,那只好 404 了
server { listen 80 default_server; server_name www.91caizhan.com 91caizhan.com ; }
为了限制无关域名的访问,一般都设置一个default域名,将不相关的都返回Invalid serverName
tcp的支持
openresty 天生就支持,而其他两个需要编译安装 nginx_tcp_proxy_module包
Nginx 从1.9.0开始发布ngx_stream_core_module
模块,该模块支持tcp代理及负载均衡。
ngx_stream_core_module
这个模块并不会默认启用,需要在编译时通过指定--with-stream
参数来激活这个模块。
stream { upstream dong5-5222 { hash $remote_addr consistent; server 10.2.40.4:5222 max_fails=3 fail_timeout=30s; server 10.2.40.5:5222 max_fails=3 fail_timeout=30s; } server { listen 5222; # server_name api.dong5.com; 基于4层的,不支持server_name proxy_timeout 30s; #设置代理超时时长 必须 proxy_pass dong5-5222; } }
使用tcp长连接可能会造成-s reload有比较久
www 9421 9361 0 14:43 ? 00:00:00 nginx: worker process is shutting down
目录浏览
当做文件下载服务器
server { listen 8000; server_name _; location / { autoindex on; autoindex_exact_size off; # 显示出文件的确切大小,单位是bytes;改为off后,显示出文件的大概大小,单位是kB或者MB或者GB autoindex_localtime on; # 默认为off,显示的文件时间为GMT时间, 改为on后,显示的文件时间为文件的服务器时间 root /home/ftpuser; } }
内部访问限制
server { listen 45673; location / { internal; # 限制为内部访问 echo "default upstream"; } }
return
location = /XIddddsss.txt { default_type text/plain; # 写好文件类型 return 200 'd6296a84657eb275c05c31b10924f6ea'; }
nginx支持websocket
在配置文件中添加如下两条 vhost/virtual_server.conf map $http_upgrade $connection_upgrade { default upgrade; '' close; } proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade;
自动跳转
自定义跳转
location / { if ($http_addr ~ "10.0.100.1") { ngx.exec("@static_route"); } if ($http_user_agent ~ "Wget") { ngx.exec("@app_route") } } location @app_route { reuturn 200 "app_route"; } location @static_route { reuturn 200 "static_route"; }
404跳转
server { location / { error_page 404 = @abc; } location @abc { rewrite .* / permanent; } }
上传大文件需要的设置
client_max_body_size 50m; // 跟文件上传大小有关 check_shm_size 128m; // 所有的后端服务器健康检查状态都存于共享内存中,该指令可以设置共享内存的大小 client_max_body_size 50m; //文件大小限制,默认1m proxy_connect_timeout 600; proxy_send_timeout 600; proxy_read_timeout 600; send_timeout 600; 连接 client_header_buffer_size 64k; // 设置最大header 请求 large_client_header_buffers 4 64k; // 每个客户端的buffer大小 client_body_buffer_size 50m; // 客户端post请求过大,不够的话nginx会创建temp文件,而ngx_lua不能访问temp文件 proxy_request_buffering: on|off
开启buffering
buffering机制的目的是为了解决收发两端速度不一致的问题。
location / { ........... proxy_buffering on; # 开启buffering,不写也没关系 proxy_buffer_size 64M; proxy_buffers 64 16M; proxy_busy_buffers_size 256M; proxy_temp_file_write_size 512M; }
说明:
- 当proxy_buffering打开的时候,Nginx会尽可能多的将后端服务器返回的内容接受并存储到自己的缓存区内,当处于off状态时,nginx不会尽可能多的从后端拿数据,而是一次最多读proxy_buffer_size大小的数据到客户端
- proxy_buffers定义了每一个request可用的缓冲区数量和大小
- proxy_buffer_size 用来定义后端服务器response时存储的第一部分的响应内容,比如header之类,默认来说它仅限定于headers的buffer区,所以它可以设置小一点而且不管proxy_buffering是否开启,proxy_buffer_size都会起作用
- 所以缓冲区的最大大小是 proxy_buffers(64*16M) + proxy_buffer_size(256M) 的内存,这只是一个request
- 如果后端返回的数据很大,这些内存都放不下,会被放到磁盘文件中,proxy_temp_file_write_size和proxy_max_temp_file_size
SSL证书
# 公网入口 server { listen 443; server_name naas.ecplive.cn; ssl on; ssl_certificate ssl/ecplive.cn.crt; ssl_certificate_key ssl/ecplive.cn.key; ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5; ssl_prefer_server_ciphers on; }
缓存
对不同资源设置不同缓存策略
location ~* ^.+/.(js|css)?$ { access_log /usr/local/nginx/logs/jscss.log; expires 1d; } location ~* ^.+/.(jpg|jpeg|gif|png|bmp)$ { access_log /usr/local/nginx/logs/image.log; expires 1d; break; }
取消nginx的缓存设置
location / { add_header Cache-Control no-cache; add_header Pragma no-cache; add_header Expires 0; }
字符集
在server中设置,注意如果转发的upstream里面是gbk编码的,就需要指定为gbk
设置之后,通过查看url为ecp_189_cn下面的页面的header可以看到charset=GBK
location / { charset gbk; proxy_pass http://ecp_189_cn; }
文件字符的转换
iconv -f utf-8 -t gbk bottomlink.html > bottomlink.html_bak
启动目录
根据不同的目录启动不同的实例
OPENRESTY_BIN="/usr/local/openresty/nginx/sbin/nginx" NGX_DIR="/usr/local/nginx" NGX_CONF=$NGX_DIR"/conf/nginx.conf" case "$1" in -k|start) $OPENRESTY_BIN -p $NGX_DIR -c $NGX_CONF ;; -t) $OPENRESTY_BIN -p $NGX_DIR -c $NGX_CONF -t ;; status) ps -ef|grep $NGX_CONF|grep -v grep ;; -s|stop) pid=$(ps -ef|grep $NGX_CONF|grep -v grep|awk '{print $2}') ps -ef|grep $pid|grep -v grep|awk '{print $2}'|xargs kill -9 ;; esac
故障处理
403 forbidden
*3975 open() "/usr/local/tengine/html/www/pandawap_uires/favicon.ico" failed (13: Permission denied)
1 目录权限要 655,即要有执行-x权限
2 selinux可能造成
3 文件没有
4 nginx的执行用户是否没有权限访问文件
No resolve
“no resolver defined to resolve xxx.xxx”
在nginx的配置文件中的http{}部分添加一行resolver 8.8.8.8;即可
426 返回错误
原因是docker容器是用HTTP1.1 的协议
http{ ''' 省去其他的配置 upstream www{ keepalive 50; # 必须配置,建议50-100之间 ''' } server { '''省去其他的配置 location / { proxy_http_version 1.1; # 后端配置支持HTTP1.1,必须配 proxy_set_header Connection ""; # 后端配置支持HTTP1.1 ,必须配置。 } ''' } ''' }
nginx里面自带变量和作用
nginx 各参数翻译,作用 $arg_PARAMETER #这个变量包含GET请求中,如果有变量PARAMETER时的值。 $args #这个变量等于请求行中(GET请求)的参数,例如foo=123&bar=blahblah; $binary_remote_addr #二进制的客户地址。 $body_bytes_sent #响应时送出的body字节数数量。即使连接中断,这个数据也是精确的。 $content_length #请求头中的Content-length字段。 $content_type #请求头中的Content-Type字段。 $cookie_COOKIE #cookie COOKIE变量的值,有一种说法是 $cookie_buriedData 就能取到buriedData了,还没试过,不知道行不行 $document_root #当前请求在root指令中指定的值。 $document_uri #与$uri相同。 $host #请求主机头字段,否则为服务器名称。 $http_referer #从哪个页面链接过来的 $hostname #Set to the machine’s hostname as returned by gethostname $http_HEADER # 测试下来好像不行,拿不到HEADER,这个参数没用 $http_user_agent #客户端agent信息 $http_x_forwarded_for #forwarded地址,7层转发之后就可以在header里加上xforward $http_cookie #客户端cookie信息 $is_args #如果有$args参数,这个变量等于”?”,否则等于”",空值。 $limit_rate #这个变量可以限制连接速率。 $query_string #与$args相同。 $request_body_file #客户端请求主体信息的临时文件名。 $request_method #客户端请求的动作,通常为GET或POST。 $remote_addr #客户端的IP地址。 $remote_port #客户端的端口。 $remote_user #已经经过Auth Basic Module验证的用户名。 $request #request 请求+参数 $request_completion #如果请求结束,设置为OK. 当请求未结束或如果该请求不是请求链串的最后一个时,为空(Empty)。 $request_filename #当前请求的文件路径,由root或alias指令与URI请求生成。 $request_uri #包含请求参数的原始URI,不包含主机名,如:”/foo/bar.PHP?arg=baz”。不能修改。 $status #本次回话的状态 $scheme #HTTP方法(如http,https)。 $server_protocol #请求使用的协议,通常是HTTP/1.0或HTTP/1.1。 $server_addr #服务器地址,在完成一次系统调用后可以确定这个值。 $server_name #服务器名称 $server_port #请求到达服务器的端口号。 $time_iso8601 # 时间 $uri #不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。该值有可能和$request_uri 不一致。$request_uri是浏览器发过来的值。该值是rewrite后的值。例如做了internal redirects后。 $upstream_addr #upstream的server地址 $upstream_response_time #upstream的响应时间 $upstream_status #upstream 回来的状态