场景

类似于秒杀活动,或者是有一些不常变动的网页,可以通过生成本地html文件,用户访问时直接通过nginx访问本地文件,不走或者减少操作数据库,以降低用户等待时间,提升用户体验。

实践

下载openresty

OpenResty - 下载

然后解压备用

新增lua工具

1、在解压目录下的lualib文件夹下新建myutil文件夹

2、新增并编辑redis_factory.lua文件,这个文件用来操作redis

local redis_factory = function(h)local h           = hh.redis           = require('resty.redis')h.cosocket_pool   = {max_idel = 10000, size = 10000}h.commands        = {"append",            "auth",              "bgrewriteaof","bgsave",            "bitcount",          "bitop","blpop",             "brpop","brpoplpush",        "client",            "config","dbsize","debug",             "decr",              "decrby","del",               "discard",           "dump","echo","eval",              "exec",              "exists","expire",            "expireat",          "flushall","flushdb",           "get",               "getbit","getrange",          "getset",            "hdel","hexists",           "hget",              "hgetall","hincrby",           "hincrbyfloat",      "hkeys","hlen","hmget",             "hmset",             "hscan","hset","hsetnx",            "hvals",             "incr","incrby",            "incrbyfloat",       "info","keys","lastsave",          "lindex",            "linsert","llen",              "lpop",              "lpush","lpushx",            "lrange",            "lrem","lset",              "ltrim",             "mget","migrate","monitor",           "move",              "mset","msetnx",            "multi",             "object","persist",           "pexpire",           "pexpireat","ping",              "psetex",            "psubscribe","pttl","publish",           "punsubscribe",      "pubsub","quit","randomkey",         "rename",            "renamenx","restore","rpop",              "rpoplpush",         "rpush","rpushx",            "sadd",              "save","scan",              "scard",             "script","sdiff",             "sdiffstore","select",            "set",               "setbit","setex",             "setnx",             "setrange","shutdown",          "sinter",            "sinterstore","sismember",         "slaveof",           "slowlog","smembers",          "smove",             "sort","spop",              "srandmember",       "srem","sscan","strlen",            "subscribe",         "sunion","sunionstore",       "sync",              "time","ttl","type",              "unsubscribe",       "unwatch","watch",             "zadd",              "zcard","zcount",            "zincrby",           "zinterstore","zrange",            "zrangebyscore",     "zrank","zrem",              "zremrangebyrank",   "zremrangebyscore","zrevrange",         "zrevrangebyscore",  "zrevrank","zscan","zscore",            "zunionstore",       "evalsha",-- resty redis private command"set_keepalive",     "init_pipeline",     "commit_pipeline",      "array_to_hash",     "add_commands",      "get_reused_times",}-- connect-- @param table connect_info, e.g { host="127.0.0.1", port=6379, password="", timeout=1000, database=0}-- @return boolean result-- @return userdata redis_instanceh.connect = function(connect_info)local redis_instance = h.redis:new()redis_instance:set_timeout(connect_info.timeout)if not redis_instance:connect(connect_info.host, connect_info.port) then return false, nilendif connect_info.password ~= '' thenredis_instance:auth(connect_info.password)endredis_instance:select(connect_info.database)return true, redis_instanceend-- spawn_client-- @param table h, include config info-- @param string name, redis config name-- @return table redis_clienth.spawn_client = function(h, name)local self = {}self.name           = ""self.redis_instance = nilself.connect        = nilself.connect_info   = {host = "",   port = 0,    password = "", timeout = 0, database = 0}-- constructself.construct = function(_, h, name)-- set infoself.name         = nameself.connect      = h.connectself.connect_info = h[name]-- gen redis proxy clientfor _, v in pairs(h.commands) doself[v] = function(self, ...)-- instance test and reconnect  if (type(self.redis_instance) == 'userdata: NULL' or type(self.redis_instance) == 'nil') thenlocal okok, self.redis_instance = self.connect(self.connect_info)if not ok then return false endend-- get datalocal vas = { ... }return self.redis_instance[v](self.redis_instance, ...)endendreturn trueend-- do constructself:construct(h, name) return selfend     local self = {}self.pool  = {} -- redis client name pool-- construct-- you can put your own construct code here.self.construct = function()returnend-- spawn-- @param string name, redis database serial name-- @return boolean result-- @return userdata redisself.spawn = function(_, name)if self.pool[name] == nil thenngx.ctx[name] = h.spawn_client(h, name) self.pool[name] = truereturn true, ngx.ctx[name]elsereturn true, ngx.ctx[name]endend-- destruct-- @return boolean allok, set_keepalive resultself.destruct = function()local allok = truefor name, _ in pairs(self.pool) dolocal ok, msg = ngx.ctx[name].redis_instance:set_keepalive(h.cosocket_pool.max_idel, h.cosocket_pool.size)if not ok then allok = false end endreturn allokend-- do constructself.construct() return self
endreturn redis_factory

