@octopus
2018-05-05T12:40:54.000000Z
字数 14595
阅读 2619
nginx
nginx -tc /etc/nginx/nginx.conf // 查看是否有配置错误ab -n 50 -c 20 www.xxxx.com // 总共请求50次,同时并发20个请求
- IO多路复用 epoll
红黑树维护申请的事件,当事件被触发,通过回调函数自动把事件 添加到双向链表中,所以最大连接无限制,效率也更高。在 nginx 中 epoll 的应用:https://www.cnblogs.com/yimuren/p/4105124.html
- 轻量级,功能模块少,代码模块化
- CPU 亲和
将nginx的每个worker进程与固定的cpu绑定,减少切换损耗的性能
- sendfile机制
静态文件不走用户空间,直接通过内核空间传递给socket(关于 sendfile:https://my.oschina.net/lemonfight/blog/659133)
user 设置 nginx 的使用用户worker_processes 工作进程数(最好与核数保持一致)error_log nginx 的错误日志pid nginx 服务启动时候的pidworker_connections 每个进程允许的最大连接数use 定义内核模型
http{...server{# http 模块下的具体服务器配置,可以配置多个listen 80;server_name localhost;location /{# 服务器的路径相关配置root /usr/local/nginx/html;index index.html index.htm}error_page 500 502 503 504 /50.html# 当页面状态码为这些时,转到 /50.htmllocation /50.html{# 定义上面的文件路径root /usr/local/nginx/html/50.html;}}server{...}}
定义日志格式,要写在 http 模块下
http{...access_log /var/log/nginx/access.log main // 类型 位置 格式名log_format main '$remote_addr [$time_local]'; // log_format 格式名 格式}
arg_PARAMETER // 参数http_HEADER // 请求头信息sent_http_HEADER // 返回头信息
// 注意,要把大写变小写,横杠变下划线,前面加$// 获取用户浏览器信息User-Agent => $http_user_agent
nginx -V 查看默认安装的模块
Syntax: stub_status
Default: -
Context: server/location
location /mystatus{stub_status;}
浏览器访问 127.0.0.1/mystatus,会看到活跃连接数、握手次数、建立连接数、总请求数、读的个数、写个数、等待个数

Syntax: limit_conn_zone key zone=name:size // 申请一块空间,设置空间名和大小和key
Default: - // 默认没有配置
Context: http // 在http下配置
Syntax: limit_conn zone number // 空间名,并发个数限制
Default: -
Context: http,server,location
Syntax: limit_req_zone key zone=name:size rate=rate // 申请一块空间,设置空间名和大小和key,设置允许请求的速率
Default: -
Context: http
Syntax: limit_req zone=name // 空间名,并发个数限制
Default: -
Context: http,server,location
// 请求限制// 解释:申请空间,将 ip 地址作为键,空间大小为1m,限制速率为1秒请求一次http{limit_req_zone $binary_remote_addr zone=req_zone:1m rate=1r/s;server{...location / {limit_req zone=req_zone;}}}
// 连接限制http{limit_conn_zone $binary_remote_addr zone=conn_zone:1m;server{...location / {limit_conn conn_zone 1;}}}
缺点:当使用代理等工具就会由 ip1->ip2->nginx ,最终获取到的是 ip2的地址,所以不精确
Syntax: allow/deny address|CIDR|unix:|all // 允许的ip地址、网段、socket、所有
Default: -
Context: http,server,location,limit_except
// ~ 表示匹配模式,匹配到以 /admin.html 开头的// 不允许本机访问,其他所有ip都可访问location ~ ^/admin.html {root /admin/deny 127.0.0.1allow all}
密码加密需要用到 htpasswd ,首先要 yum 安装它:yum -y install httpd-tools
缺点:机械化,不利于管理用户
Syntax: auth_basic string|off // 进行认证的字符串提示,或关闭认证
Default: off // 默认关闭
Context: server,location,limit_except
Syntax: auth_basic_user_file file
Default: -
Context: http,server,location,limit_except
// 1. 第一步,生成存储用户名密码的文件,写用户名和密码htpasswd -c auto_conf username// 2. 配置文件location ~ ^/admin.html {root /admin/auth_basic "input your passward!";auth_basic_user_file auto_conf;}
Syntax: sendfile on|off
Default: off // 默认关闭
Context: http,server,location
在 sendfile 开启的条件下,提高网络包的传输效率。
发送网络包时,不再一个一个发包,而是整合多个包一次发送
Syntax: tcp_nopush on|off
Default: off // 默认关闭
Context: http,server,location
在 keeplive 长连接的前提下有效
立刻发送数据包,与上面的nopush对立,在实时性要求高的场景使用
Syntax: tcp_nodelay on|off
Default: on // 默认打开
Context: http,server,location
压缩传输
Syntax: gzip on|off // 是否开启压缩传输
Default: off
Context: http,server,location
Syntax: gzip_comp_level level // 压缩比
Default: gzip_comp_level 1 // 默认是1,提高压缩比会对性能有损耗
Context: http,server,location
预读 gzip 功能,返回目录下gzip压缩过的文件
server{...sendfile on;// 所有以图片格式结尾的文件,gzip压缩,压缩比2,location ~ .*\.(jpg|gif|png)$ {gzip on;gzip_http_version 1.1;gzip_comp_level 2;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;root /opt/app/code/images;}// 所有以txt或xml格式结尾的文件,gzip压缩,压缩比1,location ~ .*\.(txt|xml)$ {gzip on;gzip_http_version 1.1;gzip_comp_level 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;root /opt/app/code/doc;}// 以download开头的文件,预读gzip,开启tcp_nopushlocation ~ ^/download {gzip_static on;tcp_nopush on;root /opt/app/code;}}
expires 1d;
Access-Control-Allow-Origin
Syntax: add_header name value; // 添加头信息
Default: -
Context: http,server,location
location .*\.(html|htm)$ {add_header Access-Control-Allow-Origin http://www.xxx.comadd_header Access-Control-Allow-Methods GET,POST;}
referer 为当前链接的上一页链接,比如在 a 页面打开了 b 的链接,b 的nginx 就可以获取 referer 值为 a 的地址
valid_referers none blocked 116.62.103.228 jeson.imoocc.com ~/baidu\./;if ($invalid_referer) {return 403;}// none 代表没有上一页,是直接打开的// blocked 代表有referer但是被防火墙或者是代理给去除了// 可以指定允许访问当前站点资源的地址或域名// 支持正则匹配// 验证通过,$invalid_referer变量值为0,未通过为1
正向代理与反向代理的区别:
- 代理的对象不一样。
- 正向代理代理的对象是客户端,比如翻墙,n个客户端去请求一个代理服务器,让代理服务器去抓我们要的页面。
- 反向代理代理的对象是服务器端,比如集群,访问的是 a.com,实际上 a.com对应很多服务器,反向代理可以把适配的某台服务器信息给用户
Syntax: proxy_pass url; // 设定反向代理的跳转url
Default: -
Context: location
// 当请求根路径时,反向道理到 8080 端口location / {proxy_pass http://127.0.0.1:8080;}
// 通过本机转发请求相应服务器// 设置浏览器代理为此服务器即可location / {proxy_pass http://$http_host$request_uri;}
location / {// 当上游服务器返回的响应是重定向或刷新请求(如HTTP响应码是301或者302)时,proxy_redirect可以重设HTTP头部的location或refresh字段。proxy_redirect default;// 由于经过代理实际客户端的ip或域名会更改,就可以通过设置头信息返回正确的头信息proxy_set_header Host $http_host;proxy_set_header X-Real-IP $remote_addr;// 设置一些超时时间proxy_connect_timeout 30;proxy_send_timeout 60;proxy_read_timeout 60;// 设置缓冲区大小,是否开启缓冲区等 详见:(https://www.cnblogs.com/me115/p/5698787.html)proxy_buffer_size 32k;proxy_buffering on;proxy_buffers 4 128k;proxy_busy_buffers_size 256k;proxy_max_temp_file_size 256k;}
当检测到某一主机无法到达,则自动不会再转发到改主机
Syntax: upstream name{...};
Default: -
Context: http // 注意是配置在 http 层
http{...upstream test { // 定义集群名以及包含的主机server 127.0.0.1:8081;server 127.0.0.1:8082;server test.com:8083;}server{...location / {proxy_pass http://test // 设置负载均衡的集群名}}}
down 当前 server 暂时不参与负载均衡
backup 预留的备份服务器,即在其他服务器‘存活’时,不参与负载均衡
max_fails 允许请求某服务器失败的次数,即当某一负载服务器挂掉,会再请求max_fails次确认
fail_timeout 设置不再请求连接失败服务器的时间,即fail_timeout后,再次请求某失败服务器
max_conns 限制最大的接收连接数
http{upstream test {server 127.0.0.1:8001 down;server 127.0.0.1:8002 backup;server 127.0.0.1:8003 max_fails=1 fail_timeout=10s;}}
轮询 按照时间顺序逐一分配到不同服务器
加权轮询 按照全权重分配,权重越大被访问的几率越高
ip_hash 每个请求按访问ip的hash结果分配,同一ip访问相同服务器,缺点在于使用代理时无法定位正确的ip
url_hash
hash关键数值
# 设置 weight 权重,如下当有7个连接请求时,5个都会到 8003 端口上去http{upstream test {server 127.0.0.1:8001;server 127.0.0.1:8002;server 127.0.0.1:8003 weight=5;}}
# 只需要在upstream加上 ip_hash ,再把其他权重设置等删掉即可http{upstream test {ip_hashserver 127.0.0.1:8001;server 127.0.0.1:8002;server 127.0.0.1:8003;}}
只要用正则提取出想要 hash 的值放到自定义变量中,再在 upstream 加上 hash $xxx 即可
http{upstream test {hash $request_uri;server 127.0.0.1:8001;server 127.0.0.1:8002;server 127.0.0.1:8003;}}
https://blog.csdn.net/u012081441/article/details/71787164
以及php配置将session写进redis的简单实现:https://www.cnblogs.com/hfdp/p/6671298.html

// proxy_cache配置语法
Syntax: proxy_cache_path path [levels=levels]
Default: -
Context: http
Syntax: proxy_cache zone|off
Default: off
Context: http,server,location
// 缓存过期时间配置
Syntax: proxy_cache_valid [code..] time;
Default: -
Context: http,server,location
// 缓存维度设置
Syntax: proxy_cache_key string;
Default: proxy_cache_key $scheme$proxy_host$request_uri;
Context: http,server,location
http{// 设置缓存目录;// levels 设置目录分级 1:2 分两级;// keys_zone 设置 key 的空间名,以及key的大小;// max_size 表示缓存大小,超过以后则根据规则删除不常用键值// inactive 60分钟内没有被用到的缓存被清除// use_temp_path 是否使用临时路径proxy_cache_path /opt/app/cache levels=1:2 keys_zone=test_cache:10m max_size=10g inactive=60m use_temp_path=off;upstream test {server 127.0.0.1:8081;server 127.0.0.1:8082;server test.com:8083;}server{location / {proxy_cache test_cache; // 使用 zone 为test_cache的配置proxy_pass http://test; // 基于代理模式缓存proxy_cache_valid 200 304 12h; // 对响应头为 200 与 304 的设置12小时过期proxy_cache_valid any 10m; // 除此之外的,设置10分钟后过期proxy_cache_key $host$uri$is_args$args; // 设置 key 格式add_header Nginx-Cache "$upstream_cache_status"; // 添加一个头信息,告诉客户端是否命中proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;// 当服务器出现以上错误码或错误信息,则轮询到下一台服务器include proxy_params;}}}
指定页面不缓存
Syntax: proxy_no_cache [args..]
Default: -
Context: http,server,location
server{// 匹配到以下页面不缓存if($request_uri ~ ^/(url3|login|register|password\/rest)) {set $cookie_nocache 1;}location /{...proxy_no_cache $cookie_nocache}}
php 等需要动态加载的文件与图片等静态文件分别配置
通过反向代理的方式,配合 location 正则匹配实现
http{upstream php_api{server 127.0.0.1:8080}server{root /xxx/publiclocation ~ \.php$ { // 以 php 结尾的文件proxy_pass http://php_apiindex index.html index.htm}location ~ \.(jpg|png|gif)$ {expires 1h;gzip on;}}}
Syntax: rewrite regex replacement[flag];
Default: -
Context: server,location,if
// 所有的url,都跳到/index.htmlrewrite ^(.*)$ /index.html break;
. 匹配除换行符以外的任意字符
? 重复0次或1次
+ 重复1次或更多次
* 重复任意次
\d 匹配数字
^ 匹配以某字符串开头
$ 匹配以某字符串结尾
{n} 重复n次
{n,} 重复n次或更多次
[c] 匹配单个字符c
[a-z] 匹配a-z中任意一个字符
\ 转义
() 提取()中的内容,用 $1 取到第1个()中的内容
break 若跳转失败,则直接返回(默认404)
last 若跳转失败,会从新发起请求,继续往下查找是否有匹配的location规则
redirect 临时重定向
permanent 永久重定向
server {root /opt/app/code;location ~ ^/break {rewrite ^/break /test/ break;// 路径下没有文件,404}location ~ ^/last {rewrite ^/last /test/ last;// 路径下没有文件,但下面定义了匹配路由,成功返回该路由}location /test/ {default_type application/json;return 200 '{"status":"success"}';}}
location / {// 匹配rewrite ^/test-(\d+)\.html$ /test-.html break;// 当请求的浏览器是Chrome时,重定向if ($http_user_agent ~* Chrome) {rewrite ^/nginx http://test.html redirect;}// 当访问的文件不存在时,重定向if (!-f $request_filename) {rewrite ^/(.*)$ http://www.baidu.com/$1 redirect;}index index.html index.htm;}
限制链接生效周期
检查链接的真实性
Syntax: secure_link expression;
Default: -
Context: http,server,location
Syntax: secure_link_md5 expression;
Default: -
Context: http,server,location

校验时主要针对两点:加密验证、过期校验
location / {// 校验的参数项,本例分别是从链接取到的 md5 参数,以及 expires 参数secure_link $arg_md5,$arg_expires;// 加密的生成方式secure_link_md5 "$secure_link_expires$uri test";// 判断是否校验成功if ($secure_link = "") {return 403;}if ($secure_link = "0") {return 410;}}
链接的生成方式是用 openssl
#!/bin/shservername="test.com"download_file="/download/file.img"time_num=$(date -d "2018-10-18 00:00:00" +%s)secret_num="test" // 与nginx的配置一致res=$(echo -n "${time_num}${download_file} ${secret_num}"|openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d =)echo "http://${servername}${download_file}?md5=${res}&expires=${time_num}"
基于ip地址匹配MaxMind GeoIp二进制文件,读取ip所在地域信息
可以实现根据地域访问特定服务器
// 1. 由于不是默认模块,需要手动引入(在全局块配置)load_module "module/ngx_http_geoip_module.so";load_module "module/ngx_stream_geoip_module.so";http{// 定义地域文件地址变量geoip_country /etc/nginx/geoip/GeoIP.dat;geoip_city /etc/nginx/geoip/GeoLiteCity.dat;server {...// 即可获取到geoip变量// $geoip_country_name 国家名// $geoip_country_code 国家代号// $geoip_city 城市location / {if ($geoip_country_code != CN) {return 403;}root /usr/share/nginx/html;index index.html index.htm;}location /myip {default_type text/plain;return 200 "$remote_addr $geoip_country_name $geoip_country_code $geoip_city";}}}
对称加密:
对称加密,即加密与解密双方都用同一套密钥
缺点: 一旦第三方 c 劫持了密钥,a 发送给 b 的信息,c 也可以解密出来,不安全

非对称加密:
非对称加密,即 b 掌管私钥,a 获得公钥,a 发给 b 的信息,只有 b 自己能解密出来,c 劫持了公钥也不能解密

上述非对称加密虽然拦截后不能识别消息,但黑客可以生成自己的一套私钥与密钥,伪装成正经服务器,这样客户收到的公钥也是黑客传的,依然不安全。
ca证书是服务器端向证书机构申请的,客户端只要用签名证书信息去查询比对即可知道是不是真的服务器,而不是黑客伪造的链接

1. 安装 openssl
2. nginx -v 查看是否有 --with-http_ssl_module 模块
3. 生成密钥key
4. 生成证书签名请求文件(csr文件)
5. 生成证书(CA 文件)
Syntax: ssl on|off;
Default: off
Context: http,server
Syntax: ssl_certificate file;
Default: -
Context: http,server
Syntax: ssl_certificate_key file;
Default: -
Context: http,server
server{listen 443;server_name test.com;keepalive_timeout 100;ssl on;ssl_session_cache shared:SSL:10m;ssl_session_timeour 10m;ssl_certificate /etc/nginx/ssl_key/jesonc.crt;ssl_certificate_key /etc/nginx/ssl_key/jesonc.key;location / {...}}
安装 lua 解释器 :yum -y install lua
#!/user/bin/luaprint("i am test")-- 行注释--[[块注释]]---- 变量a = "xxx"-- 布尔类型只有 nil 和 false 是 false,-- 数字0 与空字符串,都是 true-- 变量若无特殊说明都是全局变量-- 若声明非全局变量,前面加 local-- while 循环sum = 0num = 1while num <= 10 dosum = sum + numnum = num + 1endprint("sum = ",sum);-- for 循环sum = 0for i=1,100 dosum = sum + iend-- if elseif a = 10 and b = "xxx" thenprint("xxx")elseif c ~= 30 thenprint("xxx")elselocal d = io.read()print(d)end-- ~= 不等于-- 字符串拼接符:".."
1. 下载LuaJIT(更高效的解释器)
2. ngx_devel_kit 和lua-nginx-module
3. 重新编译 Nginx
当指定路径不存在时,转到try_files定义的路径
对缓存很有用,当缓存文件不存在时,跳转到动态页面
location / {root /opt/app/code;try_files /cache $uri @java_page;}location @java_page{proxy_pass http://127.0.0.1:9090;}
// 当请求 /url/img/1.png 时// 实际请求的地址是 root+location 即 /local/url/img/1.pnglocation /url/img/ {root /local/;}// 实际请求的地址是 root+location 即 /local/1.pnglocation /url/img/ {alias /local/;}
ip1 -> ip2 -> ipn -> 后端
1. X-Forwarded-For 获取,但容易被篡改
2. 在第一层代理设置ip变量 set x_real_ip = $remote_addr
413 Request Entity Too Large 用户上传文件过大
用户上传文件限制 client_max_body_size
502 Bad Gateway 后端错误
504 Gateway Time Out 后端超时
yum -y install httpd-tools
ab -n 1000 -c 100 http://www.test.com 共发起 2000 次连接请求,并发数是 10
Completed 100 requestsCompleted 200 requestsCompleted 300 requestsCompleted 400 requestsCompleted 500 requestsCompleted 600 requestsCompleted 700 requestsCompleted 800 requestsCompleted 900 requestsCompleted 1000 requestsFinished 1000 requestsServer Software: Apache/2.0.63Server Hostname: sports.sina.com.cnServer Port: 80Document Path: /k/2011-05-24/12095590365.shtmlDocument Length: 86680 bytesConcurrency Level: 100Time taken for tests: 66.453 seconds // 用时多少秒Complete requests: 1000 // 总共多少请求Failed requests: 0 // 失败几个Write errors: 0Total transferred: 87135790 bytesHTML transferred: 86680000 bytesRequests per second: 15.05 [#/sec] (mean) // 每秒处理多少请求Time per request: 6645.294 [ms] (mean) // 每个请求用时Time per request: 66.453 [ms] (mean, across all concurrent requests) // 后端处理每个请求用时Transfer rate: 1280.51 [Kbytes/sec] received // 数据传输速率,与网络情况有关Connection Times (ms)min mean[+/-sd] median maxConnect: 1 56 398.3 2 3003Processing: 89 6331 2603.7 6293 14626Waiting: 2 1748 1485.9 1590 6284Total: 90 6388 2615.0 6302 14627Percentage of the requests served within a certain time (ms)50% 630266% 712175% 843580% 919390% 923195% 938598% 1154999% 12459100% 14627 (longest request)
vim /etc/security/limits.conf
* soft nofile 20000* hard nofile 20000
worker_processes 16; // 16核#worker_cpu_affinity 0000000000000010 0000000000000010 0000000000000100 0000000000001000 0000000000010000 0000000000100000 0000000001000000 0000000010000000 0000000100000000 0000001000000000 0000010000000000 0000100000000000 0001000000000000 0010000000000000 0100000000000000 1000000000000000; // 手动绑定worker_cpu_affinity auto; // 自动绑定(推荐)