请教个问题:存储海量数据的多个 ES 集群之间,如何实现负载均衡,网关分流

2021-07-21 23:20:04 +08:00
 429463267

现有一个生产集群,由于数据量太大,遇到性能瓶颈,而且未来数据量还会继续扩大,打算将数据分集群拆开,尽量保证已部署的几十个 spark 服务不做修改或少量修改。

其中,spark 读写 ES 采用的是 ES 9200 端口,写多读少,ip 是写死的内网 ip,已上生产。

所以,目前的想法是,将现有的 ES 集群拆分为多个,假定为 5 ( ES-cluster1 、ES-cluster2 、ES-cluster3 、ES-cluster4 、ES-cluster5 ) 个新集群。

那么,拆完以后,不同的 index pattern 会落到不同集群上,拆分过程可能会很繁琐,估计会使用迁移工具完成。

于是需要一个 API gatway 之类的服务来分发 spark 发来的 http 请求,使得相应的请求映射到正确的新集群上。

接着,我调研了市面上可用的方案如下:

1.https://opster.com/configuration/multi-cluster-load-balancer-configuration/
为 ES 量身定制的负载均衡工具,闭源产品,而且文档基本没有,沟通全靠邮件,放弃。

2.Kong https://github.com/kong/kong

3.https://github.com/traefik/traefik

2 3 之间同类产品对比如下:
微服务五种开源 API 网关实现组件对比 - 知乎
https://zhuanlan.zhihu.com/p/61014955

8 款开源的 Kubernetes Ingress Controller/API Gateway 推荐 · Service Mesh|服务网格中文社区
https://www.servicemesher.com/blog/nginx-ingress-vs-kong-vs-traefik-vs-haproxy-vs-voyager-vs-contour-vs-ambassador/

ingress 控制器那么多,到底该选哪一个?累觉不爱。 - 知乎
https://zhuanlan.zhihu.com/p/302452502


初步结论,暂定选择 kong 或者 traefix 来实现,但还在纠结选哪个。

请各位大佬指点迷津。

2136 次点击
所在节点    程序员
20 条回复
429463267
2021-07-21 23:26:46 +08:00
misaka19000
2021-07-22 00:41:47 +08:00
Kong 好像挺好的
429463267
2021-07-22 07:49:08 +08:00
既然 es JAVA 客户端使用 http 协议通信,那么在网关层,可以通过请求的 method 、host 、path 、query params 、reqbody 来动态映射目标 es 集群
plko345
2021-07-22 08:32:07 +08:00
在 k8s 集群中?
429463267
2021-07-22 08:57:13 +08:00
@plko345 没在 k8s,在 AWS 服务器上
beyondsoft
2021-07-22 09:00:36 +08:00
投 Kong 一票
defunct9
2021-07-22 09:11:51 +08:00
traefik,空重了
tanxnative
2021-07-22 09:30:46 +08:00
自己写一下吧,写和读用一样的分片算法就好了
429463267
2021-07-22 09:39:36 +08:00
@tanxnative 如果只有一个集群的话,可以通过分片算法来分发数据,
但是多个集群之间,目前没有现成方案。
429463267
2021-07-22 09:40:53 +08:00
@defunct9 https://sm.ms/image/Msbm1uINDnLAl5d

traefik 看上去略显弱势
429463267
2021-07-22 09:41:46 +08:00
429463267
2021-07-22 09:49:17 +08:00
defunct9
2021-07-22 10:00:52 +08:00
@429463267 traefik 和 nginx ingress 都在使用,由于之前 nginx 用太多了,最近都在搞 traefik,感觉 traefik 很好用
plko345
2021-07-22 11:33:45 +08:00
对 es 只了解一点,“不同的 index pattern 会落到不同集群上“是不是就是根据 url 的 path 和参数进行 7 层的转发,如果是的话,nginx,haproxy,traefik 全都支持,选个熟悉的?性能 nginx 和 haproxy 差不多,traefik 好像弱一点
429463267
2021-07-22 14:48:08 +08:00
@plko345

