tornado高性能高并发API服务网关

Tornado 是什么?

Tornado 是一个 Python 写的:高性能异步 Web 服务器 + Web 框架

它最核心的特点:异步、非阻塞、高并发、长连接、极快


1. 一句话定位

你可以把它理解成:Python 里专门用来做「高并发 API 服务」的轻量级 Web 服务器

和 Flask、Django 最大区别:

  • Flask/Django:同步、适合普通网站、接口
  • Tornado :异步、非阻塞、适合高并发、长连接、AI 推理服务

vLLM、TGI、FastChat 等大模型推理服务 底层都用 Tornado 做 API 服务器!

vLLM 启动的 OpenAI-compatible server背后就是 Tornado

2. Tornado 最牛的地方(为什么大模型都用它)

  1. 高并发 单进程就能扛 成千上万连接,不卡不死
  2. 非阻塞 I/O等待模型推理时,不会卡住其他请求
  3. 长连接支持SSE / WebSocket 都很稳
  4. 轻量比 Django 轻太多,专门做 API 网关

3. 最简单可运行代码(一看就懂)

python 复制代码
import tornado.ioloop
import tornado.web

# 定义 API 接口
class MainHandler(tornado.web.RequestHandler):
    async def get(self):
        self.write("Hello, Tornado 高性能服务!")

# 启动服务
def make_app():
    return tornado.web.Application([(r"/", MainHandler)])

if __name__ == "__main__":
    app = make_app()
    app.listen(8888)  # 监听端口
    tornado.ioloop.IOLoop.current().start()

例2:

python 复制代码
import tornado.ioloop
import tornado.web
import tornado.httpserver
from tornado import gen
from tornado.concurrent import run_on_executor, futures


# 定义 API 接口
class MainHandler(tornado.web.RequestHandler):
    async def get(self):
        self.write("Hello, Tornado 高性能服务!")

class BaseHandler(tornado.web.RequestHandler):
    executor = None
    def initialize(self):
        # 在初始化时创建线程池
        if BaseHandler.executor is None:
            logger.info(f"创建线程池,当前活动线程数:{threading.active_count()}")
            BaseHandler.executor = futures.ThreadPoolExecutor(max_workers=ducc_config["serving"]["default_thread_pool_size"])

    def get(self):
        html = """<p>服务已启动</p>"""
        self.write(html)

    @gen.coroutine
    def post(self):
        result = yield self._call_back()
        self.write(json.dumps(result))

    @run_on_executor
    def _call_back(self):
        pass

    def set_default_headers(self):
        origin_url = str(self.request.headers.get("Origin"))
        self.set_header("Access-Control-Allow-Origin", origin_url)
        self.set_header("Access-Control-Allow-Credentials", "true")
        self.set_header("Access-Control-Allow-Headers", "x-requested-with,token")
        self.set_header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
        self.set_header("Access-Control-Max-Age", 1000)


class UrlCheckHandler(BaseHandler):
    # 接口健康检查
    def get(self):
        post_ump_monitor(umpKey="aigent.interface.healthCheck", isSuccess="true", start_time=time.time(), requestId="url-check", ducc_config=ducc_config)
        self.set_status(200)
        self.write({"status": "OK"})

class informationExtractHandler(BaseHandler):
    @run_on_executor
    def _call_back(self):
        try:
            json_req = json.loads(self.request.body)
            requestId = json_req.get("requestId", "")
            erp = json_req.get("erp", "")
            agent = json_req.get("agent", "")
            logger.info(f"{requestId} informationExtractHandler 输入:{json_req}")
            if os.path.exists(cfg.default_ducc_path):
                ducc_conf = cfg.get_ducc_obj()
            else:
                ducc_conf = cfg.get_ducc_config()
            result = information_extract(requestId, erp, ducc_conf, agent)
            logger.info(f"{requestId} informationExtractHandler 返回:{result}")
            return {"code": 200, "data": result}
        except:
            error_msg = traceback.format_exc().replace("\n", "\\n")
            logger.error(error_msg)
            return {"code": 500, "error": error_msg}
    @gen.coroutine
    def post(self):
        result = yield self._call_back()
        self.write(json.dumps(result, ensure_ascii=False))


class ChatHandler(BaseHandler):

    @run_on_executor
    def _call_back(self):
        try:
            jsonobj = self.request.body
            json_req = json.loads(jsonobj)
            logger.info(f"{json_req.get('requestId')} 接收到输入参数botChat:{json_req}")
            if os.path.exists(cfg.default_ducc_path):
                ducc_config = cfg.get_ducc_obj()
            else:
                ducc_config = cfg.get_ducc_config()
            agent2strategy: dict = ducc_config["agent2strategy"]

            def sync_process(json_req):
                logger.warning(f"处理方法")
                return result

            if json_req.get("sync", False):
                # 同步
                result = sync_process(json_req)
                return {"code": 200, "result": result}
            else:
                # 异步
                thread = threading.Thread(target=sync_process, args=(json_req,))
                thread.start()
                return {"code": 200, "result": "1"}
        except:
            error_msg = traceback.format_exc().replace("\n", "\\n")
            logger.error(error_msg)
            return {"code": 500}


if __name__ == "__main__":
    log_config()
    if not cfg.is_debug:
        thread = threading.Thread(target=update_ducc_config_sync, args=(cfg.default_ducc_path,))
        thread.start()
        logger.info("DUCC configs regularly update start.")
    app = tornado.web.Application(
        [
            # openAI接口
            (f"/openingDialog", OpeningDialogueHandler),
            # 问答接口
            (r"/botChat", ChatHandler)
        ],
        autoreload=False,
        debug=cfg.is_debug
    )
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.bind(cfg.port)
    http_server.start(1)
    logger.info(f"服务启动成功\n物理核数:{psutil.cpu_count(logical=False)}")
    tornado.ioloop.IOLoop.instance().start()

4. 在LLM服务场景里Tornado 做什么?

架构:

复制代码
用户请求 → Tornado (API 服务器) → vLLM → Qwen 模型 → 返回结果

Tornado 就是那个:接收 HTTP 请求 → 转发给模型 → 返回流式输出 的高性能网关。

相关推荐
晚霞的不甘2 小时前
CANN-MoE模型推理加速实战
人工智能·分布式·python
小新同学^O^2 小时前
简单学习 --> LangChain
python·学习·langchain
麻雀飞吧2 小时前
期货历史行情与实时数据一体化:主流平台维护负担对照
python
前端若水3 小时前
【无标题】
java·人工智能·python·机器学习
databook3 小时前
填充与积累:积分与面积的可视化
python·数学·动效
TechWayfarer4 小时前
AI大模型时代:IP数据云如何适配智能体场景需求
开发语言·人工智能·python·网络协议·tcp/ip·langchain
Ysn07194 小时前
中文乱码:在 Docker 容器中设置中文语言环境
运维·python·docker·容器