Browse Source

修复 bug 问题

origin/hotfix/hlk-flight
root 4 months ago
parent
commit
3048a01027
  1. 95
      app/core/websocket/manager.py
  2. 36
      app/core/websocket/send_controller.py
  3. 1601
      modify.md

95
app/core/websocket/manager.py

@ -53,10 +53,24 @@ class WebSocketManager:
async def create_client(self, name: str, url: str, heartbeat_interval: int = 120) -> WebSocketClient: async def create_client(self, name: str, url: str, heartbeat_interval: int = 120) -> WebSocketClient:
"""创建WebSocket客户端并自动创建3个Channel""" """创建WebSocket客户端并自动创建3个Channel"""
try: try:
# 1. 创建客户端 # 检查是否已存在客户端
client = await self._client_manager.create_client(name, url, heartbeat_interval) existing_client = self._client_manager.get_client(name)
if existing_client:
logger.info(f"WebSocket客户端 {name} 已存在,检查状态")
# 如果客户端已连接,先断开
if existing_client.is_connected:
logger.info(f"WebSocket客户端 {name} 已连接,先断开")
await self._client_manager.disconnect_client(name)
# 更新心跳间隔配置
existing_client.heartbeat_interval = heartbeat_interval
client = existing_client
else:
# 1. 创建客户端
client = await self._client_manager.create_client(name, url, heartbeat_interval)
# 2. 创建Channel # 2. 创建Channel(如果已存在会返回已存在的Channel)
await self._channel_manager.create_client_channels(name) await self._channel_manager.create_client_channels(name)
# 3. 注册消息处理器 # 3. 注册消息处理器
@ -130,15 +144,20 @@ class WebSocketManager:
# 2. 启动Channel # 2. 启动Channel
await self._channel_manager.start_client_channels(name) await self._channel_manager.start_client_channels(name)
# 3. 创建并启动发送控制器 # 3. 等待Channel完全启动(确保Channel状态为connected)
await self._wait_for_channels_ready(name)
# 4. 创建并启动发送控制器
await self._create_and_start_send_controller(name) await self._create_and_start_send_controller(name)
# 4. 启动心跳任务 # 5. 启动心跳任务
client = self._client_manager.get_client(name) client = self._client_manager.get_client(name)
if client and hasattr(client, 'heartbeat_interval'): if client and hasattr(client, 'heartbeat_interval'):
# 检查是否已存在心跳任务
await self._heartbeat_manager.stop_heartbeat_task(name) # 先停止已存在的任务
await self._heartbeat_manager.start_heartbeat_task(name, client, client.heartbeat_interval) await self._heartbeat_manager.start_heartbeat_task(name, client, client.heartbeat_interval)
# 5. 启动接收消息处理器 # 6. 启动接收消息处理器
await self._create_and_start_receive_processor(name) await self._create_and_start_receive_processor(name)
logger.info(f"WebSocket管理器客户端连接成功: {name}") logger.info(f"WebSocket管理器客户端连接成功: {name}")
@ -148,6 +167,32 @@ class WebSocketManager:
logger.error(f"WebSocket管理器连接客户端失败: {name} - {e}") logger.error(f"WebSocket管理器连接客户端失败: {name} - {e}")
return False return False
async def _wait_for_channels_ready(self, client_name: str, timeout: float = 5.0):
"""等待客户端的所有Channel完全启动"""
import asyncio
start_time = asyncio.get_event_loop().time()
while asyncio.get_event_loop().time() - start_time < timeout:
# 检查所有Channel是否都已连接
client_channels = self._channel_manager.get_client_channels(client_name)
all_connected = True
for channel_name, channel in client_channels.items():
if not channel.is_connected:
all_connected = False
logger.debug(f"等待Channel连接: {channel_name}")
break
if all_connected:
logger.info(f"所有Channel已准备就绪: {client_name}")
return True
# 等待100ms后再次检查
await asyncio.sleep(0.1)
logger.warning(f"等待Channel就绪超时: {client_name} (超时时间: {timeout}秒)")
return False
async def _create_and_start_send_controller(self, client_name: str): async def _create_and_start_send_controller(self, client_name: str):
"""创建并启动发送控制器""" """创建并启动发送控制器"""
try: try:
@ -156,11 +201,26 @@ class WebSocketManager:
logger.error(f"WebSocket客户端 {client_name} 不存在") logger.error(f"WebSocket客户端 {client_name} 不存在")
return return
# 检查是否已存在发送控制器
if client_name in self._send_controllers:
existing_controller = self._send_controllers[client_name]
logger.info(f"WebSocket发送控制器 {client_name} 已存在,先停止")
await existing_controller.stop()
del self._send_controllers[client_name]
# 获取Channel
heartbeat_channel = self._channel_manager.get_channel(f"{client_name}_heartbeat")
send_channel = self._channel_manager.get_channel(f"{client_name}_send")
if not heartbeat_channel or not send_channel:
logger.error(f"Channel不存在,无法创建发送控制器: {client_name}")
return
# 创建发送控制器 # 创建发送控制器
send_controller = WebSocketSendController( send_controller = WebSocketSendController(
client=client, client=client,
heartbeat_channel_name=f"{client_name}_heartbeat", heartbeat_channel=heartbeat_channel,
send_channel_name=f"{client_name}_send" send_channel=send_channel
) )
# 启动发送控制器 # 启动发送控制器
@ -177,6 +237,18 @@ class WebSocketManager:
async def _create_and_start_receive_processor(self, client_name: str): async def _create_and_start_receive_processor(self, client_name: str):
"""创建并启动接收消息处理器""" """创建并启动接收消息处理器"""
try: try:
# 检查是否已存在接收处理器
if client_name in self._receive_tasks:
existing_task = self._receive_tasks[client_name]
logger.info(f"WebSocket接收消息处理器 {client_name} 已存在,先停止")
if not existing_task.done():
existing_task.cancel()
try:
await existing_task
except asyncio.CancelledError:
pass
del self._receive_tasks[client_name]
# 获取接收Channel # 获取接收Channel
receive_channel = self._channel_manager.get_channel(f"{client_name}_receive") receive_channel = self._channel_manager.get_channel(f"{client_name}_receive")
if not receive_channel: if not receive_channel:
@ -286,10 +358,13 @@ class WebSocketManager:
# 3. 停止接收消息处理器 # 3. 停止接收消息处理器
await self._stop_receive_processor(name) await self._stop_receive_processor(name)
# 4. 停止Channel # 4. 等待发送控制器完全停止(确保不再访问Channel)
await asyncio.sleep(0.1)
# 5. 停止Channel
await self._channel_manager.stop_client_channels(name) await self._channel_manager.stop_client_channels(name)
# 5. 断开客户端 # 6. 断开客户端
success = await self._client_manager.disconnect_client(name) success = await self._client_manager.disconnect_client(name)
logger.info(f"WebSocket管理器客户端断开成功: {name}") logger.info(f"WebSocket管理器客户端断开成功: {name}")

