电商系统大访问量静态页优化架构

javashop电商系统中像买家端首页、商品详情页、店铺首页等这类页面有两个共同的特点,即访问量大,数据不常变动。对于这类页面,为了减轻前端服务器的压力,javashop将这些页面缓存到了Redis中,当用户访问这些页面时,服务器会通过OpenResty代理执行lua脚本访问Redis中缓存的静态页面信息。接下来,我们来详细的讲解下整个流程中所涉及到的技术点。

1、缓存静态页

缓存静态页的过程在javashop中是通过httpClient抓取前端服务器中的静态页内容放到redis中。

  1)抓取静态页信息

private String getHTML(String url, String type, int times) throws IOException {
    String html;
    // socket超时  connect超时
    RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(50000)
            .setConnectTimeout(50000)
            .build();
    CloseableHttpClient httpClient =HttpClients.custom().setDefaultRequestConfig(requestConfig).build();
    HttpGet httpGet = new HttpGet(url);
    httpGet.setHeader("Client-Type", type);
    CloseableHttpResponse response = httpClient.execute(httpGet);
    int status = response.getStatusLine().getStatusCode();

    if (status != 200) {
        html = EntityUtils.toString(response.getEntity(), "utf-8");

        debugger.log("生成静态页出错:静态页渲染服务返回" + status, "uri:" + url);
        debugger.log(html);
        if (times >= 4) {
            return ("create error ,return code is :" + status + ",url is :" + url);
        } else {
            times++;
            debugger.log(times + "次重试...");
            //重试时等待时间,在一段时间后重试   防止出现429(Too much connections in one mintue)问题 
            try {
                Thread.sleep(times * 1000);
            } catch (InterruptedException e) {
                logger.debug(e.getMessage());
            }


            html = getHTML(url, type, times);

            return html;
        }

    } else {

        if (times > 0) {
            debugger.log("重试成功");
        }
        html = EntityUtils.toString(response.getEntity(), "utf-8");
    }

    return html;
}

  2)存入redis

//生成消息
String url = getUrl(path, type);
//通过http 来获取html存储redis
String html = this.getHTML(url, type);
stringRedisTemplate.opsForValue().set(name, html);

2、访问静态页

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

OpenResty官网地址:http://openresty.org/cn/

下面我们着重介绍一下OpenResty是如何通过lua脚本访问redis的,以PC端静态页为例。

  1)首先我们准备好访问redis的lua脚本,代码如下

单机版:single_connector.lua

local request_uri = ngx.var.uri 
local redis = require "resty.redis"
local red = redis:new()

--red:set_timeout(10000) -- 1 sec

local ok, err = red:connect("ip", port)
if not ok then
    ngx.say("failed to connect: ", err)
    return
end

--如果设置了密码请打开注释,并填写密码
--local res, err = red:auth("password")
--    if not res then
--    ngx.say("failed to authenticate: ", err)
--    return
--end

local res, err = red:get(request_uri)
-- 请修改https://www.test.com 为实际配置域名或IP端口
if res == ngx.null then
    ngx.redirect("https://www.test.com/404.html")
   return
end

if not res then
    ngx.say("failed to get: " .. request_uri , err)
    return
end
red:set_keepalive(6000,1000)
ngx.say(res)

集群版:cluster_connector.lua

local request_uri = ngx.var.uri 
local config = {
    name = "testCluster",                   --rediscluster name
    -- enableSlaveRead = true,
    serv_list = {                           --redis cluster node list(host and port),
        { ip = "ip", port = port },
        { ip = "ip", port = port }
    },
    keepalive_timeout = 60000,              --redis connection pool idle timeout
    keepalive_cons = 300,                  --redis connection pool size
    connection_timout = 15000,               --timeout while connecting
    max_redirection = 5                     --maximum retry attempts for redirection
}

local redis_cluster = require "resty.rediscluster"
local red_c = redis_cluster:new(config)

-- 请修改https://www.test.com 为实际配置域名或IP端口
local v, err = red_c:get(request_uri)
if v == ngx.null then
    ngx.redirect("https://www.test.com/404.html")
   return
end

if err then
    ngx.log(ngx.ERR, "err: ", err)
else
    ngx.say(v)
end

注意:

redis配置注释掉bind 127.0.0.1、设置protected-mode 为no;否则通过lua连接redis出错

  2)在OpenResty中配置server路径  

 #新建静态页输出节点,content_by_lua_file为lua脚本实际路径。
   server {

        listen       80;
        server_name  localhost; 

        #pc端静态响应
        location /PC {
           default_type text/html;
           content_by_lua_file "/usr/local/openresty/nginx/conf/lua/single_connector.lua"; 

           #redis集群请使用此配置 
           #content_by_lua_file "/usr/local/openresty/nginx/conf/lua/cluster_connector.lua";  

        }

    }
原文地址:https://www.cnblogs.com/javashop-docs/p/13737920.html