对项目的梳理总结。
涉及到的关键字会大概说明或者换个名字。比如:动态xx改成动态数据。不然一看xx就知道是干啥的了。
会用极简的demo,告诉你主要逻辑。
项目一: 动态数据替换
功能使用场景:一个搭建活动页面的后台。生成静态json数据(方便h5、rn使用)。有的活动页面的部分数据需要变化。
具体的实现大致写了一篇用openResty做一个小功能:实现数据替换跟缓存。
架构图如下:

下面是一个原理极简demo。并不直接请求接口与反向代理到s3。为了练习方便。
首先准备了两个文件,一个叫stock.lua
,一个是page.json
(我们的json存在了亚马逊s3上,也就是你可以proxy_pass到s3)。
功能如下:
stock.lua
local cjson = require "cjson"
local uri = '/page.json'
local res = ngx.location.capture(uri)
local body = res.body
-- 下面做一个假装从其他服务器上拿到了一个库存,然后做替换。
-- 解析 body 成table
local body_table = cjson.decode(body)
-- 假设下面是从其他地方拿到的stock
local stock_list = {{product_id = 123,stock = 2000}, {product_id = 456, stock = 3000}}
for k, v in pairs(body_table.product_list) do
for sk, sv in pairs(stock_list) do
if sv.product_id == v.product_id then
v.stock = sv.stock
end
end
end
local response_body = cjson.encode(body_table)
ngx.say(response_body)
page.json (就把它当做是生成存到s3上的json吧)
{"product_list":[{"product_id":123,"product_img":"xxxx.com.png","title":"球鞋", "stock": 13},{"product_id":456,"product_img":"xxxx.com.png","title":"球拍", "stock": 14},{"product_id":789,"product_img":"xxxx.com.png","title":"球衣", "stock": 15}]}
nginx.conf 如下
proxy_cache_path /home/nobody/cache levels=1:2 keys_zone=my-cache:8m inactive=1h max_size=10m;
lua-project.com.conf nginx 配置如下:
location /page {
proxy_pass http://127.0.0.1:9527/page_cache;
proxy_cache my-cache;
proxy_cache_lock on;
proxy_cache_valid 200 10s;
proxy_cache_key $uri$is_args$args;
add_header Nginx-Cache "$upstream_cache_status";
}
location /page_cache {
content_by_lua_file /home/nobody/lua-project/stock.lua;
}
location ~ \.json$ {
root /home/nobody/lua-project/;
}
于是请求
[root@bogon ~]# curl -v lua-project.com/page
* About to connect() to lua-project.com port 80 (#0)
* Trying 127.0.0.1...
* Connected to lua-project.com (127.0.0.1) port 80 (#0)
> GET /page HTTP/1.1
> User-Agent: curl/7.29.0
> Host: lua-project.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: openresty
< Date: Mon, 15 Apr 2019 14:18:27 GMT
< Content-Type: application/octet-stream
< Transfer-Encoding: chunked
< Connection: keep-alive
<
{"product_list":[{"stock":2000,"product_img":"xxxx.com.png","title":"球鞋","product_id":123},{"stock":3000,"product_img":"xxxx.com.png","title":"球拍","product_id":456},{"stock":15,"product_img":"xxxx.com.png","title":"球衣","product_id":789}]}
* Connection #0 to host lua-project.com left intact
[root@bogon ~]# curl -v lua-project.com/page
* About to connect() to lua-project.com port 80 (#0)
* Trying 127.0.0.1...
* Connected to lua-project.com (127.0.0.1) port 80 (#0)
> GET /page HTTP/1.1
> User-Agent: curl/7.29.0
> Host: lua-project.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: openresty
< Date: Mon, 15 Apr 2019 14:26:32 GMT
< Content-Type: application/octet-stream
< Content-Length: 251
< Connection: keep-alive
< Nginx-Cache: HIT
<
{"product_list":[{"stock":2000,"product_img":"xxxx.com.png","title":"球鞋","product_id":123},{"stock":3000,"product_img":"xxxx.com.png","title":"球拍","product_id":456},{"stock":15,"product_img":"xxxx.com.png","title":"球衣","product_id":789}]}
* Connection #0 to host lua-project.com left intact
项目二: 投放接口的缓存预案
功能使用场景:排期投放后台,运营推广一些商品、banner、入口、收藏等等。大促活动有时候接口会挂掉。预案就是万一挂掉。打开预案然后走离线缓存。
项目三:短链(生成、跳转)、小程序码
功能使用场景:
项目四:商品详情、商品列表等的fastcgi_cache
功能使用场景:对商品详情页、商品列表进行 fastcgi_cache。
架构图如下:

先来看看fast_cgi 怎么用。
首先准备了两个文件,一个叫product.php
。mt_rand 是方便看效果。
<?php
//假装从数据库(或者redis之类)拿出来商品的数据
$productDetail = ["title"=>"球衣", "product_img"=> "http://xxxx.com/xxx.png", "detail"=>"纯棉吸汗,迪卡侬限量版", "stock"=>mt_rand(100,1000)];
exit(json_encode($productDetail, JSON_UNESCAPED_UNICODE));
nginx.conf 配置
fastcgi_cache_path /home/nobody/fastcgicache levels=1:2 keys_zone=fastcgi-cache:8m inactive=1h max_size=10m
location /product.php {
fastcgi_pass 127.0.0.1:9000; # 指定FastCGI服务器监听端口与地址
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_sc
ript_name;
include fastcgi_params;
# 缓存策略
fastcgi_cache fastcgi-cache;
fastcgi_cache_key "$scheme$request_method$host$request_
uri"; # 缓存key规则
fastcgi_cache_methods POST; # 默认GET HEAD 即便你不列出来也支持。但是其他的就不行了。如果你不指定POST就不能用。curl -X POST lua-project.com/product.php
fastcgi_cache_valid 200 10s; # 指定http返回代码指定缓存时间
}
cd /home/nobody/fastcgicache && watch tree。看下缓存文件是否生成了。
curl lua-project.com/product.php
看到
.
└── b
└── c5
└── 8d104512ade8f7d3ecb73df78da3cc5b
如果你想验证内容的话。可以cat下。当然你也可以watch cat 这个文件。上面缓存是10s。10s后再curl,watch cat 的内容就变更了。
串下流程
1.先用fiddler抓包。详情页。

一个详情页调用了三个接口。以第一个为例。我们看QueryString 里面的几个关键字(红框),method
、product_id
2.fastcgi_cache 那台服务器上看日志。tail -f 日志 | grep 商品id
3.再看下nginx配置文件。
看到有一个key叫做fastcgi_cache_key $bus_cache_key;
,文件里没找到。那在哪里呢?看到一个rewrite_by_lua_file 指令指向了一个rewrite.lua(项目文件,这个项目文件是用来设置各种缓存key)。追了追代码。找到了 $bus_cache_key设置地方。以上面详情页为例self.busCacheKey = self.busCacheKey .. '-' .. prd
,也就是querystring的method字段值product_detail
-商品id
(product_detail-1233344)
去缓存的目录输出下缓存文件的信息。看到里面有一个Key值(其实就是你的缓存key名呗)。
一个商品详情api代码执行流程。
1.请求接口。接口fastcgi_pass 到 fasctcgi_cache集群。
2.fasctcgi_cache 服务器,先执行 init_by_lua_file 指定的init.lua,加载一些常量与包。(比如:FASTCGI_CACHE_UPSTREAM = "/shop_fastcgi_cache")
3.接着走rewrite_by_lua_file指定的rewrite.lua文件,主要干的就是准备fastcgi_cache用的key(用到后面缓存)。还有bus_location(用给location /)。
4.走location /。echo_location $bus_location。调用子请求。
5.走location = /product_detail ,执行content_by_lua_file 指定的content.lua文件。
6.content.lua执行 productDetailBodyFilter方法。
7.productDetailBodyFilter调用FASTCGI_CACHE_UPSTREAM (值为/shop_fastcgi_cache)(capture的方式)。当然这里面还做了一些动态数据的替换哈。大致是,把其他的公共参数替换了。
8.接着执行 location = /shop_fastcgi_cache ,这里做了php程序处理,顺带做了fastcgi_cache。所以下次请求进入就走缓存。缓存时间10m。
参考资料:
- 《nginx documentation》http://nginx.org/en/docs/
- 《lor》http://lor.sumory.com/docs/getting-started-cn
- 《【nginx】关于fastcgi_cache》https://www.cnblogs.com/chenpingzhao/p/4983703.html
- 《nginx缓存设置proxy_cache》https://www.cnblogs.com/zlingh/p/5879988.html
- 《打开Nginx的rewrite日志》https://www.linuxidc.com/Linux/2013-06/86636.htm
- 《echo-nginx-module》https://github.com/openresty/echo-nginx-module
*《FastCGI模块(FastCGI)》https://www.cnblogs.com/shengshuai/archive/2013/01/11/fastcgi.html - 《通过FastCGI Cache实现服务降级》https://www.aikaiyuan.com/5708.html
网友评论