希望长大对我而言,是可以做更多想做的事,而不是被迫做更多不想做的事...... 首页 双层nginx提高本地缓存的命中率 丁D 学无止境 2019-06-05 08:50 3824已阅读 nginx 缓存 命中率 摘要我们都知道当我们在nginx部署高可用的时候,会发现nginx的本地缓存的命中率很低。本文将讲解如何提高命中率。 ###为什么nginx本地缓存的命中率低? 如下图所示: 当我们nginx部署高可用的时候,客户的请求不知道落在那个nginx上 1,当我们第一次请求落在 第一台nginx(最左)上,发现nginx本地并没有缓存, 2,nginx就必须到redis获取数据,并缓存到本地 3,将请求数据返回给客户 第二次请求理想情况下 如果我们得请求落在第一台(最左),nginx发现本地已经有缓存了, 那么可以直接返回不用请求redis 不理想情况, 当我们得第二次请求没有落在第一台机器上,落在了中间那台,nginx就发现本地还是没有缓存 会到redis集群中获取数据,并缓存本地,返回给客户。。 这样的情况下,**nginx的本地缓存命中率就很低了。。。这样会导致redis的压力暴增。。** ![alt](/upload/20190605090507.png) ###解决方案:双层nginx来分发请求 经上面的分析,我们知道了nginx命中率低的原因,就是同一个请求(getProductInfo?productId=1)被分发到不同的nginx上面,那么我们可以想办法让获取同一个数据(productId=1)的请求落在同一个nginx上面,如下图所示:![alt](/upload/20190605092239.png) 我们使用双层nginx 第一层(nginx4和5)作为分发层,做分发作用;;; 第二层(nginx1和2和3) 作为应用层,提供本地缓存的作用;;; 当我们的请求过来经nginx4。nginx4+lua脚本获取请求参数(productId取模)判断要将请求分给(nginx 1 2 3)哪一台机器。。假设是nginx1 nginx判断本地没有缓存就去redis获取并缓存到本地, 当我们得第二次同一个请求过来,nginx5,,同样取参数取模。将请求分发给nginx1,,这样nginx就不用再去redis获取了,可以直接返回。 ###部署openresty 自行查阅资料 ###工程化的nginx+lua项目结构 ```js 项目工程结构 hello hello.conf lua hello.lua lualib *.lua *.so 放在/usr/hello目录下 /usr/servers/nginx/conf/nginx.conf worker_processes 2; error_log logs/error.log; events { worker_connections 1024; } http { include mime.types; default_type text/html; lua_package_path "/usr/hello/lualib/?.lua;;"; lua_package_cpath "/usr/hello/lualib/?.so;;"; include /usr/hello/hello.conf; } /usr/hello/hello.conf server { listen 80; server_name _; location /lua { default_type 'text/html'; lua_code_cache off; content_by_lua_file /usr/example/lua/test.lua; } } ``` ###分发层 部署分发层nginx以及基于lua完成基于商品id的定向流量分发策略 ```js //hello.lua local uri_args = ngx.req.get_uri_args() local productId = uri_args["productId"] local hosts = {"192.168.31.187", "192.168.31.19"} local hash = ngx.crc32_long(productId) local index = (hash % 2) + 1 backend = "http://"..hosts[index] local requestPath = uri_args["requestPath"] requestPath = "/"..requestPath.."?productId="..productId local http = require("resty.http") local httpc = http.new() local resp, err = httpc:request_uri(backend,{ method = "GET", path = requestPath }) if not resp then ngx.say("request error: ", err) return end ngx.say(resp.body) httpc:close() ``` ###疑问 ```js 如果应用层某一台nginx宕机,,请求取模的参数要变更?? lua脚本如何时时判断应用层的活的nginx数量 或者,lua请求应用层失败在换一台?? ``` ```js 了解一下zuul网关能否替换分发层 ``` 很赞哦! (2) 上一篇:redis cluster 下一篇:双层nginx之应用层 目录 点击排行 Elasticsearch6.3.2之x-pack redis哨兵 2019-07-09 22:05 Redis+Twemproxy+HAProxy+Keepalived 2019-07-12 17:20 GC优化策略和相关实践案例 2019-10-10 10:54 JVM垃圾回收器 2019-10-10 10:23 标签云 Java Spring MVC Mybatis Ansible Elasticsearch Redis Hive Docker Kubernetes RocketMQ Jenkins Nginx 友情链接 郑晓博客 佛布朗斯基 凉风有信 MarkHoo's Blog 冰洛博客 南实博客 Rui | 丁D Java研发工程师 生活可以用「没办法」三个字概括。但别人的没办法是「腿长,没办法」、「长得好看,没办法」、「有才华,没办法」。而你的没办法,是真的没办法。 请作者喝咖啡