36
app/core/websocket/send_controller.py

@ -6,7 +6,7 @@ WebSocket发送控制器
import asyncio import asyncio
from typing import Dict, Any, Optional from typing import Dict, Any, Optional
from datetime import datetime from datetime import datetime
from app.core.websocket.channel import ChannelMessage from app.core.websocket.channel import ChannelMessage, WebSocketChannel
from app.core.websocket.client import WebSocketClient from app.core.websocket.client import WebSocketClient
from app.utils.structured_log import get_structured_logger, LogLevel from app.utils.structured_log import get_structured_logger, LogLevel
@ -23,11 +23,11 @@ class WebSocketSendController:
- 发送任务管理 - 发送任务管理
""" """
def __init__(self, client: WebSocketClient, heartbeat_channel_name: str, send_channel_name: str): def __init__(self, client: WebSocketClient, heartbeat_channel: WebSocketChannel, send_channel: WebSocketChannel):
self.client = client self.client = client
self.client_name = client.name self.client_name = client.name
self.heartbeat_channel_name = heartbeat_channel_name self.heartbeat_channel = heartbeat_channel
self.send_channel_name = send_channel_name self.send_channel = send_channel
self._send_task: Optional[asyncio.Task] = None self._send_task: Optional[asyncio.Task] = None
self._running = False self._running = False
self._created_at = datetime.now() self._created_at = datetime.now()
@ -84,26 +84,24 @@ class WebSocketSendController:
try: try:
while self._running and self.client.is_connected: while self._running and self.client.is_connected:
try: try:
# 获取Channel管理器 # 检查Channel是否存在且已连接
from app.core.websocket.channel_manager import WebSocketChannelManager if not self.heartbeat_channel or not self.send_channel:
channel_manager = WebSocketChannelManager()
# 获取Channel
heartbeat_channel = channel_manager.get_channel(self.heartbeat_channel_name)
send_channel = channel_manager.get_channel(self.send_channel_name)
if not heartbeat_channel or not send_channel:
logger.warning(f"Channel不存在,等待重试: {self.client_name}") logger.warning(f"Channel不存在,等待重试: {self.client_name}")
await asyncio.sleep(1) await asyncio.sleep(1)
continue continue
if not self.heartbeat_channel.is_connected or not self.send_channel.is_connected:
logger.warning(f"Channel未连接,等待重试: {self.client_name}")
await asyncio.sleep(1)
continue
# 优先级发送:先发送业务数据,再发送心跳 # 优先级发送:先发送业务数据,再发送心跳
message_sent = False message_sent = False
# 1. 优先发送业务数据 # 1. 优先发送业务数据
if send_channel.is_connected and send_channel.queue_size > 0: if self.send_channel.queue_size > 0:
try: try:
message = await send_channel.receive_message() message = await self.send_channel.receive_message()
if message: if message:
success = await self._send_message(message) success = await self._send_message(message)
if success: if success:
@ -115,9 +113,9 @@ class WebSocketSendController:
logger.error(f"WebSocket发送控制器发送业务消息异常: {self.client_name} - {e}") logger.error(f"WebSocket发送控制器发送业务消息异常: {self.client_name} - {e}")
# 2. 如果没有业务数据,发送心跳 # 2. 如果没有业务数据,发送心跳
if not message_sent and heartbeat_channel.is_connected and heartbeat_channel.queue_size > 0: if not message_sent and self.heartbeat_channel.queue_size > 0:
try: try:
message = await heartbeat_channel.receive_message() message = await self.heartbeat_channel.receive_message()
if message: if message:
success = await self._send_message(message) success = await self._send_message(message)
if success: if success:
@ -189,6 +187,6 @@ class WebSocketSendController:
"is_running": self._running, "is_running": self._running,
"is_connected": self.client.is_connected, "is_connected": self.client.is_connected,
"created_at": self._created_at.isoformat(), "created_at": self._created_at.isoformat(),
"heartbeat_channel": self.heartbeat_channel_name, "heartbeat_channel": self.heartbeat_channel.name,
"send_channel": self.send_channel_name "send_channel": self.send_channel.name
} }

1601
modify.md

File diff suppressed because it is too large
Loading…
Cancel
Save