Kong网关:入门、实战与进阶
上QQ阅读APP看书,第一时间看更新

2.3 项目实践

在项目实践环节,我们会继续沿用第1章的待办任务列表Web应用示例。首先尝试将网关层组件从Kong切换到Nginx,看一下整体的效果变化;然后修改Nginx配置文件,添加黑白名单和限流功能,完善应用场景;最后将网关层组件从Nginx切换到Kong,同时保留这两项功能,对比一下这两个网关组件的异同点。

2.3.1 从Kong切换到Nginx

这里我们着重介绍Nginx的网关层功能,所以基于1.5.2节的示例进行改造,从Kong网关切换到Nginx,以达到同样的效果。项目目录结构调整为:


├── Readme.md
├── backend
├── docker-compose.yml
├── frontend
└── nginx-gateway

这里我们删除了原有的kong-gateway项目及里面的文件,新增了一个nginx-gateway项目。首先修改docker-compose.yml启动文件,将原先的Kong启动项配置修改为Nginx,如代码清单2-2所示。

程序清单2-2 Nginx启动项配置


24  ...
25  ...
26   nginx:
27     build:
28       context: ./nginx-gateway
29     container_name: nginx
30     ports:
31       - '8000:8000'
32     volumes:
33       - ./nginx-gateway:/etc/nginx/conf.d
34     depends_on:
35       - backend

新增的nginx-gateway项目中包含两个配置文件:dockerfile和nginx.conf,其中dockerfile配置文件如下:


# nginx dockerfile
FROM nginx:1.17.1

nginx.conf文件中增加了代理后端的一些相关配置,其中路由信息匹配的路径是/nginx/gateway/todos,对应的后端地址为http://backend:80/todos,这里我们将Nginx监听端口修改为8000(为了不与backend项目冲突)。nginx.conf配置文件如代码清单2-3所示。

程序清单2-3 nginx.conf配置文件


  1 server {
  2   listen       8000;
  3   server_name  _;
  4
  5   location / {
  6     root   /usr/share/nginx/html;
  7     index  index.html index.htm;
  8   }
  9   location /nginx/gateway/todos {
 10     proxy_pass http://backend:80/todos;
 11   }
 12 }

在完成网关层配置之后,我们还需要对之前的前端项目做一些简单修改(变更接口访问地址),将BACKEND_URL修改为http://127.0.0.1:8000/nginx/gateway/todos,其中127.0.0.1:8000为Nginx网关层入口地址,这样请求便可先抵达网关层,匹配路由后再转发至后端服务,如代码清单2-4所示。

程序清单2-4 对前端项目修改后的配置文件


  1 import Vue from 'vue';
  2 import BootstrapVue from 'bootstrap-vue';
  3 import axios from 'axios';
  4 import App from './App.vue';
  5
  6 const http = axios.create({
  7   baseURL: process.env.BACKEND_URL ? process.env.BACKEND_URL : 'http://
        127.0.0.1:8000/nginx/gateway/todos',
  8 });
  9
 10 Vue.prototype.$http = http;
 11
 12
 13 Vue.use(BootstrapVue);
 14
 15 Vue.config.productionTip = false;
 16
 17 new Vue({
 18   render: (h) => h(App),
 19 }).$mount('#app');

至此,项目已经改造完成。读者使用docker-compose up-d指令启动服务后,在浏览器内输入http://127.0.0.1:8000访问界面,可以观察到后端服务访问地址已经变更。效果如图2-3所示。

图2-3 Nginx网关页面控制台信息

2.3.2 添加黑白名单

在完成上述步骤后,我们对接口控制方案进行升级。首先引入黑白名单功能,这个功能在实际应用中非常常见,是接口管控的基本功能。在Nginx中添加黑白名单非常简单,只需在nginx.conf配置文件中添加代码清单2-5所示的代码。

程序清单2-5 在nginx.conf配置文件中添加黑名单


9 ...
10   proxy_pass   http://backend:80/todos;
11   deny         172.20.0.1;
11   allow        all;
12 ...

第11行代码表示该Nginx服务器的路由规则为此后不再接收IP地址为172.20.0.1的服务器(即frontend服务所在服务器)发出的任务请求。在2.3.1节中,我们没有对黑白名单做任何限制,默认允许所有请求访问。此时重启Nginx服务器,在浏览器中输入http://127.0.0.1:8000,发现原先正常的接口现在已经访问不通了,效果如图2-4所示。

图2-4 Nginx配置黑名单生效

接下来,我们再修改配置,仅允许前端项目通过网关层访问后端接口,如代码清单2-6所示。

程序清单2-6 nginx.conf配置文件配置白名单


 9 ...
 10   proxy_pass   http://backend:80/todos;
 11   allow        172.20.0.1;
 12   deny         all;
 13 ...

