第03章-深度学习篇
# 3.1 动静分离
通过中间件将动态请求和静态请求分离。
**好处:**分离资源,减少不必要的请求消耗,减少请求延时。
upstream {
server 127.0.0.1:8080;
}
server {
listen 80;
server_name localhost;
root /opt/app/code;
location ~ \.jsp$ {
proxy_pass http://java_api;
index index.htm index.htm;
}
location ~ \.(jpg|png|gif)$ {
expires 1h;
gzip on;
}
location / {
index index.html index.htm;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 3.2 Rewrite规则
rewrite介绍
Nginx的rewrite可以实现url重写以及重定向,适用场景如下:
URL访问跳转,支持开发设计
页面跳转、兼容性支持、展示效果等
SEO优化
维护
后台维护、流量转发等
安全
配置语法
Syntax: rewrite regex replacement [flag];
Default: —
Context: server, location, if
2
3
如果指定的正则表达式与请求URI匹配,则URI将按照 replacement 字符串中的指定进行更改。该 rewrite 指令在其在配置文件中出现的顺序顺序地执行。可以使用标志终止指令的进一步处理。如果替换字符串以 http://,https:// 或 $scheme 开头,则处理停止,并将重定向返回给客户端。
flag参数:
flag可选值 | 含义 |
---|---|
last | 停止rewrite检测,rewrite后继续匹配location配置,相当于请求转发 |
break | 停止rewrite检测,rewrite后不再继续匹配location |
redirect | 返回302临时重定向,地址栏会显示跳转后的地址(后续还是由服务端返回重定向信息) |
permanent | 返回301永久重定向,地址栏会显示跳转后的地址(客户端保存重定向信息,不通过服务端直接重定向) |
Rewrite规则优先级
- 执行server块的rewrite指令
- 执行location匹配
- 执行选定的location中的rewrite
# 3.3 高级模块
# 3.3.1 secure_link_module模块
该模块用于检查请求的链接,限制未经授权的访问,保护资源。
- 制定并允许检查请求的链接的真实性以及保护资源免遭未经授权的访问
- 限制链接生效周期
相关配置
1、secure_link
定义一个带有变量的字符串,从中将提取链接的校验和值和过期时间。
Syntax: secure_link expression;
Default: —
Context: http, server, location
2
3
2、secure_link_md5
定义一个表达式,将为其计算MD5哈希值,并将其与请求中传递的值进行比较。
表达式应包含链接(资源)的安全部分和秘密成分。如果链接的生存期有限,则表达式还应包含*$secure_link_expires*。
Syntax: secure_link_md5 expression;
Default: —
Context: http, server, location
2
3
验证图示:
返回给客户端的下载连接:
客户端使用下载连接发起下载请求后,nginx会进行加密验证和过期验证,校验md5参数的加密信息,加密信息可基于IP等信息生成,校验expires指定的过期时间。
配置示例
location / {
# 提取链接中的加密串和过期时间
secure_link $arg_nd5,$arg_expires;
# 使用按规则加入字符串"lucifer"进行加密,与上面取到的参数对比,看是否匹配
secure_link_md5 "$secure_link_expires$uri lucifer";
# 变量$secure_link用于存放验证结果,根据结果执行以下逻辑
if ($secure_link="") {
return 403;
}
if ($secure_link="0") {
return 410;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 3.3.2 ngx_http_geoip_module模块
基于IP地址匹配MaxMind GeoIP二进制文件,读取IP所在地域信息。
# 安装模块
yum install nginx-module-geoip
2
适用场景:
- 区别国内外作HTTP访问规则
- 区别国内城市地域作HTTP访问规则
相关变量
$geoip_country_name 国家名
$geoip_country_code 国家代码(CN,US)
$geoip_city 城市名
......
2
3
4
配置示例
location / {
# 国家码不是中国就返回403
if ($geoip_country_code != CN) {
return 403;
}
root /usr/share/nginx/html;
index index.html index.htm;
}
location /my_ip {
default_type text/plain;
# 输出ip、国家名、国家码、城市名
return 200 "$remote_addr $geoip_country_name $geoip_country_code $geoip_city";
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 3.4 基于Nginx的HTTPS服务
# 3.4.1 HTTPS介绍
为什么需要HTTPS?因为HTTP不安全?
- 传输数据被中间人盗用、信息泄露
- 数据内容劫持、篡改
HTTPS协议的实现:对传输内容进行加密以及身份验证
对称加密和非对称加密
程参考:Https原理及流程 (opens new window)
# 3.4.2 生成证书
使用 openssl
生成证书请求文件,交给签名机构进行证书签名,这里我们本地签名。
mkdir ssl_key && cd ssl_key
# 用idea算法,生成mykey.key文件,加密位数1024,执行后需要指定密码,记住这个密码
openssl genrsa -idea -out mykey.key 1024
# 生成证书签名请求文件,执行期间需要填写一些信息
openssl req -new -key mykey.key -out mykey.csr
# 至此会生成两个文件,mykey.key和key.csr,发给签名机构进行签名即可
# 本地调试,自己进行签名,生成签名文件mykey.crt
openssl x509 -req -days 3650 -in mykey.csr -signkey mykey.key -out mykey.crt
2
3
4
5
6
7
8
# 3.4.3 nginx配置HTTPS
server {
listen 443; #HTTPS监听443端口
server_name 10.60.131.23;
ssl on; #开启https
#指定签名文件和key文件位置
ssl_certificate /etc/nginx/ssl_key/mykey.crt;
ssl_certificate_key /etc/nginx/ssl_key/mykey.key;
index index.html index.htm;
location / {
root /opt/app/code;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
此时重启nginx,需要输入生成key文件时的密码,重启后就可以通过浏览器使用HTTPS协议请求nginx了。
如今苹果对安全要求越来越高,苹果要求的证书需要符合以下条件:
- 服务器所有的连接使用TLS1.2以上版本(openssl 1.0.2)
- HTTPS证书必须使用SHA256以土哈希算法签名
- HTTPS证书必须使用RSA2048位或ECC256位以上公钥算法d、使用前向加密技术
# 查看openssl版本
openssl version
# 查看加密证书算法类型和加密位数
openssl x509 -noout -text -in ./mykey.crt
# 删除原来crt文件
rm mykey.crt
# 直接通过key文件生成签名文件,符合苹果要求
openssl req -days 36500 -x059 -sha256 -nodes -newkey rsa:2048 -keyout mykey.key -out mykey_apple.crt
2
3
4
5
6
7
8
9
# 3.4.4 HTTPS服务优化
激活keepalive长连接
设置ssl session缓存
ssl on; ssl_session_cache shared:SSL:10m; #配置10MB会话缓存,大约可缓存8000-10000个会话 ssl_session_timeout 10m; #会话过期时间10min
1
2
3
# 3.5 Nginx与Lua开发
Lua是一个简洁、轻量、可扩展的脚本语言。
Nginx+Lua优势:充分的结合Nginx的并发处理epoll优势和Lua的轻量实现简单的功能切高并发的场景。
# 3.5.1 Lua基础语法
安装
yum install lua
运行(分为命令行和脚本文件形式)
# lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> print("Hello, world")
Hello, world
2
3
4
# lua ./test.lua
Hello, world
2
基本语法:
布尔型:只有
nil
和false
是false
;0
和空字符串等其他的都是true
lua变量没有特殊说明的话都是全局变量
while循环语句
sum = 0 num = 1 while num <= 100 do sum = sum + num num = num + 1 end print("sum = ", sum)
1
2
3
4
5
6
7for循环
sum = 0 for i = 1, 100 do sum = sum + i end
1
2
3
4if-else判断语句
if age == 40 and sex == "male" then print("大于40男人") elseif age > 60 and sex ~= "female" then -- 不等于用~= print("非女人而且大于60") else local age = io.read() -- io库的分别从stdin和stdout读写的read和write函数 print("You age is "..age) -- 字符串拼接操作符 .. end
1
2
3
4
5
6
7
8
# 3.5.2 Nginx+Lua环境
如果需要 Nginx 结合 Lua,需要在重新编译 Nginx,以支持 Lua 模块。
- 下载 LuaJIT,一个 lua 解析器
- 下载 nginx 对应的开发库和对应模块文件,ngx_devel_kit 和 lua-nginx-module
- 解压重新编译 Nginx
具体编译步骤参考手记:Nginx编译安装Lua模块 (opens new window)
# 3.5.3 Nginx调用Lua
Nginx调用Lua模块指定
Nginx的可插拔模块化加载执行,共11个处理阶段,每个阶段都可以调用对应的Lua模块指令,来实现对应的功能。
上述有
_file
结尾的表示执行lua脚本文件,没有的表示执行单挑lua指令
Nginx调用Lua API接口
# 3.5.4 Nginx+Lua示例
# 简单示例
# 使用content_by_lua指令处理响应
# lua脚本调用ngx.say接口,输出"hello, lua"作为响应
location /hello {
default_type 'text/plain';
content_by_lua 'ngx.say("hello, lua")';
}
# 调用ngx.req.get_headers接口从请求头x_forwarded_for中获取客户端ip
# 赋值给clientIP,再调用ngx.say接口输出响应
location /myip {
default_type 'text/plain';
content_by_lua '
clientIP = ngx.req.get_headers()["x_forwarded_for"]
ngx.say("IP:", clientIP)
';
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 灰度发布示例
Nginx配置:
# 根配置,调用lua脚本接收请求处理响应
location / {
default_type 'text/html';
content_by_lua_file /opt/app/lua/dep.lua; #指定lua脚本位置
}
# 正式环境,请求转发到 127.0.0.1:8080
location @server {
proxy_pass http://127.0.0.1:8080;
}
# 灰度环境,请求转发到 127.0.0.1:9090
location @server_test {
proxy_pass http://127.0.0.1:9090;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Lua脚本内容:
-- 根据优先级依次通过请求头,nginx变量remote_addr,获取clientIP
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
-- 加载memcache库,实例化memcached对象
local memcached = require "resty.memcached"
local memc, err = memcached:new()
if not memc then
ngx.say("failed to instantiate memc: ", err)
return
end
-- 连接memcache
local ok, err = memc.connect("127.0.0.1", 11211)
if not memc then
ngx.say("failed to connect memc: ", err)
return
end
-- 以clientIP为key,获取memcache中的value
local res, flags, err = memc.get(clientIP)
nginx.say("value key: ", res, clientIP)
if err then
ngx.say("failed to get clientIP: ", err)
return
end
-- 如果命中缓存并且值为1,说明在灰度白名单,访问灰度环境
if res == 1 then
ngx.exec("@server_test") -- 走nginx配置的 location @server_test
return
end
-- 没有命中缓存,走正式环境
ngx.exec("@server") -- 走nginx配置的 location @server
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36