需求:公司目前使用Haproxy反代ES,Java前端请求正常,但出现过数次ES Master挂掉不转移故障的情况,公司领导决定用Nginx替换Haproxy作为替代。
问题:换成Nginx之后,用curl -XGET 'http://esabc.com:9231',来测试,Nginx能有效负载均衡,以及失效转移,但生产环境迁移之,Java的模块org.elasticsearch向后请求出现:400 bad request的错误,Java端的报错如下图所示:
分析:
- 查询Nginx日志,如下图所示,出现的报错与Java前端报错一致,都是400,没有更具体报错原因,无法根据日志进一步分析;
2. 网上查询400 bad request的错误,大致是Nginx里面修改以下几个参数:
client_body_buffer_size 2M;
client_max_body_size 2M;
client_header_buffer_size 2M;
large_client_header_buffers 4 2M;
但将其值改大之后,仍然出现同样的报错,并且Java开发反映代码之前生产环境运行正常,没有报错;
3. 因为本人对Python比较熟悉,我用Python的elasticsearch模块,通过Nginx发起请求,能够正常返回结果,如下图
这里可以验证Nginx以上参数默认设置没有问题,如上图,请求body很大,仍然正常返回,据此判断Java代码可能有问题,但具体不知道什么原因。
最终解决:
通过在开发端用fiddler抓包工具分析,抓取请求的URL是错误的,请求URL中在端口8888后少了“/”,例如正确的形式应该是http//:es.abc.com:8888/index/type,但抓包后获取的URL类似是:http//:es.abc.com:8888index/type,这是导致报错的直接原因。
开发根据URL错误定位到Java代码层面,发现了原来的请求代码是类似这样:IndexResponse response = client.prepareIndex("twitter", "tweet", "1").setSource(source).get();这样直接通过Haproxy或者直接请求elasticsearch没有问题,但是请求Nginx后报错了,所以最终结局办法是在Java请求代码的索引前面加上“/”,类似于这样:IndexResponse response = client.prepareIndex("/twitter", "tweet", "1").setSource(source).get(),如果在Kibana中用 GET /_cat/indices/或者 GET _cat/indices/都不会报错,至此问题解决。