赞
踩
目录
OpenResty是一个基于nginx的高性能Web平台,他用于方便的搭建能够处理高并发、扩展性极高的动态Web应用、Web服务和动态网关。他具备以下特点:1.具备nginx的完整功能 2.基于Lua语言进行扩展,集成了大量精良的Lua库、第三方模块 3.允许使用Lua自定义业务逻辑、自定义库
OpenResty提供了各种API来获取不同类型的请求参数
参数格式 | 示例 | 获取代码示例 |
路径占位符 | /test/101 | 利用正则表达式匹配:location ~ /test/(\d+) { content_by_lua_file lua/test.lua;获取后转向该路径下的test.lua文件,在该lua文件中可以通过ngx.var[1]获取到参数101 } |
请求头 | id:101 | 在lua脚本中使用 local header = ngx.req.get_headers() 可以获取到请求头header是一个table类型 |
Get请求 | ?id=101 | 与上述相同 local params = ngx.req.get_uri_args() 其中params也是一个table类型 |
Post请求 | id=101 | 首先需要读取请求体通过以下代码 ngx.req.read_body() 然后获取参数 local post = ngx.req.get_post_args() 其结果也是table类型 |
JSON数据 | {"id":101} | 首先需要读取请求体通过以下代码 ngx.req.read_body() 然后获取参数 local json=ngx.req.get_body_data()返回结果是一个string类型是json数据,后续会提到如何序列化与反序列化 |
nginx提供了内部的API用以发送http请求
local resp = ngx.location.capture("/path",{
method=ngx.HTTP_GET, -- 请求方式
args={id=1,age=10}, -- get请求的传参方式
body="id=1&age=10" -- post请求的传参方式
})
上述代码中的path是路径但是这个路径并不包含IP与端口,这个请求会被nginx内部的server监听并处理,我们这里要将去查询tomcat所以要在nginx中编写一个server对这个路径反向代理到Tomcat
location /path{
proxy_pass http://IP:8080
}
其中返回的resp包含以下内容:
resp.status:响应状态码
resp.header:响应头,是一个table数据
resp.body:响应体,也就是数据
我们可以将http查询的请求封装为一个函数,放到OpenResty的库中后续可以之间使用,首先我们需要在对应的目录下创建common.lua文件,然后在该文件中封装该方法并导出
- -- 封装方法发送http请求
- local function read_http(path, params)
- local resp = ngx.location.capture(path,{
- method=ngx.HTTP_GET,
- args=params
- })
-
- -- 处理响应
- if not resp then
- -- 打印日志返回404
- ngx.log(ngx.ERR,"error")
- ngx.exit(404)
- end
- -- 返回数据
- return resp.body
- end
-
- -- 将方法导出
- local _M = {
- read_http = read_http
- }
- return _M
此时我们可以查询Tomcat中的信息
- -- 导入所需要的库
- local common = require('common')
- -- 序列化与反序列化库
- local cjson = require('cjson')
-
- -- 获取之前封装的方法
- local read_http = common.read_http
-
- -- 获取get请求里的id:/item?id=101
- local id = ngx.req.get_uri.args().id
-
- -- 查询Tomcat
- local itemJson = read_http("/item",id)
-
- -- 将Tomcat返回的json数据转为table类型
- local item = cjson.decode(itemJson)
-
- -- 给数据中加入一个属性比如状态:state=1
- item.state = 1
-
- -- 将数据转为json格式返回
- ngx.say(cjson.encode(item))
在多级缓存的实战中Tomcat不止一个通常会有集群,那么这个时候我们需要去配置负载均衡,那么 默认的轮询机制是否可以呢,假设此时有俩台Tomcat查询同一个id对应的信息按照轮询机制则两台Tomcat会各查询一次,也就是说JVM进程缓存会在两台Tomcat上缓存2次,但是这两个数据是同一个,这就导致Tomcat集群的性能低,那么我们可以不可以通过修改负载均衡的策略让同一id对应的请求去查询统一Tomcat呢,那么两次查询去同一给Tomcat,第二次之间从JVM进程缓存里获取提高性能。我们可以通过设置达到这样的效果
配置反向代理,将指定路径代理到Tomcat集群
location /path{
proxy_pass http://tomcat-cluster;
}
集群
upstream tomcat-cluster{
hash $request_uri;
server ip:端口
……
}
服务刚启动时,Redis中并没有缓存,如果所有的商品数据在第一次查询时添加缓存,则可能会给数据库带来比较大的压力,也叫做冷启动,在实际的开发过程中,通常会利用大数据统计用户访问的热点数据,在项目启动时将这些热点数据提前查询并缓存,这就是缓存预热
- @Component
- public class RedisHandler implements InitializingBean{
-
- @Autowired
- private StringRedisTemplate redis;
-
- @Override
- public void afterPropertiesSet(){
- // 查询数据库进行缓存
- }
-
- }
在上述我们了解了如何查询Tomcat,在业务中我们首先会去查询nginx的本地缓存,然后查询Redis缓存,如果都没有数据那才去查询Tomcat那么我们如何查询Redis呢,OpenResty提供了操作Redis的模块,我们只需要引入模块即可使用
-- 引入redis模块
local redis = require('resty.redis')
-- 初始化redis对象
local red = redis:new()
-- 配置redis超时时间
red:set_timeouts(1000,1000,1000)
接着我们可以继续在common.lua里封装redis的相关方法并导出
- -- 引入Redis模块
- local redis = require('resty.redis')
- local red = redis:new()
- red:set_tiemouts(1000,1000,1000)
-
- -- 封装关闭Redis连接的方法:放入连接池中
- local function close_redis(red)
- local pool_max_idle_tiem = 10000 -- 连接空闲时间
- local pool_size = 100 -- 连接最大数
- local ok,err = red:set_keepalive(pool_max_idle_time,pool_size)
- if not ok then
- ngx.log(ngx.ERR,'放入Redis连接池失败')
- end
- end
-
- -- 封装查询Redis方法
- local function read_redis(ip,port,key)
- -- 获取连接
- local ok,err = red:connect(ip, port)
- if not ok then
- ngx.log(ngx.ERR,"连接失败")
- return nil
- end
-
- -- 查询redis
- local resp,err = red:get(key)
- if not resp then
- ngx.log(ngx.ERR,"查询失败")
- end
-
- -- 处理数据为空
- if resp == ngx.null then
- resp = nil
- ngx.log(ngx.ERR,"查询为空")
- end
-
- -- 关闭连接
- close_redis(red)
- return resp
- end
-
-
- -- 封装方法发送http请求
- local function read_http(path, params)
- local resp = ngx.location.capture(path,{
- method=ngx.HTTP_GET,
- args=params
- })
-
- -- 处理响应
- if not resp then
- -- 打印日志返回404
- ngx.log(ngx.ERR,"error")
- ngx.exit(404)
- end
- -- 返回数据
- return resp.body
- end
-
- -- 将方法导出
- local _M = {
- read_http = read_http,
- read_redis = read_redis
- }
- return _M
OpenResty为nginx提供了shared dict的功能,可以在nginx的多个worker之间共享数据,实现缓存功能
首先我们需要开启共享词典,在nginx.conf的http下配置
lua_shared_dict cache 200m; # 名为cache 大小200m
然后我们可以在lua文件中编写业务
-- 获取本地缓存
local cache = ngx.shared.cachae
-- 存入,第三参数为过期时间单位是秒,默认是0永不过期
cache.set('key','value',1000)
-- 读取
local value = cache.get('key')
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。