kbe使用tornado问题
interface里面有提到可以考虑使用Tornado,作为异步的http服务器。我试用了下,有个地方不是很明白,
tornado最后都要调用
tornado.ioloop.IOLoop.instance().start()
这一步是阻塞的while循环调用,放在interface里面的话,整个进程就停在这一步上面了。
那怎么使用tornado才能达到不影响interface进程?
使用tonado的原因是因为tonado下的http服务是异步的,这能省去我们对http异步访问的处理。
但tonado有一个问题,它使用的是自己的IOLoop来检测socket消息的访问并触发相关的http访问事件,这也就是为什么死循环的原因——脚本层一直不返回,底层自然无法处理自己的事情。
想要在Interfaces下正常使用,必须把socket连接挂到kbe的系统下面(使用KBEngine.registerReadFileDescriptor和KBEngine.registerWriteFileDescriptor),并且根据PollIOLoop的功能继承IOLoop重新写一个自己的looper,这个looper使用KBEngine.timer()定时触发来代替原PollIOLoop里的循环功能,以避免interfaces被阻塞。
耐心的看了下tornado的代码,按照兄台提到的思路,实现如下:
1、tornado\platform下新建个kbe.py,实现一个KBEIOLoop。
import KBEngine from tornado.ioloop import IOLoop, PollIOLoop from KBEDebug import * class _Select(object): def __init__(self): self._active = {} self._readable = set() self._writeable = set() def close(self): pass def register(self, fd, events): INFO_MSG('register fd %d' %(fd)) if events & IOLoop.READ: KBEngine.registerReadFileDescriptor(fd, self.onRecv) elif events & IOLoop.WRITE: KBEngine.registerWriteFileDescriptor(fd, self.onWrite) self._active[fd] = events def modify(self, fd, events): self.unregister(fd) self.register(fd, events) def unregister(self, fd): INFO_MSG('unregister fd %d' %(fd)) events = self._active.pop(fd) if events & IOLoop.READ: KBEngine.deregisterReadFileDescriptor(fd) elif events & IOLoop.WRITE: KBEngine.deregisterWriteFileDescriptor(fd) def onRecv(self, fd): self._readable.add(fd) def onWrite(self, fd): self._writeable.add(fd) def poll(self, timeout): events = {} for fd in self._readable: events[fd] = events.get(fd, 0) | IOLoop.READ for fd in self._writeable: events[fd] = events.get(fd, 0) | IOLoop.WRITE for fd,event in events.items(): self._readable.discard(fd) self._writeable.discard(fd) return events.items() class KBEIOLoop(PollIOLoop): def initialize(self, **kwargs): super(KBEIOLoop, self).initialize(impl=_Select(), **kwargs)
2、修改下ioloop的配置,把所有平台的实现全部指向KBEIOLoop
@classmethod def configurable_default(cls): """ if hasattr(select, "epoll"): from tornado.platform.epoll import EPollIOLoop return EPollIOLoop if hasattr(select, "kqueue"): # Python 2.6+ on BSD or Mac from tornado.platform.kqueue import KQueueIOLoop return KQueueIOLoop from tornado.platform.select import SelectIOLoop return SelectIOLoop """ from tornado.platform.kbe import KBEIOLoop return KBEIOLoop
3、修改下PollIOLoop的start实现,把默认的循环执行改成只执行一次
def start(self): .... .... #执行一次就退出 self._running = False finally: .... ....
这里和kbe结合的tornado实现就完成了。
使用时,我们需要定时器里面一次次的调用start。
测试样例如下:
def handle_response(response): if response.error: ERROR_MSG("Error: %s" % (response.error)) else: INFO_MSG(response.body) def request(): """ """ #非阻塞型 http_client = tornado.httpclient.AsyncHTTPClient() http_client.fetch("http://www.baidu.com/", handle_response) def onInterfaceAppReady(): """ KBEngine method. interfaces已经准备好了 """ INFO_MSG('onInterfaceAppReady: bootstrapGroupIndex=%s, bootstrapGlobalIndex=%s' % \ (os.getenv("KBE_BOOTIDX_GROUP"), os.getenv("KBE_BOOTIDX_GLOBAL"))) request() KBEngine.addTimer(0.3, 0, onTornadoIOLoop) def onTornadoIOLoop(timerID): """ """ KBEngine.delTimer( timerID ) tornado.ioloop.IOLoop.current().start() KBEngine.addTimer(0.3, 0, onTornadoIOLoop)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)