vlambda博客
学习文章列表

分布式实战: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 里面抽取出来,保持代码的可读性和可维护性。归纳一下,一共包含三步:

  1. 创建工作目录;

  2. 修改 NGINX 的配置文件,把 Lua 代码嵌入其中;

  3. 启动 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上编写应用层的代码。