在 Azure 容器应用程序上运行 WebSockets

问题描述 投票:0回答:2

我已将 WebSocket 服务部署到 Azure 容器应用程序,乍一看似乎没有问题。从客户的角度来看,这项服务似乎运行得非常完美。

但是,当查看容器的日志时,似乎充满了以下不断重复的错误。

opening handshake failed
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/websockets/http11.py", line 134, in parse
    request_line = yield from parse_line(read_line)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/websockets/http11.py", line 380, in parse_line
    line = yield from read_line(MAX_LINE_LENGTH)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/websockets/streams.py", line 46, in read_line
    raise EOFError(f"stream ends after {p} bytes, before end of line")
EOFError: stream ends after 0 bytes, before end of line

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/websockets/asyncio/server.py", line 353, in conn_handler
    await connection.handshake(
  File "/usr/local/lib/python3.12/site-packages/websockets/asyncio/server.py", line 204, in handshake
    raise self.protocol.handshake_exc
  File "/usr/local/lib/python3.12/site-packages/websockets/server.py", line 551, in parse
    request = yield from Request.parse(
              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/websockets/http11.py", line 136, in parse
    raise EOFError("connection closed while reading HTTP request line") from exc
EOFError: connection closed while reading HTTP request line

当容器在我的机器上本地运行时,这不是问题。

我的猜测是,Azure 容器应用程序会自动调用一些我的 WebSocket 服务器不支持的端点,但我无法弄清楚到底是什么以及为什么。如果有人能指出我可以改变什么的正确方向,我将不胜感激。

websocket azure-container-apps
2个回答
0
投票

在浏览了 Azure 容器应用程序的文档后,我在这里找到了解决方案:Azure 容器应用程序中的运行状况探针

似乎当没有为容器应用程序定义特定的运行状况探测器时,探测器会自动且静默地为您定义,即使它们在查看容器应用程序的配置时不可见。

这些默认探针是:

探头类型 默认值
启动 协议:TCP
端口:入口目标端口
超时:3秒
周期:1秒
初始延迟:1秒
成功阈值:1
失败阈值:240
准备就绪 协议:TCP
端口:入口目标端口
超时:5秒
周期:5秒
初始延迟:3秒
成功阈值:1
失败阈值:48
活力 协议:TCP
端口:入口目标端口

这里的问题是,对服务器根路径的 TCP 请求将不起作用,并且活性探测永远不会成功。

解决方案只是向服务器添加对简单 HTTP

/health
端点的支持,该端点会返回 200 响应。然后,有必要使用 HTTP 协议、这个新端点和正确的端口显式地定义容器的活性探针。

活性探针是必需的,并且不能被忽略,但以这种方式设置它,将确保日志不会因错误而混乱。


0
投票

EOFError: EOF when reading a line
函数尝试读取一行输入时,Python 中的
input()
错误就会发生。有关更多详细信息,请参阅此文档来解决 EOF 错误。

以下是在 Azure 容器应用程序上创建和部署 WebSocket 的步骤:

  • 创建容器注册表并激活管理员用户。
  • 在我们的项目结构中,确保在 Python 中创建并激活虚拟环境。以下是我的项目结构:

app.py

from flask import Flask, render_template
from flask_socketio import SocketIO
from flask_cors import CORS  

app = Flask(__name__)
CORS(app)  
socketio = SocketIO(app, cors_allowed_origins="*")  


@app.route('/')
def index():
    return render_template('index.html')

@socketio.on('message')
def handle_message(msg):
    print('Received message: ' + msg)
    socketio.emit('message', msg)  

if __name__ == '__main__':
    socketio.run(app)


模板/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flask WebSocket Example</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
</head>
<body>
    <h1>Flask WebSocket Example</h1>
    <input type="text" id="message" placeholder="Enter a message">
    <button onclick="sendMessage()">Send Message</button>
    <p id="response"></p>

    <script>
       
        const socket = io('http://localhost:5000');
        
   
        socket.on('message', (msg) => {
            console.log('Received message: ' + msg);
            document.getElementById('response').textContent = 'Received: ' + msg;
        });


        function sendMessage() {
            const message = document.getElementById('message').value;
            socket.emit('message', message);  
        }
    </script>
</body>
</html>





需求.txt:

 flask
Flask-SocketIO
flask-cors
eventlet
gunicorn

Docker:


FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
COPY . /app
EXPOSE 5000
#CMD ["python", "app.py"]
CMD ["gunicorn", "-k", "eventlet", "-w", "1", "app:app", "--bind", "0.0.0.0:5000"]

Output in local 使用以下命令构建图像

docker build -t websocket-chat .
Build image

然后标记图像以匹配 ACR 存储库格式:

docker tag websocket-chat  AzureRegisterName.azurecr.io/websocket-chat:latest

通过以下命令登录到您的 Azure 容器注册表:

az acr login -n 

acr login 现在,将标记的映像推送到您的 Azure 容器注册表:

docker push AzureRegisterName.azurecr.io/websocket-chat:latest

acr push

如果是 Web 应用程序,请确保在“配置”>“Web 套接字”>“打开”中打开“Web 套接字”选项。确保端口 80 和 443。

转到容器注册表中的“存储库”部分,选择镜像,然后单击“运行实例”。

azure image from register

然后就开始创建Container了。输入Container名称,选择Public IP地址为Yes,并配置端口。

Container creation

使用 IP 地址浏览您的容器应用程序。

Container Output

© www.soinside.com 2019 - 2024. All rights reserved.