Nginx的学习
特点:
- 高效
- 可靠
- 开源
包括场景:
- 代理服务
- 动态缓存
- 动静分离
- 负载均衡
- Nginx和LUA的开发
- …
中间件架构:
- Nginx应用层的安全防护
- sql注入
- 请求的访问控制
- 请求的频率控制
- 防爬虫控制
- 基于Nginx的中间件架构的性能优化问题
- http性能压测
- 性能瓶颈分析
- 系统性能优化
- 基于Nginx的性能配置优化
技术原理:
- http协议原理
- linux系统原理
内容框架
基础内容
- 快速安装
- 配置语法
- 默认模块
- Nginx的log
- 访问限制
- HTTP请求和连接
- 请求限制和连接限制
- access模块的配置语法
- 请求限制的局限性
- 基本安全认证
- auth模块的配置语法
- 安全认证的局限性
实践内容
- 静态资源WEB服务
- 什么是静态资源
- 静态资源服务的场景
- 静态资源服务的配置
- 客户端缓存
- 静态资源的压缩
- 防盗链
- 跨域访问
- 代理服务
- 负载均衡
- 缓存服务
深度内容
- 动静分离
- rewrite规则
- 进阶模块的配置
- HTTPS服务
- HTTPS协议
- 配置语法
- 配置
- 苹果要求的https服务
- Nginx和LUA开发
架构内容
- 常见问题
- Nginx中间件性能的优化
- 如何调试性能优化
- 性能优化大的影响因素
- 操作系统的性能优化
- Nginx性的优化
- Nginx于安全
- 新版本特征
- 中间件架构的设计
Leader的品质
- 实践经验
- 指引方向
- 提升团队的技术
环境
centos 7.0+ x64
确认:
- 网络
- yum源
- 关闭iptables
- 停用selinux
安装库:
yum install gcc gcc-c++ autoconf pcre pcre-devel make automake
安装工具:
yum install wget httpd-tools vim
环境初始化
cd /apt
mkdir app download logs work backup
常用linux命令yum list | grep [查找的包]
列出已安装相关包
关闭iptables规则:
iptables -L
查看是否具有规则
iptables -F
关闭
iptables -t nat -L
查看规则
iptables -t nat -F
关闭规则
关闭slinux:
getenforce
查看slinux状态 disabled是关闭
setenforce 0
关闭slinux
基础篇
什么是中间件
网站后台会存在许多应用服务:
[操作系统—去驱动–>硬件] —提供—>[应用服务A,应用服务B…]
存在的问题:
- 应用和应用之间的相互调用
- 应用直接和操作系统之间的交互
- 层次化的应用不够隔离,代码耦合度高
对应这些问题就需要一个东西来代理合成处理应用的请求,让应用只去负责对业务逻辑的处理,这个东西就是中间件
WEB请求--->[中间件<判断请求是否具有业务逻辑性>]----不具有业务逻辑性-->[操作系统]
| ↑
具有业务逻辑性 |
↓ |
[应用]------------------------------------------
|
↓
[ 中间件 ]
↓
[其他应用]
↓
...
用到中间件的常见场景: 负载均衡 缓存服务 安全应用的防控
常见的HTTP服务
- HTTPD-Apache
- IIS 微软
- GWS-Google
为什么选择nginx
原因一 技术层面:
- 采用IO多路复用的epoll
所谓IO多路复用 解决的问题就是高并发
请求 → 线程→
-------→|----------| |---------|-----→
-------→| |-----socket—→| |-----→
-------→|----------| |---------|-----→
处理IO请求方式有 串行处理 和 并行处理 为了提高效率防止阻塞 使用并行处理的方式
- 将一个Socket 作为复用 开启多线程的方式
串行的例子:
- 高中老师在自习课解决学生的问题的时候,老师会被某些同学还没有完成任务引起阻塞导致你的问题得不到解决
并行例子:
- 火影忍者分身术[多线程]—资源消耗查克拉
多路复用:
- 让问题去找你,哪个学生效率高先答完题然后拿着结果去找老师,老师处理问题
专业上的解释:
对于IO请求要获取文件资源上的处理的时候,或获取文件的描述符,如果这个文件的描述符还没有就绪,这个请求将等待,直到描述符状态为就绪的时候,请求通过上报请求通知的机制告诉应用程序当前请求就绪,可以执行操作
特点:多个描述符的IO操作都能在一个线程内并发交替的顺序完成,这里的复用指的是复用同一个线程
什么是epoll
是常见的系统内核的IO多路复用模型
模型有:
- select
- poll
- epoll
select:
资源fd未就绪的时候,IO请求在应用层面是被Block的,但是维护着一个[fd]列表
当fd状态就绪的时候,select模型会遍历这个[fd]列表去唤醒可以被执行的IO进程
- 方式 线性的去遍历[fd]列表
- 问题一: 线性遍历固有效率低下的问题
- 问题二: [fd]列表的规模是最大1024个,所以在数量上有限制
epoll模型:
- 当fd状态就绪的时候,采用系统的回调函数直接将fd放入就绪列表,效率更高
- 无最大连接数量的限制
场景比喻:
select 餐馆结账 客人—>服务员 ----> 服务员告诉收营员说 有人要结账 ---->收营员挨个桌子问谁要结账
epoll 餐馆结账 客人—>服务员 ----> 服务员告诉收营员说 有人要结账,号码为xxx ---->收营员直接去xxx号收账
原因二
- 功能模块少
- 只保留http请求的核心代码
- 可作为插件的模块不会被集成 [ 类比 :flask django]
- 代码模块化
原因三
CPU亲和(affinity)
为什么需要CPU亲和
多核心cpu
Nginx是通过多worker进程实现工作的,我们可以经不同的worker绑定到相应的CPU核心上,均匀分配,降低CUP自动调度引起的不必要的性能的损失
即:将CPU的核心和Nginx的工作进程绑定在一起
原因三四 sendfile 的工作机制[处理静态文件]
文件请求的路径:
File → [kernel space]→[user space]→[user space]→[kernel space]→Socket
sendfile跳过的用户空间,直接通过内核空间完成静态文件的请求
File → [kernel space]→ [kernel space]→Socket
Nginx的安装
有哪些版本?
- Mainline version – 开发版
- Stable version – 稳定版
配置官方nginx yum源:
vim /etc/yum.repos.d/nginx.repo
粘贴进入:
[nginx]
name=nginx repo
baseurl=http://nginx/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
yum install nginx
使用yum安装之后,在那些位置,安装了什么文件
基本目录
编译参数
Nginx基本配置语法
rpm -ql nginx
查看在那些目录安装了什么文件
路径 | 类型 | 作用 |
---|---|---|
/etc/logratate.d/nginx | 配置文件 | Nginx日志轮转,用于logrotate服务的日志切割 |
/etc/nginx; /etc/nginx/nginx.conf; /etc/nginx/conf.d; /etc/nginx/conf.d/default.conf | 目录,配置文件 | Nginx主配置文件 |
/etc/nginx/fastcgi_params; /etc/nginx/uwsig_params; /etc/nginx/scgi_params; | 配置文件 | cgi相关配置,fastcgi配置 |
/etc/nginx/koi-utf; /etc/nginx/koi-win; /etc/nginx/win-utf; | 配置文件 | 编码转换映射转换文件 |
/etc/nginx/mime.types | 配置文件 | 设置http协议的Content-type于扩展名的对应关系 |
/usr/lib/systemd/system.nginx-debug.service; /usr/lig/systemd/system/nginx.service; /etc/sysconfig/nginx; /etc/sysconfig/nginx-debug; | 配置文件 | 用于配置系统守护进程管理器管理方式 |
/usr/lib64/nginx/modules; /etc/nginx/modules; | 目录 | Nginx模块目录 |
/usr/sbin/nginx; /usr/sbin/nginx-debug | 命令 | nginx服务启动管理的终端命令 |
/usr/share/doc/nginx-x.x.x; /usr/share/doc/nginx-x.x.x/COPYRIGHT; /usr/share/man/man8/nginx.8.gz; | 文件,目录 | Nginx手册和帮助文件 |
/var/cache/nginx | 目录 | nginx缓存目录 |
/var/log/nginx | 目录 | nginx日志目录 |
nginx -V
查看编译参数
以--with--xxxx
开头的是nginx默认启动的哪些模块
安装目录或者路径
--prefix=/etc/nginx
--sbin-path=/usr/sbin/nginx
--modules-path=/usr/lib64/nginx/modules
--conf-path=/etc/nginx/nginx.conf
--error-log-path=/var/log/nginx/error.log
--http-log-path=/var/log/nginx/access.log
--pid-path=/var/run/nginx.pid
--lock-path=/var/run/nginx.lock
执行模块的时候nginx所保留的临时性文件
--http-client-body-temp-path=/var/cache/nginx/client_temp
--http-proxy-temp-path=/var/cache/nginx/proxy_temp
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp
--http-scgi-temp-path=/var/cache/nginx/scgi_temp
启动用户和所属用户组
--user=nginx
--group=nginx
重启nginx服务的命令
systemctl restart nginx.service
systemctl reload nginx.service
软重启-不停止服务
HTTP请求
request
客户端----------------------→服务端
↑ response |
\----------------------------------
基于TCP协议
载体 — 报文
请求报文(request) — 包括 : 请求行,请求头,请求数据
相应报文(response)—包括 : 状态行,消息头,相应正文
Nginx的日志类型
- error.log
- 错误状态信息
- access_log
- 每次Http请求的访问状态信息
主配置: /etc/nginx/nginx.conf
错误日志文件 + 级别:/var/log/nginx/error.log warn
状态日志文件 + 级别: /var/log/nginx/access.log main
main 对应 log_format 定义的 main 变量
默认变量的格式为:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
$remote_addr 客户端的IP地址
$remote_user 客户端请求nginx认证的用户名<前提开启用户认证,否则不被记录>
$time_local 服务器时间
$request request头的请求行<请求方法,http协议版本等等..>
$status 相应状态
$body_bytes_sent 服务端口相应到客户端的body信息的是大小
$http_referer 上一级页面的地址
$http_user_agent 客户端身份
$http_x_forwarded_for 真实地址 代理地址 http扩展信息
依赖于log_format变量的配置
以上变量的配置依据Nginx内置变量
Nginx有哪些变量
Http请求变量: arg_PAPAMETER http_HEADER sent_http_HEADER
例如如果想要记录请求头中的user_agent,那么就在log_format 中 配置 ‘$http_user-agent’ 这样access.log就会记录每一次请求的user-agent信息
注意:每次修改配置文件之后
nginx -t -c /etc/nginx/nginx.conf
对修改的配置文件进行语法和路径上的检查
nginx -s reload -c /etc/nginx/nginx.conf
重载配置文件
Nginx的一些内置变量:
http://nginx/en/docs/http/ngx_http_core_module.html#var_status
自定义变量
Nginx的模块
- 官方模块 nginx自带的默认模块以及官方支持的模块
- 第三方模块 自定义的模块
官方模块:
--with-http_stub_status_module
展示Nginx处理当前连接的状态,将恐Nginx当前连接的信息
文档地址:http://nginx/en/docs/http/ngx_http_stub_status_module.html
配置语法:
Syntax: stub_status;
Default: —
Context: server, location
解释: 需要配置的信息为 stub_status;
默认是--
没有配置 配置的位置在server下的location /etc/nginx/conf.d/default.conf
添加:
location = /basic_status {
stub_status;
}
检查并重载配置文件之后
访问http://[服务器地址]/basic_status
获取当前Nginx连接状态
active connections: xxx 连接数
server accepts handles requests xxx xxx xxx 三个数 分别是nginx处理的握手的总次数 nginx处理的总连接数 总的请求数
一般情况下 总握手数=总连接数 代表着没有丢失
Reading x 正在读的个数 Writing x 正在写的个数 waiting x 既没有读也没有写的连接数
--with-http_random_index_module
在主目录中随机选中一个页面作为主页 <不会选择.开头的隐藏文件> 应用场景[生成不同的随机主页]
文档地址http://nginx/en/docs/http/ngx_http_random_index_module.html
配置语法:
Syntax: random_index on | off;
Default: random_index off;
Context: location
配置在location下/etc/nginx/conf.d/default.conf
对原有的location进行修改
location / {
root /usr/share/nginx/html; # 主目录
random_index on; # 添加这个
# index index.html index.htm; 注释掉
}
--with-http_sub_module
服务端对客户端相应的Http内容进行替换
文档地址http://nginx/en/docs/http/ngx_http_sub_module.html
配置语法:[一]
Syntax: sub_filter string replacement; [string]要被的内容替换 [replacement]替换后的内容
Default: —
Context: http, server, location
可以加在http下 server下 或者location下 如果放在http下,则可以实现对多个server进行替换
配置语法:[二]
Syntax: sub_filter_last_modified on | off;
Default: sub_filter_last_modified off;
Context: http, server, location
主要用于缓存,判断请求的头信息是否发生变更,如果发生变更就返回新的内容,否则不做返回
配置语法:[三]
Syntax: sub_filter_once on | off;
Default: sub_filter_once on;
Context: http, server, location
匹配规则,on表示只匹配第一个off表示扫描匹配
Nginx的请求限制
- 连接频率限制 limit_conn_module
- 请求频率限制 limit_req_module
HTTP协议的连接于请求
|→ SYN →|
|← SYN,ACK ←| 三次握手建立连接
|→ ACK →|
|→HTTP(Req) →| 连接成功之后发送请求
|← HTTP(Res)←|
|→ FIN →| 不断交互FIN和ACK保持连接状态
|← ACK ←|
client ... server
HTTP1.0 TCP不可复用
HTTP1.1 顺序性TCP复用
HTTP2.0 多路复用TCP复用
结论: HTTP建立在TCP上,一次连接(TCP请求)至少可以产生一次HTTP请求
针对连接的限制
文档地址http://nginx/en/docs/http/ngx_http_limit_conn_module.html
配置语法:[一]
Syntax: limit_conn_zone key zone=name:size;
Default: —
Context: http
以某个变量作为key[例如客户端IP,$remote_addr],开辟一块空间,储存key,定义空间的name,定义空间的大小[1M,2M]
配置语法:[二,结合一使用]
Syntax: limit_conn zone number;
Default: —
Context: http, server, location
这里的zone是配置1配置的空间的name,number是对并发数量的限制
针对请求的限制
文档地址:http://nginx/en/docs/http/ngx_http_limit_req_module.html
配置语法:[一]
Syntax: limit_req_zone key zone=name:size rate=rate [sync];
Default: —
Context: http
rate是请求的速率,通常以秒为单位,每秒允许请求多少个 rate=1r/s
配置语法:[二,结合一使用]
Syntax: limit_req zone=name [burst=number] [nodelay | delay=number];
Default: —
Context: http, server, location
burst=3 nodelay 超出部分的三个会延迟返回,其他的忽略
安装httpd后会附带ab压力测试工具
ab -n 50 -c 20 http://xxxxxxxxxxx
-n 总请求数量
-c 并发量
发现请求限制为1 那么只能返回1个正常200数据
连接限制为1 ,返回>1个正常200数据,因为一次连接可以允许多次请求,所以连接限制结合请求限制使用
Nginx的访问控制
- 基于IP的访问控制 http_access_module
- 基于用户的信任登陆 [登陆认证] http_auth_basic_module
IP访问控制
文档地址:http://nginx/en/docs/http/ngx_http_access_module.html
配置语法:[一]
Syntax: allow address | CIDR | unix: | all;
Default: —
Context: http, server, location, limit_except
address 允许的ip ; CIDR 允许的网段 ; unix: 是socket方式 ; all表示所有
配置语法:[二] 黑名单
Syntax: deny address | CIDR | unix: | all;
Default: —
Context: http, server, location, limit_except
配置的时候先配置deny x.x.x.x ; 再配置allow all; 表示除了黑名单,以外的都可以
先配置allow x.x.x.x 在配置 deny all;表示只允许白名单的ip访问
IP访问控制的局限性
服务端不能有效的判断请求是否是客户端发送过来的,也就是说通过代理可以突破这个访问控制
这里就提及到http_x_forwarded_for这个http请求头信息
remote_addr服务端和请求端直接建立连接的请求端地址
http_x_forwarded_for会记录整个ip通过代理的记录,理论上来说第一个ip为真实地址,往后的proxy_1,proxy_2,…
为了解决这个局限性:
- 方法一: 采用别的HTTP头信息进行访问控制,如:http_x_forwarded_for
- 方法二: 结合geo模块
- 方法三: 通过HTTP自定义变量传递
信任用户登陆的访问控制
文档地址:http://nginx/en/docs/http/ngx_http_auth_basic_module.html
配置语法:[一]
Syntax: auth_basic string | off;
Default: auth_basic off;
Context: http, server, location, limit_except
string 是一个字符串,可以作为前端的登陆提示,表示开启用户验证
配置语法:[二]
Syntax: auth_basic_user_file file;
Default: —
Context: http, server, location, limit_except
file储存的是用户名和密码
存储格式:
# comment
name1:password1
name2:password2:comment
name3:password3
加密方式:htpasswd工具
在配置文件的上级目录,/etc/nginx 执行命令生成用户名_密码的文件
htpasswd -c ./auth_conf username
password:xxxxxxx
re-type password:xxxxxxxx
信任用户登陆的访问控制的局限性
- 一,依赖文件储存用户信息
- 二,操作管理机械,效率低下<管理用户信息文件很低效率>
解决方案
- 一 Nginx结合LUA实现高效验证
- 二 Nginx和LDAP大同,利用nginx-auth-ldap模块高效验证
进阶篇
- 静态资源WEB服务
- 代理服务
- 负载均衡调度器SLB
- 动态缓存
静态资源
什么是静态资源?非服务器动态运行生成的文件
类型 | 种类 |
---|---|
浏览器渲染 | HTML,CSS,JS |
图片 | jpeg,gif,png |
视频 | flv,mpeg |
文件 | txt,任意下载文件 |
静态资源-CDN
静态资源回溯 静态资源请求
Nginx[资源中心]-----------→Nginx[北京代理] ←User[北京]
-----------→Nginx[山东代理]
.......
文档地址http://nginx/en/docs/http/ngx_http_core_module.html#sendfile
配置语法–sendfile
Syntax: sendfile on | off;
Default: sendfile off;
Context: http, server, location, if in location
在sendfile开启的条件下配置tcp-nopush提高传输效率
文档:http://nginx/en/docs/http/ngx_http_core_module.html#tcp_nopush
语法:
Syntax: tcp_nopush on | off;
Default: tcp_nopush off;
Context: http, server, location
目的是将小包裹打包成大包裹整体发送
与之相反的是tcp_nodelay
文档:http://nginx/en/docs/http/ngx_http_core_module.html#tcp_nodelay
语法:
Syntax: tcp_nodelay on | off;
Default: tcp_nodelay on;
Context: http, server, location
效果是小文件实时发送,提高传输的实时性,前提是keepalive打开
异步存取模块提高效率
文档:http://nginx/en/docs/http/ngx_http_core_module.html#aio
语法:
Syntax: aio on | off | threads[=pool];
Default: aio off;
Context: http, server, location
三个模块的配置结果一般为:
location /video/ {
sendfile on;
tcp_nopush on;
aio on;
}
静态文件压缩配置
一般使用gzip的方式,模块为ngx_http_gzip_module,目的是提高传输效率
文档http://nginx/en/docs/http/ngx_http_gzip_module.html#gzip
语法:
Syntax: gzip on | off;
Default: gzip off;
Context: http, server, location, if in location
过程:
[Nginx服务端]<压缩>---------→<解压>[浏览器客户端]
配置gzip压缩的比率
文档:http://nginx/en/docs/http/ngx_http_gzip_module.html#gzip_comp_level
语法:
Syntax: gzip_comp_level level;
Default: gzip_comp_level 1;[1-9]
Context: http, server, location
理论比率越高,数据包越小,但是服务器的高比率压缩此操作耗费性能
配置gzip_http_version 主流是1.1
语法:
Syntax: gzip_http_version 1.0 | 1.1;
Default: gzip_http_version 1.1;
Context: http, server, location
配置压缩文件的类型:
文档:http://nginx/en/docs/http/ngx_http_gzip_module.html#gzip_types
语法:
Syntax: gzip_types mime-type ...;
Default: gzip_types text/html;
Context: http, server, location
可用类型text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png
扩展Nginx的压缩模块
http_gzip_static_module 预压缩,会首先查看是否已经有压缩文件,响应压缩文件,而不是重新压缩后响应[会耗费硬盘资源,减轻压缩的时候对性能的消耗]
http_gunzip_module 应用gunzip的压缩方式[某些浏览器不支持gzip]
浏览器缓存
HTTP协议定义的缓存机制(如 :Expires;Cache-control等头信息)
本地浏览器没有缓存的请求过程:
[浏览器]→[无换尺寸]→[请求web服务器]→[请求响应,协商]→[呈现] <在客户端生成缓存>
浏览器有缓存的请求
[浏览器]→[本地缓存]→[有效校验]→[呈现]
校验机制:
描述 | 校验内容 |
---|---|
校验本地缓存是否过期 | Expires[1.0],Cache-Control(max-age)[1.1]<本地验证> |
协议中Etag头信息 | Etag<向服务端验证> |
Last-Modified头信息 | Last-Modified<向服务端验证> |
Last-Modified存储的是时间,如果跟服务器最新数据的时间不一致就会响应更新之后的数据
Last-Modified只能精确到秒,所以在一秒内数据的更新会校验通过,忽略响应新数据
Etag储存的是储存特殊字符串,后台数据更新,这串字符串在后台的部分就会改变,校验不通过,响应更新之后的新数据
解决了Last-Modified只能精确到秒的局限性
配置 expries
配置浏览器的本地缓存
文档地址:http://nginx/en/docs/http/ngx_http_headers_module.html#expires
配置语法:
Syntax: expires [modified] time;
expires epoch | max | off;
Default: expires off;
Context: http, server, location, if in location
例如配置:
location ~ .*\.(html|htm)${
expries 24h;
root /opt/app/code
}
跨站访问
浏览器出于安全考虑默认禁止跨站请求<避免跨站伪造攻击>
多域名之间的访问需要打开跨站请求
虽然浏览器关闭了跨站请求,但是会根据响应头信息去控制跨站请求的开启或者关闭
文档地址http://nginx/en/docs/http/ngx_http_headers_module.html#add_header
配置语法:
Syntax: add_header name value [always];
Default: —
Context: http, server, location, if in location
为响应添加响应头Access-Control-Allow-Origin
name = Access-Control-Allow-Origin
value = 允许的那些站点可以跨站访问 如果是* 则所有站点 www.baicu
name = Access-Control-Allow-Methods
value = GET,POST,PUT,DELECT,OPTIONS 可支持的请求方式
防盗链
目的:防止资源盗用或者非正常用户对服务器的压力
设置思路:
- 判断正常和非正常用户
方式:
使用http_referers
文档地址:http://nginx/en/docs/http/ngx_http_referer_module.html#valid_referers
配置语法:
Syntax: valid_referers none | blocked | server_names | string ...;
Default: —
Context: server, location
none 允许空 blocked[非标准http://] xxx.xx.xxx.xxx[指定域名或IP地址]
配置示例
valid_referers none blocked 116.62.103.228 ~ .*\.google;
if ($invalid_referer){
return 403;
}
配置只是为了能够正常获得$invalid_referer变量,如果无法正常获得,那么这个变量就是1,正常获得的话就是0
Nginx的代理服务
[客户端] →[代理]→[服务端]
| |------- HTTP ----→| |→[HTTP Server ]
| | -ICMP\POP\IMAP→ | |→[Mail Server ]
| 客户 | | Nginx | |
| |------- HTTPS ----→| |→[HTTP Server ]
| |------- RTMP -----→| |→[media Server]
正向代理:
|
[客户端]←→[代理服务] → | →[服务端]
|
翻墙,通过国外的代理去获取国外信息
反向代理:
|
[客户端]→ | →[代理服务]←→[服务端]
|
正向代理和反向代理的区别:
代理服务所服务的对象不一样,正向代理的代理服务是为客户端服务的,反向代理的代理服务是为服务端服务的
代理配置
反向代理的配置
文档地址:http://nginx/en/docs/http/ngx_http_proxy_module.html#proxy_pass
配置语法:
Syntax: proxy_pass URL;
Default: —
Context: location, if in location, limit_except
URL = http://localhost:8000
URL = https://localhost:8000
netstat -luntp|grep nginx
查询nginx使用到的端口
思路:服务器配置nginx代理,监听两个端口,80端口为监听客户端对代理服务的请求,监听的8000端口为反向代理的服务端
客户端通过代理服务的域名+80端口发送请求 Nginx代理将请求通过8000端口发送到服务端,服务端相应数据到Nginx代理,Nginx代理通过当前80端口将数据返回给客户
配置正向代理的语法和反向代理一致
现在只有这台主机可以访问某个网站,当前服务器的地址为123.23.23.333:80,监听80端口
URL = $http_host$request_url
配置DNS解析 resolver 8.8.8.8
客户端浏览器配置代理服务器地址123.23.23.333:80
思路:代理去访问允许有访问的网址,客户端配置代理服务,代理服务为代理主机的监听端口和公共IP
缓冲区
模块proxy_buffer
文档地址http://nginx/en/docs/http/ngx_http_proxy_module.html#proxy_buffering
配置语法:
Syntax: proxy_buffering on | off;
Default: proxy_buffering on;
Context: http, server, location
开启这像功能后,Nginx将经可能的将一个请求的所有信息收集完,再整体返回给客户端,减少IO损耗
默认数据会临时储存在内存,如果内存不够,那么将会被储存到硬盘的临时目录
相关联的扩展配置
proxy_buffer_size[32k] proxy_buffers[4 128k] proxy_busy_buffers_size[256k] proxy_max_temp_file_size[256k]
跳转重定向配置
模块proxy_redirect
文档地址http://nginx/en/docs/http/ngx_http_proxy_module.html#proxy_redirect
配置语法:
Syntax: proxy_redirect default;
proxy_redirect off;
proxy_redirect redirect replacement;
Default: proxy_redirect default;
Context: http, server, location
服务端→客户端的 状态为301的时候
常用配置实例:
proxy_redirect default;
代理头信息配置
模块proxy_set_header
文档地址http://nginx/en/docs/http/ngx_http_proxy_module.html#proxy_set_header
配置语法:
Syntax: proxy_set_header field value;
Default:
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
Context: http, server, location
常用配置实例:
proxy_set_header Host %http_host;
proxy_set_header X-Real-Ip $remote_addr;
相关扩展proxy_hide_header,proxy_set_body
连接超时
代理----→服务端的连接超时配置
模块proxy_connect_timeout
文档地址http://nginx/en/docs/http/ngx_http_proxy_module.html#proxy_connect_timeout
配置语法:
Syntax: proxy_connect_timeout time;
Default: proxy_connect_timeout 60s;
Context: http, server, location
常用配置案例:
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_time_out 60;
相关扩展 procy_read_timeout,已经建立好连接后,读取数据的等待时间
proxy_send_timeout服务端请求完成后响应到客户端的等待时间
将通用的模块配置配置到一个文件内
在配置文件中include 文件名
从文件中导入配置
Nginx作为负载均衡服务
对,负载均衡的分类[按照地域划分]
GSLB:
全局负载均衡
张三在北京,请求调度节点,调度节点返回张三对应地址,张三通过对应地址访问到应用服务[北京的],应用服务响应数据给张三
这样没有对中心节点请求,所以不会给中心服务端造成压力
SLB:
[用户节点]<—>[调度节点]<------>[服务节点]
按照网络模型划分:
四层负载均衡:
传输层 对客户端的请求进行TCP/IP协议的包转发,效率快,底层处理
七层负载均衡:
应用层 可以实现Http信息的控制[改写,头信息,安全规格的控制,转发]
Nginx是典型的七层负载均衡
Nginx实现负载均衡主要是通过proxy_pass代理
[客户]→[Nginx]-<proxy_pass>→[虚拟服务池upstream server]
虚拟服务池中的服务单元是轮询的,Nginx分发请求
upstream的配置
文档地址http://nginx/en/docs/http/ngx_http_upstream_module.html#upstream
配置语法:
Syntax: upstream name { ... }
Default: —
Context: http
exiample:
upstream backend {
server backend1.example weight=5;
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
server backup1.example backup;
}
backend 是自定义的虚拟服务池的名字
server 后配置虚拟服务的IP:port 或者域名
weight代表着当前虚拟服务的权重
backup代表着当前虚拟服务是备份服务器 有其他server存活的情况下是不提供服务的
down 表示当前的server不参与负载均衡
max_fails允许请求失败的次数
fail_timeout 服务请求失败之后当前服务暂停的时间
max_conns 最大连接数 服务器性能不一定均衡,性能高的多配置,性能低的少配置
调度算法
轮询 按照时间顺序逐一分配到后端服务器
加权轮询 权重大的被分配到的机率大
ip_hash 每个请求按照访问IP的hash结果分配,这样的作用是保证同一个ip只能访问固定的一台服务器
last_conn 最少连接数,哪个服务器上的当前连接数少,就往那个服务器上分配请求
url_hash 请求的url的hash来固定分配服务器
hash_关键值 hash自定义的key
关于缓存和用户登录状态的记录在经过轮询之后会出现问题,所以有了ip_hash
配置方式是直接在upstream中假如一行ip_hash ;
ip_hash基于的是$remote_addr,所以难免会有代理的局限性
结合hash_关键值 自定义hash key来解决这个问题
文档地址http://nginx/en/docs/http/ngx_http_upstream_module.html#hash
hash_关键字的配置语法
Syntax: hash key [consistent];
Default: —
Context: upstream
This directive appeared in version 1.7.2.
key是可以自定义的 将key定义成为$request_uri
就会将除了域名之外的部分作为hash关键字去分配服务器
存在问题?在实际开发中$request_uri
会携带一长串的数据,不仅仅是url还具有?k=v
类的数据,这些数据是常常改变的,这种改变会引起服务器的切换
所以我么需要在配置中,定义正则判断,来控制hash关键字
Nginx作为缓存服务
缓存的类型
[客户端]←→[Nginx]←→[服务端]
缓存放在服务端 [服务端缓存] 常用到memercache 和 redis
缓存放在Nginx [代理缓存]
缓存放在浏览器 [客户端缓存]
代理缓存示意图:
Nginx缓存服务的配置
首先配置缓存路径
模块proxy_chahe_path
文档地址http://nginx/en/docs/http/ngx_http_proxy_module.html#proxy_cache_path
配置语法
Syntax: proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time]
[max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number]
[loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time]
[purger_threshold=time];
Default: —
Context: http
内容
- path 缓存的目录
- levels 对目录的分级 一般配置成为
1:2
按照两级目录来左缓存 - keys_zone 定义的缓存空间的名字和大小
- max_size 缓存目录的自增大小的限制,当增加达到限制就不再增加,触发淘汰规则,将不常用到的缓存淘汰掉
- inactive 不活跃的时间 [60m60分钟] 在时间达到后没有被再次缓存就会将其清理掉
- use_temp_path 是否使用临时空间的配置,一般关闭
示例
proxy_cache_path /opt/code/cache levels=1:2 keys_zone=myzone:10m max_size=10g inactive=60m use_temp_path=off
开启缓存的配置
模块proxy_cache
文档地址http://nginx/en/docs/http/ngx_http_proxy_module.html#proxy_cache
配置语法
Syntax: proxy_cache zone | off;
Default: proxy_cache off;
Context: http, server, location
针对以上对proxy_cache_path的配置,在location中配置
proxy_cache myzone
配置缓存的过期时间
模块proxy_cache_valid
文档地址http://nginx/en/docs/http/ngx_http_proxy_module.html#proxy_cache_valid
配置语法
Syntax: proxy_cache_valid [code ...] time;
Default: —
Context: http, server, location
针对以上对proxy_cache_path的配置,在location中配置
proxy_cache_valid 200 304 12h;
200和304返回的信息在12h后过期
proxy_cache_valid any 10m;
除了以上200和304以外的数据在10min过期
配置缓存的维度
模块proxy_cache_key
文档地址http://nginx/en/docs/http/ngx_http_proxy_module.html#proxy_cache_key
配置语法
Syntax: proxy_cache_key string;
Default: proxy_cache_key $scheme$proxy_host$request_uri;
Context: http, server, location
默认配置 为http协议+域名+请求路由
针对以上对proxy_cache_path的配置,在location中配置
proxy_cache_key $host$uri$is_args$args
add_header Nginx_Cache "upsteam_cache_status"
添加头信息,告诉浏览器服务器缓存的状态
proxy_next_upsteam error timeout invalid_header http_500 http_502 http_503 http_504;
当服务器出错后切换服务器
当缓存生效后,清理指定的缓存文件
- 直接使用 linux 的删除将指定缓存文件删除
- 使用第三方模块去支持
ngx_cache_purge
如何指定某些页面不做缓存[登陆页面,支付页面…]
模块proxy_no_cache
文档地址http://nginx/en/docs/http/ngx_http_proxy_module.html#proxy_no_cache
配置语法
Syntax: proxy_no_cache string ...;
Default: —
Context: http, server, location
示例
if ($request_uri ~ ^/(login|register|password\/reset)){
set $cookie_nocache 1;
}
location /{
...;
proxy_no_cache $cookie_nocache $arg_nocache $arg_comment
}
当访问匹配到以上url后会设置$cookie_nocache=1 所以下面proxy_no_cache
会将cookie_nocache
为1的响应数不做缓存
Nginx大文件的分片请求
模slice
文档地址http://nginx/en/docs/http/ngx_http_slice_module.html#slice
配置语法
Syntax: slice size;
Default: slice 0;
Context: http, server, location
官方示例
location / {
slice 1m;
proxy_cache cache;
proxy_cache_key $uri$is_args$args$slice_range;
proxy_set_header Range $slice_range;
proxy_cache_valid 200 206 1h;
proxy_pass http://localhost:8000;
}
过程,客户端请求Nginx,Nginx拿着请求去请求后端服务器获取文件大小,Nginx根据分片配置将请求分为小的请求并发的去请求许多服务器,Nginx获得分片文件,将分片文件合并后响应给客户端
优势:
子请求响应的服务器数据为独立的子文件,所以当一个子请求失败后,不会影响其他子请求,失败的请求会重新发送新的请求
局限:
slice设置的很小 ,文件又特别大,会有可能将文件描述符用光
Nginx的动静分离
什么是动静分离?
利用中间件,将动态请求和静态请求分离
目的:
分离资源,减少不必要的请求消耗,降低请求延迟
当动态请求的数据在后端出现问题的时候,不会影响到对静态资源的请求
层次关系:
场景:
动态资源一般都是.jsp .php结尾的
所以可以通过匹配来分离两种请求
root = /opt/app/code;
location ~ .*\.(jsp|php)${
proxy_pass http://simple_api;
}
location ~.*\.(jpg|gif|png)${
expire 1h;
gzip on;
}
location /{
index index.html index.htm;
}
Nginx的Rewrite规则
rewrite可以实现对url的重写以及重定向 所依赖的就是正则匹配
场景
- url访问跳转,支持开发设计
- 页面跳转
- 兼容性支持(新版本,旧版本,老用户,新用户)
- 展示性效果(复杂url用简单url来展示)
- SEO优化
- 维护
- 后台维护
- 流量转发
- 安全
- 伪静态处理
rewrite的配置
模块rewrite
文档地址http://nginx/en/docs/http/ngx_http_rewrite_module.html#rewrite
配置语法
Syntax: rewrite regex replacement [flag];
Default: —
Context: server, location, if
regex = 正则规则
replacement = 替换
[flag] 标识
例如当服务器维护的时候,将所有的访问重定向到一个静态页面
rewrite ^(.*)$ /page/maintian.html break
例如将IE的请求重定向到IE所支持的页面
if ($http_user_agent ~ MSIE){
rewrite ^(.*)$ /msie/$1 break;
}
[flag]标识:
-
last 停止rewrite检查
-
break 停止rewrite检查
-
redirect 返回302临时重定向,地址上会显示跳转后的地址
-
permanent 返回301永久重定向,地址上会显示跳转后的地址
rewrite定义的配置的优先级
-
server块下的rewrite
-
location匹配
-
执行location中的rewrite
Nginx中的高级模块
secure_link_module模块
作用:
- 指定并允许检查请求的链接的真实性以及保护资源免遭未经过授权的访问
- 限制链接的生效周期
文档地址http://nginx/en/docs/http/ngx_http_secure_link_module.html#secure_link
配置语法
Syntax: secure_link expression;
Default: —
Context: http, server, location
官方示例
location /s/ {
secure_link $arg_md5,$arg_expires; # arg_md5是获取md5这个参数,$arg_expires是获取expires参数
secure_link_md5 "$secure_link_expires$uri$remote_addr secret";# 这里规定了加密的方式 secret是自定义密钥字符串
if ($secure_link = "") {
return 403;
}
if ($secure_link = "0") {
return 410;
}
...
}
场景___生成有时效的下载链接
这个期间,后台存在两个校验
- md5校验
- expires校验
一般加密的方式:ip+url 或者 cookie信息 等添加上我们规定好的一段密钥
加密过程是后台服务器(python,php等)生成加密之后的字符串,然后拼接成为下载链接返回给Nginx再返回给客户端
客户端使用加密之后的下载链接去请求下载资源
- 下载链接被更改的化Nginx就会验证不通过返回403
- 下载链接如果没有携带加密参数Nginx也会验证不通过返回403
上面的验证是Nginx来处理的,并没有给web后台造成压力
geoip_module模块
基于IP地址匹配MaxMind Geoip二进制文件,读取ip所在的地域信息
属于三方包,需要按章yum install -y nginx-module-geoip
模块安装在/etc/nginx/module/
目录下
修改nginx.conf配置文件来将这个模块加载进Nginx服务
/etc/nginx/nginx.conf
添加
load_module "modules/ngx_http_geoip_module.so";
检查并重载nginx配置文件
下载geoip数据库
https://geolite.maxmind/download/geoip/database/GeoLite2-City.tar.gz
https://geolite.maxmind/download/geoip/database/GeoLite2-Country.tar.gz
使用gunzip
命令解压文件
场景
- 区别国内和国外的HTTP访问规则
- 区别国内城市的HTTP访问规则
通过geoip可以进行区域防控
HTTPS服务
为什么使用HTTPS,而不是用HTTP?
- HTTP传输数据可以被中间人盗用,信息泄露
- 数据内容容易被劫持,篡改(弹出广告,直接重定向)
原理:
对传输内容进行加密以及身份验证
- 对称加密
- 非对称加密
对称加密特征是加密方的加密密钥和解密方的解密密钥是同一把密钥
非对称加密使用的是公钥和私钥的方式
HTTPS同时运用到了对称加密和非对称加密两种方式
客户端通过SSL连接请求服务器,服务器返回公钥,客户端利用公钥对对称加密的密码进行非对称加密后发送给服务端,服务端利用私钥解密出对称加密的密码,然后双方使用对称加密的方式传输数据
非对称对连接的要求高,每次连接都需要携带公钥,所以需要的资源多,因此在第一次连接的时候使用非对称的方式,验证成功之后使用对称的方式就可以在保证安全的情况下降低对性能的要求
中间人的伪装劫持
中间人伪装只是简单的利用公钥的方式是没有办法避免的
所以不再发送公钥,而是使用CA签名的证书
中间人是无法实现对CA签名证书的校验的
客户端通过第三方的CA签名机构对CA签名证书经进行校验
CA签名证书中包含了服务端发送过来的公钥
CA签名证书的生成
(自签名证书)
系统上要装有openssl
nginx上要有–with-http_ssl_module
步骤:
- 生成key密钥
- 生成证书签名请求文件(csr)
- 生成证书签名文件(CA)
在/etc/nginx
下创建ssl_key
目录
进入ssl_key目录执行命令openssl genrsa -idea -out jesonc.key 1024
会要求输入两密码,这个密码是维护这个key的密码,需要牢记
Enter pass phrase for jesonc.key:
Verifying - Enter pass phrase for jesonc.key:
生成key成功之后,需要生成csr请求文件
openssl req -new -key jesonc.key -out jesonc.csr
第一个会让输入密码,即上面定义的维护密码
然后按照要求添加数据
最后会输入第二个密码,这个密码是用来维护证书的密码,可以不写,也可以自定义个新密码
最后会生成这个csr文件
然后生成证书文件
openssl x509 -req -days 3650 -in jesonc.csr -signkey jesonc.key -out jesonc.crt
默认过期时间是一个月 这里将它改成3650天
执行后会输入密钥的维护密码,就是定义的第一个密码
密码验证后会申城crt证书文件
[root@VM_0_10_centos ssl_key]# tree
.
|-- jesonc.crt
|-- jesonc.csr
`-- jesonc.key
配置Nginx的ssl
文档地址http://nginx/en/docs/http/ngx_http_ssl_module.html#ssl
配置语法:
一
Syntax: ssl on | off;
Default: ssl off;
Context: http, server
开关
二
Syntax: ssl_buffer_size size;
Default: ssl_buffer_size 16k;
Context: http, server
This directive appeared in version 1.5.9.
缓冲区的大小 小的4k 一般16k
三
Syntax: ssl_certificate file;
Default: —
Context: http, server
CA文件的路径
四
Syntax: ssl_certificate_key file;
Default: —
Context: http, server
密钥文件的路径
官方示例
server {
listen 443 ssl;
server_name example;
ssl_certificate example.rsa.crt;
ssl_certificate_key example.rsa.key;
ssl_certificate example.ecdsa.crt;
ssl_certificate_key example.ecdsa.key;
...
}
生成苹果要求的CA文件
openssl req -days 3650 -x509 -sha256 -nodes -newkey rsa:2048 -keyout jesonc.key -out jesonc_apple.crt
直接使用key文件生成crt,不再需要csr请求文件
回车之后,输入要求输入的相关信息
生成crt证书文件之后,替换到nginx的配置文件中即可
如何将已经存在密码的key文件生成一个脱去密码的key文件?
openssl res -in ./xxxxold.key -out ./xxxnew.key
输入保护密码后就可以生成一个新的没有密码的xxxnew.key文件
HTTPS服务的优化
HTTPS请求需要在HTTP连接建立起来之前先进行SSL的握手来获取CA证书,所以对比HTTP请求会多了一次连接请求,服务端对应的要进行ssl认证,这样对服务端新能的要求就提高了.
为什么还要推荐HTTPS呢?因为服务器水平方向的扩容(负载均衡),性能的扩充使得企业会在性能和安全的权衡上偏向于安全
但是还是要考虑性能
- 激活keepalive长连接(一次连接可以处理多次请求)
- 设置ssl session缓存(通过缓存来提高性能)
sever下配置
keepalive_timeout 100;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
Nginx
Nginx于Lua开发
- Lua及基础语法
- Nginx于Lua环境
- 场景:用Nginx结合Lua实现代码的灰度分布
Lua
一种简洁,轻量,可扩展的脚本语言
Nginx+Lua的优势:
充分的结合Nginx的并发处理epoll优势和Lua的轻量实现简单功能的高并发的场景.
基础语法
变量定义 a = 1
打赢 print()
交互式执行 文件脚本式执行
行注释–
块注释 --[[ --]]
布尔型只有nil和false是false,数字0,空字符串"",("\0")都是true
数值类型上,只有浮点型
lua的变量如过没有做特殊说明,那么都是全局变量,局部变量需要用local声明
--while循环语句
sum = 0
num = 1
while num <= 100 do
sum = sum + num
num = num + 1
end
print("sum=",sum)
--for循环
sum = 0
for i = 1,100 do
sum = sum + i
end
print("sum=",sum)
--分支结构
if age == 40 and sex == 'Male' then
print('40岁的男人')
elseif age > 60 and sex ~= "Female" then
print("大于60岁的非女人")
else
local age=io.read() --id.read()是从stdin读取输入信息
print('You age is'..age)--..是字符串拼接的操作
end
Lua不指出++或者+=操作
Nginx+lua环境的搭建
- LuaJIT
- ngx_devel_kit和lua-nginx-module
安装LuaJIT
wget http://luajit/download/LuaJIT-2.0.2.tar.gz
编译安装,以及添加系统环境变量
make install PREFIX=/usr/local/LuaJIT
export LUAJIT_LIB=/usr/local/LuaJIT/lib
export LUAJIT_INC=/usr/local/LuaJIT/include/luajit-2.0
安装ngx_devel_kit和lua-nginx-module
wget https://github/simpl/ngx_devel_kit/archive/v0.3.0.tar.gz
wget https://github/openresty/lua-nginx-module/archive/v0.10.9rc7.tar.gz
编译方式:
./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie' --add-module=/opt/download/ngx_devel_kit-0.3.0 --add-module=/opt/download/lua-nginx-module-0.10.9rc7
安装
make -j 4 && make install
加载库文件
加载lua库,加入到ld.so.conf文件
echo "/usr/local/LuaJIT/lib" >> /etc/ld.so.conf
然后执行如下命令:
ldconfig
Nginx调用Lua的指令
按照模块的执行的过程
set_by_lua
set_by_lua_file 设置变量,实现复杂的赋值操作
access_by_lua
access_by_lua_file 请求访问阶段,用于访问控制
content_by_lua
content_by_lua_file 内容处理,接收请求,对响应的内容进行处理
nginx调用Lua的Api
ngx.var nginx变量
ngx.req.get_headers 获取请求头
ngx.req.get_uri_args 获取url请求参数
ngx.redirect 重定向
ngx.print 输出响应内容
ngx.say 通 ngx.print 但是会最后输出一个换行符
ngx.header 输出响应头
灰度发布
按照一定关系的区别,分部分的代码进行上线,是代码的发布能够平滑过渡的上线.(先指定某一些用户可以使用,然后再慢慢的完善)
- 使用用户的cookies信息区别(指定某个用户可以使用)
- 根据用户的IP地址区别
场景:
8080端口存放着和测试服务相关的代码(准备新更新的代码)
9090端口存放着已经上线的旧的代码
过程:
- 请求经过Nginx+Lua来区别IP,正常用户的IP会去访问老的服务
- 属于测试用户的IP会被发送到8080端口做测试用户的服务
区分的过程就是nginx+Lua来实现的
Memcache中存储的是测试用户的IP,Lua去调用Memcache,中的IP列表和当前请求用户的IP进行匹配
启动tomcat的时候会用到java环境
安装Java环境yum -y install java-1.8.0-openjdk*
启动方式为’sh tomcat/bin/catalina.sh start’
启动memcache
memcached -p11211 -u nobody -d
lua 调用 memcache的模块需要手动安装
git clone https://github/openresty/lua-resty-memcached.git
cp .resty/bin /usr/share/lua/5.1/
手动操作memcache
telnet 127.0.0.1 11211
get key
get 121.69.21.82
VALUE 121.69.21.82 0 1
1
END
set key value
获取数据直接get就可以,设置数据有特殊的语法
例如设置一个k:v为192.168.1.1 xxx的键值对
set 121.69.21.82 0 0 1
1
STORED
配置lua脚本
clientIP = ngx.req.get_headers()["X_Real_IP"]
if clientIP == nil then
clientIP = ngx.req.get_headers()["x_forwarded_for"]
end
if clientIP == nil then
clientIP = ngx.var.remote_addr
end
local memcached = require "resty.memcached"
local memc, err = memcached:new()
if not memc then
ngx.say("failed to instantiate memc:",err)
return
end
local ok, err = memc:connect("127.0.0.1",11211)
if not ok then
ngx.say("failed to connect:",err)
return
end
local res,flags,err = memc:get(clientIP)
--ngx.say("value key:", res,clientIP)
if err then
ngx.say("failed to get clientIP",err)
return
end
if res == "1" then
ngx.exec("@server_test")
--ngx.say("sssssssssssss-ttttt")
return
end
ngx.exec("@server")
--ngx.say("server--------")
return
nginx的配置文件
server {
listen 80;
server_name 140.143.79.12;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location /hello {
default_type 'text/plain';
content_by_lua 'ngx.say("heool word lua")';
}
location /myip {
default_type 'text/plain';
content_by_lua '
clientIP = ngx.req.get_headers()["x_forwarded_for"]
ngx.say("IP:",clientIP)';
}
location / {
default_type 'text/html';
content_by_lua_file /opt/app/code/lua_index.lua;
}
location @server {
# proxy_pass http://127.0.0.1:9090;
content_by_lua 'ngx.say("server")';
}
location @server_test {
# proxy_pass http://127.0.0.1:8080;
content_by_lua 'ngx.say("server_test")';
}
error_page 500 404 502 503 504 /50x.html;
location /50x.html {
root /usr/share/nginx/html;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
Nginx常见的问题
- 相同serve_name的多个虚拟主机优先级访问
- location匹配的优先级
- try_files的使用
- nginx的别名alias和root的区别
- 用什么方法传递用户的真实IP
虚拟主机优先级
在conf.d目录下有server_1.conf和server_2.conf两个虚拟主机
这两个主机各自有各自的资源目录
不同的在于这两个主机的定义
server {
listen 80;
server_name server_1 xxx.xxx;
location {
-
}
}
server {
listen 80;
server_name server_2 xxx.xxx;
location {
-
}
}
# 都配置有相同的域名
当运行
nginx -tc .etc/nginx/nginx.conf
检查配置文件的时候会warning报告域名冲突,但是检查的结果是success!
当reload之后,访问域名返回的结果是server_1的内容
当更改server_1→server_3后重新reload访问域名的时候是server_2的内容
所以是按照命名顺序来分配优先级的
还有就是,我们配置相同的域名,但是我们使用的是IP去访问服务器,如果这个ip没有被配置到服务之内,也会按照服务的命名顺序来分配优先级的
location匹配符号的优先级
= 进行普通字符的精确匹配<完全匹配> 优先级高
^~ 进行普通字符匹配,匹配前缀 优先级中
\* 后面加正则表达式,表示将执行正则匹配 优先级低<*号区分大小写 >
tryfiles文件检索
location {
root /opt/app/code/cache;
try_files $uri @java_page;
}
location @java_page {
proxy_pass http://127.0.0.1:9090;
}
检索顺序,首先在定义的目录中获取文件,如果获取不到,会专向@java_page将请求转发到@java_page,@java_page来处理请求
所以try_files可以运用在缓存的场景下
alias和root的区别
root指定程序的资源根目录,请求方式是路径
例如定义root /local_path/image/;
请求xxx.xxx/request_path/image/cat.png
会在/local_path/image/目录下寻找/request_path/image/cat.png
alias却没有这么的严格
定义alias /local_path/image/;
请求xxx.xxx/request_path/image/cat.png
会在寻找/local_path/image/cat.png
获取用户的真实IP
用户通过层层代理之后,服务器使用remote_addr就无法获到用户的真实ip了
使用x-forwarded-for 这个头信息又容易被篡改
所以最好的方式是和一级代理取得联系(一级代理可以接触到真实ip)
一级代理中设置set x_real_ip=$remote_addr
自定义个头变量来保存用户的真实IP,通过层层传递传递到服务器
常见的nginx错误信息
413 Request Entity Too Large
- 用户上传文件限制 client_max_body_size
502 bad gateway
- 后端服务无法响应,例如flask服务没启动起来
504 Gateway Time-out
- 后端服务执行超时 后端服务业务逻辑执行时间超过nginx的等待时间
Nginx的性能优化
- 性能优化考虑点
- 压力测试工具ab
- 系统于Nginx性能优化
性能优化考虑点
- 当前系统结构的瓶颈
如何达到这些数据?
- 观察指标
- 压力测试
- 了解业务模式
- 接口业务类型(抢购)
- 系统层次化的结构(代理?后台直接?动静分离?)
- 性能安全权衡
当前系统日志检测,性能分析 ,压力测试工具获取性能数据 通过这三种方式来获取当前系统结构中的瓶颈.
ab压力测试工具的使用
一.安装
yum install -y httpd-tools
二.使用
ab -n 2000 -c 2 http://127.0.0.1/xxx.xxx
-n 请求的总数
-c 并发数
-k 是否开启长连接
系统于Nginx的性能优化
-
网络
-
系统
-
服务
-
程序
-
数据库,底层服务
-
文件句柄
Linux\Unix 一切接文件,文件句柄就是一个索引(调用文件,启动服务或功能都会生成文件句柄)默认限制1024
- 设置方式
系统全局性修改,用户局部性修改,进程局部性修改
全局和用户配置在:
/etc/security/limits.conf
针对Nginx进程的配置
/etc/nginx/nginx.conf
在配置文件的全局设置
worker_rlimit_notfile 65535
变量,为当前Nginx进程的文件句柄限制
- 针对CPU的亲和配置
减少切换的频率,降低系统性能的损耗
安全篇
- 常见的恶意行为
- 常见的应用层的恶意攻击手段
- Nginx防攻击的策略
- 场景:Nginx+Lua的waf防护墙
常见的恶意行为
爬虫恶意抓取,资源盗用
基础防盗链功能-目的让恶意用户不能轻易抓取网站信息
secure_link_module 对数据安全性进行有效性加密和验证
access_module对后台,部分用户服务进行有效控制
攻击手段
后台密码撞库-通过猜测密码字典不断对后台登陆系统进行尝试,获取后台登陆密码
方法一:后台密码复杂度
方法二:access_module 对后台提供IP防控
方法三:预警机制
文件上传漏洞-利用这些可以上传的接口上传可执行的恶意代码
location ^~/upload {
root /opt/app/images;
if ($request_filename ~*(.*)\.php) {
return 403;
}
}
SQL注入-利用为过滤/未审核用户输入的攻击方法,应用程序运行本不应该执行的SQL代码
场景:
用户→Nginx+Lua→PHP→mariadb
防火墙流程
下载waf
https://github/loveshell/ngx_lua_waf.git
将其放在/etc/nginx/wfa文件夹中
修改conf.lua中的文件路径
在Nginx.conf中的http中配置
在vaf配置中
CCrate="100/60"
配置同一个IP每60s允许访问100次
如何基于Nginx中间件架构
Nginx在整个架构中所处的角色
- 静态资源服务
- 静态资源的类型分类(视频,html…)
- 浏览器端缓存(不同数据有效期不同)
- 静态资源防盗链
- 流量限制
- 静态资源占用空间(压缩,压缩格式)
- 代理服务
- 代理的协议类型
- 正向代理
- 反向代理
- 负载均衡(哈希策略,后端节点检查机制,检查超时时间,代理缓存[类型,时间,目录])
- 头信息处理
- 动静分离
设计评估
- 硬件要满足什么要求
- CPU
- 内存
- 硬盘
代理服务 要求 高性能的CPU高内存,很少一部分硬盘空间来存储日志
静态资源服务 要求普通CPU内存,但是高效高容量的硬盘
- 系统
- 用户权限
- 日志存放目录
- 相关联的服务
- LVS 负载均衡
- keepalive 负载均衡
- syslog 日志同步
- Fastcgi
配置的注意事项
- 合理配置[作用范围]
- 了解原理
- 关注日志
更多推荐
Nginx学习笔记(一)
发布评论