zoukankan      html  css  js  c++  java
  • 54_基于nginx+lua+java完成多级缓存架构的核心业务逻辑


    分发层nginx,lua应用,会将商品id,商品店铺id,都转发到后端的应用nginx

    /usr/servers/nginx/sbin/nginx -s reload

    1、应用nginx的lua脚本接收到请求

    2、获取请求参数中的商品id,以及商品店铺id

    3、根据商品id和商品店铺id,在nginx本地缓存中尝试获取数据

    4、如果在nginx本地缓存中没有获取到数据,那么就到redis分布式缓存中获取数据,如果获取到了数据,还要设置到nginx本地缓存中

    但是这里有个问题,建议不要用nginx+lua直接去获取redis数据

    因为openresty没有太好的redis cluster的支持包,所以建议是发送http请求到缓存数据生产服务,由该服务提供一个http接口

    缓存数生产服务可以基于redis cluster api从redis中直接获取数据,并返回给nginx

    cd /usr/hello/lualib/resty/
    wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http_headers.lua
    wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http.lua

    5、如果缓存数据生产服务没有在redis分布式缓存中没有获取到数据,那么就在自己本地ehcache中获取数据,返回数据给nginx,也要设置到nginx本地缓存中

    6、如果ehcache本地缓存都没有数据,那么就需要去原始的服务中拉去数据,该服务会从mysql中查询,拉去到数据之后,返回给nginx,并重新设置到ehcache和redis中

    这里先不考虑,后面要专门讲解一套分布式缓存重建并发冲突的问题和解决方案

    7、nginx最终利用获取到的数据,动态渲染网页模板

    cd /usr/hello/lualib/resty/
    wget https://raw.githubusercontent.com/bungle/lua-resty-template/master/lib/resty/template.lua
    mkdir /usr/hello/lualib/resty/html
    cd /usr/hello/lualib/resty/html
    wget https://raw.githubusercontent.com/bungle/lua-resty-template/master/lib/resty/template/html.lua

    在hello.conf的server中配置模板位置

    set $template_location "/templates";
    set $template_root "/usr/hello/templates";

    mkdir /usr/hello/templates

    vi product.html

    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>商品详情页</title>
    </head>
    <body>
    商品id: {* productId *}<br/>
    商品名称: {* productName *}<br/>
    商品图片列表: {* productPictureList *}<br/>
    商品规格: {* productSpecification *}<br/>
    商品售后服务: {* productService *}<br/>
    商品颜色: {* productColor *}<br/>
    商品大小: {* productSize *}<br/>
    店铺id: {* shopId *}<br/>
    店铺名称: {* shopName *}<br/>
    店铺等级: {* shopLevel *}<br/>
    店铺好评率: {* shopGoodCommentRate *}<br/>
    </body>
    </html>

    8、将渲染后的网页模板作为http响应,返回给分发层nginx

    hello.conf中:

    lua_shared_dict my_cache 128m;

    lua脚本中:

    local uri_args = ngx.req.get_uri_args()
    local productId = uri_args["productId"]
    local shopId = uri_args["shopId"]

    local cache_ngx = ngx.shared.my_cache

    local productCacheKey = "product_info_"..productId
    local shopCacheKey = "shop_info_"..shopId

    local productCache = cache_ngx:get(productCacheKey)
    local shopCache = cache_ngx:get(shopCacheKey)

    if productCache == "" or productCache == nil then
    local http = require("resty.http")
    local httpc = http.new()

    local resp, err = httpc:request_uri("http://192.168.31.179:8080",{
    method = "GET",
    path = "/getProductInfo?productId="..productId,
    keepalive=false
    })

    productCache = resp.body
    cache_ngx:set(productCacheKey, productCache, 10 * 60)
    end

    if shopCache == "" or shopCache == nil then
    local http = require("resty.http")
    local httpc = http.new()

    local resp, err = httpc:request_uri("http://192.168.31.179:8080",{
    method = "GET",
    path = "/getShopInfo?shopId="..shopId,
    keepalive=false
    })

    shopCache = resp.body
    cache_ngx:set(shopCacheKey, shopCache, 10 * 60)
    end

    local cjson = require("cjson")
    local productCacheJSON = cjson.decode(productCache)
    local shopCacheJSON = cjson.decode(shopCache)

    local context = {
    productId = productCacheJSON.id,
    productName = productCacheJSON.name,
    productPrice = productCacheJSON.price,
    productPictureList = productCacheJSON.pictureList,
    productSpecification = productCacheJSON.specification,
    productService = productCacheJSON.service,
    productColor = productCacheJSON.color,
    productSize = productCacheJSON.size,
    shopId = shopCacheJSON.id,
    shopName = shopCacheJSON.name,
    shopLevel = shopCacheJSON.level,
    shopGoodCommentRate = shopCacheJSON.goodCommentRate
    }

    local template = require("resty.template")
    template.render("product.html", context)

    第一次访问的时候,其实在nginx本地缓存中是取不到的,所以会发送http请求到后端的缓存服务里去获取,会从redis中获取

    拿到数据以后,会放到nginx本地缓存里面去,过期时间是10分钟

    然后将所有数据渲染到模板中,返回模板

    以后再来访问的时候,就会直接从nginx本地缓存区获取数据了

    缓存数据生产 -> 有数据变更 -> 主动更新两级缓存(ehcache+redis)-> 缓存维度化拆分

    分发层nginx + 应用层nginx -> 自定义流量分发策略提高缓存命中率

    nginx shared dict缓存 -> 缓存服务 -> redis -> ehcache -> 渲染html模板 -> 返回页面

    还差最后一个很关键的要点,就是如果你的数据在nginx -> redis -> ehcache三级缓存都不在了,可能就是被LRU清理掉了

    这个时候缓存服务会重新拉去数据,去更新到ehcache和redis中,这里我们还没讲解

    分布式的缓存重建的并发问题

  • 相关阅读:
    03.部署 kubectl 命令行工具
    02.创建 CA 证书和秘钥
    01.组件版本和集群环境
    23.kubernetes 组件版本和配置策略
    22.Kubernetes Ingress: HTTP 7层路由机制
    Python程序中#-*-coding: UTF-8 -*-的作用
    Python程序中首行#!/usr/bin/env python的作用
    mac install php dev
    linux的nohup disown setsid screen
    linux 常用查找命令 小技巧
  • 原文地址:https://www.cnblogs.com/hg-super-man/p/12783789.html
Copyright © 2011-2022 走看看