新年快乐~~~

上一篇文章讲到使用多级缓存来减少数据库的访问来加快网页的速度,只是,仍旧没有“嗖”一下就加载出来的感觉,想再优化一下,优化代码什么的已经到了极限。上周无意中看到了openresty,能够直接在nginx层直接对请求处理,而不需要每次都访问tomcat,特别是对于自己的首页http://www.wenzhihuai.com来说,由于首页内容广泛,需要涉及的方法太多,每次打开首页都得耗费大量的时间。

一、整体架构

目前本人总共有三个服务器:

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即可。

![](http://image.wenzhihuai.com/images/20180214105827.png)

步骤:
1.请求到达nginx后,openresty通过lua读取本地缓存,如果不命中,则回源到tomcat集群。
2.tomcat集群首先从自己的服务器中读取一级缓存Ehcache,如果没有命中,则继续回源到二级缓存。
3.读取二级缓存Redis,如果依旧没有命中,则回源到MySQL服务器。

二、配置过程

2.1 Openresty

安装过程可以直接参考官方文档:http://openresty.org/cn/download.html,安装前还需安装以下开发库:

yum install pcre-devel openssl-devel gcc curl

然后进行编译安装:

tar -xzvf openresty-VERSION.tar.gz
cd openresty-VERSION/
./configure
make
sudo make install

2.2 Nginx相关配置

Openresty自带了Nginx。所以,只要安装好了Openresty,即可直接使用nginx来配置。

以下只是部分,需要全部的请查看mynginxconfig

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;
}
}
...
}

2.3 lua脚本

脚本记得放在/opt/lua/hello.lua目录下,对应nginx的配置,同时需要引入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

2.4 更新首页到redis

每隔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);
}
}
}

碰到的问题

capture报错

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"

打开网页乱码,用curl正常显示

查了好久,才发现Openresty如果使用nginx.location.capture是重新请求一次的,如果带有请求头并且开启了gzip压缩,那么数据就相当于被再次压缩。

![](http://image.wenzhihuai.com/images/20180210073318.png)

解决办法:去掉请求头部

ngx.req.set_header("Accept-Encoding", "");

使用Openresty加快网页速度的更多相关文章

  1. Web 性能优化:21 种优化 CSS 和加快网站速度的方法

    这是 Web 性能优化的第 4 篇,上一篇在下面看点击查看: Web 性能优化:使用 Webpack 分离数据的正确方法 Web 性能优化:图片优化让网站大小减少 62% Web 性能优化:缓存 Re ...

  2. 简单几步优化你的windows,加快开机速度(重装windows之后要做的几件事)

    每个人都想要让自己的系统运行得快一些,开机快一些,我就来说说我自己的经验,我使用的系统是windows8.1,当然这有些方法也适用于其他的系统,我每次重装完系统之后第一件事就是下面几步,当然重装系统之 ...

  3. 慢腾腾的Quartus prime16.0加快编译速度

    前言 当一个工程反复修改的时候,可能有时候源代码没有更改,为了加快编译速度可以配置quartus一些选项.当然,初次编译的速度是否会提升,未验证.更高级的设计分区以及逻辑锁区提升速度,以后阐述. 流程 ...

  4. 在VisualGDB中配置预编译头加快编译速度

    今天是中秋佳节,但是写完已经是第二天凌晨了,还是祝大家中秋快乐! VS对C++的支持相较GCC太弱了,连续几个VS版本对C++的改进都很小.很少.对Cpper也许是一种痛,我们也许希望能使用VS的强大 ...

  5. Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...

  6. Android Studio 如何导出和导入自己的常用设置,避免重复制造轮子。加快开发速度

    Android Studio 如何导出和导入自己的常用设置,避免重复制造轮子.加快开发速度 作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 在使用 A ...

  7. 简单修改hosts文件加快打开网页速度

    这个电脑小技巧的帖子菲菲博客分享如何通过简单一招利用修改系统的hosts文件来实现有效加快浏览器打开网页的速度.尤其是网络繁忙时DNS服务器负担加重的时候效果特别明显,有兴趣就和菲菲一起来学习一下吧, ...

  8. IntelliJ下使用Code/Live Template加快编码速度:程序员的工作不是写程序,而是写程序解决问题

    程序员的工作不是写程序,而是写程序解决问题. --- 某不知名程序员 我们每天都在写代码,有些代码有结构性的相似,但不是所有的代码都可以被抽成方法.在这种情况下,我们应该考虑使用template的方式 ...

  9. 优化SQLServer数据库加快查询速度

    查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 ...

随机推荐

  1. 通俗理解TCP握手次数是三次

    理解之后,应该说是至少三次就可以保证可靠传输了. 看到网上一篇帖子http://www.cnblogs.com/TechZi/archive/2011/10/18/2216751.html是这么说的, ...

  2. IntelliJ IDEA 配置 smartGit

    教你如何在IntelliJ IDEA中配置smartGit? 一.第一种方式: 1.在启动IDEA工具时,点击下拉按钮"Check out from Version Control" ...

  3. 通过Git Gui Here上传本地项目到GitHub上

    要使用此种方法上传本地项目到GitHub上,前提得是你已安装Git for window工具. Git for window下载地址:http://www.xp510.com/xiazai/Appli ...

  4. Spark算子--join

      join--Transformation类算子 代码示例 result  

  5. DEDECMS中的几个常见的自定义常量DEDEMEMBER等位置

    http://www.dede58.com/a/dedejq/3567.html dedecms新建栏目时默认都是允许投稿的,可以投稿本来对网站来说是件好事,但是dedecms是开源的,使用太广泛了, ...

  6. 微信小程序版2048

    最近流行微信"跳一跳"小游戏,我也心血来潮写了一个微信小程序版2048,本篇文章主要分享实现2048的算法以及注意的点,一起来学习吧!(源码地址见文章末尾)   算法 1.生成4* ...

  7. vue 入门第一课

    windows安装git 安装淘宝镜像 npm install -g cnpm --registry=https://registry.npm.taobao.org 全局安装vue cnpm inst ...

  8. 7系列高速收发器总结 GTP IP核使用篇

    上一篇7系列收发器博文讲解了GTP IP核的基本配置,本文继续分析如何将它使用起来.生成IP核后打开example design,先看看工程中包含的文件结构. 顶层文件下包含了gtp ip核系统顶层文 ...

  9. SSH key introduction

    Preface At the first time, we take the connection with GitLab remote server. You need to type userna ...

  10. awk数组结合+=统计题

    awk增加统计列值为增加列数或进行运行结果统计,使用符号 + =.增加的结果赋给符号左边变量值,增加到变量的域在符号右边.例如将 $ 1加入变量total,表达式为toatl+=$1.列值增加很有用. ...