在使用 Sync.pool 管理调用 Thrift 的 goroutine,减少创建及销毁 goroutine 开销,c 为调用client。
c := pool.Get()
defer pool.Put(c)
以下为调用逻辑....
问题现象
主要表现为:Client 端在通过 Thrift 协议调用 Server 端时,只有 HTTP Status 返回 413,但是无其他任何有用信息,body 也是空。
问题原因
那接下来,需要根据上述的问题现象,分析出问题的根因。
- 先看看 HttpStatus 413是什么意思?
HTTP Status 413 (请求实体过大),而针对该问题也主要为header过大。
服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。
PS: 这里请求实体过大的意思是包括 header 和 body(一开始定位时只定位了 body,就进坑了- -)
- 因为在使用 Thrift 作为 RPC 框架时,会设置 header(使用的是以下 Addheader 方法)。但对于存在于 pool 中的 goroutine,通过以下代码,
p.header.Add(key, value)得知,如果调用 Addheader 会不断增加 header 中的内容。所以导致请求实体过大。
// Set the HTTP Header for this specific Thrift Transport
// It is important that you first assert the TTransport as a THttpClient type
// like so:
// httpTrans := trans.(THttpClient)
// httpTrans.SetHeader("User-Agent","Thrift Client 1.0")
func (p \*THttpClient) SetHeader(key string, value string) {
p.header.Add(key, value)
}
解决方案
那知道问题根因之后,则需要解决该类问题,而推荐的解决方案有以下几种:
-
自己继承后重新实现(推荐)
-
修改 thrfit 包中 SetHeader/Flush方法,增加重置 header 逻辑
-
每次都重新创建 Thrift 连接
环境
-
Go:1.5
-
Linux:Linux version 2.6.32-279.el6.x86_64 (gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)
-
OS:CentOS release 6.3 (Final) 2.6.32-279.el6.x86_64
-
CPU:12
-
Mem:8G
-
网络协议:Thrift