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)
复制代码

 

posted on   &大飞  阅读(250)  评论(0编辑  收藏  举报

编辑推荐:
· 从 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)

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示