3、新增并编辑mysql_factory.lua文件,这个文件用来操作数据库

local mysql = require("resty.mysql")  local mysql_pool = {}  --[[  先从连接池取连接,如果没有再建立连接.  返回:  false,出错信息.  true,数据库连接
--]]
function mysql_pool:get_connect(cfg)  if ngx.ctx[mysql_pool] then  return true, ngx.ctx[mysql_pool]  end  local client, errmsg = mysql:new()  if not client then  return false, "mysql.socket_failed: " .. (errmsg or "nil")  end  client:set_timeout(10000)  --30秒  local options = {  host = cfg.mysqlConfig.prod.host,  port = cfg.mysqlConfig.prod.port,  user = cfg.mysqlConfig.prod.user,  password = cfg.mysqlConfig.prod.password,  database = cfg.mysqlConfig.prod.database  }  local result, errmsg, errno, sqlstate = client:connect(options)  if not result then  return false, "mysql.cant_connect: " .. (errmsg or "nil") .. ", errno:" .. (errno or "nil") ..  ", sql_state:" .. (sqlstate or "nil")  end  local query = "SET NAMES " .. "utf8"  local result, errmsg, errno, sqlstate = client:query(query)  if not result then  return false, "mysql.query_failed: " .. (errmsg or "nil") .. ", errno:" .. (errno or "nil") ..  ", sql_state:" .. (sqlstate or "nil")  end  ngx.ctx[mysql_pool] = client  -- 测试,验证连接池重复使用情况  --[[ comments by leon1509  local count, err = client:get_reused_times()  ngx.say("xxx reused times" .. count);  --]]  return true, ngx.ctx[mysql_pool]
end  --[[  把连接返回到连接池  用set_keepalive代替close() 将开启连接池特性,可以为每个nginx工作进程,指定连接最大空闲时间,和连接池最大连接数  --]]
function mysql_pool:close()  if ngx.ctx[mysql_pool] then  -- 连接池机制,不调用 close 而是 keeplive 下次会直接继续使用  -- lua_code_cache 为 on 时才有效  -- 60000 : pool_max_idle_time , 100:connections  ngx.ctx[mysql_pool]:set_keepalive(60000, 80)  -- 调用了 set_keepalive,不能直接再次调用 query,会报错  ngx.ctx[mysql_pool] = nil  end
end  --[[  查询  有结果数据集时返回结果数据集  无数据数据集时返回查询影响  返回:  false,出错信息,sqlstate结构.  true,结果集,sqlstate结构.
--]]
function mysql_pool:query(sql, flag)  local ret, client = self:get_connect(flag)  if not ret then  return false, client, nil  end  local result, errmsg, errno, sqlstate = client:query(sql)  while errmsg == "again" do  result, errmsg, errno, sqlstate = client:read_result()  end  self:close()  if not result then  errmsg = "mysql.query_failed:" .. (errno or "nil") .. (errmsg or "nil")  return false, errmsg, sqlstate  end  return true, result, sqlstate
end  return mysql_pool

