
# ELB使用WebSocket协议实现聊天信息实时交互
WebSocket协议是一种在单个TCP连接上进行全双工通信的网络协议。WebSocket协议通信下，服务器可以主动向客户端发送数据，使得客户端和服务器之间的连接更持久，数据交换更简单，通信过程更高效。应用型ELB默认支持WebSocket协议，可以帮助您对需要实时通信的业务进行负载。
#### Websocket协议概述
- **什么是Websocket协议**
  当前Web应用场景日渐丰富多样，对通信技术的要求也更高。例如实时社交、协同办公、在线客服通知等功能要求服务器能够实时推送数据。采用轮询技术的传统方案，即客户端在固定时间间隔内向服务器发送请求以获取最新数据，在以上场景存在明显缺陷。如果客户端需要频繁发送请求，而HTTP头字段信息冗长，会导致有效数据信息占比低、带宽资源浪费并增加服务器的压力。
  为了适应以上业务场景需求，HTML5引入支持了WebSocket协议。在全双工通信下，服务器和客户端能同时收发数据，服务器可以主动推送新数据，减少客户端的询问请求。这种双向通信机制有效减少通信冗余，提升了实时业务体验，还可以帮助您节省服务器资源和带宽资源。
  更多关于WebSocket协议的详细信息，您参考官方文档[The WebSocket Protocol](https://datatracker.ietf.org/doc/html/rfc6455)。
  **ELB的HTTP/HTTPS监听默认支持WebSocket协议**。
  
- **Websocket协议** **适用场景**
  Websocket协议的核心优势为**全双工实时通信** ，广泛应用于需要**高频交互** 和**低延迟**的业务场景。
  - **实时社交与互动**：在线聊天室、直播弹幕、多人在线棋牌类游戏等需要不同玩家的状态同步。
  
  - **协同办公** **与在线教育**：多人文档在线编辑、在线课堂互动等需要结果共享。
  
  - **地图导航**：交通导航中乘客位置变化和主动推送拥堵情况。
  
  - **客服与通知**：用户与客服之间即时信息互通。
   
 
#### 实践方案架构
图1客户端通过ELB访问Websocket应用程序   
![](https://support.huaweicloud.com/bestpractice-elb/zh-cn_image_0000002364348489.png "点击放大")
本实践方案提供一个简易的聊天信息实时交互示例如下：客户端向服务器端发送请求，服务器端进行响应，客户端接收响应后发送新的请求，服务器端再次响应的实时交互。
#### 准备工作
- 创建独享型ELB实例，并选择了应用型规格实例，且ELB已绑定EIP。具体操作，请参见[购买独享型负载均衡器](https://support.huaweicloud.com/usermanual-elb/elb_lb_000006.html)和[绑定IPv4公网IP](https://support.huaweicloud.com/usermanual-elb/elb_ug_fz_0015.html)。
- 创建两台ECS，ECS与已创建的ELB实例属于同一个VPC，更多详细设置请参考[快速购买ECS](https://support.huaweicloud.com/usermanual-ecs/ecs_03_7012.html)，本实践方案以ECS安装CentOS系统为例。第一台ECS_client用作客户端发送HTTP请求，第二台ECS_server用作部署WebSocket应用的后端服务器。
 
#### 步骤一：在后端服务器中部署WebSocket应用
1. 远程登录后端服务器ECS_server。 弹性云服务器有多种登录方法，具体请参见[登录弹性云服务器](https://support.huaweicloud.com/ecs_faq/ecs_faq_0632.html)。
   
2. 执行以下命令确保服务器端的python版本不低于python 3.7。
   ```
   yum install python39
   ```
   
3. websockets 库提供了简洁的 API，使得在 Python 中建立 WebSocket 连接变得容易，执行以下命令安装最新版websockets库。
   1. 安装Python包管理工具pip。
      ```
      sudo yum install python3-pip
      ```
      
   
   2. 安装WebSocket
      ```
      pip install websockets
      ```
      
    
4. 在后端服务器中，新建目录websocket。
   ```
   mkdir websocket
   ```
   
5. 在websocket目录下，新建一个websocket_server.py文件，并且在其中部署测试websocket应用服务。
   1. 新建websocket_server.py文件。
      ```
      vi websocket_server.py
      ```
      
   
   2. 按**i** 键进入编辑模式。
      单击查看本示例代码参考
      - websocket_server.py文件脚本，默认端口配置为8081。
        ```
        import asyncio
        import websockets
        async def echo(websocket):
            print(websocket.request.path)
            try:
                async for message in websocket:
                    print(f"Received: {message}")
                    await websocket.send("Hello client,this is server!")
                    print(f"Sent: Hello client,this is server!")
            except websockets.exceptions.ConnectionClosed as e:
                print(f"Connection closed with error: {e}")
            except Exception as e:
                print(f"Unexpected error: {e}")
        async def main():
            print("Starting server...")
            start_server = await websockets.serve(echo, "0.0.0.0", 8081)
            print("Server started")
            while True:
                await asyncio.sleep(1)
        asyncio.run(main())
        ```
        
        
    
6. 按**Esc** 键，输入**:wq**保存websocket_server.py文件。
7. 运行websocket_server.py文件。
   ```
   python3 websocket_server.py
   ```
   
8. 收到如[图2]的回显，表示WebSocket应用部署成功。
   图2WebSocket应用部署成功   
   ![](https://support.huaweicloud.com/bestpractice-elb/zh-cn_image_0000002375332889.png "点击放大") 
 
#### 步骤二：在客户端中部署WebSocket应用
1. 远程登录客户端ECS_client。 弹性云服务器有多种登录方法，具体请参见[登录弹性云服务器](https://support.huaweicloud.com/ecs_faq/ecs_faq_0632.html)。
   
2. 执行以下命令确保客户端的python版本不低于python 3.7。
   ```
   yum install python39
   ```
   
3. 执行以下命令在客户端中安装最新版websockets库。
   1. 安装Python包管理工具pip。
      ```
      sudo yum install python3-pip
      ```
      
   
   2. 安装WebSocket
      ```
      pip install websockets
      ```
      
    
4. 在客户端服务器中，新建目录websocket_client。
   ```
   mkdir websocket_client
   ```
   
5. 在websocket目录下，新建一个websocket_client.py文件，并且在其中部署websocket应用服务。
   1. 新建websocket_client.py文件。
      ```
      vi websocket_client.py
      ```
      
   
   2. 按**i** 键进入编辑模式。
      单击查看本示例代码参考
      - websocket_client.py文件脚本，使客户端可以访问ELB对外服务的EIP地址和端口，本实践示例端口为8081端口。
        ```
        import asyncio
        import websockets
        async def hello():
            uri = "ws://EIP_ELB:8081" 
            try:
                async with websockets.connect(uri) as websocket:
                    while True:
                        await websocket.send("Hello server,this is client!")
                        print("Sent: Hello server,this is client!")
                        response = await websocket.recv()
                        print(f"Received: {response}")
                        await asyncio.sleep(1)
            except websockets.exceptions.ConnectionClosedError as e:
                print(f"Connection closed with error: {e}")
        asyncio.get_event_loop().run_until_complete(hello())
        ```
        
        
    
6. 按**Esc** 键，输入**:wq**保存websocket_client.py文件。
 
 #### 步骤三：创建HTTP后端服务器组并添加后端服务器
1. 进入[后端服务器组列表页面](https://console.huaweicloud.com/vpc/?locale=zh-cn#/elb/elbPool/list)。
2. 在后端服务器列表页面，单击页面右上角"创建后端服务器组"按钮。
3. 在配置后端分配策略页面，选择将后端服务器组Server_Group关联至已经创建完成的ELB实例，后端协议选择"HTTP"。
4. 其余设置保持默认，单击"下一步"。
5. 在添加后端服务器页面，云服务器页签下，单击"添加云服务器"。
6. 在添加后端服务器侧拉窗中，选择ECS_server，并设置业务端口为8081。
7. 单击"下一步"后确认配置信息。
8. 单击"立即创建"。
 
#### 步骤四：创建HTTP监听器并选择后端服务器组
1. 进入[弹性负载均衡列表页面](https://console.huaweicloud.com/vpc/?locale=zh-cn#/elb/list)。
2. 在目标弹性负载均衡实例的操作列，单击"添加监听器"。
3. 在添加监听器页面，协议类型选择"HTTP"，端口设置为"8081"。
   图3添加HTTP监听器   
   ![](https://support.huaweicloud.com/bestpractice-elb/zh-cn_image_0000002341330246.png "点击放大") 
4. 单击"下一步：配置后端分配策略"，后端服务器组参数选择"使用已有"。选择[步骤三]创建完成的服务器组Server_Group，完成后单击"下一步：确认配置"。
5. 确认配置参数后，单击"提交"，完成HTTP监听器的创建。
 
#### 步骤五：验证结果
1. 远程登录客户端ECS_client。
2. 运行代码python websocket_client.py文件。
   ```
   python3 websocket_client.py
   ```
   
3. 看到客户端和后端服务器相继打印"Sent: Hello server, this is client!"和"Received: Hello client, this is server!"，验证了ELB通过WebSocket协议实现了实时聊天。
   图4ELB通过WebSocket协议实现了实时聊天。   
   ![](https://support.huaweicloud.com/bestpractice-elb/zh-cn_image_0000002341493904.png "点击放大") 
 
