Tornado AsyncHTTPClient性能降低

2024-05-08 20:04:15 发布

您现在位置:Python中文网/ 问答频道 /正文

设置:Python 2.7.15,Tornado 5.1

我有一台每秒处理~40/recommend请求的web服务器机器。 平均响应时间为25ms,但存在很大的差异(有些请求可能需要500毫秒以上)。在

每个请求在内部生成1-8个Elasticsearch查询(HTTP请求)。 每个Elasticsearch查询可能需要1-150毫秒

Elasticsearch请求通过elasticsearch-dsl库同步处理。在

目标是减少i/o等待时间(查询到Elasticsearch)并每秒处理更多请求,这样我就可以减少机器的数量。 有一件事是不能接受的-我不想增加平均处理时间(25毫秒)。在

我在web上发现了一些tornado elasticsearch实现,但由于我只需要使用elasticsearch(/_search)的一个端点,所以我尝试单独使用。在

下面是我的web服务器的退化实现。在相同的负载下(每秒约40个请求),平均请求响应时间增加到200ms!在

深入研究,我发现内部异步处理时间(对Elasticsearch的查询)不稳定,每个fetch调用所花费的时间可能不同,并且总平均值(在ab负载测试中)很高。在

我使用ab来模拟负载,并通过打印当前的fetch处理时间、平均fetch处理时间和最大处理时间进行内部测量。 一次执行一个请求时(并发1): ab -p es-query-rcom.txt -T application/json -n 1000 -c 1 -k 'http://localhost:5002/recommend'

我的指纹看起来像:[avg req_time: 3, dur: 3] [current req_time: 2, dur: 3] [max req_time: 125, dur: 125] reqs: 8000

但是当我试图增加并发性(最多8个):ab -p es-query-rcom.txt -T application/json -n 1000 -c 8 -k 'http://localhost:5002/recommend'

现在我的指纹看起来像:[avg req_time: 6, dur: 13] [current req_time: 4, dur: 4] [max req_time: 73, dur: 84] reqs: 8000

平均需求现在是x2慢了(或x4根据我的测量)! 我错过了什么?为什么我看到这种堕落?在

网络_服务器.py:

import tornado
from tornado.httpclient import AsyncHTTPClient
from tornado.options import define, options
from tornado.httpserver import HTTPServer
from web_handler import WebHandler

SERVICE_NAME = 'web_server'
NUM_OF_PROCESSES = 1


class Statistics(object):
    def __init__(self):
        self.total_requests = 0
        self.total_requests_time = 0
        self.total_duration = 0
        self.max_time = 0
        self.max_duration = 0


class RcomService(object):
    def __init__(self):
        print 'initializing RcomService...'
        AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient", max_clients=3)
        self.stats = Statistics()

    def start(self, port):
        define("port", default=port, type=int)
        db = self.get_db(self.stats)
        routes = self.generate_routes(db)
        app = tornado.web.Application(routes)
        http_server = HTTPServer(app, xheaders=True)
        http_server.bind(options.port)
        http_server.start(NUM_OF_PROCESSES)
        tornado.ioloop.IOLoop.current().start()

    @staticmethod
    def generate_routes(db):
        return [
            (r"/recommend", WebHandler, dict(db=db))
        ]

    @staticmethod
    def get_db(stats):
        return {
            'stats': stats
        }


def main():
    port = 5002
    print('starting %s on port %s', SERVICE_NAME, port)

    rcom_service = RcomService()
    rcom_service.start(port)


if __name__ == '__main__':
    main()

网络_处理程序.py:

^{pr2}$

我尝试使用async类(Simplevscurl),即max_clients大小,但我不知道在我的情况下什么是最好的调优。 但是


Tags: importselfwebhttpdbtimeportdef
1条回答
网友
1楼 · 发布于 2024-05-08 20:04:15

时间增加可能是因为并发==1时,CPU利用率不足,而c==8时,CPU利用率为100%+并且无法赶上所有请求。例如,抽象CPU每秒可以处理1000个操作,发送一个请求需要50个CPU操作,读取一个请求结果也需要50个CPU操作。当你有5个RPM时,你的CPU利用率为50%,平均请求时间为50毫秒(发送请求)+请求时间+50毫秒(读取请求)。但是,例如,当你有40个RPS(大于5个RPS的8倍),你的CPU将被过度利用400%,一些完成的请求将等待解析,所以现在平均请求时间是50毫秒+请求时间+CPU等待时间+50毫秒

总而言之,我的建议是检查两个负载上的CPU利用率,当然,要分析发送请求和解析响应所需的时间,CPU可能是您的瓶颈。在

相关问题 更多 >