Python jsocket服务端遇客户端断开连接崩溃,如何保障服务持续运行
问题根因
崩溃是老旧jsocket库和高版本Python的兼容性问题导致的:
- 你使用的
jsocket库开发时适配的是Python 2或早期Python 3版本,清理退出连接线程时调用的是旧版线程存活判断方法isAlive(),而Python 3.9+版本已将该方法重命名为is_alive(),调用时会找不到对应属性 - 服务端只有在连接断开后触发旧线程清理逻辑时才会调用
isAlive()方法,所以首次连接断开前服务端运行正常,断开后立刻触发崩溃 - 你自定义的
DataloggerServer类中已经写了isAlive方法的注释模板,只是没有放开启用
解决方案
方案1:补全自定义类兼容方法(无需修改第三方库,最简便)
直接将你代码中注释掉的isAlive方法放开即可,修改后的类定义如下:
class DataloggerServer(jsocket.ServerFactoryThread): # 这是服务端工厂为每个新连接实例化的处理线程类 def __init__(self): super(DataloggerServer, self).__init__() self.timeout = 2.0 # 放开该方法即可兼容旧jsocket库的调用 def isAlive(self): # 底层调用高版本Python标准的线程存活判断方法 return super().is_alive() def _process_message(self, obj): # 原有的业务处理逻辑完全不需要修改 logging.debug("Recived object %s", obj) if obj != '': if obj['type'] == "REQ_VAR_SAMPLE": data = obj['data'] var_name = data["id"] logging.debug("Got variable name %s", var_name) if var_name == 'EMERGENCY': value = 0 if random.random() < 0.75 else 1 logging.debug("variable value: %s", value) elif var_name == "RPM_SPINDLE": value = 70 if random.random() < 0.85 else 45 elif var_name == "FEEDRATE_OVERRIDE": value = 50 if random.random() < 0.85 else 75 sample = {} timestamp = int(time.time()*1000) sample['timestamp'] = timestamp sample['value'] = value logging.debug("created sample %s", sample) else: logging.info(obj) sample = {} data = {'sample': sample} res_obj = { "type": "RESP_SAMPLE", "data": data } logging.debug("Response object: %s", res_obj) self.send_obj(res_obj)
方案2:修改jsocket库源码(适合多服务端复用同一份库的场景)
找到报错日志中提示的jsocket/tserver.py文件,定位到第189行,将原有代码:
if not t.isAlive():
修改为:
if not t.is_alive():
即可全局解决该库的兼容性问题,所有基于该库开发的服务端都不会再出现这个报错。
额外稳定性优化建议
如果客户端短连接请求频率较高,可以在_process_message方法外层加上异常捕获,避免客户端发送非法格式请求导致单个处理线程崩溃:
def _process_message(self, obj): try: # 原有业务逻辑全部放在try块内 except Exception as e: logging.error(f"处理请求异常: {str(e)}", exc_info=True) # 可按需返回错误响应,或直接结束当前线程
内容的提问来源于stack exchange,提问作者zunbeltz
相关产品推荐
相关产品推荐

