之前发过 openresty 的相关文章, 也是用于加速网页速度的, 但是上次没有优化好代码, 这次整理了下, 优化了 nginx 的配置和 lua 的代码, 感兴趣的话可以看看上篇的文章:
https://www.cnblogs.com/w1570631036/p/8449373.html
为了学习, 不断的给自己的服务器装东西, 又是 logstash, 又是 kafka, 导致主站网络负载, cpu 消耗过大, 再加上 tomcat 这个本身就特别占用内存的东西, 只要稍微刷新一下网站, 就能感受到蜗牛般的速度, 实在受不了, 前段时间给网站加了 n 多层缓存, 依旧没有改观多少, 想了想, 算了, 一直都这么卡, 还不如直接将动态的网站直接变成静态网页存储在 redis 里面, 然后关掉 tomcat, 貌似没有改观多少, 但是在 xshell 里面敲命令没那么卡了, 这里, 也提出了一种别样的网站加速方法 --redis 存储静态网页.
一, 总体流程如下
1. 一次请求过来, 通过 openresty 的 nginx 来访问 lua 脚本;
2. 读取 redis 中是否存在该 uri 对应的静态网页, 如果有, 则直接返回, 否则回源到 tomcat, 然后将响应的内容保存到 redis 里面.
二, nginx 的设置
openresty 中自带了 nginx, 所以只需要配置一下即可, 我们最终的目前是拦截所有以 html 结尾的请求, 如果是以其他后缀结尾的, 比如 do, 则可以直接回滚到 tomat 里面去.
由于篇幅的关系, 只粘贴部分 nginx 配置, 想看全的请转至: https://github.com/Zephery/micro-service/blob/master/conf/nginx/mynginxconfig.ngx
- server {
- listen 80;
- # listen 443 ssl; # ssl
- server_name www.wenzhihuai.com;
- location ~ .*\.(html)$ { // 拦截所有以 html 结尾的请求, 调用 lua 脚本
- ...
- charset utf8;
- proxy_pass_request_headers off ;
- # 关闭缓存 lua 脚本, 调试的时候专用
- lua_code_cache off;
- content_by_lua_file /opt/lua/hello.lua;
- }
- location / { //nginx 是按顺序匹配的, 如果上面的不符合, 那么将回滚 tomcat
- default_type text/html;
- root html;
- index index.html index.htm;
- ...
- # websocket
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "upgrade";
- proxy_pass http://backend;
- }
三, lua 脚本
为了方便 key 的操作, 经过测试, 即使 uri 带有各种字符, 比如 ? . html = & 等, 都是可以直接设置为 redis 中的 key 的, 所以, 不是那么的需要考虑 redis 的 key 违反规则, 可以直接将 uri 设置为 key. 具体流程如下:
- local key = request_uri
- 首先, key 为请求访问的 uri
- local resp, err = red:get(key)
- 去 redis 上查找有没有
- if resp == ngx.null then
- 如果没有
- ngx.req.set_header("Accept", "text/html,application/xhtml+xml,application/xml;")
- ngx.req.set_header("Accept-Encoding", "")
- 这里, 特别需要注意的是, 要把头部的信息去掉, 这里之前说过.(如果不去掉, 就是 gzip 加密返回, 然后再经过一层 gzip 加密返回给用户, 导致用户看到的是 gzip 压缩过的乱码)
- local targetURL = string.gsub(uri, "html", "do")
- 这里讲 html 替换为 do, 即: 不拦截 *.do 的请求, 其可以直接访问 tomcat
- local respp = ngx.location.capture(targetURL, { method = ngx.HTTP_GET, args = uri_args })
- 开始回源到 tomcat
- red:set(key, respp.body)
- 将 uri(key) 和响应的内容设到 redis 里面去
- red:expire(key, 600)
- lua redis 并没有提供在 set 的时候同时设置过期时间, 所以, 额外加一行设置过期时间
- ngx.print(respp.body)
- 将响应的内容输出给用户
- return
- end
- ngx.print(resp)
四, 测试
进行一次测试, 以访问 http://www.wenzhihuai.com/jaowejoifjefoijoifaew.html 为例, 我的网站并没有设置这个 uri, 所以, 访问的时候, 会统一调到错误页面, 之后, 会在 redis 中看到有这条记录:
该地址已经成功被缓存到 redis 里面去, 点击其他页面, 可以看到, 只要是点击的页面, 都被缓存到 redis 里面去了. 总体来说, 如果不设置过期时间, 可以把整个网页静态化缓存到 redis 里面, 甚至是可以关闭 tomcat 了, 但是这种做法只适用于万年不变的页面, 至于用于企业的话,,,,
后记:
其实我有个疑问, 我的代码里, 并没有设置 lua 断开 redis 的连接, 不知道会不会有影响, 而且它这个是指每次请求过来, 都需要重新连接 redis 么? 光是 TCP 三次握手就耗时不少啊, 不知道怎么优化这些信息.
全部代码如下:
- local redis = require "resty.redis"
- local red = redis:new()
- local request_uri = ngx.var.request_uri
- local ngx_log = ngx.log
- local ngx_ERR = ngx.ERR
- local function close_redis(red)
- if not red then
- return
- end
- local pool_max_idle_time = 10000
- local pool_size = 100
- red:set("pool_size", pool_size)
- local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)
- if not ok then
- ngx_log(ngx_ERR, "set redis keepalive error :", err)
- end
- end
- local uri = ngx.var.uri
- red:set_timeout(1000)
- red:connect("119.23.46.71", 6340)
- red:auth("root")
- local uri_args = ngx.req.get_uri_args()
- local key = request_uri
- local resp, err = red:get(key)
- if resp == ngx.null then
- ngx.req.set_header("Accept", "text/html,application/xhtml+xml,application/xml;")
- ngx.req.set_header("Accept-Encoding", "")
- local targetURL = string.gsub(uri, "html", "do")
- local respp = ngx.location.capture(targetURL, { method = ngx.HTTP_GET, args = uri_args })
- red:set(key, respp.body)
- red:expire(key, 600)
- ngx.print(respp.body)
- return
- end
- ngx.print(resp)
- close_redis(red)
来源: https://www.cnblogs.com/w1570631036/p/9226519.html