0%

仓库地址: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实现的。