1月 112018
 

gnocchi-api 访问基本在10s +, why ?

gnocchi-api 使用了 wsgiref , wsgiref 使用了 :

/usr/bin/gnocchi-api:

/usr/lib64/python2.7/wsgiref/simple_server.py :

(这里提到了个REMOTE_HOST的环境变量,含义就是“REMOTE_ADDR 对应的域名”, 而 address_string() 的命名也是ip地址对应的域名的意思,因为绝大部分的ip地址是反解不到域名的,所以,这个逻辑基本可以注释掉,不过,直接修改人家的代码不大好)

然而上面的 WSGIRequestHandler 基本上会执行到get_environ() , 进而执行到 BaseHTTPServer.py 中的 self.address_string() ,如下:

address_string() 函数又调用了 /usr/lib64/python2.7/socket.py 中的 getfqdn(), 如下:

然后就肯定会执行到gethostbtaddr() 了,该函数的具体实现又是什么逻辑呢? socket.py import了 _socket 模块中的所有函数,而gethostbyaddr()正是_socket 模块实现的,_socket 模块的实现见: /usr/lib64/python2.7/lib-dynload/_socketmodule.so , 可见,这是一个c实现的so文件,稍后再看:

 

测试发现,该函数当遇到IP地址时,肯定会做一次反向地址解析,反向地址解析不是所有dns都能支持的很好的,有些能快速返回,有些却不能(具体原因,稍后再查),比如: 公网地址的反向地址解析可以很快返回,私网地址的反向地址解析就很慢

 

解决办法:

办法一: 在 dns 上给自己的IP地址添加反向地址解析,这样反向地址解析就可以很快; 给每个IP地址都添加反向地址解析的话,比较麻烦,最好能有一个更好的办法,让某一类IP地址能直接返回错误,或返回一个自定义的域名; 这个办法的优点是: 不需要修改程序 ; 如果搞不定dns,那就修改程序吧

办法二: 修改/usr/lib64/python2.7/BaseHTTPServer.py  ,在 address_string() 中直接返回host,而不进行socket.getfqdn(host) 的调用

办法三: 修改 /usr/lib64/python2.7/socket.py 中的 getfqdn() 函数,对于ip地址的情况,不再调用 gethostbyaddr()

办法四: 其实,不是特别有信心的话,不要修改的太底层,没准儿影响到别的程序的; 更好的办法是:

在 /usr/bin/gnocchi-api 中wss.make_server(…) 时,提供了三个参数,还有两个参数是可以定制的,我们可以自己在 /usr/bin/gnocchi-api  中实现一个 MyWSGIRequestHandler ,继承自./simple_server.py 中的WSGIRequestHandler , 然后覆盖其中的address_string() 方法即可

 

按照办法四 修改后的 /usr/bin/gnocchi-api 如下:

 

测试发现,访问确实快多了,不再感觉到延迟了

 Posted by at 上午 11:56