最近,我有幸接触到 medcl 大神的杰作:极限网关(INFINI GATEWAY)。INFINI Gateway 有很多优点,也有很多应用的场景。你可以在官方网站上进行阅读。简单说来,极限网关(INFINI Gateway)是一个面向 Elasticsearch 的高性能应用网关,它包含丰富的特性,使用起来也非常简单。极限网关工作的方式和普通的反向代理一样,我们一般是将网关部署在 Elasticsearch 集群前面, 将以往直接发送给 Elasticsearch 的请求都发送给网关,再由网关转发给请求到后端的 Elasticsearch 集群。因为网关位于在用户端和后端 Elasticsearch 之间,所以网关在中间可以做非常多的事情, 比如可以实现索引级别的限速限流、常见查询的缓存加速、查询请求的审计、查询结果的动态修改等等。
INFINI Gateway 它是如何和其它软件栈进行集成的呢?根据官方的介绍,网关通常是以这样的形式来进行接入的:
如上所示,INFINI 网关针对所有的请求是透明的。我们原本的发向 Elasticsearch 的请求,现在只要提交给网关就可以了。对于客户端开发者来说,你无需了解网关后面是如何连接 Elasticsearch 的。网关位于 Elasticsearch 的前端。所有的请求都发向网关,再由网关进行转发到 Elasticsearch。当然它不是简单的转发,它可以把请求分发至各个 Elasticsearch 节点或不同的 Elasticsearch 集群,也可以针对请求依据一些规则进行修改或者拒绝等操作,或者针对 _bulk 请求进行分析来提高摄入数据的速度。网关还可以实现负载均衡的功能,限流,使用 cache,甚至针对请求进行分析。也可以依据一定的条件进行修改或聚合来自其它数据源的数据。根据测评,极限网关相比同类主流网关类产品速度快 20% 以上。它对 Elasticsearch 做了细致的优化,并使得写入和查询的速度得到成倍的提升。
如上所示,在上面的架构中还采用了 VIP(浮动 IP)。我们可以在系统中部署2个 INFINI Gateway。一旦其中的一个由于一些原因不能正常工作,那么另外一个就会自动接管,从而避免 single point of failure。
在今天的展示中,我将使用最新的 Elastic Stack 8.1 来进行展示。
安装
Elastic Stack
如果你还没安装好自己的 Elasticsearch 及 Kibana,那么请参阅文章:
特别地,你可以参考如下的文章来安装好 Elastic Stack 8.1:
当我们安装好自己的 Elasticsearch 后,我们可以使用如下的方式来进行查看:
curl -k -u elastic:_3DAof2=LryludRa5Zho -XGET "https://192.168.0.3:9200/"
1. $ curl -k -u elastic:_3DAof2=LryludRa5Zho -XGET "https://192.168.0.3:9200/"
2. {
3. "name" : "liuxgm.local",
4. "cluster_name" : "elasticsearch",
5. "cluster_uuid" : "SNZ_-EOOR8-tdb-I-BG_jA",
6. "version" : {
7. "number" : "8.1.1",
8. "build_flavor" : "default",
9. "build_type" : "tar",
10. "build_hash" : "d0925dd6f22e07b935750420a3155db6e5c58381",
11. "build_date" : "2022-03-17T22:01:32.658689558Z",
12. "build_snapshot" : false,
13. "lucene_version" : "9.0.0",
14. "minimum_wire_compatibility_version" : "7.17.0",
15. "minimum_index_compatibility_version" : "7.0.0"
16. },
17. "tagline" : "You Know, for Search"
18. }
请注意上面的 _3DAof2=LryludRa5Zho 是我的集群超级用户 elastic 的密码,而 192.168.0.3 是我的 Elasticsearch 的访问地址。
INFINI Gateway
安装 INFINI Gateway 也非常简单。我们需要去 release.infinilabs.com 去下载我们需要的版本。
我们选择 gateway:
也许我比较喜欢尝鲜,我选择 snapshot。这里有每天的一个 build。它含有最新的功能,虽然可能会有 bug:
对于我的苹果电脑 Apple chipset 来说,我选择如上所示的 mac-arm6 版本。我们使用如下的命令来进行解压缩:
unzip gateway-1.6.0_SNAPSHOT-591-mac-arm64.zip
1. $ pwd
2. /Users/liuxg/gateway
3. $ ls -al
4. total 49976
5. drwxr-xr-x 6 liuxg staff 192 Apr 6 09:44 .
6. drwxr-xr-x+ 159 liuxg staff 5088 Apr 6 09:43 ..
7. -rw-r--r--@ 1 liuxg staff 6176162 Mar 24 15:21 gateway-1.6.0_SNAPSHOT-591-mac-arm64.zip
8. -rwxr-xr-x@ 1 liuxg staff 19401090 Mar 23 19:06 gateway-mac-arm64
9. -rw-r--r--@ 1 liuxg staff 4290 Mar 23 19:04 gateway.yml
10. drwxr-xr-x@ 21 liuxg staff 672 Mar 20 23:42 sample-configs
如上所示,当解压缩后,它含有一个默认的 gateway.yml 配置文件。它还含有一个 sample-configs 目录。这个目录含有多个实例配置文件。我们在命令行中运行 gateway:
gateway-mac-arm64 --help
1. $ pwd
2. /Users/liuxg/gateway
3. $ ls -al
4. total 49976
5. drwxr-xr-x 6 liuxg staff 192 Apr 6 09:44 .
6. drwxr-xr-x+ 159 liuxg staff 5088 Apr 6 09:43 ..
7. -rw-r--r--@ 1 liuxg staff 6176162 Mar 24 15:21 gateway-1.6.0_SNAPSHOT-591-mac-arm64.zip
8. -rwxr-xr-x@ 1 liuxg staff 19401090 Mar 23 19:06 gateway-mac-arm64
9. -rw-r--r--@ 1 liuxg staff 4290 Mar 23 19:04 gateway.yml
10. drwxr-xr-x@ 21 liuxg staff 672 Mar 20 23:42 sample-configs
11. $ ./gateway-mac-arm64 --help
12. Usage of ./gateway-mac-arm64:
13. -config string
14. the location of config file, default: gateway.yml (default "gateway.yml")
15. -debug
16. run in debug mode, gateway will quit with panic error
17. -log string
18. the log level, options: trace,debug,info,warn,error (default "info")
19. -service string
20. service management, options: install,uninstall,start,stop
21. -v version
如上所示,我们可以把 gateway 以 service 的方式来进行运行,这样当我们的系统启动后,我们不再需要手动来启动 gateway。在 macOS 下,我们可以这样运行:
sudo ./gateway-mac-arm64 -service install
1. $ sudo ./gateway-mac-arm64 -service install
2. Password:
3. Success
我们可以通过如下的方式来禁止以服务的方式来运行:
sudo ./gateway-mac-arm64 -service uninstall
1. $ sudo ./gateway-mac-arm64 -service uninstall
2. Success
当然,我们也可以使用 start 及 stop 选项来启动或停止服务的运行。
这样我们的安装就完成了。
运行 Gateway 的方式
我们有两种方式来运行 Gateway:
./gateway-mac-arm64
如果以这样的方式来运行 gateway,那么它的默认配置文件是在该目录下的 gateway.yml 文件:
1. $ pwd
2. /Users/liuxg/gateway
3. $ ls
4. gateway-1.6.0_SNAPSHOT-591-mac-arm64.zip log
5. gateway-mac-arm64 sample-configs
6. gateway.yml
另外,我们也可以通过如下的方式来进行运行:
./gateway-mac-arm64 -config ./sample-configs/hello_world.yml
在上面,我们指定了一个配置文件。
1. $ ./gateway-mac-arm64 -config ./sample-configs/hello_world.yml
3. ___ _ _____ __ __ __ _
4. / _ \ /_\ /__ \/__\/ / /\ \ \/_\ /\_/\
5. / /_\///_\\ / /\/_\ \ \/ \/ //_\\\_ _/
6. / /_\\/ _ \/ / //__ \ /\ / _ \/ \
7. \____/\_/ \_/\/ \__/ \/ \/\_/ \_/\_/
9. [GATEWAY] A light-weight, powerful and high-performance elasticsearch gateway.
10. [GATEWAY] 1.6.0_SNAPSHOT, 2022-03-23 11:04:26, 2023-12-31 10:10:10, 6c3c047b27d353696da1454fc71bcc564103bf2f
11. [04-06 10:23:58] [INF] [app.go:174] initializing gateway.
12. [04-06 10:23:58] [INF] [app.go:175] using config: /Users/liuxg/gateway/sample-configs/hello_world.yml.
13. [04-06 10:23:58] [INF] [instance.go:72] workspace: /Users/liuxg/gateway/data/gateway/nodes/c96fjfl9so256esepqp0
14. [04-06 10:23:58] [INF] [app.go:283] gateway is up and running now.
15. [04-06 10:23:58] [INF] [api.go:262] api listen at: http://0.0.0.0:2900
16. [04-06 10:23:58] [INF] [entry.go:302] entry [my_es_entry] listen at: http://0.0.0.0:8000
17. [04-06 10:23:58] [INF] [module.go:116] all modules are started
上面的 hello_world.yml 文件非常简单:
sample-configs/hello_world.yml
1. path.data: data
2. path.logs: log
4. entry:
5. - name: my_es_entry
6. enabled: true
7. router: my_router
8. max_concurrency: 200000
9. network:
10. binding: 0.0.0.0:8000
12. flow:
13. - name: hello_world
14. filter:
15. - echo:
16. message: "hello world"
17. router:
18. - name: my_router
19. default_flow: hello_world
解释:
- 上面的 path.data 定义的是 data 的路径。比如在当前的 gateway 安装目录下,含有一个叫做 data 的目录。
- 上面的 path.logs 定义的是 日志的路径。如上所示,我们可以看到一个叫做 log 的目录。
- entry:定义网关的请求入口,极限网关支持 HTTP 和 HTTPS 两种模式,HTTPS 可以自动生成证书。可以有多个 entry。
- router:义请求的路由规则,根据 Method 和请求地址来进行路由到指定的 Flow 处理流程里面去。
- flow:定义数据的处理逻辑,每个请求会经过一系列的 Filter 操作,Flow 用来将这些 Filter 组织起来。
- filter:由若干个不同的 Filter 组件构成,每个 Filter 在设计的时候只处理一件事情,通过多个 Filter 组成变成一个 Flow。
整个极限网关的数据流是这样的:
从上面的流中,我们可以看出来,数据是从 entry 进入,然后由 router 流向 flow。每个 flow 又含有各个不同的 filters。每个 filter 都有自己独特的功能。
我们下面来做一个简单的测试。如上面 gateway 启动的画面显示所示,我们看到 gateway 是在端口 0.0.0.0:8000 侦听的。0.0.0.0 意味着它绑定了当前电脑的所有网络接口。我们可以通过如下的命令来获得所有当前电脑的网络接口:
ifconfig
一般来说,它绑定了当前电脑的 localhost 及 privateIP 地址。我们使用如下的方式来访问 gateway:
1. $ curl http://localhost:8000
2. hello world$
从上面,我们可以看出来。这个是一个简单的 echo 命令。它返回 hello world。这说明我们的 gateway 的安装是没有任何问题的。细心的开发者发现 hello world 是没有换行符的。我们可以重新修正 hello_world.yml 文件如下:
sample-configs/hello_world.yml
1. path.data: data
2. path.logs: log
4. entry:
5. - name: my_es_entry
6. enabled: true
7. router: my_router
8. max_concurrency: 200000
9. network:
10. binding: 0.0.0.0:8000
12. flow:
13. - name: hello_world
14. filter:
15. - echo:
16. message: "hello world\n"
17. router:
18. - name: my_router
19. default_flow: hello_world
我们在上面的 message 中添加了一个换行符。重新启动 gateway,并再次运行上面的 curl 指令:
1. $ curl http://localhost:8000
2. hello world
这次,我们可以看到自动换行了。
如何连接到 Elasticsearch 和 Kibana
连接到 Elasticsearch 集群
我们可以参阅在安装目录中的 sample-configs/elasticsearch-proxy.yml 文件。如果你想创建多个节点的集群,请参阅我之前的文章 “Elasticsearch:在多个机器上创建多节点的 Elasticsearch 集群 - Elastic Stack 8.0”。我们可以通过如下的命令来验证集群含有的节点:
curl --insecure -u elastic:u7-KUuNhF2DcGCCtugU0 -XGET "https://192.168.0.3:9200/_cat/nodes"
1. $ curl --insecure -u elastic:u7-KUuNhF2DcGCCtugU0 -XGET "https://192.168.0.3:9200/_cat/nodes"
2. 192.168.0.3 3 100 15 4.41 cdfhilmrstw * liuxgm.local
3. 192.168.0.8 19 97 6 0.57 0.35 0.30 cdfhilmrstw - liuxg
在上面,它显示是有两个节点组成的集群。我们可以修改 elasticsearch-proxy.yml 文件如下:
sample-configs/elasticsearch-proxy.yml
1. path.data: data
2. path.logs: log
4. entry:
5. - name: my_es_entry
6. enabled: true
7. router: my_router
8. max_concurrency: 10000
9. network:
10. binding: 0.0.0.0:8000
12. flow:
13. - name: es-flow
14. filter:
15. - elasticsearch:
16. elasticsearch: es-server
18. router:
19. - name: my_router
20. default_flow: es-flow
22. elasticsearch:
23. - name: es-server
24. enabled: true
25. endpoints:
26. - https://192.168.0.3:9200
27. - https://192.168.0.8:9200
28. basic_auth:
29. username: elastic
30. password: u7-KUuNhF2DcGCCtugU0
请注意上面的 password 配置。你需要根据自己的设置而改变。
我们使用如下的方法来启动 gateway:
./gateway-mac-arm64 -config ./sample-configs/elasticsearch-proxy.yml
1. $ ./gateway-mac-arm64 -config ./sample-configs/elasticsearch-proxy.yml
3. ___ _ _____ __ __ __ _
4. / _ \ /_\ /__ \/__\/ / /\ \ \/_\ /\_/\
5. / /_\///_\\ / /\/_\ \ \/ \/ //_\\\_ _/
6. / /_\\/ _ \/ / //__ \ /\ / _ \/ \
7. \____/\_/ \_/\/ \__/ \/ \/\_/ \_/\_/
9. [GATEWAY] A light-weight, powerful and high-performance elasticsearch gateway.
10. [GATEWAY] 1.6.0_SNAPSHOT, 2022-03-23 11:04:26, 2023-12-31 10:10:10, 6c3c047b27d353696da1454fc71bcc564103bf2f
11. [04-06 12:26:45] [INF] [app.go:174] initializing gateway.
12. [04-06 12:26:45] [INF] [app.go:175] using config: /Users/liuxg/gateway/sample-configs/elasticsearch-proxy.yml.
13. [04-06 12:26:45] [INF] [instance.go:72] workspace: /Users/liuxg/gateway/data/gateway/nodes/c96fjfl9so256esepqp0
14. [04-06 12:26:45] [INF] [app.go:283] gateway is up and running now.
15. [04-06 12:26:45] [INF] [api.go:262] api listen at: http://0.0.0.0:2900
16. [04-06 12:26:45] [INF] [entry.go:302] entry [my_es_entry] listen at: http://0.0.0.0:8000
17. [04-06 12:26:45] [INF] [module.go:116] all modules are started
18. [04-06 12:26:45] [INF] [actions.go:280] elasticsearch [es-server] is available
如上所示,它显示 elasticsearch [es-server] is available 这个信息。如果你没有看到这个信息,则表明你的配置是有问题的。
为了能够通过 gateway 访问 Elasticsearch,我们通过如下的方式来进行访问。首先,我们把 Elasticsearch 安装目录下的证书文件拷贝过。这个证书在如下的地址:
1. $ pwd
2. /Users/liuxg/elastic/elasticsearch-8.1.1
3. $ ls config/certs/
4. http.p12 http_ca.crt transport.p12
在上面,显示的 http_ca.crt 就是所需要的证书。我们拷贝到下述命令运行的目录中,然后运行:
1. $ pwd
2. /Users/liuxg/gateway
3. $ ls
4. data http_ca.crt
5. gateway-1.6.0_SNAPSHOT-591-mac-arm64.zip log
6. gateway-mac-arm64 sample-configs
7. gateway.yml
8. $ curl --cacert ./http_ca.crt -u elastic:u7-KUuNhF2DcGCCtugU0 http://0.0.0.0:8000
9. {
10. "name" : "liuxg",
11. "cluster_name" : "elasticsearch",
12. "cluster_uuid" : "53aivEciQ-28pjjkYR-qlQ",
13. "version" : {
14. "number" : "8.1.2",
15. "build_flavor" : "default",
16. "build_type" : "deb",
17. "build_hash" : "31df9689e80bad366ac20176aa7f2371ea5eb4c1",
18. "build_date" : "2022-03-29T21:18:59.991429448Z",
19. "build_snapshot" : false,
20. "lucene_version" : "9.0.0",
21. "minimum_wire_compatibility_version" : "7.17.0",
22. "minimum_index_compatibility_version" : "7.0.0"
23. },
24. "tagline" : "You Know, for Search"
25. }
如果你看到上面的输出则标明你的配置是成功的。我们可以通过如下的方法来获得所有的节点:
1. $ curl --cacert ./http_ca.crt -u elastic:u7-KUuNhF2DcGCCtugU0 http://0.0.0.0:8000/_cat/nodes
2. 192.168.0.3 4 99 12 4.25 cdfhilmrstw * liuxgm.local
3. 192.168.0.8 21 98 4 0.05 0.06 0.12 cdfhilmrstw - liuxg
由于是自签名证书,我们也可以使用如下的方式来获得:
1. $ curl -k -u elastic:u7-KUuNhF2DcGCCtugU0 http://0.0.0.0:8000/_cat/nodes
2. 192.168.0.3 4 99 15 3.93 cdfhilmrstw * liuxgm.local
3. 192.168.0.8 27 98 4 0.01 0.05 0.11 cdfhilmrstw - liuxg
或者:
1. $ curl --insecure -u elastic:u7-KUuNhF2DcGCCtugU0 http://0.0.0.0:8000/_cat/nodes
2. 192.168.0.8 28 98 4 0.01 0.04 0.10 cdfhilmrstw - liuxg
3. 192.168.0.3 4 99 15 8.63 cdfhilmrstw * liuxgm.local
之前没有网关的情况下,我们的请求都发向 Elasticsearch 的集群。现在有了网关的存在,我们直接把请求发向网关的地址就可以了。
连接到 Kibana
如同在文章一开始的架构图中所示,我们也可以把 Kibana 接入到 gateway 上去。我们按照通常的方法来安装 Kibana。具体步骤可以参阅文章 “Elasticsearch:在多个机器上创建多节点的 Elasticsearch 集群 - Elastic Stack 8.0”。为了测试方便,我们需要在 config/kibana.yml 文件中做如下的改动:
server.host: "0.0.0.0"
把 Kibana 绑定于电脑所有的网络接口上。我们可以通过 localhost:5601 及 privateIP:5601 的格式进行访问。
我们创建如下的一个 gateway.yml 文件:
1. path.data: data
2. path.logs: log
4. entry:
5. - name: my_es_entry
6. enabled: true
7. router: my_router
8. max_concurrency: 10000
9. network:
10. binding: 0.0.0.0:8000
11. - name: my_kibana_entry
12. enabled: true
13. router: my_kibana_router
14. network:
15. binding: 0.0.0.0:5602
17. flow:
18. - name: es-flow
19. filter:
20. - elasticsearch:
21. elasticsearch: es-server
22. - name: logout_flow
23. filter:
24. - set_response:
25. status: 401
26. body: "Success logout!"
27. - drop:
28. - name: replace_logo_flow
29. filter:
30. - redirect:
31. uri: https://elasticsearch.cn/uploads/event/20211120/458c74ca3169260dbb2308dd06ef930a.png
32. - name: kibana_flow
33. filter:
34. - basic_auth:
35. valid_users:
36. elastic: u7-KUuNhF2DcGCCtugU0 # super user elastic account
37. - http:
38. schema: "http" #https or http
39. host: "192.168.0.3:5601"
41. router:
42. - name: my_router
43. default_flow: es-flow
44. - name: my_kibana_router
45. default_flow: kibana_flow
46. rules:
47. - method:
48. - GET
49. - POST
50. pattern:
51. - "/_logout"
52. flow:
53. - logout_flow
54. - method:
55. - GET
56. pattern:
57. - "/plugins/kibanaReact/assets/illustration_integrations_lightmode.svg"
58. flow:
59. - replace_logo_flow
61. elasticsearch:
62. - name: es-server
63. enabled: true
64. endpoints:
65. - https://192.168.0.3:9200
66. - https://192.168.0.8:9200
67. basic_auth:
68. username: elastic
69. password: u7-KUuNhF2DcGCCtugU0
请注意我在上面使用了超级用户 elastic 来配置 Kibana。在实际的使用中,我们可以使用创建的账号来访问 Kibana。
我们使用如下的方法来启动 gateway:
./gateway-mac-arm64
我们可以看到:
1. $ ./gateway-mac-arm64
3. ___ _ _____ __ __ __ _
4. / _ \ /_\ /__ \/__\/ / /\ \ \/_\ /\_/\
5. / /_\///_\\ / /\/_\ \ \/ \/ //_\\\_ _/
6. / /_\\/ _ \/ / //__ \ /\ / _ \/ \
7. \____/\_/ \_/\/ \__/ \/ \/\_/ \_/\_/
9. [GATEWAY] A light-weight, powerful and high-performance elasticsearch gateway.
10. [GATEWAY] 1.6.0_SNAPSHOT, 2022-03-23 11:04:26, 2023-12-31 10:10:10, 6c3c047b27d353696da1454fc71bcc564103bf2f
11. [04-06 13:36:39] [INF] [app.go:174] initializing gateway.
12. [04-06 13:36:39] [INF] [app.go:175] using config: /Users/liuxg/gateway/gateway.yml.
13. [04-06 13:36:39] [INF] [instance.go:72] workspace: /Users/liuxg/gateway/data/gateway/nodes/c96fjfl9so256esepqp0
14. [04-06 13:36:39] [INF] [app.go:283] gateway is up and running now.
15. [04-06 13:36:39] [INF] [api.go:262] api listen at: http://0.0.0.0:2900
16. [04-06 13:36:39] [INF] [entry.go:302] entry [my_es_entry] listen at: http://0.0.0.0:8000
17. [04-06 13:36:39] [INF] [entry.go:302] entry [my_kibana_entry] listen at: http://0.0.0.0:5602
18. [04-06 13:36:39] [INF] [module.go:116] all modules are started
19. [04-06 13:36:39] [INF] [actions.go:280] elasticsearch [es-server] is available
从上面我们可以看到有两个 entry:my_es_entry 及 my_kibana_entry。
如何调试
在上面,我只对 gateway 的一个安装做了简单的介绍。在 gateway 的官方网站中,有许多的过滤器。这些是在请求发向 Elasticsearh 之前可以在网关做很多额外工作的地方。在开发的过程中,有一个良好的调试工具会给我们的开发带来很多的好处。在上面,我们除了可以使用 echo 来输出一些文字之外,我们还可以通过 dump 指令来查看请求及响应的内容。
下面,我们来做一个简单的展示。首先我们在 Elasticsearch 中创建如下的一个索引:
1. PUT twitter/_doc/1
2. {
3. "name": "liuxg",
4. "company": "elastic"
5. }
我们可以做如上所示的搜索:
1. GET twitter/_search
2. {
3. "query": {
4. "match": {
5. "name": "liuxg"
6. }
7. }
8. }
我们按照上面的方法点击 Copy as cURL。我们把拷贝下来的内容放入到下面的 curl 指令中去:
1. curl --insecure -u elastic:u7-KUuNhF2DcGCCtugU0 -XGET "http://0.0.0.0:8000/twitter/_search" -H 'Content-Type: application/json' -d'
2. {
3. "query": {
4. "match": {
5. "name": "liuxg"
6. }
7. }
8. }'
上面的结果为:
1. $ curl --insecure -u elastic:u7-KUuNhF2DcGCCtugU0 -XGET "http://0.0.0.0:8000/twitter/_search" -H 'Content-Type: application/json' -d'
2. > {
3. > "query": {
4. > "match": {
5. > "name": "liuxg"
6. > }
7. > }
8. > }'
9. {"took":2,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":1,"relation":"eq"},"max_score":0.2876821,"hits":[{"_index":"twitter","_id":"1","_score":0.2876821,"_source":{
10. "name": "liuxg",
11. "company": "elastic"
12. }
13. }]}
显然这个是我们想要的结果。
到目前位置,结果非常完美。我们可以使用 dump 过滤器来展示很多的细节。我们接着修改上面的 gateway.yml 文件。
gateway.yml
1. path.data: data
2. path.logs: log
4. entry:
5. - name: my_es_entry
6. enabled: true
7. router: my_router
8. max_concurrency: 10000
9. network:
10. binding: 0.0.0.0:8000
11. - name: my_kibana_entry
12. enabled: true
13. router: my_kibana_router
14. network:
15. binding: 0.0.0.0:5602
17. flow:
18. - name: es-flow
19. filter:
20. - echo:
21. message: "Before ES request\n"
22. - dump:
23. uri: true
24. request_header: true
25. request_body: true
26. response_body: true
27. status_code: true
28. context:
29. - _ctx.id
30. - _ctx.tls
31. - _ctx.remote_addr
32. - _ctx.local_addr
33. - _ctx.request.host
34. - _ctx.request.method
35. - _ctx.request.uri
36. - _ctx.request.path
37. - _ctx.request.body
38. - _ctx.request.body_length
39. - _ctx.request.query_args.from
40. - _ctx.request.query_args.size
41. - _ctx.request.header.Accept
42. - _ctx.request.user
43. - _ctx.response.status
44. - _ctx.response.body
45. - _ctx.response.content_type
46. - _ctx.response.body_length
47. - _ctx.response.header.Env
48. - elasticsearch:
49. elasticsearch: es-server
50. - echo:
51. message: "After ES request\n"
52. - dump:
53. uri: true
54. request_header: true
55. request_body: true
56. response_body: true
57. status_code: true
58. context:
59. - _ctx.id
60. - _ctx.tls
61. - _ctx.remote_addr
62. - _ctx.local_addr
63. - _ctx.request.host
64. - _ctx.request.method
65. - _ctx.request.uri
66. - _ctx.request.path
67. - _ctx.request.body
68. - _ctx.request.body_length
69. - _ctx.request.query_args.from
70. - _ctx.request.query_args.size
71. - _ctx.request.header.Accept
72. - _ctx.request.user
73. - _ctx.response.status
74. - _ctx.response.body
75. - _ctx.response.content_type
76. - _ctx.response.body_length
77. - _ctx.response.header.Env
79. - name: logout_flow
80. filter:
81. - set_response:
82. status: 401
83. body: "Success logout!"
84. - drop:
85. - name: replace_logo_flow
86. filter:
87. - redirect:
88. uri: https://elasticsearch.cn/uploads/event/20211120/458c74ca3169260dbb2308dd06ef930a.png
89. - name: kibana_flow
90. filter:
91. - basic_auth:
92. valid_users:
93. elastic: u7-KUuNhF2DcGCCtugU0 # super elastic account
94. - http:
95. schema: "http" #https or http
96. host: "192.168.0.3:5601"
98. router:
99. - name: my_router
100. default_flow: es-flow
101. - name: my_kibana_router
102. default_flow: kibana_flow
103. rules:
104. - method:
105. - GET
106. - POST
107. pattern:
108. - "/_logout"
109. flow:
110. - logout_flow
111. - method:
112. - GET
113. pattern:
114. - "/plugins/kibanaReact/assets/illustration_integrations_lightmode.svg"
115. flow:
116. - replace_logo_flow
118. elasticsearch:
119. - name: es-server
120. enabled: true
121. endpoints:
122. - https://192.168.0.3:9200
123. - https://192.168.0.8:9200
124. basic_auth:
125. username: elastic
126. password: u7-KUuNhF2DcGCCtugU0
在上面,请注意 echo 和 dump 过滤器的部分。我们分别在 Elasticsearch 请求前后 dump 请求及响应的值。我们重新运行 gateway:
./gateway-mac-arm64
我们在 gateway 的 console 里可以看到如下的输出:
接下来,我们再创建一个文档:
1. PUT twitter/_doc/2
2. {
3. "name": "zhang san",
4. "company": "elastic"
5. }
如果我们使用如下的方式来搜索的话,应该是两个文档:
1. GET twitter/_search?filter_path=**.hits
2. {
3. "query": {
4. "match": {
5. "company": "elastic"
6. }
7. }
8. }
上面返回的结果将会是:
1. {
2. "hits" : {
3. "hits" : [
4. {
5. "_index" : "twitter",
6. "_id" : "1",
7. "_score" : 0.13353139,
8. "_source" : {
9. "name" : "liuxg",
10. "company" : "elastic"
11. }
12. },
13. {
14. "_index" : "twitter",
15. "_id" : "2",
16. "_score" : 0.13353139,
17. "_source" : {
18. "name" : "zhang san",
19. "company" : "elastic"
20. }
21. }
22. ]
23. }
24. }
接下来,我们来尝试修改请求,不管在任何情况下,返回的结果只有一个。我们修改 gateway.yml 文件如下:
gateway.yml
1. path.data: data
2. path.logs: log
4. entry:
5. - name: my_es_entry
6. enabled: true
7. router: my_router
8. max_concurrency: 10000
9. network:
10. binding: 0.0.0.0:8000
11. - name: my_kibana_entry
12. enabled: true
13. router: my_kibana_router
14. network:
15. binding: 0.0.0.0:5602
17. flow:
18. - name: es-flow
19. filter:
20. - echo:
21. message: "Before ES request\n"
22. - request_body_json_set:
23. path:
24. - size -> 1
25. - dump:
26. uri: true
27. request_header: true
28. request_body: true
29. response_body: true
30. status_code: true
31. context:
32. - _ctx.id
33. - _ctx.tls
34. - _ctx.remote_addr
35. - _ctx.local_addr
36. - _ctx.request.host
37. - _ctx.request.method
38. - _ctx.request.uri
39. - _ctx.request.path
40. - _ctx.request.body
41. - _ctx.request.body_length
42. - _ctx.request.query_args.from
43. - _ctx.request.query_args.size
44. - _ctx.request.header.Accept
45. - _ctx.request.user
46. - _ctx.response.status
47. - _ctx.response.body
48. - _ctx.response.content_type
49. - _ctx.response.body_length
50. - _ctx.response.header.Env
51. - elasticsearch:
52. elasticsearch: es-server
53. - set_response_header:
54. headers:
55. - Env -> Dev
56. - echo:
57. message: "After ES request\n"
58. - dump:
59. uri: true
60. request_header: true
61. request_body: true
62. response_body: true
63. status_code: true
64. context:
65. - _ctx.id
66. - _ctx.tls
67. - _ctx.remote_addr
68. - _ctx.local_addr
69. - _ctx.request.host
70. - _ctx.request.method
71. - _ctx.request.uri
72. - _ctx.request.path
73. - _ctx.request.body
74. - _ctx.request.body_length
75. - _ctx.request.query_args.from
76. - _ctx.request.query_args.size
77. - _ctx.request.header.Accept
78. - _ctx.request.user
79. - _ctx.response.status
80. - _ctx.response.body
81. - _ctx.response.content_type
82. - _ctx.response.body_length
83. - _ctx.response.header.Env
85. - name: logout_flow
86. filter:
87. - set_response:
88. status: 401
89. body: "Success logout!"
90. - drop:
91. - name: replace_logo_flow
92. filter:
93. - redirect:
94. uri: https://elasticsearch.cn/uploads/event/20211120/458c74ca3169260dbb2308dd06ef930a.png
95. - name: kibana_flow
96. filter:
97. - basic_auth:
98. valid_users:
99. elastic: u7-KUuNhF2DcGCCtugU0 # super elastic account
100. - http:
101. schema: "http" #https or http
102. host: "192.168.0.3:5601"
104. router:
105. - name: my_router
106. default_flow: es-flow
107. - name: my_kibana_router
108. default_flow: kibana_flow
109. rules:
110. - method:
111. - GET
112. - POST
113. pattern:
114. - "/_logout"
115. flow:
116. - logout_flow
117. - method:
118. - GET
119. pattern:
120. - "/plugins/kibanaReact/assets/illustration_integrations_lightmode.svg"
121. flow:
122. - replace_logo_flow
124. elasticsearch:
125. - name: es-server
126. enabled: true
127. endpoints:
128. - https://192.168.0.3:9200
129. - https://192.168.0.8:9200
130. basic_auth:
131. username: elastic
132. password: u7-KUuNhF2DcGCCtugU0
在上面,我们在请求之前,通过 request_body_json_set 过滤器把请求里的 body 进行修改。把 size 设置为 1。
1. - request_body_json_set:
2. path:
3. - size -> 1
这样我们的请求就变成了:
1. GET twitter/_search?filter_path=**.hits
2. {
3. "size": 1,
4. "query": {
5. "match": {
6. "company": "elastic"
7. }
8. }
9. }
虽然,在客户端,我们任然可以通过如下的方式来进行请求:
1. curl --insecure -u elastic:u7-KUuNhF2DcGCCtugU0 -XGET "http://0.0.0.0:8000/twitter/_search?filter_path=**.hits" -H 'Content-Type: application/json' -d'
2. {
3. "query": {
4. "match": {
5. "company": "elastic"
6. }
7. }
8. }'
但是我们得到的结果是:
1. $ curl --insecure -u elastic:u7-KUuNhF2DcGCCtugU0 -XGET "http://0.0.0.0:8000/twitter/_search?filter_path=**.hits" -H 'Content-Type: application/json' -d'
2. {
3. "query": {
4. "match": {
5. "company": "elastic"
6. }
7. }
8. }'
9. {"hits":{"hits":[{"_index":"twitter","_id":"1","_score":0.18232156,"_source":{"name":"liuxg","company":"elastic"}}]}}After ES request
我们只看到一个结果,而不之前的两个尽管我们的请求没有设置 size 的值。
另外,我们也可以干预返回的响应。我们在请求之后,也添加了如下的过滤器:
1. - set_response_header:
2. headers:
3. - Env -> Dev
在我们的 gateway 运行的 console 中,我们可以看到:
显然,我们针对 response 做了修改。
我们在这里可以看到许多关于请求及响应的详细情况。我们可以根据这些 context,请求的类型,请求的 body,响应的 body 结合一些条件可以做出非常多的用户案例。比如在文章 “使用极限网关来处置 Elasticsearch 的 Apache Log4j 漏洞” 中介绍的那样,可以修复漏洞。拒绝一些请求。再比如,在文章 “在线查询修复的实现” 中,它实现对请求的修复。当然也可以对 response 进行修改。
结论
INFINI 网关置于 Elasticsearch 集群的前端。它是一个轻量级的高可用的网关。它可对客户端的请求动态地进行截获及分析。它含有丰富的过滤器供开发者使用。我们可以充分利用这些过滤器对来自客户端的请求进行分析,组装,拒绝,也可以针对响应做更改。当然,它还有很多其它的功能供开发者使用,比如,轻松实现跨集群搜索及备份。针对一些请求进行限流。有很多功能需要我们一起共同挖掘。