仓库地址:https://github.com/elastic/go-elasticsearch
仓库简介:The official Go client for Elasticsearch
分支:v7.11.0
README & MakeFile
使用了goreportcard对项目的质量进行了分析。
使用了codecov对代码覆盖率进行测试,网站界面用起来还挺舒服的。这个项目的覆盖率有80%+,挺高的。
使用了Github Action对项目进行自动构建编译。
使用MakeFile封装了一系列构建命令,其中有Unit-test和integration-test。它使用了go的条件编译,来区分两种测试。
比如/esutil
下的测试代码属于unit-test。它不需要依赖es组件。
比如/estransport
下的测试代码属于integration-test。它依赖了es组件,需要在本地先起好es。
发现Makefile还挺强大的,可以节省很多的重复性工作。比如其中的release命令,甚至可以将代码发布到Github的流程自动化。为了方便测试,Makefile也集成了用docker起ES的命令。通过Makefile,也可以很好的实践项目到API文档的输出。
Client
项目的入口在于elasticsearch.go
,它提供了创建Client的函数。另外也有对应的一些_test.go文件,包括example, benchmark, test等。
Client
包含了两个成员,一个是esapi.API
,另一个是estransport.Interface
。
API
:
/esapi/doc.go
的文档提供了比较充分的说明。API是自动根据ES官方client标准生成的,生成代码在/internal/cmd/generate。更牛的是,ES官方还提供了client test,以保证不同语言实现的client都能复用。
API本身是个结构体,成员是函数。API的调用设计,提供了struct和function两种方式。为了实现struct方式的调用,Request定义了Do的method,感觉用起来还挺奇怪的。更倾向于使用function的模式,更紧凑一些。
estransport.Interface
:
/estransport/doc.go
有文档说明。estransport感觉蛮可配置化的,包括重试策略、节点选择、连接池、Logger等。estransport.go
: 核心文件。主要实现函数是Perform。logger.go
: 实现了日志的采集,其实不仅是日志,其他metrics的埋点也可以在这里做。metrics.go
: 实现了metrics的采集。connection.go
: 实现了连接池。只有在输入多个URL的时候有效。假如是使用云厂商的,一般会提供一个VIP,云厂商做了负载均衡。
NewClient
源码阅读收获:
- 默认是使用http.DefaultTransport,该transport没有设置读取header的超时时间,所以假如是客户端返回response慢,那么可能会导致hang住。
Perform
源码阅读收获:
- 为了实现重试,会将request body拷贝一份,因为http请求发送出去后就没了。http内置了GetBody函数可实现多次读取body。
- 默认超时是不会自动重试的,需要配置enableRetryOnTimeout为true才会。为什么这么设计?
- 为了实现并发访问,很多地方使用了Lock来实现的,包括对pool, metrics等字段的访问。
- 使用sleep来实现退避重试。
- 还是使用transport来发起请求,并在发起请求后使用logger来记录请求情况,用户可以用该logger记录日志、打点等。
Connection
源码阅读收获:
- 创建连接池只需要少量参数(host, username, password)。当真正发起请求前,需要将这些参数的绑定到Request中,以便发起http请求。
- Next用于获取连接,OnSuccess用于归还成功的连接,OnFailure用于归还失败的连接。
- 实现了两种连接池,一种是单URL地址的连接池,另一种是多URL地址的连接池。后者相比于前者多了一个负载均衡策略,代码中定义了Selector来抽象。
- singleConnectionPool其实只会返回自己的URL,没有建立连接的概念。这里复用连接是依赖底层的http client实现的。