分布式实战:Nginx缓存之OpenResty部署
本文首发于Ressmix个人站点:https://www.tpvlog.com
经过前面几章的讲解,我已经通过代码实现了三级缓存架构中的JVM本地缓存和Redis分布式缓存。本章,我将讲解最后的一层——Nginx缓存,我将使用OpenResty这个基于Nginx的开源框架,来实现请求分发和Nginx缓存。
一、基本架构
我先来讲解下整个Nginx集群的架构和部署,我会把Nginx集群分为两层:流量分发层和应用层。
流量分发层:用于根据请求的参数,计算路由信息(比如对商品ID哈希,计算路由信息),然后将请求分发到应用层;
应用层:用于实现多级缓存架构中的Nginx缓存,应用层包含了缓存的存取控制逻辑,同时会调用下游的真正应用服务。
我们来思考下,为什么要分这两层,而不是直接部署一个Nginx集群,采用Round-Robin之类的算法均匀分发请求至后端服务?
其实,主要的目的就是提升Niginx缓存命中率。如果只有一层Nginx集群,那么请求一般会均匀的分发到各个Nginx上,对于商品请求来说,同一个商品ID的多次不同请求,很可能第一次命中到A这台Nginx服务器,第二次命中到B这台Nginx服务器,导致重复两次生成Nginx缓存,缓存命中率下降。当商品数量非常多的情况下,很可能最终的结果就是每台Nginx上都保存了同一个商品的缓存。
有了流量分发层,我们就可以控制路由策略,让某些请求固定路由到下游指定的应用服务器,比如同一个商品ID,固定路由到同一台应用层Nginx服务器。
本章,我将把ressmix-dsf01作为流量分发层Nginx服务器,把ressmix-dsf02和ressmix-dsf03作为应用层Nginx服务器。生产环境中,Nginx服务器的数量需要你们自己根据系统的流量做好评估。
二、OpenResty部署
OpenResty是一个基于 NGINX 的开源框架,开发人员可以使用 Lua 脚本调动 Nginx 支持的各种 C 以及 Lua 模块。在性能方面,OpenResty可以快速构造出超高性能 Web 应用系统。
关于OpenResty是什么,读者可以先把它简单当成一个集成了Nginx的API网关,也可以先看看我的这篇文章,更过关于OpenResty的知识,可以参考网上的资料。
本节,我将在ressmix-dsf01、ressmix-dsf02、ressmix-dsf03上部署OpenResty。
2.1 OpenResty安装
首先,安装一些依赖:
1yum install readline-devel pcre-devel openssl-devel perl gcc
2yum install pcre-devel openssl-devel gcc curl
然后,从官方(https://openresty.org/cn/)下载最新的 OpenResty 源码包并解压、编译、安装:
1cd /usr/local
2wget https://openresty.org/download/openresty-1.15.8.3.tar.gz
3tar xzvf openresty-1.15.8.3.tar.gz
4cd openresty-1.15.8.3
5./configure
6make
7sudo make install
按照上述步骤,openresty程序会被安装到
/usr/local/openresty
目录,我们也可以通过指定--prefix=/usr/local/openresty
参数来自定义安装位置。
为了方便使用,我们添加openresty到.bashrc
环境变量中:
1export OPENRESTY_HOME=/usr/local/openresty
2export PATH=$OPENRESTY_HOME/bin:$OPENRESTY_HOME/nginx/sbin:$PATH
然后执行source ~/.bashrc
立即生效。
2.2 测试
安装成功后,我们来测试下OpenResty,首先建立一个项目工作目录,我这里取名为www
:
1mkdir -p /usr/local/www
2cd /usr/local/www
3mkdir logs/ conf/
接着,我们在 conf 目录下创建一个 nginx.conf
文件:
1worker_processes 1;
2error_log logs/error.log;
3events {
4 worker_connections 1024;
5}
6http {
7 server {
8 listen 80;
9 location /product {
10 default_type text/html;
11 content_by_lua_block {
12 ngx.say("<p>hello, world</p>")
13 }
14 }
15 }
16}
最后,启动openresty服务,如果没有任何输出,说明启动成功:
1openresty -p /usr/local/www -c /usr/local/www/conf/nginx.conf
这里要注意下,-p
用于指定我们的项目的根目录,-c
指定我们项目的配置文件,这两个环境变量后续都会用到。最后,我们可以通过curl验证下:
1[root@ressmix-dsf02 conf] curl http://localhost:8080
2<p>hello, world</p>
停止openresty服务可以通过命令
openresty -p /usr/local/www -c /usr/local/www/conf/nginx.conf -s stop
实现
2.3 模块化开发
上述我是直接把Lua脚本写在nginx.conf
配置中的,真正的OpenResty项目中,我们需要把 Lua 代码从 nginx.conf
里面抽取出来,保持代码的可读性和可维护性。归纳一下,一共包含三步:
创建工作目录;
修改 NGINX 的配置文件,把 Lua 代码嵌入其中;
启动 OpenResty 服务。
首先,我们在工作目录/usr/local/www/
下创建一个lua子目录,专门用来存放lua代码:
1cd /usr/local/www/
2mkdir lua
然后,在里面创建一个测试脚本——hello.lua
:
1ngx.say("hello, world")
修改 nginx.conf 的配置,把 content_by_lua_block
改为 content_by_lua_file
:
1worker_processes 1;
2error_log logs/error.log;
3events {
4 worker_connections 1024;
5}
6http {
7 server {
8 listen 80;
9 location /product {
10 default_type text/html;
11 content_by_lua_file lua/hello.lua;
12 }
13 }
14}
可以看到,content_by_lua_file指定的是一个相对路径,因为我们启动时会在-p
参数中带上项目的根路径。整体的项目目录结构如下:
1[root@ressmix-dsf01 www]# pwd
2/usr/local/www
3[root@ressmix-dsf01 www]# ls -al
4total 40
5drwxr-xr-x 10 root root 4096 Jun 2 02:05 .
6drwxr-xr-x. 9 root root 4096 Jun 2 01:08 ..
7drwxr-xr-x 2 root root 4096 Jun 2 02:09 conf
8drwxr-xr-x 2 root root 4096 Jun 2 03:18 logs
9drwxr-xr-x 2 root root 4096 Jun 2 02:07 lua
最后,启动 OpenResty 服务:
1openresty -p /usr/local/www -c /usr/local/www/conf/nginx.conf
然后再通过curl http://localhost/product
命令测试下就可以了。
我们也可以通过
openresty -s stop -p /usr/local/www
停止openresty服务,或者通过
三、总结
本章,我介绍了三级缓存架构中的Nginx缓存层的基本架构,我把它分为流量分发层和应用层。并且,我手把手带领搭建部署了OpenResty。下一章,我将在ressmix-dsf01上编写流量分发层的lua代码,在ressmix-dsf02、ressmix-dsf03上编写应用层的代码。