该配置中表示该Nginx服务器的路由规则为仅允许接收IP地址为172.20.0.1的服务器发出的请求。需要注意的是,在配置多规则情况下,Nginx默认自上而下读取规则,所以配置顺序不能写错,在配置较多规则时,可以使用ngx_http_geo_module模块变量。

2.3.3 添加限流

这一节中,我们继续在接口上添加限流功能。限流的目的在于防止恶意请求攻击和请求流量超过系统峰值,保障服务器可以正常运行。这里我们主要针对请求URI进行限流(不包括请求URI中的参数)。整体项目结构依旧不做更改,继续修改nginx.conf配置文件,如代码清单2-7所示。

程序清单2-7 在nginx.conf配置文件中添加限流功能


  1 limit_req_zone $uri zone=api_read:10m rate=3r/m;
  2
  3 server {
  4   listen       8000;
  5   server_name  _;
  6
  7   location / {
  8     root   /usr/share/nginx/html;
  9     index  index.html index.htm;
 10   }
 11   location /nginx/gateway/todos {
 12     proxy_pass http://backend:80/todos;
 13     limit_req zone=api_read;
 14     limit_req_status 503;
 15   }
 16 }

·第1行代码:表示根据请求URI,限制其请求速率为每分钟3次,zone为存储的空间,空间名为api_read,大小为10MB。

·第13行代码:表示在当前location配置块中使用这个限流组件。

·第14行代码:表示限流生效时返回的状态码(状态码可自定义,默认返回503)。

图2-5 Nginx限流效果

修改完成后,使用docker restart nginx指令使配置文件生效。打开浏览器访问http://127.0.0.1:8000,发现该接口已经无法正常访问,效果如图2-5所示。

但是,使用浏览器并不能直接地体会限流功能(也有可能是其他因素导致功能无法使用)。我们可以使用curl指令查看接口的响应状态码来分辨接口是否真被限流了。这里执行如下指令进行对比:


$ curl -I -m 10 -o /dev/null -s -w %{http_code} http://127.0.0.1:8000/
  nginx/gateway/todos/
200
$ curl -I -m 10 -o /dev/null -s -w %{http_code} http://127.0.0.1:8000/
  nginx/gateway/todos/
503

可以发现,第一次调用接口成功返回200,紧接着第二次调用接口返回503,表示该接口已经被限流。

2.3.4 从Nginx切换到Kong

在2.3.2节和2.3.3节中,我们已经使用Nginx服务器实现了简单的黑白名单和限流功能,本节我们将切换为Kong网关,看一下Kong网关是如何实现这些功能的。这里我们沿用1.5.2节中的案例,在此基础上进行改造。项目目录结构保持不变,修改其中的kong.yml配置文件,如代码清单2-8所示。

程序清单2-8 kong.yml配置文件


 14 ...
 15 plugins:
 16   - name: rate-limiting
 17     config:
 18       minute: 3
 19       policy: local
 20     route: route_todolists
 21   - name: ip-restriction
 22     config:
 23       whitelist: ["172.21.0.1"]
 24     route: route_todolists

在上述配置文件中,我们添加了名为rate-limiting和ip-restriction的插件(插件会在第11章做重点介绍),表示只允许访问172.21.0.1(即frontend地址),且每分钟只能访问3次。配置完成后,使用docker-compose up-d指令重新启动示例服务,在浏览器中输入http://127.0.0.1:8000,对比添加完插件之后接口响应内容与原先的差异。效果如图2-6和图2-7所示。

图2-6 Kong限流效果图一

图2-7 Kong限流效果图二

响应头中的X-RateLimit-Limit-Minute表示限流的次数,即每分钟3次;X-RateLimit-Remaining-Minute表示限流剩余的次数;RateLimit-Reset表示还需要多长时间才能重置限流插件、恢复访问,单位为秒。

2.3.5 小结

同第1章一样,笔者将上述三个示例都封装成独立的项目,运行docker-compose up-d指令即可启动。

我们从这几个例子中已经可以分辨出Kong网关与Nginx服务器之间的一些异同。首先,它们从大的功能层面上趋于一致,都能用比较简单的方式满足一般的定制化需求,但是在功能实现细节上略有不同。具体到限流插件,Nginx服务器配置每分钟访问3次,系统默认会将该配置转化为每20秒访问1次。Kong网关在限流上相对人性化,效果与预想的保持一致。再如黑白名单功能,Nginx支持更加灵活的设定,同时开放黑白名单功能,并全部交由开发者配置。Kong网关则在单个插件上仅支持黑名单或白名单,限定了使用场景。

这些功能点差异本身并没有优劣之分,用户仅需根据业务场景做出调整即可。