世中鲜人 2026-01-24 11:03 采纳率: 0%
浏览 3

odoo18一个模型启用两个长对话监听

odoo18

问题描述:在win10环境中的odoo18跑一个主线程的moudel,在根据该主线程内new两个长对话的websocerkt,本地无问题正常监听两个对话。如果放在linux中跑同一个odoo18的moudel内容,效果为什么不一样呢。只有moudel的主线程开启了,但两个new的长对话没有实时监听。

初步问题排查方向:在new线程时调用run方法时进行日志分析,是否正常new

  • 写回答

2条回答 默认 最新

  • 檀越@新空间 2026-01-24 11:04
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    在Odoo 18中,如果你在一个模型中启用了两个长对话(long polling)WebSocket监听,并且在 Windows 10 环境下运行正常,但在 Linux 环境下出现问题(即只开启了一个主线程,而两个新的长对话没有实时监听),这通常与以下几点有关:


    🧩 问题分析

    1. 操作系统差异

    • Windows 和 Linux 在线程调度、网络接口处理、以及某些系统调用上存在差异。
    • 特别是对于多线程的并发执行、套接字(Socket)绑定、信号处理等方面。

    2. 线程创建和启动方式不一致

    • 在 Linux 中,如果使用的是 非守护线程(non-daemon thread),可能会因为主线程未退出导致子线程被提前终止。
    • 或者,某些线程可能因资源限制(如文件描述符、内存等)未能正确启动。

    3. WebSocket/长轮询实现方式问题

    • 如果你通过 threading.Thread 创建了两个 WebSocket 监听器,那么需要确保:
      • 每个线程都正确地调用了 start() 方法;
      • 每个线程的 run() 方法内有正确的逻辑;
      • 没有发生阻塞或死锁。

    ✅ 解决方案

    一、检查线程是否成功启动

    1.1 添加日志输出

    确保每个线程都成功启动。例如,在 Thread.start() 之后添加日志:

    import threading
    import logging
    
    _logger = logging.getLogger(__name__)
    
    class MyWebSocketListener(threading.Thread):
        def __init__(self, *args, **kwargs):
            super(MyWebSocketListener, self).__init__(*args, **kwargs)
            self.name = "WebSocketListener"
        
        def run(self):
            _logger.info(f"WebSocket listener {self.name} started.")
            # 这里写你的 WebSocket 监听逻辑
    

    1.2 启动线程时添加日志

    listener1 = MyWebSocketListener()
    listener2 = MyWebSocketListener()
    
    listener1.start()
    listener2.start()
    
    _logger.info("WebSocket listeners started.")
    

    重点: 确保在 Linux 上也能看到“WebSocket listener X started.”的日志信息。


    二、确认线程是否阻塞或卡死

    2.1 检查线程内的逻辑是否阻塞

    • 确保 run() 方法中没有阻塞操作(如长时间等待、死循环、无超时的 socket 接收等)。
    • 使用 try-except 捕获异常并记录日志,防止线程崩溃。
    def run(self):
        try:
            while True:
                # 你的监听逻辑
                pass
        except Exception as e:
            _logger.error(f"WebSocket listener error: {e}")
    

    三、避免主线程过早结束

    3.1 确保主线程不会提前退出

    • 如果主线程在子线程启动前就退出,会导致子线程无法运行。
    • 可以通过 join() 来等待子线程完成,或者设置为 daemon thread
    listener1.setDaemon(True)  # 设置为守护线程,不影响主线程
    listener2.setDaemon(True)
    
    listener1.start()
    listener2.start()
    

    重点: 如果你在 Linux 下发现只有主线程运行,而子线程没有启动,可能是由于主线程提前退出。


    四、检查网络配置和权限

    4.1 确认端口可访问

    • 确保两个 WebSocket 监听的端口在 Linux 系统中是开放的,并且没有被防火墙阻挡。
    • 使用 netstat -tuln 查看监听状态。

    4.2 检查用户权限

    • 如果你使用的是非 root 用户,可能无法绑定到某些端口(如 80、443)。
    • 可以尝试使用 sudo 运行 Odoo 服务,或修改端口为 1024 以上。

    五、代码示例(修正后的版本)

    import threading
    import logging
    import time
    
    _logger = logging.getLogger(__name__)
    
    class WebSocketListener(threading.Thread):
        def __init__(self, port):
            super(WebSocketListener, self).__init__()
            self.port = port
            self.daemon = True  # 设置为守护线程
    
        def run(self):
            _logger.info(f"Starting WebSocket listener on port {self.port}")
            try:
                # 模拟 WebSocket 监听逻辑
                while True:
                    _logger.debug(f"Listening on port {self.port}...")
                    time.sleep(5)
            except Exception as e:
                _logger.error(f"WebSocket listener error: {e}")
    
    # 启动两个 WebSocket 监听器
    if __name__ == "__main__":
        listener1 = WebSocketListener(8001)
        listener2 = WebSocketListener(8002)
        
        listener1.start()
        listener2.start()
        
        _logger.info("WebSocket listeners started successfully.")
    

    📌 总结

    | 问题点 | 原因 | 解决方法 | |--------|------|----------| | 线程未启动 | 主线程提前退出或未调用 start() | 添加日志,确保 start() 被调用,设置为守护线程 | | 线程阻塞 | run() 方法中存在死循环或阻塞操作 | 使用 try-except 捕获异常,避免程序卡死 | | 网络配置错误 | 端口未开放或权限不足 | 检查端口监听状态,使用 netstatsudo |


    如有更多代码片段或具体错误日志,可以进一步提供,我可以帮你更精确地定位问题。

    评论

报告相同问题?

问题事件

  • 创建了问题 1月24日