这是我用 fiddler 抓到的包,详细记录了 spark 使用 ESHaghilevelClient 写入数据的 HTTP 报文:

```http

### spark ESOperator 写入
POST http://1.2.3.4:9200/_bulk?timeout=1m HTTP/1.1
Content-Length: 500
Content-Type: application/json
Host: 1.2.3.4:9200
Connection: Keep-Alive
User-Agent: Apache-HttpAsyncClient/4.1.4 (Java/1.8.0_181)
Authorization: Basic ***

{"index":{"_index":"index2","_id":"3"}}
{"content":"这是内容 3","doc_id":3,"headline":"标题 3"}
{"index":{"_index":"index2","_id":"4"}}
{"content":"这是内容 4","doc_id":4,"headline":"标题 4"}
{"index":{"_index":"index1","_id":"1"}}
{"content":"这是内容 1","doc_id":1,"headline":"标题 1"}
{"index":{"_index":"index1","_id":"2"}}
{"content":"这是内容 2","doc_id":2,"headline":"标题 2"}
{"index":{"_index":"index1","_id":"1"}}
{"content":"这是内容 5","doc_id":1,"headline":"标题 5"}

### 响应
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 928

{"took":1731,"errors":false,"items":[{"index":{"_index":"index2","_type":"_doc","_id":"3","_version":1,"result":"created","_shards":{"total":2,"successful":2,"failed":0},"_seq_no":0,"_primary_term":1,"status":201}},{"index":{"_index":"index2","_type":"_doc","_id":"4","_version":1,"result":"created","_shards":{"total":2,"successful":2,"failed":0},"_seq_no":1,"_primary_term":1,"status":201}},{"index":{"_index":"index1","_type":"_doc","_id":"1","_version":1,"result":"created","_shards":{"total":2,"successful":2,"failed":0},"_seq_no":0,"_primary_term":1,"status":201}},{"index":{"_index":"index1","_type":"_doc","_id":"2","_version":1,"result":"created","_shards":{"total":2,"successful":2,"failed":0},"_seq_no":1,"_primary_term":1,"status":201}},{"index":{"_index":"index1","_type":"_doc","_id":"1","_version":2,"result":"updated","_shards":{"total":2,"successful":2,"failed":0},"_seq_no":2,"_primary_term":1,"status":200}}]}
###

### ESClient 删除 index
DELETE http://12.3.4:9200/index1 HTTP/1.1
Content-Length: 0
Host: 1.2.3.4:9200
Connection: Keep-Alive
User-Agent: Apache-HttpAsyncClient/4.1.4 (Java/1.8.0_181)
Authorization: Basic ***

### 响应
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 21

{"acknowledged":true}
###
```

初步想法是解析 ReqBody,然后根据 index 名称拆分为多个 http 请求发到对应的 ES 集群上,最后响应全部结果给客户端。
但是响应的报文格式应该是无法兼容 ESHighLevelClient 。。。
429463267
2021-07-22 17:15:20 +08:00
https://www.cnblogs.com/zhoujie/p/kong2.html

看了 kong 的文档,发现他的 路由能力太弱了,无法解析请求体。
Morriaty
2021-07-23 10:09:50 +08:00
有个中国 elastic 员工写的 https://github.com/medcl/infini-gateway,a high performance and lightweight gateway written in golang, for elasticsearch and his friends.

唯一的问题是,emm,It is currently under heavy developemnt, API or configurations are not supposed to be stable.
429463267
2021-07-23 22:33:32 +08:00
@Morriaty 谢谢老哥,我去围观下
429463267
2021-07-23 22:55:35 +08:00
@Morriaty
下载源码看了一眼,有很多依赖都是来自一个 infini.sh 的站点,然鹅,这个站点已经无法访问了。所以二次开发受阻。
Morriaty
2021-07-26 10:45:55 +08:00
@429463267 作者 issue 里有提,这个网站在维护

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/790950

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX