近期遇到如下的问题,有一份其他系统部署到我放系统中的一个接口,我方并没有这个系统的源代码,现有需求是从他方系统中取得他数据并将数据放入到ElasticSearch中索引,要求是实时完成这个需求,如果在已经有对方系统源代码的情况下可以通过修改源码将原有系统中的数据再提交到我放ElasticSearch中,或者写入我方消息队列,通过消息队列写入到ElasticSearch中。可是现在无对方源码,对方也不会对现有程序进行修改以满足我方的要求。原本是采用定时去读取对方数据库的方式,但是在业务逻辑是遇到各种各样的问题实时性也不够。于是想到拦截对方一个提交数据并写入数据库的接口来实现,但是这就要涉及比较复杂的方式还需要改对方系统提交数据按个接口的配置,难道就没有其他方案了?
其实问题的本质是如果能够让提交对方接口的数据同时也提交到我方系统的话就可以解决这个问题。那强大的nginx是否有这个功能?
通过一系列的搜索调研后发现是可以的。显示搜索了到了post_action 方法:详细方式如下:
server {
listen 80;
server_name cms.bulletin.jszbtb.com;
location /xxfbcms/api/directive/contentcreate {
proxy_pass http://xxx.xxx.xxx.xxx/xxfbcms/api/directive/contentcreate;
post_action @sub;
}
location @sub {
proxy_pass http://127.0.0.1:8099;
}
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
}
测试后发现是可行的,在127.0.0.1的8099端口是部署的Java程序收集的了post过来的表单数据并能够顺利处理掉。于是在测试系统上进行了一段时间的测试,本以为是完全没有问题的,但是实际运行中发现了ElasticSearch中缺少数据,原本以为是索引建立程序的问题,因为我8099端口上部署的程序会先放入的消息队列中,然后消费者程序会消费消息,写入队列,怀疑是处理的问题。但是仔细排查后发现并不是,自我构造在消息队列中的数据是可以顺利进行的索引的,并且从8099端口上Java的日志中找到大量的莫名其妙的错误,似乎和对formdata parse有关,导致io的错误,进一步观察nginx日志后,发现似乎是数据并没有正常post到8099上而且有些正确的post到了有些没有。在nginx日志文件中观察到:
2020/01/08 09:40:21 [alert] 20383#0: *50068 sendfile() failed (9: Bad file descriptor) while sending request to upstream, client: 172.17.0.2, server: cms.bulletin.jszbtb.com, request: "POST /xxfbcms/api/directive/contentcreate HTTP/1.1", upstream: "http://127.0.0.1:8099/xxfbcms/api/directive/contentcreate", host: "cms.bulletin.jszbtb.com"
大量的存在,怀疑就是数据么有发送到8099上,但是正常发送到了原有的服务器上。于是原因定位在了nginx上。
查询这个些错误,发现POST_ACTION是undocument的是不稳定的不建议使用,这真是一个教训啊,难道就没有其他方式?不见得,其实nginx提供了mirror功能来实现类似需求,这个模块就是ngx_http_mirror_module。具体用法:
server {
listen 80;
server_name cms.bulletin.jszbtb.com;
location /xxfbcms/api/directive/contentcreate {
proxy_pass http://192.168.3.4:8081/xxfbcms/api/directive/contentcreate;
mirror /xxfbcmsmirror/api/directive/contentcreate;
}
location /xxfbcmsmirror/api/directive/contentcreate {
internal;
proxy_pass http://127.0.0.1:8099;
}
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
}
重启nginx后,进过观察发现问题解决,日志中没有这些问题了。类似方式可以做一个参考,用于上下游的多次镜像提交。
本文为Lokie.Wang原创文章,转载无需和我联系,但请注明来自lokie博客http://lokie.wang