新年快樂~~~
上一篇文章講到使用多級緩存來減小數據庫的訪問來加快網頁的速度,只是,仍舊沒有「嗖」一下就加載出來的感受,想再優化一下,優化代碼什麼的已經到了極限。上週無心中看到了openresty,可以直接在nginx層直接對請求處理,而不須要每次都訪問tomcat,特別是對於本身的首頁http://www.wenzhihuai.com來講,因爲首頁內容普遍,須要涉及的方法太多,每次打開首頁都得耗費大量的時間。html
目前本人總共有三個服務器:
A:119.23.46.71(深圳,Nginx環境,本地Redis,tomcat服務器)
B:119.29.188.224(廣州,tomcat服務器)
C:47.95.10.139(北京,tomact服務器)
爲了減小後端的相應時間,以前使用的是在應用裏集成ehcache做爲一級緩存,redis做爲二級緩存。這種架構存在一種特殊的狀況:當Nginx將首頁的請求分發給北京節點的時候,響應將變得極其緩慢,用戶的請求須要從深圳到北京,再從北京回到深圳,光是延時就要耗費40ms(最好的狀況),因爲網速是1M/s,最壞的狀況下,響應用戶的請求也得耗費幾秒。因此,爲了減小這種極端狀況,設計了這款架構(我的項目隨便整整而已,怎麼來都行啦)。
因爲是博客類的項目,對於一致性要求並不高,因此乾脆直接將首頁緩存到Redis便可。
java
安裝過程能夠直接參考官方文檔:http://openresty.org/cn/download.html,安裝前還需安裝如下開發庫:nginx
yum install pcre-devel openssl-devel gcc curl
而後進行編譯安裝:git
tar -xzvf openresty-VERSION.tar.gz cd openresty-VERSION/ ./configure make sudo make install
Openresty自帶了Nginx。因此,只要安裝好了Openresty,便可直接使用nginx來配置。
如下只是部分,須要所有的請查看mynginxconfiggithub
http { include mime.types; default_type application/octet-stream; # 須要添加lua的相關庫 lua_package_path "/opt/openresty/lualib/?.lua;;"; lua_package_cpath "/opt/openresty/lualib/?.so;;"; ... access_log logs/access.log main; sendfile on; keepalive_timeout 65; upstream backend { #consistent_hash was not configured hash $uri; server 47.95.10.139:8080; server 119.23.46.71:8080; server 119.29.188.224:8080; } server { listen 80; server_name www.wenzhihuai.com; # 精確匹配,打開首頁的時候進入 location = / { default_type text/html; root html; index index.html index.htm; ... # 關閉緩存lua腳本,調試的時候專用 lua_code_cache off; content_by_lua_file /opt/lua/hello.lua; # 此處不要proxy_pass了,不然lua腳本沒用 # proxy_pass http://backend; } # 若是上面的不符合,則匹配下面的 location / { default_type text/html; root html; index index.html index.htm; # 對請求進行反向代理 proxy_pass http://backend; } } ... }
腳本記得放在/opt/lua/hello.lua目錄下,對應nginx的配置,同時須要引入redis模塊。redis
local redis = require "resty.redis" local red = redis:new() local request_uri = ngx.var.request_uri if (request_uri == "/" or request_uri == "/index.html") then red:set_timeout(1000) -- 1 sec red:connect("119.23.46.71", 6340) local ok, err = red:auth("root") if not ok then ngx.say("failed to connect: ", err) return end --緩存的首頁放在key爲index裏 local resp, errr = red:get("index") if not resp then return end if resp == ngx.null then resp = "<h1>hello world</h1>" end --若是找到,則輸出內容 ngx.print(resp) red:close() return end local pagenum = ngx.req.get_uri_args()["pagenum"] --由於在nginx中設置了proxy_pass_request_headers off,即不講請求頭部傳到lua,因此頭部須要從新設置 ngx.req.set_header("Accept", "text/html,application/xhtml+xml,application/xml;") --這裏回源到tomcat的時候,Accept-Encoding默認爲gzip,即返回來數據已是gzip壓縮過了的,返回到用戶的時候又被壓縮了一次,會形成一堆亂碼。因此將Accept-Encoding設置爲空。 ngx.req.set_header("Accept-Encoding", "") local respp = ngx.location.capture("/index.do", { method = ngx.HTTP_GET, args = { pagenum = pagenum } }) --打印 ngx.print(respp.body) return
每隔20秒直接訪問後端進行首頁的抓取,而後存儲到redis裏面,簡單粗暴。數據庫
@Controller @SuppressWarnings("unchecked") public class TimeController { //logger private static final Logger logger = LoggerFactory.getLogger(TimeController.class); @Scheduled(cron = "0/20 * * * * ?") public void refreshIndex() throws Exception { String ip = IPUtils.getServerIp().replaceAll("\n", ""); if (REGULARIP.equals(ip)) { String content = HttpHelper.getInstance().get("http://119.29.188.224:8080"); JedisUtil.getInstance().set("index", content); } } }
2018/02/10 18:53:51 [error] 2833#0: *3942 lua subrequests cycle while processing "/index.html", client: 113.108.186.130, server: www.wenzhihuai.com, request: "GET /index.html?pagenum=23 HTTP/1.1", subrequest: "/index.html", host: "www.wenzhihuai.com" 2018/02/10 18:53:51 [error] 2833#0: *3942 lua entry thread aborted: runtime error: /opt/lua/hello.lua:25: failed to issue subrequest: -1 stack traceback: coroutine 0: [C]: in function 'capture' /opt/lua/hello.lua:25: in function </opt/lua/hello.lua:1>, client: 113.108.186.130, server: www.wenzhihuai.com, request: "GET /index.html?pagenum=23 HTTP/1.1", subrequest: "/index.html", host: "www.wenzhihuai.com"
查了很久,才發現Openresty若是使用nginx.location.capture是從新請求一次的,若是帶有請求頭而且開啓了gzip壓縮,那麼數據就至關於被再次壓縮。
後端
解決辦法:去掉請求頭部
ngx.req.set_header("Accept-Encoding", "");緩存