Nginx
nginx如何去处理一个请求
How nginx processes a request
首先根据请求的域名向server
节点寻找匹配的server_name
,找到最匹配的server
后,然后在此server
节点中根据请求的url
寻找一个最匹配的location
,然后在location
找到对应要访问的upstream
,location
中设定了可以携带的请求头,带着可以携带的请求头以upstream
中配置的策略访问节点
location
中对的url
匹配规则(寻找最精准的进行匹配)
location [ = | ~ | ~* | ^~ ]
= 精准匹配 location =/api {...}
~ 区分大小写匹配 location ~/api {...}
~* 不区分大小写匹配 location ~*/api {...}
^~ 以/aaa(区分大小写)为开头的都匹配 location ^~/aaa {...}
location ^~*/aaa/bbb$ {...} 必须以三个/aaa开头,bbb结尾
nginx
中可以使用哪些变量
名称 说明
$arg_name 请求中的name参数
$args 请求中的参数
$content_length HTTP 请求信息里的"Content-Length"
$content_type 请求信息里的"Content-Type"
$host 请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名
$hostname 机器名使用 gethostname系统调用的值
$http_cookie cookie 信息
$http_referer 引用地址
$http_user_agent 客户端代理信息
$http_via 最后一个访问服务器的Ip地址。
$http_x_forwarded_for 相当于网络访问路径
$is_args 如果请求行带有参数,返回“?”,否则返回空字符串
$limit_rate 对连接速率的限制
$nginx_version 当前运行的nginx版本号
$pid worker进程的PID
$query_string 与$args相同
$remote_addr 客户端IP地址
$remote_port 客户端端口号
$request 用户请求
$request_method 请求的方法,比如"GET"、"POST"等
$request_uri 请求的URI,带参数
$scheme 所用的协议,比如http或者是https
$server_name 请求到达的服务器名
$server_port 请求到达的服务器端口号
$server_protocol 请求的协议版本,"HTTP/1.0"或"HTTP/1.1"
$uri 请求的URI,可能和最初的值有不同,比如经过重定向之类的
简单使用如下
events {
#在linux系统上使用这种模式会提高很大效率
use epoll;
#连接最大数为(worker_connections * worker_processes)
worker_connections 1024;
}
server{
...
#5简单防爬配置
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot") {
return 403;
}
location / {
# 1 允许代理节点获得请求头中的信息
# 用户的真实ip,如果不配置此信息代理节点获得不到用户的ip
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#2 解决跨域配置
#允许跨域请求的域,*和$http_origin 代表所有
#不然会报No 'Access-Control-Allow-Origin' header is present on
#the requested resource. Origin 'null' is therefore not allowed access.
add_header 'Access-Control-Allow-Origin' $http_origin;
#允许带上cookie请求
add_header 'Access-Control-Allow-Credentials' 'true';
#允许携带哪些header
add_header 'Access-Control-Allow-Headers' 'DNT,web-token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
#允许请求的方法,比如 GET/POST/PUT/DELETE
add_header Access-Control-Allow-Methods 'GET,POST,OPTIONS';
#3 如果预检请求则返回成功,不需要转发到后端,节约资源
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 200;
}
#4 防盗链设置
valid_referers none blocked www.lizhiyu.xyz;
if ($invalid_referer) {
#或者永久重定向本网站首页
return 403;
}
#valid_referers: 指定资源访问是通过以下几种方式为合法,即白名单。
#none:允许缺失的头部访问。
#blocked:允许referer没有对应值的请求。
#server_names:若referer站点域名与server_name中本机配的域名一样允许访问。
}
}
Nginx可用性探测
Nginx可以配置一些策略,来实现反向代理,如果反向代理的节点不可用,Nginx则在固定间内不会再去访问这个节点
这个固定时间和定义代理节点不可用配置如下
proxy_next_upstream说明
max_fails,fail_timeout,backup, down说明
upstream test {
#配置的代理节点
#此节点如果访问max_fails次出错则在fail_timeout时间内不再访问
#出现错误后过了fail_timeout会再次访问
#max_fails如果配置成0则代表不管出现多少次错误都会访问
server localhost:8080 max_fails=2 fail_timeout=60s;
server localhost:8081 max_fails=2 fail_timeout=60s;
}
server{
location /api/ {
proxy_pass http://test;
#定义怎样才算次服务器不可用
#当请求连接后台出错、连接响应出错、连接超时、http状态码
#当fail_timeout时间内出现max_fails次此错误则代表此节点不可用
proxy_next_upstream error timeout http_500 http_503 http_404;
}
}
Nginx搭建静态资源服务器
将1.jpg文件放到/software/img
目录下
然后访问https://www.lizhiyu.xyz/img/1.jpg
即可下载图片
配置文件如下
location /img {
alias /software/img/;
}
Nginx配置https服务
安装依赖
yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel
刪除安裝过的包,然后重新安装nginx(因为需要安装ssl模块)
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
make
make install
配置文件如下
http {
server {
listen 80;
server_name localhost;
location / {
# 配置http 永久重定向到https
rewrite ^/(.*) https://www.lizhiyu.xyz/$1 permanent;
}
}
# HTTPS server
server {
# https使用443端口,记得将开启端口
listen 443 ssl;
# 配置域名
server_name www.lizhiyu.xyz;
#证书位置
ssl_certificate /usr/local/https/5148543_www.lizhiyu.xyz.pem;
#密钥位置
ssl_certificate_key /usr/local/https/5148543_www.lizhiyu.xyz.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
}
Nginx流量统计
access.log 日志记录格式如下
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"' $request_time;
access日志记录格式选为为main
access_log logs/access.log main;
查看访问最频繁的前100个IP
awk '{print $1}' access.log | sort -n |uniq -c | sort -rn | head -n 100
统计访问最多的url 前20名
cat access.log |awk '{print $7}'| sort|uniq -c| sort -rn| head -20 | more
统计耗时接口, 列出传输时间超过 2 秒的接口,显示前5条
cat access.log|awk '($NF > 2){print $7}'|sort -n|uniq -c|sort -nr|head -5
备注:$NF 表示最后一列, awk ‘{print $NF}’
Nginx黑白名单拦截
nginx.conf
配置文件中配置如下
全局异常兜底数据返回
{
#配置为引入黑名单配置
include blacklist.conf;
server {..}
}
nginx.conf
和blacklist.conf
在同级目录下,blacklist.conf配置如下
{
#配置禁止访问的ip(再次访问会返回403状态码)
deny 192.168.8.113;
deny 106.121.65.84;
}
配置完成后执行./nginx.conf -s reload
命令
执行完这个命令master
进程会通知 worker
进程执行完当前任务后关闭
master
去加载完配置文件再创建新的 worker
进程执行任务
异常兜底返回
为了防止后端出现错误返回错误信息,在nginx层面对错误信息进行拦截
配置信息如下
server{
location /img {
alias /software/img/;
#异常返回兜底开启
proxy_intercept_errors on;
}
#当后端返回状态码为 404 500 .... 会返回200的状态码
error_page 404 500 502 503 504 =200 /default_api;
#当出现错误码就会访问这个location
location = /default_api {
#返回数据格式
default_type application/json;
#返回的数据信息
return 200 '{"code":"-1","msg":"invoke fail, not found "}';
}
}
OpenResty的学习
由于Nginx是用c语言编写,想要扩展Nginx就要书写c语言(不易于扩展),使用OpenResty可以对Nginx通过lua脚本进行扩展,例如lua脚本操作redis等
介绍: OpenResty中自带Nginx,同时提供了一些插件
安装
使用
openResty会分为多个阶段按顺序处理每一个请求,主要包括如下阶段
init_by_lua_file
初始化阶段
init_worker_by_lua_file
初始化worker阶段
rewrite_by_lua_file
重定向阶段
access_by_lua_file
访问控制阶段
content_by_lua_file
内容生成阶段
简单的使用
查看版本
resty -V (能够查看到openresty版本 和 安装过的模块)
编辑:/usr/local/openresty/nginx/conf/nginx.conf
http{
#生产环境要开启on,本地测试可以使用off达到时时刷新
lua_code_cache off;
# 虚拟机主机块
server{
# 监听端口
listen 80;
# 配置请求的路由
location /{
#指定格式为html
default_type text/html;
#content_by_lua_block是openResty中接收请求的一个阶段
#是生成内容的阶段
content_by_lua_block{
#输出一句话
ngx.say("hello world");
}
}
}
}
#使用其他方式
http{
#设置lua扩展库的位置 (位置就固定写这个)
lua_package_path "$prefix/lualib/?.lua;;";
#设置c扩展库的位置
lua_package_cpath "$prefix/lualib/?.so;;";
server{
# 监听端口
listen 80;
# 配置请求的路由
location /{
#格式
default_type text/html;
#执行learn.lua脚本
content_by_lua_file lua/learn.lua;
}
}
}
#限速使用例子
location /download {
#access_by_lua_block 是openResty接收请求的一个阶段
#这个阶段用来控制访问
access_by_lua_block {
#limit_rate 是nginx中可以使用的变量(上面有说写)、
#在openResty中可以通过ngx.var.variable使用此变量
ngx.var.limit_rate = "300K"
}
alias /usr/local/software/app;
}
#黑名单使用例子
location / {
#访问控制阶段
access_by_lua_file lua/blackList.lua;
proxy_pass http://upstreamName;
}
blackList.lua内容如下
local black_ips = {["127.0.0.1"]=true}
local ip = ngx.var.remote_addr
if true == black_ips[ip] then
#返回一个403状态码
ngx.exit(ngx.HTTP_FORBIDDEN)
return;
end
停止
./nginx -s stop
启动
./nginx -c /usr/local/openresty/nginx/conf/nginx.conf
重新加载
./nginx -s reload