4、新增并编辑config_constant.lua文件,这个文件用来配置redis和mysql的连接信息

config = {}config.redisConfig = {redis_a = {--iphost = '127.0.0.1',--端口port = 6379,--密码password = 'qweasdzczs',--超时时间,如果是测试环境debug的话,这个值可以给长一点;如果是正式环境,可以设置为200timeout = 2000,--redis的库database = 0,},}config.mysqlConfig = {prod = {host = '127.0.0.1',port = 3306,user = 'root',password = '!@#QWEasdzxc',database = 'file',}
}
return config

5、新增并编辑article.lua文件,这个是业务文件,目的实现文章的静态化访问

--平台公共的配置文件常量
local config = require "myutil.config_constant"
--redis连接池工厂
local redis_factory = require('myutil.redis_factory')(config.redisConfig) -- import config when construct
--获取redis的连接实例
local ok, redis_a = redis_factory:spawn('redis_a')
local json = require("cjson")--获取URL链接中的文章ID,例、http://testdomain.com/article/66666666,http://testdomain.com/article/66666666.html,key为66666666或者66666666.html
local key = ngx.re.sub(ngx.var.uri, "^/article/(.*)", "$1", "o")
if (string.len(key) == 0) then -- 传参有误,根目录下要有404.htmlngx.req.set_uri('/404.html')
end--在redis中获取key对应的值
local va = redis_a:get("article:"..key)local file = nilif(va and va  ~= ngx.null) then--redis中存在数据file = json.decode(va)
else--mysql连接池local mysqlUtil = require "myutil.mysql_factory"--组装sql语句local sql = "SELECT id, article_name articleName, html_path htmlPath, create_time createTime, user_id userId FROM article_info where id = "..key--执行sql语句local ret, res, sqlstate = mysqlUtil:query(sql, config);--判断查询结果if((not ret) or res ==nil or #res<1) thenlocal hasSplit, endSplit = string.find(key,'%.',1)if(hasSplit)thenlocal keySplit = string.sub(key, 0, hasSplit - 1)sql = "SELECT id, article_name articleName, html_path htmlPath, create_time createTime, user_id userId FROM article_info where id = "..keySplitret, res, sqlstate = mysqlUtil:query(sql, config);endend--判断查询结果if(ret and res ~=nil and #res>0) then--取出最新的值file = res[1]local fileStr = json.encode(file)redis_a:set("article:"..key,fileStr)end
end
if (file) then -- 根据数据库中配置的地址加载文件local du = file.htmlPathngx.req.set_uri(du)
elsengx.req.set_uri('/404.html')
end

配置Nginx

nginx通过rewrite + lua的方式访问

worker_processes  1;events {worker_connections  1024;
}http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;autoindex on;# 显示目录autoindex_exact_size on;# 显示文件大小autoindex_localtime on;# 显示文件时间server {listen       80;server_name  localhost;location /article {root d:/;#这里的lua文件的路径为绝对路径,请根据自己安装的实际路径填写#记得斜杠是/这个,从window中拷贝出来的是\这样,这样是有问题的,务必注意rewrite_by_lua_file D:/openresty-test/lualib/myutil/article.lua;}}}

Openresty/Lua/Redis/Mysql实现静态化网页加载相关推荐

  1. OpenResty+Lua+redis+mysql实现高性能高可用限流缓存

    OpenResty(又称:ngx_openresty) 是一个基于 NGINX 的可伸缩的 Web 平台.并发性能可在10k-1000k OpenResty安装 1.添加仓库执行命令 yum inst ...

  2. 如何提升网页加载性能

    摘自 https://github.com/xitu/gold-miner/blob/master/TODO/building-a-shop-with-sub-second-page-loads-le ...

  3. 内容分发网络 CDN 是如何提高网页加载时间的?

    几乎 Internet 上的每个人都体验过内容分发网络 (CDN) 的好处.大多数科技公司,包括谷歌.苹果和微软等公司,都使用 CDN 来减少加载网页内容的延迟. CDN 通常会将服务器放置在不同网络 ...

  4. web前端 网页加载 性能优化大全

    web前端 性能优化 - - 如何提高网页加载速度 文章目录 web前端 性能优化 --- --- 如何提高网页加载速度 1. 减少DNS查找 2. 使用CDN托管资源 3. 减少Http请求 浏览器 ...

  5. centos uwsgi配置_centos下配置nginx+uwsgi运行py以及静态文件的加载

    其实不限于centos,个人觉得所有的linux都一样,就好像你喜欢把钱放在左边的口袋,我喜欢把钱放右边的口袋,还有的人喜欢把钱放里面的口袋,无非是配置文件的地方不一样 首先安装nginx,嗯,这个自 ...

  6. 用 Flask 来写个轻博客 (28) — 使用 Flask-Assets 压缩 CSS/JS 提升网页加载速度

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 Flask-Assets 将 Flask-Assets 应用 ...

  7. 静态原型设计 加载中_见解1:原型设计有助于填补静态设计留下的空白。

    静态原型设计 加载中 In April 2015, I joined the Disney Parks creative team to design mobile experiences for t ...

  8. 关于前端性能优化问题,认识网页加载过程和防抖节流

    前端性能优化-网页加载过程.性能优化方法.防抖和节流 一.网页加载过程 1.加载资源的形式 2.加载资源的过程 3.渲染页面的过程 4.关于window.onload 和 DOMContentLoad ...

  9. 打开服务器网页要5秒,网页优化技巧 如何把网页加载时间控制在1.5秒以内

    今天为大家分享"如何把网页加载时间控制在1.5秒以内(必看)"当然了,控制在2秒以内其实是完全可以的,我们为什么要控制页面打开速度那?首先百度会对加载慢的页面进行打击,对SEO排名 ...

最新文章

  1. 荣耀30pro系统_荣耀30 pro:正式再见!
  2. Keep 再融资以后
  3. cpp遇到问题:include重复包含导致的redefinition
  4. 掌握python编程语言tensorflow_手把手教你eclipse集成Python语言+Tensorflow环境
  5. Springmvc 中org.springframework.http.converter.json.MappingJackson2HttpMessageConverter依赖jackson包...
  6. arcgis计算地形起伏度
  7. 模拟生态圈_电源工程师必备求生技能——经典20种模拟电路
  8. android 录音原始文件_Android 11可能最终会取消Android对视频录制的4GB文件大小限制...
  9. hive数据库的哪些函数操作是否走MR
  10. hdu3068 求一个字符串中最长回文字符串的长度 Manacher算法
  11. MMKV_MMKV—强大的存储工具
  12. excel易用宝的修复
  13. Mybatis多参数查询与列表查询不同方式实现
  14. imx8qxp uuu 下载脚本example_kernel_emmc.uuu注释
  15. 简单学生成绩分析系统
  16. CentOS防火墙配置(资源)
  17. 如何在EverEdit编辑器中一键编译运行JAVA并接收键盘输入数据
  18. 阅读笔记04——魔鬼搭讪学
  19. java的concurrenthashmap和hashtab
  20. css如何去掉或修改浏览器默认滚动条

热门文章

  1. 内网如何映射到外网,本文使用ant123工具实现
  2. 【深度学习】Ubuntu18.04安装NVIDIA GTX960M驱动
  3. iOS:蓝牙通讯中的进制转换
  4. 浙江大学数据结构(4.1二叉搜索树)
  5. 双机互备是什么意思?双机互备就是双机热备吗?
  6. java语法分析生成器,语法词法生成器
  7. r7 6800hs参数 锐龙r7 6800hs评测
  8. 基于MATLAB的人脸识别算法的研究
  9. wireshark拦截手机数据包
  10. HotSpot设计原理与实现:一、初识HotSpot