并发架构三

一个网站的性能好与坏,网络io和磁盘io这两块的影响是比较大的,现在引入缓存的目的是提高网站的性能,其实本质是不走磁盘走内存达到减少磁盘io提高性能的目的 加入缓存是减少的磁盘的io但是增加了网络io所以可以考虑把网络io也给优化优化 然后就引入了本地缓存(jvm缓存)

本地缓存(jvm缓存)

本地缓存用java的线程安全的hashmap可以实现 但是java没有给我实现淘汰策略 也就是只能正常的删除与添加 但是会有个别的数据不能删除 个别的数据可以删除 这样的场景java没有给我提供解决方案 这是需要我们自己写 然后谷歌实现了这种工具类

引入gava

com.google.guavaguava22

利用guava的缓存:它给我们实现了设置数据的过期时间 设置初始化空间大小 最大空间大小

com.tuling.tulingmall.component.LocalCache // 使用时百度它的api即可

布隆过滤器

布隆过滤器的使用方式 可以实现spring在启动时回调的方法 去访问数据库 把所有的主键查找出来 放到布隆过滤器中 这样布隆过滤器就有了数据库中所有的数据 当有人恶意攻击时 布隆过滤器中没有这个主键就给它返回一个错误信息 这样就很安全了 当添加了一条数据时再次调用布隆过滤器的添加方法把新的数据的主键放进去即可 布隆过滤器只保存key 不需要担心大key的问题 就一个数字不会占用很大的空间上亿的数据也就是十几m

现在我们给我们的应用程序加了两个缓存性能已经很高了 但是还是可以进一步的优化 一个程序是前端发送请求后端进行处理 然后可以在前端加上一层缓存 当前端发送请求的时候先访问它的缓存 如果没有再进入 服务器的缓存或数据库中拿取 实现方式 之前说的静态化处理 如果商品很多 生成文件同步文件就很慢 然后就可以利用Nginx加lua脚本实现前端的本地缓存进行进一步的性能提升 实现思路就是前端发送请求的时候是发到Nginx中 而Nginx是有一个缓存的 然后我们可以把这个缓存打开 然后利用lua脚本去这个缓存中拿数据 如果拿不到 就使用lua脚本访问我们的服务端拿数据然后再把数据放到Nginx的缓存中 并让lua脚本生成一个html 然后进行返回

动态的静态化可以使用OpenResty

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 等都进行一致的高性能响应。
官网:http://openresty.org/cn/

加入依赖

流量分发的nginx,会发送http请求到后端的应用层nginx上去,所以要先引入lua http lib包
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
最近网络不稳定,也可以从:https://github.com/bungle/lua-resty-template 去下载这两个lua脚本

文件放在:openresty-1.15.8.2-win642\lualib\resty // openresty-1.15.8.2-win642是openresty程序所在的目录

操作:
在nginx.conf文http模块中加入:
导入lua相关的包

lua_package_path '../lualib/?.lua;;'; 
lua_package_cpath '../lualib/?.so;;';
lua_package_path '../lualib/?.lua;;';
lua_package_cpath '../lualib/?.so;;';
include lua.conf;

lua.conf文件中

 server {listen 300;location /product {default_type 'text/html;charset=UTF-8';lua_code_cache on; // 开启缓存content_by_lua_file D:/ProgramData/nginx/dis.lua;}
}

我们监听300这个端口号,如果请求路径是product 那我们就让他包含dis.lua文件的内容
并且是开启lua缓存的哦

接下来我们来看下dis.lua脚本

dis.lua
local uri_args = ngx.req.get_uri_args() 
local productId = uri_args["productId"]
local host = {"127.0.0.1:222","127.0.0.1:333"} 
local hash = ngx.crc32_long(productId)
hash = (hash % 2) + 1
backend = "http://"..host[hash]
local method = uri_args["method"]
local requestBody = "/"..method.."?productId="..productId
local http = require("resty.http")  
local httpc = http.new()  local resp, err = httpc:request_uri(backend, {  method = "GET",  path = requestBody,keepalive=false
})if not resp then  ngx.say("request error :", err)  return  
endngx.say(resp.body)  httpc:close() 

这个文件大家看阅读下源码,大致意思就是截取传过来的productid 然后从我配置的host服务中hash取其中已一台服务,然后通过服务请求拿到相应的数据,然后对数据进行输出。

接下来我们再看下端口222和端口333这两个服务。我们来看下nginx.conf配置:

	lua_package_path '../lualib/?.lua;;';lua_package_cpath '../lualib/?.so;;';include lua.conf;

lua.conf 配置

lua_shared_dict my_cache 128m;server {listen 222;set $template_location "/templates";set $template_root "D:/ProgramData/nginx/";location /product {default_type 'text/html;charset=UTF-8';lua_code_cache on; content_by_lua_file D:/ProgramData/nginx/product.lua;}
}

请求后台:

product.lua
local uri_args = ngx.req.get_uri_args()
local productId = uri_args["productId"]
local productInfo = nil
if productInfo == "" or productInfo == nil thenlocal http = require("resty.http")local httpc = http.new()local resp, err = httpc:request_uri("http://127.0.0.1:8866",{method = "GET",path = "/pms/productInfo/"..productId})productInfo = resp.body
end
ngx.say(productInfo);

此时我们可以正常去访问后台,并且能拿到后台的数据,那我们请求都会请求到后台,那就没有起到作用了。

加入缓存(升级版):

product.lua
local uri_args = ngx.req.get_uri_args()
local productId = uri_args["productId"]
local cache_ngx = ngx.shared.my_cache
local productCacheKey = "product_info_"..productId
local productCache = cache_ngx:get(productCacheKey)
if productCache == "" or productCache == nil thenlocal http = require("resty.http")local httpc = http.new()local resp, err = httpc:request_uri("http://127.0.0.1:8866",{method = "GET",path = "/pms/productInfo/"..productId})productCache = resp.bodylocal expireTime = math.random(600,1200)cache_ngx:set(productCacheKey, productCache, expireTime)
endlocal cjson = require("cjson")
local productCacheJSON =cjson.decode(productCache) 
ngx.say(productCache);
local context = {id = productCacheJSON.data.id,name = productCacheJSON.data.name,price = productCacheJSON.data.price,pic = productCacheJSON.data.pic,detailHtml = productCacheJSON.data.detailHtml
}
local template = require("resty.template")
template.render("product.html", context)html模板:

商品id: {* id *}
商品名称: {* name *}
商品价格: {* price *}
商品库存:
商品描述: {* detailHtml *}

这样就有三层缓存了

Nginx一层、jvm本地缓存、redis


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部