记一篇 lua与Openresty多级缓存的应用

1. nginx 优化#

  1. nginx 优化

一个简单的 nginx 配置文件:

user nginx; #用户
worker_processes auto;#进程数量 推荐auto,自动去服务器的cpu核心数
error_log /var/log/nginx/error.log  error;
pid /var/run/nginx.pid;
worker_rlimit_nofile 204800;
events
{
    use epoll;#使用Linux中效率最高的epoll
    worker_connections 204800;
}
http
{
    include mime.types;#nginx支持的文件类型
    default_type application/octet-stream;
    charset utf-8;
    server_names_hash_bucket_size 128;
    client_header_buffer_size 2k;
    large_client_header_buffers 4 4k;
    client_max_body_size 8m;
    sendfile on;
    tcp_nopush on;
    keepalive_timeout 60;
    fastcgi_cache_path /usr/local/nginx/fastcgi_cache levels=1:2
    keys_zone=TEST:10m
    inactive=5m;

    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    fastcgi_buffer_size 4k;
    fastcgi_buffers 8 4k;
    fastcgi_busy_buffers_size 8k;
    fastcgi_temp_file_write_size 8k;
    fastcgi_cache TEST;
    fastcgi_cache_valid 200 302 1h;
    fastcgi_cache_valid 301 1d;
    fastcgi_cache_valid any 1m;
    fastcgi_cache_min_uses 1;
    fastcgi_cache_use_stale error timeout invalid_header http_500;
    open_file_cache max=204800 inactive=20s;
    open_file_cache_min_uses 1;
    open_file_cache_valid 30s;
    tcp_nodelay on;
    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml;
    gzip_vary on;
    include /etc/nginx/conf.d/*.conf;
}

备注:
open_file_cache 配置的常用参数

  • max=204800 表示设置缓存文件的最大数目为 204800, 超过此数字后 Nginx 将按照 LRU 原则丢弃冷数据。
  • inactive=20s 与 open_file_cache_min_uses 2 表示如果在 20s 天内某文件被访问的次数低于 2 次,那就将它从缓存中删除。
  • open_file_cache_valid 30s 表示每 30s 分钟检查一次缓存中的文件元信息是否是最新的,如果不是则更新之
  • tcp_nodelay off,会增加通信的延时,但是会提高带宽利用率。在高延时、数据量大的通信场景中应该会有不错的效果
  • tcp_nodelay on,会增加小包的数量,但是可以提高响应速度。在及时性高的通信场景中应该会有不错的效果

gzip 配置的常用参数

  • gzip on|off; #是否开启 gzip

  • gzip_buffers 32 4K| 16 8K #缓冲 (压缩在内存中缓冲几块?每块多大?)

  • gzip_comp_level [1-9] #推荐 6 压缩级别 (级别越高,压的越小,越浪费 CPU 计算资源)

  • gzip_disable #正则匹配 UA 什么样的 Uri 不进行 gzip

  • gzip_min_length 200 # 开始压缩的最小长度 (再小就不要压缩了,意义不在)

  • gzip_http_version 1.0|1.1 # 开始压缩的 http 协议版本 (可以不设置,目前几乎全是 1.1 协议)

  • gzip_proxied # 设置请求者代理服务器,该如何缓存内容

  • gzip_types text/plain application/xml # 对哪些类型的文件用压缩 如 text/plain application/javascript application/x-javascript text/javascript text/css application/xml;

  • gzip_vary on|off # 是否传输 gzip 压缩标志

2. 多级缓存#

2.1 lua 与 Openresty 介绍#

lua 是一个小巧的脚本语言,由标准 C 编写而成,几乎在所有操作系统和平台上都可以编译运行。其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

应用场景:游戏开发、独立应用脚本、redis 中嵌套调用实现类似事务的功能,web 容器汇总处理 NGINX 的过滤缓存等等逻辑

Openresty 介绍

OpenResty 是一个基于 Nginx 与 Lua 的高性能 web 平台,由中国人章亦春发起,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便搭建能处理超高并发、扩展性极高的动态 Web 应用、web 服务和动态网关

OpenResty 简单理解成就相当于封装了 NGINX,并且集成了 LUA 脚本,开发人员只需要简单的使用其提供了模块就可以实现相关的逻辑,而不像之前,还需要在 NGINX 中编写 lua 的脚本。

安装

  1. 拉取一个 Openresty 的镜像
    docker pull openresty/openresty
  2. 随便构建一个容器
    docker run -p 90:90 -d --name openresty openresty/openresty
  3. 进入容器,查看配置文件的路径
docker exec -it openresty bash

cd /etc/nginx/conf.d
  1. 退出容器,复制容器中配置文件到宿主机

    docker cp openresty:/etc/nginx/conf.d/default.conf /docker/openresty/conf/default.conf
    
    docker stop openresty
    docker rm openresty
    
    docker run -p 90:90 -d --name openresty -v /docker/openresty/conf/default.conf:/etc/nginx/conf.d/default.conf --privileged=true openresty/openresty
  2. 修改配置文件

# 修改 nginx.conf 文件
http {
    #添加设置共享内存 dis_cache 对象大小
    lua_shared_dict  dis_cache 120m;
}
server
{
    listen       90;
    listen       [::]:90;
    server_name  localhost;
    root /docker/www/webserver;
    index index.html;
    location /product_cate_cache {
       content_by_lua_file /docker/www/lua/product_cate_cache.lua;
    }
}

2.2 首页多级缓存策略 (这里以商城首页的分类数据为例,实际场景还有:猜你喜欢的商品,热商品)#

1、使用 Lua 查询 Nginx 缓存,如果有缓存,则直接将缓存中的分类数据返回

2、如果 Nginx 缓存中没有分类数据,则通过 Lua 脚本查询 Redis,如果 Redis 中有数据,则将数据存入到 Nginx 缓存中,并返回查询到的数据

3、如果 Redis 中也没有缓存,则此时通过 Lua 脚本查询 Mysql,如果 Mysql 中有数据,将分类数据存入到 Redis 缓存,并返回数据

ngx.header.content_type = "application/json;charset=utf8"
local cache_ngx = ngx.shared.dis_cache;
local contentCache = cache_ngx:get("product_cate_cache");
if contentCache == "" or contentCache == nil then
    local redis = require("resty.redis");
    local red = redis:new()
    red:set_timeout(2000)
    red:connect("172.17.0.5", 6379)
    local rescontent = red:get("product_cate_cache");
    if ngx.null == rescontent or false == rescontent or "" == rescontent then
        local cjson = require("cjson");
        local mysql = require("resty.mysql");
        local db = mysql:new();
        db:set_timeout(2000)
        local props = {
            host = "127.0.0.1",
            port = 3306,
            database = "good",
            user = "root",
            password = "root"
        }
        local res = db:connect(props);
        local select_sql = "select * from product_cate"
        res = db:query(select_sql);
        local responsejson = cjson.encode(res);
        red:set("product_cate_cache", responsejson);
        ngx.say(responsejson);
        db:close()
        else
        cache_ngx:set("product_cate_cache", rescontent, 10 * 60);
        ngx.say(rescontent)
    end
    red:close()
    else
    ngx.say(contentCache)
end
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 2

你这种还要在这里面写查询数据库的相关代码,其实直接接管接口请求来做缓存即可

10个月前 评论
Coolr (楼主) 10个月前