OpenResty与Lua实现高并发请求处理

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 Tair(兼容Redis),内存型 2GB
简介: OpenResty与Lua实现高并发请求处理

OpenResty与Lua实现高并发请求处理


前言

官网:http://openresty.org/cn/


介绍

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


OpenResty 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。


OpenResty 的目标是让你的Web服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。


配置

安装 OpenResty 软件后,因为 OpenResty 基于 Nginx 开发,所以配置 OpenResty 只需要配置 Nginx 即可。


在 OpenResty 安装目录下配置 nginx

# nginx 拦截 /update_context 请求,交给 lua 脚本处理
location /update_context {
  content_by_lua_file /root/lua/update_content.lua
}
location /get_context {
  content_by_lua_file /root/lua/get_content.lua
}

Lua 脚本

lua redis 脚本参考:https://github.com/openresty/lua-resty-redis


lua mysql 脚本参考:https://github.com/openresty/lua-resty-mysql


update_content.lua 脚本

ngx.header.content_type="application/json;charset=utf8"
local cjson = require("cjson")
local mysql = require("resty.mysql")
-- 获取用户的请求参数
local uri_args = ngx.req.get_uri_args()
-- 获取请求参数中的 id
local id = uri_args["id"]
-- 连接 mysql
local db = mysql:new()
db:set_timeout(1000)
local props = {
    host = "192.168.8.4",
    port = 3306,
    database = "changgou_content",
    user = "root",
    password = "123456"
}
-- 查询mysql
local res = db:connect(props)
local select_sql = "select url,pic from tb_content where status = '1' and category_id =" ..id.." order by sort_order"
res = db:query(select_sql)
db:close()
-- 连接redis
local redis = require "resty.redis"
local red = redis:new()
red:set_timeouts(1000, 1000, 1000)
local ok, err = red:connect("192.168.8.4", 6379)
if not ok then
    ngx.say("failed to connect: ", err)
    return
end
red:set("content_"..id, cjson.encode(res))
red:close()
ngx.say("{flag:true}")

get_content.lua 脚本

ngx.header.content_type="application/json;charset=utf8"
local cjson = require("cjson")
local mysql = require("resty.mysql")
local uri_args = ngx.req.get_uri_args()
local id = uri_args["id"]
-- 获取nginx缓存数据,如果没有从redis中获取
-- 需要定义 ngx.shared.dis_cache 模块,lua 缓存命名空间(dis_cache)
local cache_ngx = ngx.shared.dis_cache;
local contentCache = cache_ngx:get("content_"..id)
if contentCache == "" or contentCache == nil then
    ngx.say("contentCache not found ")
else
    ngx.say(contentCache)
    return
end
-- 连接redis
local redis = require "resty.redis"
local red = redis:new()
red:set_timeouts(1000, 1000, 1000)
local ok, err = red:connect("192.168.8.4", 6379)
if not ok then
    ngx.say("failed to connect: ", err)
    return
end
-- 从 redis 中获取数据
local res, err = red:get("content_"..id)
if not res then
    ngx.say("failed to get content_"..id, err)
    return
end
if res == ngx.null then
    ngx.say("content_"..id.." not found.")
    -- redis缓存中没有连接数据库查询,并放入redis缓存中
    local db = mysql:new()
    local props = {
        host = "192.168.8.4",
        port = 3306,
        database = "changgou_content",
        user = "root",
        password = "123456"
    }
    local ok, err, errcode, sqlstate = db:connect(props)
    if not ok then
        ngx.say("failed to connect: ", err, ": ", errcode, " ", sqlstate)
        return
    end
    ngx.say("connected to mysql.")
     local select_sql = "select url,pic from tb_content where status = '1' and category_id =" ..id.." order by sort_order"
    local res, err, errcode, sqlstate = db:query(select_sql)
    if not res then
        ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
        return
    end
    -- 设置缓存到 nginx 中, 10*60: 10分钟
    cache_ngx:set("content_"..id, res, 10*60)
    -- 存入缓存到 redis 中
    red:set("content_"..id, cjson.encode(res))
    -- 输出
    ngx.say("content_"..id, cjson.encode(res))
    db:close()
    return
end
-- 设置缓存到 nginx 中
cache_ngx:set("content_"..id, res, 10*60)
ngx.say("content_"..id, res)
red:close()


定义 ngx.shared.dis_cache 模块 ,需要在 nginx 配置文件中的 http 模块下添加

# 定义 lua 缓存命名空间(dis_cache)及其大小(128m)
lua_shared_dict dis_cache 128m;


如图


image.png

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
7月前
|
存储 缓存 Java
Openresty(lua+nginx)-Guava-Redis做多级缓存
Openresty(lua+nginx)-Guava-Redis做多级缓存
86 1
|
7月前
|
缓存 安全 API
【亿级数据专题】「高并发架构」盘点本年度探索对外服务的百万请求量的API网关设计实现
公司对外开放的OpenAPI-Server服务,作为核心内部系统与外部系统之间的重要通讯枢纽,每天处理数百万次的API调用、亿级别的消息推送以及TB/PB级别的数据同步。经过多年流量的持续增长,该服务体系依然稳固可靠,展现出强大的负载能力。
178 9
【亿级数据专题】「高并发架构」盘点本年度探索对外服务的百万请求量的API网关设计实现
|
缓存 NoSQL 中间件
redis如何通过读写分离来承载读请求高并发
redis如何通过读写分离来承载读请求高并发
102 0
浅谈基于openresty(nginx+lua)开发轻量级,按流量控制的灰度模块(下)
浅谈基于openresty(nginx+lua)开发轻量级,按流量控制的灰度模块
154 0
|
14天前
|
Web App开发 网络安全 数据安全/隐私保护
Lua中实现HTTP请求的User-Agent自定义
Lua中实现HTTP请求的User-Agent自定义
|
2月前
|
网络协议
Lua中实现异步HTTP请求的方法
Lua中实现异步HTTP请求的方法
|
2月前
|
缓存 负载均衡 API
抖音抖店API请求获取宝贝详情数据、原价、销量、主图等参数可支持高并发调用接入演示
这是一个使用Python编写的示例代码,用于从抖音抖店API获取商品详情,包括原价、销量和主图等信息。示例展示了如何构建请求、处理响应及提取所需数据。针对高并发场景,建议采用缓存、限流、负载均衡、异步处理及代码优化等策略,以提升性能和稳定性。
|
3月前
|
存储 JSON Ubuntu
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
|
5月前
|
存储 安全 Java
Java面试题:假设你正在开发一个Java后端服务,该服务需要处理高并发的用户请求,并且对内存使用效率有严格的要求,在多线程环境下,如何确保共享资源的线程安全?
Java面试题:假设你正在开发一个Java后端服务,该服务需要处理高并发的用户请求,并且对内存使用效率有严格的要求,在多线程环境下,如何确保共享资源的线程安全?
72 0
|
6月前
|
并行计算 Go 数据处理
掌握Go语言:Go 并发编程,轻松应对大规模任务处理和高并发请求(34)
掌握Go语言:Go 并发编程,轻松应对大规模任务处理和高并发请求(34)
下一篇
DataWorks