{"id":64186,"date":"2026-01-22T23:04:41","date_gmt":"2026-01-22T15:04:41","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/64186.html"},"modified":"2026-01-22T23:04:41","modified_gmt":"2026-01-22T15:04:41","slug":"fchat%e4%b8%93%e4%b8%9a%e8%81%8a%e5%a4%a9%e6%9c%8d%e5%8a%a1%e5%99%a8-%e6%89%93%e9%80%a0%e9%ab%98%e6%95%88%e5%ae%9e%e6%97%b6%e9%80%9a%e8%ae%af%e5%b9%b3%e5%8f%b0%e7%9a%84%e5%88%a9","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/64186.html","title":{"rendered":"Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u2014\u2014\u6253\u9020\u9ad8\u6548\u5b9e\u65f6\u901a\u8baf\u5e73\u53f0\u7684\u5229\u5668"},"content":{"rendered":"<p>  \u672c\u6587\u8fd8\u6709\u914d\u5957\u7684\u7cbe\u54c1\u8d44\u6e90&#xff0c;\u70b9\u51fb\u83b7\u53d6  <img decoding=\"async\" alt=\"menu-r.4af5f7ec.gif\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122150439-69723c87ed57a.gif\" style=\"width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text\" \/> <\/p>\n<p> \u7b80\u4ecb&#xff1a;Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u662f\u4e00\u6b3e\u4e13\u4e3a\u6784\u5efa\u7a33\u5b9a\u3001\u5b89\u5168\u3001\u53ef\u6269\u5c55\u7684\u5b9e\u65f6\u901a\u8baf\u7cfb\u7edf\u800c\u8bbe\u8ba1\u7684\u9ad8\u6027\u80fd\u670d\u52a1\u5668\u8f6f\u4ef6&#xff0c;\u9002\u7528\u4e8e\u4f01\u4e1a\u6c9f\u901a\u3001\u5728\u7ebf\u5ba2\u670d\u3001\u793e\u4ea4\u5e94\u7528\u7b49\u591a\u573a\u666f\u3002\u5176\u5177\u5907\u5f3a\u5927\u7684\u6d88\u606f\u5904\u7406\u80fd\u529b&#xff0c;\u652f\u6301\u6587\u672c\u3001\u56fe\u7247\u3001\u8bed\u97f3\u3001\u89c6\u9891\u7b49\u591a\u79cd\u6d88\u606f\u7c7b\u578b&#xff0c;\u5e76\u91c7\u7528SSL\/TLS\u52a0\u5bc6\u6280\u672f\u4fdd\u969c\u901a\u4fe1\u5b89\u5168\u3002\u63d0\u4f9b\u5b8c\u5584\u7684API\u548cSDK&#xff0c;\u4fbf\u4e8e\u5f00\u53d1\u8005\u5feb\u901f\u96c6\u6210\u4e0e\u5b9a\u5236\u3002\u540c\u65f6\u652f\u6301\u96c6\u7fa4\u90e8\u7f72\u4e0e\u8d1f\u8f7d\u5747\u8861&#xff0c;\u5177\u5907\u826f\u597d\u7684\u5f39\u6027\u4f38\u7f29\u80fd\u529b&#xff0c;\u9002\u5408\u9ad8\u5e76\u53d1\u73af\u5883\u4e0b\u7684\u7a33\u5b9a\u8fd0\u884c\u3002  <img decoding=\"async\" alt=\"Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668.rar\" src=\"https:\/\/unita.co\/wp-content\/uploads\/2023\/05\/2-6-1024x566.png\" \/> <\/p>\n<h2> 1. Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u6982\u8ff0\u4e0e\u5e94\u7528\u573a\u666f <\/h2>\n<p> Fchat \u662f\u4e00\u6b3e\u9762\u5411\u9ad8\u5e76\u53d1\u3001\u4f4e\u5ef6\u8fdf\u573a\u666f\u6253\u9020\u7684\u4e13\u4e1a\u7ea7\u5373\u65f6\u901a\u8baf\u670d\u52a1\u5668&#xff0c;\u5177\u5907\u7a33\u5b9a\u3001\u9ad8\u6548\u3001\u53ef\u6269\u5c55\u7684\u7279\u6027&#xff0c;\u9002\u7528\u4e8e\u4f01\u4e1a\u5185\u90e8\u901a\u4fe1\u3001\u5728\u7ebf\u5ba2\u670d\u3001\u793e\u4ea4\u5e73\u53f0\u804a\u5929\u6a21\u5757\u7b49\u591a\u79cd\u4e1a\u52a1\u573a\u666f\u3002\u5176\u6838\u5fc3\u529f\u80fd\u5305\u62ec\u5b9e\u65f6\u6d88\u606f\u6536\u53d1\u3001\u6d88\u606f\u6301\u4e45\u5316\u3001\u7528\u6237\u72b6\u6001\u7ba1\u7406\u3001\u7fa4\u7ec4\u901a\u4fe1\u7b49&#xff0c;\u80fd\u591f\u652f\u6491\u5343\u4e07\u7ea7\u5e76\u53d1\u8fde\u63a5\u3002 <\/p>\n<p> \u5728\u6280\u672f\u67b6\u6784\u4e0a&#xff0c;Fchat \u91c7\u7528\u5206\u5e03\u5f0f\u90e8\u7f72\u4e0e\u5fae\u670d\u52a1\u8bbe\u8ba1\u7406\u5ff5&#xff0c;\u7ed3\u5408\u9ad8\u6027\u80fd\u7f51\u7edc\u901a\u4fe1\u6846\u67b6&#xff0c;\u5b9e\u73b0\u6d88\u606f\u7684\u5feb\u901f\u6295\u9012\u4e0e\u7cfb\u7edf\u9ad8\u53ef\u7528\u6027\u3002\u5176\u5e95\u5c42\u652f\u6301\u591a\u79cd\u901a\u4fe1\u534f\u8bae&#xff0c;\u5e76\u53ef\u901a\u8fc7\u63d2\u4ef6\u673a\u5236\u7075\u6d3b\u6269\u5c55\u529f\u80fd\u6a21\u5757&#xff0c;\u6ee1\u8db3\u4e0d\u540c\u884c\u4e1a\u4e0e\u573a\u666f\u7684\u5b9a\u5236\u5316\u9700\u6c42\u3002 <\/p>\n<p> \u901a\u8fc7\u672c\u7ae0\u7684\u5b66\u4e60&#xff0c;\u8bfb\u8005\u5c06\u4e86\u89e3 Fchat \u7684\u6574\u4f53\u67b6\u6784\u5b9a\u4f4d\u3001\u6280\u672f\u4f18\u52bf\u4ee5\u53ca\u5728\u4e0d\u540c\u5e94\u7528\u573a\u666f\u4e0b\u7684\u90e8\u7f72\u4e0e\u4f7f\u7528\u65b9\u5f0f&#xff0c;\u4e3a\u540e\u7eed\u6df1\u5165\u638c\u63e1\u5176\u901a\u4fe1\u673a\u5236\u4e0e\u5f00\u53d1\u96c6\u6210\u6253\u4e0b\u575a\u5b9e\u57fa\u7840\u3002 <\/p>\n<h2> 2. \u5b9e\u65f6\u901a\u8baf\u67b6\u6784\u8bbe\u8ba1\u4e0e\u5b9e\u73b0 <\/h2>\n<p> \u5b9e\u65f6\u901a\u8baf\u662f\u73b0\u4ee3\u4e92\u8054\u7f51\u5e94\u7528\u7684\u6838\u5fc3\u529f\u80fd\u4e4b\u4e00&#xff0c;\u5c24\u5176\u5728\u4f01\u4e1a\u7ea7\u804a\u5929\u3001\u5728\u7ebf\u5ba2\u670d\u3001\u793e\u4ea4\u5e73\u53f0\u7b49\u573a\u666f\u4e2d&#xff0c;\u5bf9\u901a\u8baf\u7684\u5b9e\u65f6\u6027\u3001\u7a33\u5b9a\u6027\u3001\u53ef\u6269\u5c55\u6027\u8981\u6c42\u6781\u9ad8\u3002Fchat \u4f5c\u4e3a\u4e00\u6b3e\u9ad8\u6027\u80fd\u7684\u5373\u65f6\u901a\u8baf\u670d\u52a1\u5668&#xff0c;\u5176\u5e95\u5c42\u901a\u8baf\u67b6\u6784\u8bbe\u8ba1\u5145\u5206\u8003\u8651\u4e86\u9ad8\u5e76\u53d1\u3001\u4f4e\u5ef6\u8fdf\u3001\u53ef\u6269\u5c55\u7b49\u5173\u952e\u8981\u7d20&#xff0c;\u6784\u5efa\u4e86\u4e00\u5957\u5b8c\u6574\u4e14\u9ad8\u6548\u7684\u901a\u8baf\u4f53\u7cfb\u3002 <\/p>\n<p> \u672c\u7ae0\u5c06\u4ece Fchat \u7684\u901a\u8baf\u67b6\u6784\u7ec4\u6210\u3001\u901a\u4fe1\u534f\u8bae\u9009\u578b\u4e0e\u4f18\u5316\u3001\u9ad8\u53ef\u7528\u67b6\u6784\u8bbe\u8ba1\u4e09\u4e2a\u65b9\u9762&#xff0c;\u6df1\u5165\u89e3\u6790\u5176\u5b9e\u65f6\u901a\u8baf\u67b6\u6784\u7684\u8bbe\u8ba1\u539f\u7406\u4e0e\u5b9e\u73b0\u673a\u5236&#xff0c;\u5e2e\u52a9\u8bfb\u8005\u7406\u89e3\u5176\u6280\u672f\u6838\u5fc3\u548c\u843d\u5730\u903b\u8f91\u3002 <\/p>\n<h3> 2.1 Fchat\u901a\u8baf\u67b6\u6784\u7684\u7ec4\u6210 <\/h3>\n<p> Fchat \u7684\u901a\u8baf\u67b6\u6784\u7531\u591a\u4e2a\u6838\u5fc3\u6a21\u5757\u7ec4\u6210&#xff0c;\u5305\u62ec\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u7aef\u4ea4\u4e92\u6d41\u7a0b\u3001\u6d88\u606f\u4e2d\u8f6c\u670d\u52a1\u5668\u3001\u72b6\u6001\u540c\u6b65\u4e0e\u5fc3\u8df3\u673a\u5236\u7b49\u3002\u8fd9\u4e9b\u6a21\u5757\u534f\u540c\u5de5\u4f5c&#xff0c;\u6784\u6210\u4e86\u4e00\u4e2a\u9ad8\u6548\u3001\u7a33\u5b9a\u7684\u5373\u65f6\u901a\u8baf\u7cfb\u7edf\u3002 <\/p>\n<h4> 2.1.1 \u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u7aef\u4ea4\u4e92\u6d41\u7a0b <\/h4>\n<p> Fchat \u7684\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u7aef\u4ea4\u4e92\u6d41\u7a0b\u662f\u6574\u4e2a\u901a\u8baf\u7cfb\u7edf\u7684\u57fa\u7840\u3002\u5ba2\u6237\u7aef\u901a\u8fc7\u5efa\u7acb\u8fde\u63a5\u3001\u53d1\u9001\u8bf7\u6c42\u3001\u63a5\u6536\u54cd\u5e94\u7684\u65b9\u5f0f\u4e0e\u670d\u52a1\u7aef\u8fdb\u884c\u6570\u636e\u4ea4\u4e92\u3002 <\/p>\n<h5> \u4ea4\u4e92\u6d41\u7a0b\u56fe&#xff08;Mermaid&#xff09; <\/h5>\n<p>sequenceDiagram<br \/>\n    participant Client<br \/>\n    participant Server<br \/>\n    Client-&gt;&gt;Server: \u5efa\u7acb\u8fde\u63a5&#xff08;Connect&#xff09;<br \/>\n    Server&#8211;&gt;&gt;Client: \u8fde\u63a5\u786e\u8ba4&#xff08;ACK&#xff09;<br \/>\n    Client-&gt;&gt;Server: \u53d1\u9001\u767b\u5f55\u8bf7\u6c42&#xff08;Login&#xff09;<br \/>\n    Server&#8211;&gt;&gt;Client: \u767b\u5f55\u6210\u529f\u6216\u5931\u8d25\u54cd\u5e94<br \/>\n    Client-&gt;&gt;Server: \u53d1\u9001\u6d88\u606f\u8bf7\u6c42&#xff08;Send Message&#xff09;<br \/>\n    Server&#8211;&gt;&gt;Client: \u6d88\u606f\u53d1\u9001\u72b6\u6001\u53cd\u9988<br \/>\n    Server-&gt;&gt;Client: \u63a5\u6536\u5230\u7684\u6d88\u606f\u63a8\u9001<br \/>\n    Client-&gt;&gt;Server: \u53d1\u9001\u65ad\u5f00\u8bf7\u6c42&#xff08;Logout&#xff09;<br \/>\n    Server&#8211;&gt;&gt;Client: \u65ad\u5f00\u8fde\u63a5\u786e\u8ba4<\/p>\n<h5> \u6d41\u7a0b\u8bf4\u660e <\/h5>\n<li>  \u5efa\u7acb\u8fde\u63a5  &#xff1a;\u5ba2\u6237\u7aef\u4f7f\u7528 TCP \u6216 WebSocket \u534f\u8bae\u4e0e\u670d\u52a1\u7aef\u5efa\u7acb\u8fde\u63a5\u3002 <\/li>\n<li>  \u767b\u5f55\u8bf7\u6c42  &#xff1a;\u5ba2\u6237\u7aef\u53d1\u9001\u5305\u542b\u7528\u6237\u540d\u3001\u5bc6\u7801\u3001\u8bbe\u5907\u4fe1\u606f\u7b49\u5b57\u6bb5\u7684\u767b\u5f55\u8bf7\u6c42\u3002 <\/li>\n<li>  \u8eab\u4efd\u9a8c\u8bc1  &#xff1a;\u670d\u52a1\u7aef\u9a8c\u8bc1\u7528\u6237\u8eab\u4efd\u5e76\u8fd4\u56de\u767b\u5f55\u72b6\u6001\u3002 <\/li>\n<li>  \u6d88\u606f\u6536\u53d1  &#xff1a;\u767b\u5f55\u6210\u529f\u540e&#xff0c;\u5ba2\u6237\u7aef\u53ef\u53d1\u9001\u6d88\u606f&#xff0c;\u670d\u52a1\u7aef\u63a5\u6536\u5e76\u8f6c\u53d1\u7ed9\u76ee\u6807\u7528\u6237\u3002 <\/li>\n<li>  \u6d88\u606f\u63a8\u9001  &#xff1a;\u670d\u52a1\u7aef\u4e3b\u52a8\u5c06\u6d88\u606f\u63a8\u9001\u7ed9\u76ee\u6807\u5ba2\u6237\u7aef\u3002 <\/li>\n<li>  \u65ad\u5f00\u8fde\u63a5  &#xff1a;\u5ba2\u6237\u7aef\u53d1\u9001\u767b\u51fa\u8bf7\u6c42&#xff0c;\u670d\u52a1\u7aef\u5173\u95ed\u8fde\u63a5\u3002 <\/li>\n<h5> \u4ee3\u7801\u793a\u4f8b&#xff1a;\u5ba2\u6237\u7aef\u8fde\u63a5\u4e0e\u767b\u5f55\u6d41\u7a0b&#xff08;WebSocket&#xff09; <\/h5>\n<p>const WebSocket &#061; require(&#039;ws&#039;);<\/p>\n<p>const ws &#061; new WebSocket(&#039;ws:\/\/fchat-server:8080&#039;);<\/p>\n<p>ws.on(&#039;open&#039;, function open() {<br \/>\n    \/\/ \u53d1\u9001\u767b\u5f55\u8bf7\u6c42<br \/>\n    const loginData &#061; {<br \/>\n        action: &#039;login&#039;,<br \/>\n        username: &#039;user123&#039;,<br \/>\n        password: &#039;pass123&#039;,<br \/>\n        deviceId: &#039;device001&#039;<br \/>\n    };<br \/>\n    ws.send(JSON.stringify(loginData));<br \/>\n});<\/p>\n<p>ws.on(&#039;message&#039;, function incoming(data) {<br \/>\n    const message &#061; JSON.parse(data);<br \/>\n    console.log(&#039;Received message:&#039;, message);<br \/>\n    if (message.type &#061;&#061;&#061; &#039;login_success&#039;) {<br \/>\n        console.log(&#039;\u767b\u5f55\u6210\u529f&#039;);<br \/>\n    } else if (message.type &#061;&#061;&#061; &#039;message&#039;) {<br \/>\n        console.log(&#039;\u6536\u5230\u6d88\u606f:&#039;, message.content);<br \/>\n    }<br \/>\n});<\/p>\n<h5> \u4ee3\u7801\u89e3\u6790 <\/h5>\n<ul>\n<li>  WebSocket  &#xff1a;\u4f7f\u7528 Node.js \u7684  ws  \u6a21\u5757\u5efa\u7acb WebSocket \u8fde\u63a5\u3002 <\/li>\n<li>  open  \u4e8b\u4ef6&#xff1a;\u8fde\u63a5\u5efa\u7acb\u540e\u53d1\u9001\u767b\u5f55\u8bf7\u6c42\u3002 <\/li>\n<li>  message  \u4e8b\u4ef6&#xff1a;\u76d1\u542c\u670d\u52a1\u7aef\u63a8\u9001\u7684\u6d88\u606f&#xff0c;\u8fdb\u884c\u89e3\u6790\u548c\u5904\u7406\u3002 <\/li>\n<li>  loginData  &#xff1a;\u5c01\u88c5\u767b\u5f55\u4fe1\u606f&#xff0c;\u5305\u62ec\u7528\u6237\u540d\u3001\u5bc6\u7801\u3001\u8bbe\u5907ID\u7b49\u3002 <\/li>\n<li>  message.type  &#xff1a;\u6839\u636e\u6d88\u606f\u7c7b\u578b\u5224\u65ad\u662f\u767b\u5f55\u54cd\u5e94\u8fd8\u662f\u666e\u901a\u6d88\u606f\u3002 <\/li>\n<\/ul>\n<h4> 2.1.2 \u6d88\u606f\u4e2d\u8f6c\u670d\u52a1\u5668\u7684\u8bbe\u8ba1\u539f\u7406 <\/h4>\n<p> \u5728\u5206\u5e03\u5f0f\u7cfb\u7edf\u4e2d&#xff0c;\u6d88\u606f\u4e2d\u8f6c\u670d\u52a1\u5668&#xff08;Message Broker&#xff09;\u8d1f\u8d23\u63a5\u6536\u5ba2\u6237\u7aef\u53d1\u9001\u7684\u6d88\u606f&#xff0c;\u5e76\u8f6c\u53d1\u7ed9\u76ee\u6807\u5ba2\u6237\u7aef\u6216\u670d\u52a1\u7aef\u6a21\u5757\u3002Fchat \u7684\u6d88\u606f\u4e2d\u8f6c\u670d\u52a1\u5668\u91c7\u7528\u5f02\u6b65\u975e\u963b\u585e\u67b6\u6784&#xff0c;\u652f\u6301\u9ad8\u5e76\u53d1\u4e0b\u7684\u6d88\u606f\u5904\u7406\u3002 <\/p>\n<h5> \u67b6\u6784\u56fe&#xff08;Mermaid&#xff09; <\/h5>\n<p>graph LR<br \/>\n    A[Client] &#8211;&gt; B[Message Broker]<br \/>\n    B &#8211;&gt; C[Message Processing]<br \/>\n    B &#8211;&gt; D[Push Server]<br \/>\n    C &#8211;&gt; E[Database]<br \/>\n    D &#8211;&gt; F[Target Client]<\/p>\n<h5> \u8bbe\u8ba1\u7279\u70b9 <\/h5>\n<li>  \u5f02\u6b65\u5904\u7406  &#xff1a;\u91c7\u7528\u4e8b\u4ef6\u9a71\u52a8\u6a21\u578b&#xff0c;\u6d88\u606f\u5230\u8fbe\u540e\u7acb\u5373\u5165\u961f&#xff0c;\u5f02\u6b65\u5904\u7406\u907f\u514d\u963b\u585e\u4e3b\u7ebf\u7a0b\u3002 <\/li>\n<li>  \u8d1f\u8f7d\u5747\u8861  &#xff1a;\u591a\u4e2a\u6d88\u606f\u4e2d\u8f6c\u670d\u52a1\u5668\u4e4b\u95f4\u4f7f\u7528\u4e00\u81f4\u6027\u54c8\u5e0c\u7b97\u6cd5\u8fdb\u884c\u6d88\u606f\u8def\u7531\u3002 <\/li>\n<li>  \u6d88\u606f\u961f\u5217  &#xff1a;\u96c6\u6210 Kafka \u6216 RocketMQ&#xff0c;\u5b9e\u73b0\u6d88\u606f\u7f13\u51b2\u4e0e\u6301\u4e45\u5316\u3002 <\/li>\n<li>  \u591a\u534f\u8bae\u652f\u6301  &#xff1a;\u652f\u6301 TCP\u3001WebSocket\u3001HTTP \u591a\u79cd\u534f\u8bae\u63a5\u5165\u3002 <\/li>\n<h5> \u4ee3\u7801\u793a\u4f8b&#xff1a;\u6d88\u606f\u4e2d\u8f6c\u670d\u52a1\u5668\u4f2a\u4ee3\u7801&#xff08;Go&#xff09; <\/h5>\n<p>func handleClient(conn net.Conn) {<br \/>\n    for {<br \/>\n        msg, err :&#061; readMessage(conn)<br \/>\n        if err !&#061; nil {<br \/>\n            log.Println(&#034;Error reading:&#034;, err.Error())<br \/>\n            break<br \/>\n        }<\/p>\n<p>        \/\/ \u5f02\u6b65\u8f6c\u53d1\u6d88\u606f<br \/>\n        go func(m Message) {<br \/>\n            err :&#061; messageQueue.Publish(&#034;messages&#034;, m)<br \/>\n            if err !&#061; nil {<br \/>\n                log.Println(&#034;Failed to publish message:&#034;, err)<br \/>\n            }<br \/>\n        }(msg)<br \/>\n    }<br \/>\n}<\/p>\n<h5> \u4ee3\u7801\u89e3\u6790 <\/h5>\n<ul>\n<li>  handleClient  &#xff1a;\u5904\u7406\u5ba2\u6237\u7aef\u8fde\u63a5&#xff0c;\u6301\u7eed\u8bfb\u53d6\u6d88\u606f\u3002 <\/li>\n<li>  readMessage  &#xff1a;\u4ece\u8fde\u63a5\u4e2d\u8bfb\u53d6\u6d88\u606f\u5185\u5bb9\u3002 <\/li>\n<li>  messageQueue.Publish  &#xff1a;\u5c06\u6d88\u606f\u53d1\u5e03\u5230\u6d88\u606f\u961f\u5217\u4e2d&#xff0c;\u5b9e\u73b0\u5f02\u6b65\u8f6c\u53d1\u3002 <\/li>\n<li>  go func()  &#xff1a;\u4f7f\u7528 Go \u534f\u7a0b\u5b9e\u73b0\u975e\u963b\u585e\u5f02\u6b65\u5904\u7406\u3002 <\/li>\n<\/ul>\n<h4> 2.1.3 \u72b6\u6001\u540c\u6b65\u4e0e\u5fc3\u8df3\u673a\u5236 <\/h4>\n<p> \u4e3a\u4e86\u4fdd\u8bc1\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u7aef\u4e4b\u95f4\u7684\u8fde\u63a5\u72b6\u6001\u4e00\u81f4\u6027&#xff0c;Fchat \u5f15\u5165\u4e86\u5fc3\u8df3\u673a\u5236\u548c\u72b6\u6001\u540c\u6b65\u7b56\u7565\u3002 <\/p>\n<h5> \u5fc3\u8df3\u673a\u5236\u6d41\u7a0b&#xff08;Mermaid&#xff09; <\/h5>\n<p>sequenceDiagram<br \/>\n    participant Client<br \/>\n    participant Server<br \/>\n    loop \u6bcf\u96945\u79d2<br \/>\n        Client-&gt;&gt;Server: \u53d1\u9001\u5fc3\u8df3\u5305&#xff08;Ping&#xff09;<br \/>\n        Server&#8211;&gt;&gt;Client: \u56de\u590d\u5fc3\u8df3\u54cd\u5e94&#xff08;Pong&#xff09;<br \/>\n    end<\/p>\n<h5> \u5b9e\u73b0\u903b\u8f91 <\/h5>\n<li>  \u5b9a\u65f6\u53d1\u9001\u5fc3\u8df3  &#xff1a;\u5ba2\u6237\u7aef\u6bcf\u9694\u56fa\u5b9a\u65f6\u95f4&#xff08;\u59825\u79d2&#xff09;\u53d1\u9001\u5fc3\u8df3\u5305\u3002 <\/li>\n<li>  \u670d\u52a1\u7aef\u54cd\u5e94  &#xff1a;\u670d\u52a1\u7aef\u63a5\u6536\u5230\u5fc3\u8df3\u5305\u540e&#xff0c;\u8bb0\u5f55\u5ba2\u6237\u7aef\u6d3b\u8dc3\u72b6\u6001\u3002 <\/li>\n<li>  \u8d85\u65f6\u68c0\u6d4b  &#xff1a;\u670d\u52a1\u7aef\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4&#xff08;\u598215\u79d2&#xff09;&#xff0c;\u82e5\u672a\u6536\u5230\u5fc3\u8df3\u5219\u6807\u8bb0\u4e3a\u65ad\u5f00\u3002 <\/li>\n<li>  \u72b6\u6001\u540c\u6b65  &#xff1a;\u5ba2\u6237\u7aef\u65ad\u5f00\u540e&#xff0c;\u670d\u52a1\u7aef\u901a\u77e5\u76f8\u5173\u7528\u6237\u8be5\u7528\u6237\u4e0b\u7ebf\u3002 <\/li>\n<h5> \u4ee3\u7801\u793a\u4f8b&#xff1a;\u5fc3\u8df3\u68c0\u6d4b&#xff08;Node.js&#xff09; <\/h5>\n<p>setInterval(() &#061;&gt; {<br \/>\n    if (lastPongTime &lt; Date.now() &#8211; 15000) {<br \/>\n        console.log(&#039;\u5ba2\u6237\u7aef\u5df2\u65ad\u5f00&#039;);<br \/>\n        ws.close();<br \/>\n    } else {<br \/>\n        ws.send(JSON.stringify({ type: &#039;ping&#039; }));<br \/>\n    }<br \/>\n}, 5000);<\/p>\n<h5> \u4ee3\u7801\u89e3\u6790 <\/h5>\n<ul>\n<li>  setInterval  &#xff1a;\u6bcf5\u79d2\u6267\u884c\u4e00\u6b21\u5fc3\u8df3\u68c0\u6d4b\u3002 <\/li>\n<li>  lastPongTime  &#xff1a;\u8bb0\u5f55\u6700\u540e\u4e00\u6b21\u6536\u5230 Pong \u54cd\u5e94\u7684\u65f6\u95f4\u3002 <\/li>\n<li>  15000ms  &#xff1a;15\u79d2\u672a\u6536\u5230\u54cd\u5e94\u89c6\u4e3a\u65ad\u5f00\u8fde\u63a5\u3002 <\/li>\n<li>  ws.send  &#xff1a;\u53d1\u9001\u5fc3\u8df3\u5305&#xff08;Ping&#xff09;\u3002 <\/li>\n<\/ul>\n<h3> 2.2 \u901a\u4fe1\u534f\u8bae\u9009\u578b\u4e0e\u4f18\u5316 <\/h3>\n<p> Fchat \u652f\u6301\u591a\u79cd\u901a\u4fe1\u534f\u8bae&#xff0c;\u4e3b\u8981\u5305\u62ec TCP \u548c WebSocket&#xff0c;\u540c\u65f6\u652f\u6301\u81ea\u5b9a\u4e49\u534f\u8bae\u5c01\u88c5&#xff0c;\u4ee5\u6ee1\u8db3\u4e0d\u540c\u573a\u666f\u4e0b\u7684\u901a\u8baf\u9700\u6c42\u3002 <\/p>\n<h4> 2.2.1 TCP\u4e0eWebSocket\u534f\u8bae\u5bf9\u6bd4 <\/h4>\n<table>\n<tr> \u7279\u6027  TCP  WebSocket <\/tr>\n<tbody>\n<tr>\n<td> \u4f20\u8f93\u5c42\u534f\u8bae <\/td>\n<td> \u57fa\u4e8e TCP <\/td>\n<td> \u57fa\u4e8e TCP <\/td>\n<\/tr>\n<tr>\n<td> \u8fde\u63a5\u4fdd\u6301 <\/td>\n<td> \u957f\u8fde\u63a5 <\/td>\n<td> \u957f\u8fde\u63a5 <\/td>\n<\/tr>\n<tr>\n<td> HTTP\u517c\u5bb9 <\/td>\n<td> \u4e0d\u517c\u5bb9 <\/td>\n<td> \u517c\u5bb9 <\/td>\n<\/tr>\n<tr>\n<td> \u8bf7\u6c42\/\u54cd\u5e94\u6a21\u578b <\/td>\n<td> \u65e0 <\/td>\n<td> \u652f\u6301 <\/td>\n<\/tr>\n<tr>\n<td> \u6570\u636e\u683c\u5f0f <\/td>\n<td> \u4e8c\u8fdb\u5236\u6216\u81ea\u5b9a\u4e49\u534f\u8bae <\/td>\n<td> \u652f\u6301\u6587\u672c\u548c\u4e8c\u8fdb\u5236 <\/td>\n<\/tr>\n<tr>\n<td> \u9002\u7528\u4e8e\u79fb\u52a8\u7aef <\/td>\n<td> \u4e00\u822c <\/td>\n<td> \u66f4\u9002\u5408 <\/td>\n<\/tr>\n<tr>\n<td> NAT\/\u9632\u706b\u5899\u7a7f\u900f\u80fd\u529b <\/td>\n<td> \u5f31 <\/td>\n<td> \u5f3a <\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h5> \u9002\u7528\u573a\u666f\u5206\u6790 <\/h5>\n<ul>\n<li>  TCP  &#xff1a;\u9002\u7528\u4e8e\u5185\u7f51\u901a\u4fe1\u3001\u9ad8\u541e\u5410\u91cf\u3001\u4f4e\u5ef6\u8fdf\u573a\u666f\u3002 <\/li>\n<li>  WebSocket  &#xff1a;\u9002\u7528\u4e8e\u516c\u7f51\u901a\u4fe1\u3001\u6d4f\u89c8\u5668\u7aef\u652f\u6301\u3001\u5b9e\u65f6\u6027\u8981\u6c42\u9ad8\u7684\u573a\u666f\u3002 <\/li>\n<\/ul>\n<h4> 2.2.2 \u81ea\u5b9a\u4e49\u534f\u8bae\u5c01\u88c5\u4e0e\u89e3\u6790\u7b56\u7565 <\/h4>\n<p> \u4e3a\u4e86\u63d0\u5347\u4f20\u8f93\u6548\u7387\u548c\u5b89\u5168\u6027&#xff0c;Fchat \u4f7f\u7528\u81ea\u5b9a\u4e49\u4e8c\u8fdb\u5236\u534f\u8bae\u8fdb\u884c\u6d88\u606f\u4f20\u8f93\u3002 <\/p>\n<h5> \u534f\u8bae\u7ed3\u6784\u793a\u4f8b <\/h5>\n<table>\n<tr> \u5b57\u6bb5\u540d  \u7c7b\u578b  \u957f\u5ea6&#xff08;\u5b57\u8282&#xff09;  \u8bf4\u660e <\/tr>\n<tbody>\n<tr>\n<td> Magic Number <\/td>\n<td> uint8 <\/td>\n<td> 1 <\/td>\n<td> \u534f\u8bae\u6807\u8bc6\u7b26 <\/td>\n<\/tr>\n<tr>\n<td> Version <\/td>\n<td> uint8 <\/td>\n<td> 1 <\/td>\n<td> \u534f\u8bae\u7248\u672c\u53f7 <\/td>\n<\/tr>\n<tr>\n<td> MessageType <\/td>\n<td> uint16 <\/td>\n<td> 2 <\/td>\n<td> \u6d88\u606f\u7c7b\u578b <\/td>\n<\/tr>\n<tr>\n<td> Length <\/td>\n<td> uint32 <\/td>\n<td> 4 <\/td>\n<td> \u6d88\u606f\u4f53\u957f\u5ea6 <\/td>\n<\/tr>\n<tr>\n<td> Payload <\/td>\n<td> byte[] <\/td>\n<td> \u53ef\u53d8 <\/td>\n<td> \u6d88\u606f\u4f53\u5185\u5bb9 <\/td>\n<\/tr>\n<tr>\n<td> CRC32 <\/td>\n<td> uint32 <\/td>\n<td> 4 <\/td>\n<td> \u6821\u9a8c\u7801 <\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h5> \u89e3\u6790\u4ee3\u7801&#xff08;Python&#xff09; <\/h5>\n<p>import struct<br \/>\nimport zlib<\/p>\n<p>def parse_message(data):<br \/>\n    # \u89e3\u6790\u534f\u8bae\u5934<br \/>\n    header &#061; struct.unpack(&#039;!BBHI&#039;, data[:8])<br \/>\n    magic, version, msg_type, length &#061; header<br \/>\n    payload &#061; data[8:8&#043;length]<br \/>\n    crc &#061; struct.unpack(&#039;!I&#039;, data[8&#043;length:8&#043;length&#043;4])[0]<\/p>\n<p>    # \u6821\u9a8c<br \/>\n    if zlib.crc32(payload) !&#061; crc:<br \/>\n        raise ValueError(&#034;CRC\u6821\u9a8c\u5931\u8d25&#034;)<\/p>\n<p>    return {<br \/>\n        &#039;magic&#039;: magic,<br \/>\n        &#039;version&#039;: version,<br \/>\n        &#039;type&#039;: msg_type,<br \/>\n        &#039;payload&#039;: payload<br \/>\n    }<\/p>\n<h5> \u4ee3\u7801\u89e3\u6790 <\/h5>\n<ul>\n<li>  struct.unpack  &#xff1a;\u7528\u4e8e\u89e3\u6790\u56fa\u5b9a\u957f\u5ea6\u7684\u534f\u8bae\u5934\u5b57\u6bb5\u3002 <\/li>\n<li>  zlib.crc32  &#xff1a;\u8ba1\u7b97\u6d88\u606f\u4f53\u7684 CRC \u6821\u9a8c\u7801&#xff0c;\u786e\u4fdd\u6570\u636e\u5b8c\u6574\u6027\u3002 <\/li>\n<li>  payload  &#xff1a;\u89e3\u6790\u51fa\u7684\u6d88\u606f\u4f53&#xff0c;\u540e\u7eed\u53ef\u8fdb\u4e00\u6b65\u53cd\u5e8f\u5217\u5316\u4e3a JSON \u6216 Protobuf \u5bf9\u8c61\u3002 <\/li>\n<\/ul>\n<h4> 2.2.3 \u534f\u8bae\u7248\u672c\u7ba1\u7406\u4e0e\u517c\u5bb9\u6027\u5904\u7406 <\/h4>\n<p> Fchat \u7684\u534f\u8bae\u7248\u672c\u91c7\u7528\u8bed\u4e49\u5316\u7248\u672c\u53f7&#xff08;\u5982 v1.0.0&#xff09;&#xff0c;\u901a\u8fc7\u7248\u672c\u53f7\u5224\u65ad\u662f\u5426\u517c\u5bb9&#xff0c;\u5b9e\u73b0\u5411\u524d\u517c\u5bb9\u548c\u5411\u540e\u517c\u5bb9\u3002 <\/p>\n<h5> \u7248\u672c\u63a7\u5236\u7b56\u7565 <\/h5>\n<ul>\n<li>  \u4e3b\u7248\u672c\u53f7\u53d8\u66f4  &#xff1a;\u8868\u793a\u534f\u8bae\u7ed3\u6784\u53d1\u751f\u91cd\u5927\u53d8\u5316&#xff0c;\u4e0d\u517c\u5bb9\u65e7\u7248\u672c\u3002 <\/li>\n<li>  \u6b21\u7248\u672c\u53f7\u53d8\u66f4  &#xff1a;\u65b0\u589e\u5b57\u6bb5\u6216\u6269\u5c55\u529f\u80fd&#xff0c;\u4fdd\u6301\u517c\u5bb9\u3002 <\/li>\n<li>  \u4fee\u8ba2\u53f7\u53d8\u66f4  &#xff1a;\u4fee\u590d Bug&#xff0c;\u4e0d\u5f71\u54cd\u7ed3\u6784&#xff0c;\u5b8c\u5168\u517c\u5bb9\u3002 <\/li>\n<\/ul>\n<h5> \u4ee3\u7801\u903b\u8f91&#xff08;Go&#xff09; <\/h5>\n<p>func handleMessage(header Header, payload []byte) error {<br \/>\n    switch header.Version {<br \/>\n    case 1:<br \/>\n        return handleV1Message(payload)<br \/>\n    case 2:<br \/>\n        return handleV2Message(payload)<br \/>\n    default:<br \/>\n        return fmt.Errorf(&#034;\u4e0d\u652f\u6301\u7684\u534f\u8bae\u7248\u672c: %d&#034;, header.Version)<br \/>\n    }<br \/>\n}<\/p>\n<h5> \u4ee3\u7801\u89e3\u6790 <\/h5>\n<ul>\n<li>  handleMessage  &#xff1a;\u6839\u636e\u534f\u8bae\u7248\u672c\u53f7\u9009\u62e9\u4e0d\u540c\u7684\u5904\u7406\u903b\u8f91\u3002 <\/li>\n<li>  handleV1Message  \/  handleV2Message  &#xff1a;\u5206\u522b\u5904\u7406\u4e0d\u540c\u7248\u672c\u7684\u6d88\u606f\u683c\u5f0f\u3002 <\/li>\n<\/ul>\n<h3> 2.3 \u9ad8\u53ef\u7528\u67b6\u6784\u8bbe\u8ba1 <\/h3>\n<p> Fchat \u91c7\u7528\u5206\u5e03\u5f0f\u67b6\u6784&#xff0c;\u652f\u6301\u591a\u8282\u70b9\u90e8\u7f72\u3001\u6545\u969c\u8f6c\u79fb\u3001\u6570\u636e\u6301\u4e45\u5316\u7b49\u673a\u5236&#xff0c;\u786e\u4fdd\u7cfb\u7edf\u7684\u9ad8\u53ef\u7528\u6027\u548c\u7a33\u5b9a\u6027\u3002 <\/p>\n<h4> 2.3.1 \u6545\u969c\u8f6c\u79fb\u673a\u5236&#xff08;Failover&#xff09; <\/h4>\n<p> Fchat \u7684\u6545\u969c\u8f6c\u79fb\u673a\u5236\u901a\u8fc7\u5065\u5eb7\u68c0\u67e5\u548c\u4e3b\u4ece\u5207\u6362\u5b9e\u73b0&#xff0c;\u786e\u4fdd\u5728\u8282\u70b9\u5b95\u673a\u65f6\u4ecd\u80fd\u63d0\u4f9b\u670d\u52a1\u3002 <\/p>\n<h5> \u6545\u969c\u8f6c\u79fb\u6d41\u7a0b&#xff08;Mermaid&#xff09; <\/h5>\n<p>graph LR<br \/>\n    A[\u4e3b\u8282\u70b9] &#8211;&gt;|\u5b95\u673a| B[\u76d1\u63a7\u670d\u52a1]<br \/>\n    B &#8211;&gt; C[\u9009\u4e3e\u65b0\u4e3b\u8282\u70b9]<br \/>\n    C &#8211;&gt; D[\u4ece\u8282\u70b9\u5347\u7ea7\u4e3a\u4e3b]<br \/>\n    D &#8211;&gt; E[\u7ee7\u7eed\u63d0\u4f9b\u670d\u52a1]<\/p>\n<h5> \u5b9e\u73b0\u65b9\u5f0f <\/h5>\n<ul>\n<li>  \u5065\u5eb7\u68c0\u67e5  &#xff1a;\u5b9a\u65f6\u5411\u5404\u8282\u70b9\u53d1\u9001\u5fc3\u8df3\u5305&#xff0c;\u68c0\u6d4b\u662f\u5426\u5b58\u6d3b\u3002 <\/li>\n<li>  ZooKeeper\/Etcd  &#xff1a;\u7528\u4e8e\u8282\u70b9\u6ce8\u518c\u3001\u9009\u4e3e\u4e3b\u8282\u70b9\u3002 <\/li>\n<li>  \u81ea\u52a8\u5207\u6362  &#xff1a;\u4e3b\u8282\u70b9\u5b95\u673a\u540e&#xff0c;\u4ece\u8282\u70b9\u63a5\u7ba1\u670d\u52a1\u5e76\u540c\u6b65\u72b6\u6001\u3002 <\/li>\n<\/ul>\n<h4> 2.3.2 \u6570\u636e\u6301\u4e45\u5316\u4e0e\u72b6\u6001\u540c\u6b65 <\/h4>\n<p> \u4e3a\u4e86\u4fdd\u8bc1\u6d88\u606f\u4e0d\u4e22\u5931&#xff0c;Fchat \u5c06\u6d88\u606f\u6301\u4e45\u5316\u5230\u6570\u636e\u5e93\u4e2d&#xff0c;\u5e76\u901a\u8fc7\u72b6\u6001\u540c\u6b65\u673a\u5236\u7ef4\u62a4\u7528\u6237\u5728\u7ebf\u72b6\u6001\u3002 <\/p>\n<h5> \u6570\u636e\u7ed3\u6784\u793a\u4f8b&#xff08;MySQL&#xff09; <\/h5>\n<p>CREATE TABLE messages (<br \/>\n    id BIGINT AUTO_INCREMENT PRIMARY KEY,<br \/>\n    sender VARCHAR(64),<br \/>\n    receiver VARCHAR(64),<br \/>\n    content TEXT,<br \/>\n    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP<br \/>\n);<\/p>\n<h5> \u540c\u6b65\u7b56\u7565 <\/h5>\n<ul>\n<li>  \u6d88\u606f\u5199\u5165  &#xff1a;\u6d88\u606f\u53d1\u9001\u65f6\u5199\u5165\u6570\u636e\u5e93\u3002 <\/li>\n<li>  \u72b6\u6001\u540c\u6b65  &#xff1a;\u7528\u6237\u767b\u5f55\/\u767b\u51fa\u65f6\u66f4\u65b0\u72b6\u6001\u8868\u3002 <\/li>\n<li>  \u6d88\u606f\u62c9\u53d6  &#xff1a;\u5ba2\u6237\u7aef\u79bb\u7ebf\u65f6&#xff0c;\u4e0b\u6b21\u767b\u5f55\u62c9\u53d6\u672a\u8bfb\u6d88\u606f\u3002 <\/li>\n<\/ul>\n<h4> 2.3.3 \u8282\u70b9\u76d1\u63a7\u4e0e\u5065\u5eb7\u68c0\u67e5 <\/h4>\n<p> Fchat \u4f7f\u7528 Prometheus &#043; Grafana \u5b9e\u73b0\u8282\u70b9\u76d1\u63a7&#xff0c;\u7ed3\u5408\u5065\u5eb7\u68c0\u67e5\u63a5\u53e3\u5b9e\u73b0\u670d\u52a1\u72b6\u6001\u53ef\u89c6\u5316\u3002 <\/p>\n<h5> \u5065\u5eb7\u68c0\u67e5\u63a5\u53e3&#xff08;HTTP&#xff09; <\/h5>\n<p>GET \/healthz<\/p>\n<h5> \u8fd4\u56de\u793a\u4f8b <\/h5>\n<p>{<br \/>\n    &#034;status&#034;: &#034;ok&#034;,<br \/>\n    &#034;timestamp&#034;: &#034;2024-04-05T12:00:00Z&#034;,<br \/>\n    &#034;node&#034;: &#034;server-01&#034;,<br \/>\n    &#034;load&#034;: &#034;low&#034;<br \/>\n}<\/p>\n<h5> \u76d1\u63a7\u6307\u6807 <\/h5>\n<ul>\n<li> CPU \u4f7f\u7528\u7387 <\/li>\n<li> \u5185\u5b58\u4f7f\u7528 <\/li>\n<li> \u8fde\u63a5\u6570 <\/li>\n<li> \u6d88\u606f\u961f\u5217\u957f\u5ea6 <\/li>\n<li> \u9519\u8bef\u7387 <\/li>\n<\/ul>\n<h2> 3. \u6d88\u606f\u961f\u5217\u4e0e\u5e76\u53d1\u5904\u7406\u673a\u5236 <\/h2>\n<p> \u5728\u9ad8\u5e76\u53d1\u3001\u9ad8\u6027\u80fd\u7684\u5373\u65f6\u901a\u8baf\u7cfb\u7edf\u4e2d&#xff0c;  \u6d88\u606f\u961f\u5217  &#xff08;Message Queue&#xff09;\u626e\u6f14\u7740\u81f3\u5173\u91cd\u8981\u7684\u89d2\u8272\u3002Fchat \u901a\u8fc7\u5f15\u5165\u9ad8\u6548\u7684\u6d88\u606f\u961f\u5217\u7cfb\u7edf&#xff0c;\u5b9e\u73b0\u5f02\u6b65\u5904\u7406\u3001\u89e3\u8026\u901a\u4fe1\u6a21\u5757\u3001\u63d0\u5347\u7cfb\u7edf\u7684\u541e\u5410\u80fd\u529b\u548c\u7a33\u5b9a\u6027\u3002\u540c\u65f6&#xff0c;\u4e3a\u4e86\u5e94\u5bf9\u6d77\u91cf\u6d88\u606f\u7684\u5904\u7406\u538b\u529b&#xff0c;Fchat \u5728\u5e76\u53d1\u5904\u7406\u673a\u5236\u4e0a\u4e5f\u8fdb\u884c\u4e86\u6df1\u5ea6\u4f18\u5316&#xff0c;\u5305\u62ec\u7ebf\u7a0b\u6c60\u8c03\u5ea6\u3001\u5185\u5b58\u7ba1\u7406\u3001\u9650\u6d41\u964d\u7ea7\u7b49\u5173\u952e\u6280\u672f\u624b\u6bb5\u3002 <\/p>\n<p> \u672c\u7ae0\u5c06\u56f4\u7ed5\u4ee5\u4e0b\u51e0\u4e2a\u65b9\u9762\u5c55\u5f00&#xff1a; <\/p>\n<ul>\n<li>  \u6d88\u606f\u961f\u5217\u7684\u9009\u578b\u4e0e\u5e94\u7528\u573a\u666f  <\/li>\n<li>  \u5f02\u6b65\u6d88\u606f\u5904\u7406\u6d41\u7a0b\u4e0e\u673a\u5236\u8bbe\u8ba1  <\/li>\n<li>  \u9ad8\u5e76\u53d1\u4e0b\u7684\u7ebf\u7a0b\u8c03\u5ea6\u4e0e\u8d44\u6e90\u63a7\u5236\u4f18\u5316  <\/li>\n<\/ul>\n<h3> 3.1 \u6d88\u606f\u961f\u5217\u7684\u5f15\u5165\u4e0e\u9009\u578b <\/h3>\n<h4> 3.1.1 Kafka\u3001RabbitMQ\u4e0eRocketMQ\u5bf9\u6bd4 <\/h4>\n<p> \u5728Fchat\u7684\u8bbe\u8ba1\u4e2d&#xff0c;\u6d88\u606f\u961f\u5217\u7684\u9009\u62e9\u76f4\u63a5\u5f71\u54cd\u7cfb\u7edf\u7684\u541e\u5410\u80fd\u529b\u3001\u6d88\u606f\u53ef\u9760\u6027\u4ee5\u53ca\u53ef\u6269\u5c55\u6027\u3002\u5e38\u89c1\u7684\u6d88\u606f\u961f\u5217\u4e2d\u95f4\u4ef6\u5305\u62ec  Apache Kafka  \u3001  RabbitMQ  \u548c  RocketMQ  &#xff0c;\u5b83\u4eec\u5404\u81ea\u6709\u5176\u9002\u7528\u573a\u666f\u3002 <\/p>\n<table>\n<tr> \u5bf9\u6bd4\u7ef4\u5ea6  Kafka  RabbitMQ  RocketMQ <\/tr>\n<tbody>\n<tr>\n<td> \u541e\u5410\u91cf <\/td>\n<td> \u6781\u9ad8&#xff0c;\u9002\u5408\u65e5\u5fd7\u7c7b\u6570\u636e <\/td>\n<td> \u4e2d\u7b49&#xff0c;\u9002\u5408\u4e8b\u52a1\u6027\u6d88\u606f <\/td>\n<td> \u9ad8&#xff0c;\u9002\u7528\u4e8e\u590d\u6742\u4e1a\u52a1\u573a\u666f <\/td>\n<\/tr>\n<tr>\n<td> \u6d88\u606f\u6301\u4e45\u5316 <\/td>\n<td> \u652f\u6301&#xff0c;\u57fa\u4e8e\u6587\u4ef6\u7cfb\u7edf <\/td>\n<td> \u652f\u6301&#xff0c;\u4f46\u6027\u80fd\u8f83\u4f4e <\/td>\n<td> \u652f\u6301&#xff0c;\u78c1\u76d8\u4e0e\u5185\u5b58\u7ed3\u5408 <\/td>\n<\/tr>\n<tr>\n<td> \u5ef6\u8fdf <\/td>\n<td> \u8f83\u9ad8&#xff0c;\u9002\u5408\u6279\u91cf\u5904\u7406 <\/td>\n<td> \u4f4e\u5ef6\u8fdf&#xff0c;\u9002\u5408\u5b9e\u65f6\u5904\u7406 <\/td>\n<td> \u4e2d\u7b49&#xff0c;\u652f\u6301\u5f02\u6b65\u5237\u76d8 <\/td>\n<\/tr>\n<tr>\n<td> \u53ef\u9760\u6027 <\/td>\n<td> \u9ad8&#xff0c;\u652f\u6301\u526f\u672c\u673a\u5236 <\/td>\n<td> \u9ad8&#xff0c;\u652f\u6301\u786e\u8ba4\u673a\u5236 <\/td>\n<td> \u9ad8&#xff0c;\u652f\u6301\u540c\u6b65\u53cc\u5199 <\/td>\n<\/tr>\n<tr>\n<td> \u4f7f\u7528\u573a\u666f <\/td>\n<td> \u5927\u6570\u636e\u65e5\u5fd7\u3001\u4e8b\u4ef6\u6eaf\u6e90 <\/td>\n<td> \u5b9e\u65f6\u4e1a\u52a1\u6d41\u7a0b\u3001\u8ba2\u5355\u7cfb\u7edf <\/td>\n<td> \u804a\u5929\u3001\u4ea4\u6613\u3001\u91d1\u878d\u7b49\u590d\u6742\u7cfb\u7edf <\/td>\n<\/tr>\n<tr>\n<td> \u90e8\u7f72\u4e0e\u8fd0\u7ef4\u590d\u6742\u5ea6 <\/td>\n<td> \u4e2d\u7b49&#xff0c;\u9700\u7ba1\u7406ZooKeeper\u96c6\u7fa4 <\/td>\n<td> \u7b80\u5355&#xff0c;\u5355\u8282\u70b9\u90e8\u7f72\u5373\u53ef <\/td>\n<td> \u8f83\u590d\u6742&#xff0c;\u9700\u7ba1\u7406Broker\u4e0eNameServer <\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p> \u5728 Fchat \u4e2d&#xff0c;  RocketMQ  \u88ab\u9009\u4e3a\u9ed8\u8ba4\u6d88\u606f\u961f\u5217\u7cfb\u7edf&#xff0c;\u539f\u56e0\u5982\u4e0b&#xff1a; <\/p>\n<ul>\n<li>  \u652f\u6301\u6d88\u606f\u987a\u5e8f\u6027  &#xff1a;\u804a\u5929\u6d88\u606f\u9700\u8981\u4fdd\u8bc1\u987a\u5e8f\u6027&#xff0c;RocketMQ \u63d0\u4f9b\u4e86\u987a\u5e8f\u6d88\u606f\u673a\u5236\u3002 <\/li>\n<li>  \u9ad8\u541e\u5410\u4e0e\u4f4e\u5ef6\u8fdf\u517c\u987e  &#xff1a;\u9002\u7528\u4e8e\u804a\u5929\u6d88\u606f\u7684\u5373\u65f6\u6027\u8981\u6c42\u3002 <\/li>\n<li>  \u6d88\u606f\u53ef\u9760\u6027\u9ad8  &#xff1a;\u901a\u8fc7\u540c\u6b65\u5237\u76d8\u4e0e\u53cc\u5199\u673a\u5236\u4fdd\u969c\u6d88\u606f\u4e0d\u4e22\u5931\u3002 <\/li>\n<li>  \u826f\u597d\u7684\u793e\u533a\u652f\u6301\u4e0e\u751f\u6001\u96c6\u6210  &#xff1a;\u6613\u4e8e\u4e0e Fchat \u7684 Java \u67b6\u6784\u96c6\u6210\u3002 <\/li>\n<\/ul>\n<h4> 3.1.2 Fchat\u4e2d\u6d88\u606f\u961f\u5217\u7684\u5e94\u7528\u573a\u666f <\/h4>\n<p> Fchat \u4f7f\u7528 RocketMQ \u6765\u5904\u7406\u4ee5\u4e0b\u51e0\u7c7b\u6d88\u606f\u573a\u666f&#xff1a; <\/p>\n<ul>\n<li>  \u5728\u7ebf\u6d88\u606f\u5e7f\u64ad  &#xff1a;\u7528\u6237\u53d1\u9001\u7684\u6d88\u606f\u901a\u8fc7 RocketMQ \u5f02\u6b65\u5206\u53d1\u7ed9\u591a\u4e2a\u63a5\u6536\u65b9\u3002 <\/li>\n<li>  \u79bb\u7ebf\u6d88\u606f\u63a8\u9001  &#xff1a;\u7528\u6237\u79bb\u7ebf\u65f6\u7684\u6d88\u606f\u6682\u5b58\u81f3 MQ&#xff0c;\u5f85\u7528\u6237\u4e0a\u7ebf\u540e\u62c9\u53d6\u3002 <\/li>\n<li>  \u7cfb\u7edf\u72b6\u6001\u901a\u77e5  &#xff1a;\u5982\u7528\u6237\u4e0a\u4e0b\u7ebf\u3001\u5fc3\u8df3\u4e22\u5931\u3001\u670d\u52a1\u5f02\u5e38\u7b49\u4e8b\u4ef6\u5e7f\u64ad\u3002 <\/li>\n<li>  \u65e5\u5fd7\u4e0e\u76d1\u63a7\u6570\u636e\u91c7\u96c6  &#xff1a;\u5c06\u7cfb\u7edf\u8fd0\u884c\u65e5\u5fd7\u548c\u76d1\u63a7\u6570\u636e\u901a\u8fc7 MQ \u5f02\u6b65\u53d1\u9001\u81f3\u5206\u6790\u5e73\u53f0\u3002 <\/li>\n<\/ul>\n<h5> \u793a\u4f8b\u4ee3\u7801&#xff1a;Fchat\u4e2d\u6d88\u606f\u53d1\u9001\u903b\u8f91&#xff08;\u57fa\u4e8eRocketMQ&#xff09; <\/h5>\n<p>import org.apache.rocketmq.client.exception.MQClientException;<br \/>\nimport org.apache.rocketmq.client.producer.DefaultMQProducer;<br \/>\nimport org.apache.rocketmq.common.message.Message;<\/p>\n<p>public class FchatMessageProducer {<br \/>\n    private DefaultMQProducer producer;<\/p>\n<p>    public FchatMessageProducer(String groupName) {<br \/>\n        producer &#061; new DefaultMQProducer(groupName);<br \/>\n        producer.setNamesrvAddr(&#034;127.0.0.1:9876&#034;); \/\/ RocketMQ Name Server\u5730\u5740<br \/>\n    }<\/p>\n<p>    public void sendMessage(String topic, String tag, String body) throws MQClientException {<br \/>\n        Message msg &#061; new Message(topic, tag, body.getBytes());<br \/>\n        producer.send(msg); \/\/ \u53d1\u9001\u6d88\u606f<br \/>\n    }<\/p>\n<p>    public void start() throws MQClientException {<br \/>\n        producer.start();<br \/>\n    }<\/p>\n<p>    public void shutdown() {<br \/>\n        producer.shutdown();<br \/>\n    }<br \/>\n}<\/p>\n<h6> \u4ee3\u7801\u903b\u8f91\u5206\u6790&#xff1a; <\/h6>\n<li>  DefaultMQProducer  &#xff1a;\u521b\u5efa\u4e00\u4e2a RocketMQ \u6d88\u606f\u751f\u4ea7\u8005\u5b9e\u4f8b\u3002 <\/li>\n<li>  setNamesrvAddr  &#xff1a;\u6307\u5b9a RocketMQ \u7684 Name Server \u5730\u5740\u3002 <\/li>\n<li>  Message  &#xff1a;\u6784\u9020\u6d88\u606f\u5bf9\u8c61&#xff0c;\u6307\u5b9a topic\u3001tag \u548c body\u3002 <\/li>\n<li>  send  &#xff1a;\u53d1\u9001\u6d88\u606f\u5230 Broker\u3002 <\/li>\n<li>  start  \/  shutdown  &#xff1a;\u542f\u52a8\u548c\u5173\u95ed\u751f\u4ea7\u8005\u3002 <\/li>\n<h3> 3.2 \u5f02\u6b65\u6d88\u606f\u5904\u7406\u6d41\u7a0b <\/h3>\n<h4> 3.2.1 \u6d88\u606f\u5165\u961f\u4e0e\u51fa\u961f\u673a\u5236 <\/h4>\n<p> Fchat \u7684\u6d88\u606f\u5904\u7406\u6d41\u7a0b\u91c7\u7528\u5178\u578b\u7684  \u751f\u4ea7\u8005-\u6d88\u8d39\u8005\u6a21\u578b  &#xff0c;\u901a\u8fc7 RocketMQ \u5b9e\u73b0\u6d88\u606f\u7684\u5f02\u6b65\u5165\u961f\u4e0e\u51fa\u961f\u3002 <\/p>\n<p>graph TD<br \/>\n    A[\u5ba2\u6237\u7aef\u53d1\u9001\u6d88\u606f] &#8211;&gt; B[\u6d88\u606f\u5165\u961f\u81f3RocketMQ]<br \/>\n    B &#8211;&gt; C[\u6d88\u606f\u6301\u4e45\u5316]<br \/>\n    C &#8211;&gt; D[\u6d88\u606f\u51fa\u961f]<br \/>\n    D &#8211;&gt; E[\u6d88\u8d39\u8005\u6d88\u8d39\u6d88\u606f]<br \/>\n    E &#8211;&gt; F[\u6d88\u606f\u5206\u53d1\u81f3\u76ee\u6807\u7528\u6237]<\/p>\n<h5> \u5165\u961f\u6d41\u7a0b <\/h5>\n<li> \u7528\u6237\u53d1\u9001\u6d88\u606f&#xff0c;\u5ba2\u6237\u7aef\u901a\u8fc7 REST \u6216 WebSocket \u63d0\u4ea4\u81f3 Fchat \u670d\u52a1\u3002 <\/li>\n<li> Fchat \u670d\u52a1\u9a8c\u8bc1\u6d88\u606f\u683c\u5f0f\u548c\u6743\u9650\u540e&#xff0c;\u5c06\u6d88\u606f\u5c01\u88c5\u4e3a RocketMQ \u7684  Message  \u5bf9\u8c61\u3002 <\/li>\n<li> \u8c03\u7528  send  \u65b9\u6cd5\u5c06\u6d88\u606f\u6295\u9012\u81f3 RocketMQ\u3002 <\/li>\n<li> \u6d88\u606f\u88ab\u5199\u5165 Broker \u7684 CommitLog \u6587\u4ef6&#xff0c;\u5e76\u6839\u636e Topic \u548c Tag \u5efa\u7acb\u7d22\u5f15\u3002 <\/li>\n<h5> \u51fa\u961f\u6d41\u7a0b <\/h5>\n<li> Fchat \u7684\u6d88\u606f\u6d88\u8d39\u8005\u76d1\u542c\u6307\u5b9a Topic\u3002 <\/li>\n<li> \u5f53\u65b0\u6d88\u606f\u5230\u8fbe\u65f6&#xff0c;\u6d88\u8d39\u8005\u901a\u8fc7  pull  \u6216  push  \u6a21\u5f0f\u83b7\u53d6\u6d88\u606f\u3002 <\/li>\n<li> \u6d88\u8d39\u8005\u89e3\u6790\u6d88\u606f\u5185\u5bb9&#xff0c;\u5e76\u8fdb\u884c\u4e1a\u52a1\u5904\u7406&#xff08;\u5982\u67e5\u627e\u63a5\u6536\u8005\u3001\u63a8\u9001\u6d88\u606f\u7b49&#xff09;\u3002 <\/li>\n<li> \u6d88\u606f\u5904\u7406\u5b8c\u6210\u540e&#xff0c;\u5411 RocketMQ \u8fd4\u56de\u6d88\u8d39\u786e\u8ba4\u3002 <\/li>\n<h5> \u793a\u4f8b\u4ee3\u7801&#xff1a;\u6d88\u606f\u6d88\u8d39\u8005\u793a\u4f8b <\/h5>\n<p>import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;<br \/>\nimport org.apache.rocketmq.client.consumer.listener.*;<br \/>\nimport org.apache.rocketmq.common.message.MessageExt;<\/p>\n<p>public class FchatMessageConsumer {<br \/>\n    private DefaultMQPushConsumer consumer;<\/p>\n<p>    public FchatMessageConsumer(String groupName) throws MQClientException {<br \/>\n        consumer &#061; new DefaultMQPushConsumer(groupName);<br \/>\n        consumer.setNamesrvAddr(&#034;127.0.0.1:9876&#034;);<br \/>\n        consumer.subscribe(&#034;CHAT_TOPIC&#034;, &#034;*&#034;); \/\/ \u8ba2\u9605\u6240\u6709tag\u7684\u6d88\u606f<br \/>\n    }<\/p>\n<p>    public void registerListener() {<br \/>\n        consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -&gt; {<br \/>\n            for (MessageExt msg : msgs) {<br \/>\n                String messageBody &#061; new String(msg.getBody());<br \/>\n                System.out.println(&#034;\u6536\u5230\u6d88\u606f: &#034; &#043; messageBody);<br \/>\n                \/\/ \u5904\u7406\u6d88\u606f\u903b\u8f91&#xff0c;\u5982\u5206\u53d1\u7ed9\u7528\u6237<br \/>\n            }<br \/>\n            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;<br \/>\n        });<br \/>\n    }<\/p>\n<p>    public void start() throws MQClientException {<br \/>\n        consumer.start();<br \/>\n    }<br \/>\n}<\/p>\n<h6> \u4ee3\u7801\u903b\u8f91\u5206\u6790&#xff1a; <\/h6>\n<li> \u521b\u5efa  DefaultMQPushConsumer  &#xff0c;\u6307\u5b9a\u6d88\u8d39\u7ec4\u3002 <\/li>\n<li> \u8bbe\u7f6e Name Server \u5730\u5740\u5e76\u8ba2\u9605 Topic\u3002 <\/li>\n<li> \u6ce8\u518c\u76d1\u542c\u5668&#xff0c;\u5b9e\u73b0  MessageListenerConcurrently  \u63a5\u53e3\u3002 <\/li>\n<li> \u6d88\u8d39\u6d88\u606f\u65f6&#xff0c;\u904d\u5386  msgs  &#xff0c;\u89e3\u6790\u5e76\u5904\u7406\u6bcf\u6761\u6d88\u606f\u3002 <\/li>\n<li> \u8fd4\u56de\u6d88\u8d39\u72b6\u6001&#xff0c;\u6210\u529f\u6216\u5931\u8d25\u3002 <\/li>\n<h4> 3.2.2 \u6d88\u606f\u91cd\u8bd5\u4e0e\u786e\u8ba4\u673a\u5236\u8bbe\u8ba1 <\/h4>\n<p> \u6d88\u606f\u7684  \u53ef\u9760\u6027  \u662f\u5373\u65f6\u901a\u8baf\u7cfb\u7edf\u7684\u5173\u952e\u3002Fchat \u901a\u8fc7\u4ee5\u4e0b\u673a\u5236\u4fdd\u969c\u6d88\u606f\u7684\u53ef\u9760\u6295\u9012&#xff1a; <\/p>\n<ul>\n<li>  \u6d88\u8d39\u5931\u8d25\u91cd\u8bd5  &#xff1a;\u82e5\u6d88\u8d39\u8005\u5904\u7406\u5931\u8d25&#xff0c;RocketMQ \u4f1a\u81ea\u52a8\u91cd\u8bd5&#xff08;\u6700\u591a16\u6b21&#xff0c;\u9ed8\u8ba4\u6307\u6570\u9000\u907f&#xff09;\u3002 <\/li>\n<li>  \u6d88\u8d39\u786e\u8ba4\u673a\u5236  &#xff1a;\u6d88\u8d39\u8005\u5fc5\u987b\u8fd4\u56de  CONSUME_SUCCESS  &#xff0c;\u5426\u5219\u89c6\u4e3a\u5931\u8d25&#xff0c;\u89e6\u53d1\u91cd\u8bd5\u3002 <\/li>\n<li>  \u6b7b\u4fe1\u961f\u5217  &#xff1a;\u82e5\u6d88\u606f\u591a\u6b21\u5931\u8d25&#xff0c;\u5c06\u88ab\u79fb\u81f3\u6b7b\u4fe1\u961f\u5217&#xff0c;\u4f9b\u540e\u7eed\u4eba\u5de5\u5904\u7406\u3002 <\/li>\n<\/ul>\n<h5> \u8868\u683c&#xff1a;\u6d88\u606f\u91cd\u8bd5\u7b56\u7565 <\/h5>\n<table>\n<tr> \u91cd\u8bd5\u6b21\u6570  \u91cd\u8bd5\u95f4\u9694 <\/tr>\n<tbody>\n<tr>\n<td> 1 <\/td>\n<td> 10s <\/td>\n<\/tr>\n<tr>\n<td> 2 <\/td>\n<td> 30s <\/td>\n<\/tr>\n<tr>\n<td> 3 <\/td>\n<td> 1min <\/td>\n<\/tr>\n<tr>\n<td> 4 <\/td>\n<td> 2min <\/td>\n<\/tr>\n<tr>\n<td> 5 <\/td>\n<td> 3min <\/td>\n<\/tr>\n<tr>\n<td> \u2026 <\/td>\n<td> \u2026 <\/td>\n<\/tr>\n<tr>\n<td> 16 <\/td>\n<td> 2h <\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3> 3.3 \u9ad8\u5e76\u53d1\u4e0b\u7684\u7ebf\u7a0b\u8c03\u5ea6\u4e0e\u8d44\u6e90\u63a7\u5236 <\/h3>\n<h4> 3.3.1 \u7ebf\u7a0b\u6c60\u914d\u7f6e\u4e0e\u4efb\u52a1\u8c03\u5ea6\u7b56\u7565 <\/h4>\n<p> Fchat \u91c7\u7528\u7ebf\u7a0b\u6c60\u6765\u7ba1\u7406\u5e76\u53d1\u4efb\u52a1&#xff0c;\u63d0\u5347\u7cfb\u7edf\u8d44\u6e90\u5229\u7528\u7387\u548c\u54cd\u5e94\u901f\u5ea6\u3002\u7ebf\u7a0b\u6c60\u7684\u914d\u7f6e\u5e94\u6839\u636e\u5b9e\u9645\u4e1a\u52a1\u8d1f\u8f7d\u8fdb\u884c\u4f18\u5316\u3002 <\/p>\n<h5> \u793a\u4f8b&#xff1a;\u7ebf\u7a0b\u6c60\u914d\u7f6e <\/h5>\n<p>import java.util.concurrent.*;<\/p>\n<p>public class FchatThreadPool {<br \/>\n    private static ExecutorService executor &#061; new ThreadPoolExecutor(<br \/>\n            10, \/\/ \u6838\u5fc3\u7ebf\u7a0b\u6570<br \/>\n            50, \/\/ \u6700\u5927\u7ebf\u7a0b\u6570<br \/>\n            60L, TimeUnit.SECONDS,<br \/>\n            new LinkedBlockingQueue&lt;&gt;(1000), \/\/ \u961f\u5217\u5bb9\u91cf<br \/>\n            new ThreadPoolExecutor.CallerRunsPolicy()); \/\/ \u62d2\u7edd\u7b56\u7565<\/p>\n<p>    public static void submit(Runnable task) {<br \/>\n        executor.submit(task);<br \/>\n    }<\/p>\n<p>    public static void shutdown() {<br \/>\n        executor.shutdown();<br \/>\n    }<br \/>\n}<\/p>\n<h6> \u7ebf\u7a0b\u6c60\u53c2\u6570\u8bf4\u660e&#xff1a; <\/h6>\n<ul>\n<li>  corePoolSize  &#xff1a;\u6838\u5fc3\u7ebf\u7a0b\u6570&#xff0c;\u4fdd\u6301\u6d3b\u8dc3\u7ebf\u7a0b\u6570\u3002 <\/li>\n<li>  maximumPoolSize  &#xff1a;\u6700\u5927\u7ebf\u7a0b\u6570&#xff0c;\u5904\u7406\u7a81\u53d1\u8d1f\u8f7d\u3002 <\/li>\n<li>  keepAliveTime  &#xff1a;\u7a7a\u95f2\u7ebf\u7a0b\u5b58\u6d3b\u65f6\u95f4\u3002 <\/li>\n<li>  workQueue  &#xff1a;\u4efb\u52a1\u961f\u5217&#xff0c;\u7528\u4e8e\u7f13\u5b58\u5f85\u5904\u7406\u4efb\u52a1\u3002 <\/li>\n<li>  handler  &#xff1a;\u62d2\u7edd\u7b56\u7565&#xff0c;\u5f53\u961f\u5217\u6ee1\u4e14\u7ebf\u7a0b\u6570\u8fbe\u5230\u4e0a\u9650\u65f6\u5982\u4f55\u5904\u7406\u65b0\u4efb\u52a1\u3002 <\/li>\n<\/ul>\n<h5> \u7ebf\u7a0b\u6c60\u7b56\u7565\u9009\u62e9\u5efa\u8bae&#xff1a; <\/h5>\n<table>\n<tr> \u573a\u666f  \u5efa\u8bae\u7b56\u7565 <\/tr>\n<tbody>\n<tr>\n<td> \u9ad8\u5e76\u53d1\u6d88\u606f\u5904\u7406 <\/td>\n<td>  CallerRunsPolicy  &#xff08;\u8c03\u7528\u8005\u6267\u884c&#xff09; <\/td>\n<\/tr>\n<tr>\n<td> \u8d44\u6e90\u53d7\u9650\u73af\u5883 <\/td>\n<td>  AbortPolicy  &#xff08;\u629b\u51fa\u5f02\u5e38&#xff09; <\/td>\n<\/tr>\n<tr>\n<td> \u4efb\u52a1\u91cd\u8981\u6027\u9ad8 <\/td>\n<td>  DiscardOldestPolicy  &#xff08;\u4e22\u5f03\u6700\u8001\u4efb\u52a1&#xff09; <\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4> 3.3.2 \u5185\u5b58\u4f7f\u7528\u4f18\u5316\u4e0eGC\u8c03\u4f18 <\/h4>\n<p> \u5728\u9ad8\u5e76\u53d1\u573a\u666f\u4e0b&#xff0c;\u9891\u7e41\u7684\u5bf9\u8c61\u521b\u5efa\u4e0e\u9500\u6bc1\u4f1a\u5e26\u6765\u4e25\u91cd\u7684 GC \u538b\u529b\u3002Fchat \u901a\u8fc7\u4ee5\u4e0b\u65b9\u5f0f\u4f18\u5316\u5185\u5b58\u4e0e GC \u8868\u73b0&#xff1a; <\/p>\n<ul>\n<li>  \u5bf9\u8c61\u590d\u7528  &#xff1a;\u4f7f\u7528\u5bf9\u8c61\u6c60\u6216\u7f13\u5b58\u673a\u5236\u51cf\u5c11 GC \u9891\u7387\u3002 <\/li>\n<li>  \u5806\u5185\u5b58\u914d\u7f6e  &#xff1a;\u5408\u7406\u8bbe\u7f6e  -Xms  \u4e0e  -Xmx  &#xff0c;\u907f\u514d\u9891\u7e41 Full GC\u3002 <\/li>\n<li>  \u9009\u62e9\u5408\u9002\u7684\u5783\u573e\u56de\u6536\u5668  &#xff1a;\u5982 G1 \u6216 ZGC&#xff0c;\u9002\u7528\u4e8e\u4f4e\u5ef6\u8fdf\u573a\u666f\u3002 <\/li>\n<li>  JVM\u53c2\u6570\u4f18\u5316\u793a\u4f8b  &#xff1a; <\/li>\n<\/ul>\n<p>java -Xms4g -Xmx4g \\\\<br \/>\n     -XX:&#043;UseG1GC \\\\<br \/>\n     -XX:MaxGCPauseMillis&#061;200 \\\\<br \/>\n     -jar fchat-server.jar<\/p>\n<h6> \u53c2\u6570\u8bf4\u660e&#xff1a; <\/h6>\n<ul>\n<li>  -Xms  \/  -Xmx  &#xff1a;\u521d\u59cb\u5806\u4e0e\u6700\u5927\u5806\u5927\u5c0f\u3002 <\/li>\n<li>  -XX:&#043;UseG1GC  &#xff1a;\u542f\u7528 G1 \u5783\u573e\u56de\u6536\u5668\u3002 <\/li>\n<li>  -XX:MaxGCPauseMillis&#061;200  &#xff1a;\u8bbe\u7f6e\u6700\u5927 GC \u6682\u505c\u65f6\u95f4\u76ee\u6807\u3002 <\/li>\n<\/ul>\n<h4> 3.3.3 \u9650\u6d41\u4e0e\u964d\u7ea7\u7b56\u7565\u5b9e\u65bd <\/h4>\n<p> \u5728\u6d41\u91cf\u7a81\u589e\u6216\u7cfb\u7edf\u5f02\u5e38\u65f6&#xff0c;Fchat \u901a\u8fc7  \u9650\u6d41  \u4e0e  \u964d\u7ea7  \u673a\u5236\u4fdd\u969c\u6838\u5fc3\u670d\u52a1\u53ef\u7528\u3002 <\/p>\n<h5> \u9650\u6d41\u7b56\u7565 <\/h5>\n<ul>\n<li>  \u4ee4\u724c\u6876\u7b97\u6cd5  &#xff08;Token Bucket&#xff09;&#xff1a;\u63a7\u5236\u5355\u4f4d\u65f6\u95f4\u5185\u5141\u8bb8\u5904\u7406\u7684\u6d88\u606f\u6570\u91cf\u3002 <\/li>\n<li>  \u6f0f\u6876\u7b97\u6cd5  &#xff08;Leaky Bucket&#xff09;&#xff1a;\u4ee5\u56fa\u5b9a\u901f\u7387\u5904\u7406\u8bf7\u6c42&#xff0c;\u8d85\u51fa\u90e8\u5206\u62d2\u7edd\u3002 <\/li>\n<\/ul>\n<h5> \u964d\u7ea7\u7b56\u7565 <\/h5>\n<ul>\n<li>  \u529f\u80fd\u964d\u7ea7  &#xff1a;\u5173\u95ed\u975e\u6838\u5fc3\u529f\u80fd&#xff08;\u5982\u79bb\u7ebf\u6d88\u606f\u63a8\u9001&#xff09;\u3002 <\/li>\n<li>  \u63a5\u53e3\u964d\u7ea7  &#xff1a;\u8fd4\u56de\u7f13\u5b58\u6570\u636e\u6216\u9ed8\u8ba4\u503c&#xff0c;\u907f\u514d\u7cfb\u7edf\u96ea\u5d29\u3002 <\/li>\n<li>  \u7194\u65ad\u673a\u5236  &#xff1a;\u4f7f\u7528 Hystrix \u6216 Sentinel \u5b9e\u73b0\u81ea\u52a8\u7194\u65ad\u4e0e\u6062\u590d\u3002 <\/li>\n<\/ul>\n<h5> \u793a\u4f8b&#xff1a;\u4f7f\u7528 Sentinel \u5b9e\u73b0\u9650\u6d41 <\/h5>\n<p>import com.alibaba.csp.sentinel.Entry;<br \/>\nimport com.alibaba.csp.sentinel.SphU;<br \/>\nimport com.alibaba.csp.sentinel.slots.block.BlockException;<\/p>\n<p>public class FchatSentinel {<br \/>\n    public void processMessage() {<br \/>\n        Entry entry &#061; null;<br \/>\n        try {<br \/>\n            entry &#061; SphU.entry(&#034;SendMessageQps&#034;); \/\/ \u5b9a\u4e49\u8d44\u6e90\u540d<br \/>\n            \/\/ \u6267\u884c\u53d1\u9001\u6d88\u606f\u903b\u8f91<br \/>\n        } catch (BlockException e) {<br \/>\n            System.out.println(&#034;\u8bf7\u6c42\u88ab\u9650\u6d41&#034;);<br \/>\n            \/\/ \u6267\u884c\u964d\u7ea7\u903b\u8f91<br \/>\n        } finally {<br \/>\n            if (entry !&#061; null) {<br \/>\n                entry.exit();<br \/>\n            }<br \/>\n        }<br \/>\n    }<br \/>\n}<\/p>\n<h6> \u903b\u8f91\u8bf4\u660e&#xff1a; <\/h6>\n<ul>\n<li>  SphU.entry  &#xff1a;\u5c1d\u8bd5\u8fdb\u5165\u9650\u6d41\u89c4\u5219\u3002 <\/li>\n<li> \u82e5\u8d85\u8fc7 QPS \u9650\u5236&#xff0c;\u629b\u51fa  BlockException  &#xff0c;\u6267\u884c\u964d\u7ea7\u903b\u8f91\u3002 <\/li>\n<li> \u6700\u540e\u5fc5\u987b\u8c03\u7528  exit()  \u91ca\u653e\u8d44\u6e90\u3002 <\/li>\n<\/ul>\n<p> \u672c\u7ae0\u4ece\u6d88\u606f\u961f\u5217\u7684\u5f15\u5165\u4e0e\u9009\u578b\u5165\u624b&#xff0c;\u6df1\u5165\u8bb2\u89e3\u4e86\u5f02\u6b65\u6d88\u606f\u5904\u7406\u6d41\u7a0b\u7684\u8bbe\u8ba1\u4e0e\u5b9e\u73b0&#xff0c;\u5305\u62ec\u6d88\u606f\u5165\u961f\u3001\u51fa\u961f\u3001\u91cd\u8bd5\u4e0e\u786e\u8ba4\u673a\u5236\u3002\u6700\u540e&#xff0c;\u8ba8\u8bba\u4e86\u5728\u9ad8\u5e76\u53d1\u573a\u666f\u4e0b\u7684\u7ebf\u7a0b\u8c03\u5ea6\u3001\u5185\u5b58\u4f18\u5316\u3001GC\u8c03\u4f18\u4ee5\u53ca\u9650\u6d41\u964d\u7ea7\u7b49\u5173\u952e\u6280\u672f\u624b\u6bb5\u3002\u8fd9\u4e9b\u673a\u5236\u5171\u540c\u4fdd\u969c\u4e86 Fchat \u5728\u9ad8\u5e76\u53d1\u3001\u5927\u6570\u636e\u91cf\u573a\u666f\u4e0b\u7684\u7a33\u5b9a\u8fd0\u884c\u4e0e\u9ad8\u6548\u54cd\u5e94\u3002 <\/p>\n<h2> 4. \u6d88\u606f\u7c7b\u578b\u652f\u6301&#xff08;\u6587\u672c\u3001\u56fe\u7247\u3001\u8bed\u97f3\u3001\u89c6\u9891&#xff09; <\/h2>\n<p> Fchat\u4f5c\u4e3a\u4e00\u6b3e\u9762\u5411\u9ad8\u5e76\u53d1\u573a\u666f\u7684\u4e13\u4e1a\u5373\u65f6\u901a\u8baf\u670d\u52a1\u5668&#xff0c;\u5fc5\u987b\u5177\u5907\u5bf9\u591a\u79cd\u6d88\u606f\u7c7b\u578b\u7684\u5168\u9762\u652f\u6301\u80fd\u529b&#xff0c;\u5305\u62ec\u6587\u672c\u3001\u56fe\u7247\u3001\u8bed\u97f3\u3001\u89c6\u9891\u7b49\u591a\u5a92\u4f53\u5185\u5bb9\u3002\u672c\u7ae0\u5c06\u6df1\u5165\u63a2\u8ba8Fchat\u5982\u4f55\u901a\u8fc7\u6d88\u606f\u683c\u5f0f\u5b9a\u4e49\u3001\u4e0a\u4f20\u4e0e\u5206\u53d1\u673a\u5236\u3001\u524d\u7aef\u89e3\u6790\u4e0e\u6e32\u67d3\u6280\u672f&#xff0c;\u5b9e\u73b0\u5bf9\u591a\u79cd\u6d88\u606f\u7c7b\u578b\u7684\u652f\u6301&#xff0c;\u5e76\u786e\u4fdd\u5728\u9ad8\u5e76\u53d1\u573a\u666f\u4e0b\u7684\u7a33\u5b9a\u6027\u4e0e\u6027\u80fd\u3002 <\/p>\n<h3> 4.1 \u591a\u5a92\u4f53\u6d88\u606f\u7684\u683c\u5f0f\u4e0e\u7f16\u7801 <\/h3>\n<p> \u5728\u5373\u65f6\u901a\u8baf\u7cfb\u7edf\u4e2d&#xff0c;\u4e0d\u540c\u7c7b\u578b\u7684\u6d88\u606f\u9700\u8981\u4ee5\u7edf\u4e00\u7684\u65b9\u5f0f\u8fdb\u884c\u7f16\u7801\u548c\u5c01\u88c5&#xff0c;\u4ee5\u4fdd\u8bc1\u5728\u4f20\u8f93\u8fc7\u7a0b\u4e2d\u7684\u517c\u5bb9\u6027\u4e0e\u9ad8\u6548\u6027\u3002Fchat\u91c7\u7528\u57fa\u4e8eJSON\u7684\u7ed3\u6784\u5316\u6d88\u606f\u4f53\u8bbe\u8ba1&#xff0c;\u7ed3\u5408\u4e8c\u8fdb\u5236\u6570\u636e\u6d41\u7684\u65b9\u5f0f\u5904\u7406\u591a\u5a92\u4f53\u5185\u5bb9\u3002 <\/p>\n<h4> 4.1.1 \u6587\u672c\u6d88\u606f\u7ed3\u6784\u5b9a\u4e49 <\/h4>\n<p> Fchat\u7684\u6587\u672c\u6d88\u606f\u4f7f\u7528\u7ed3\u6784\u5316JSON\u683c\u5f0f&#xff0c;\u5b9a\u4e49\u5982\u4e0b&#xff1a; <\/p>\n<p>{<br \/>\n  &#034;msgId&#034;: &#034;20250405-123456-001&#034;,<br \/>\n  &#034;sender&#034;: &#034;user123&#034;,<br \/>\n  &#034;receiver&#034;: &#034;user456&#034;,<br \/>\n  &#034;type&#034;: &#034;text&#034;,<br \/>\n  &#034;content&#034;: {<br \/>\n    &#034;text&#034;: &#034;Hello, Fchat!&#034;<br \/>\n  },<br \/>\n  &#034;timestamp&#034;: 1743623456<br \/>\n}<\/p>\n<p>  \u53c2\u6570\u8bf4\u660e&#xff1a;  <\/p>\n<ul>\n<li>  msgId  &#xff1a;\u6d88\u606f\u552f\u4e00\u6807\u8bc6\u7b26&#xff0c;\u7528\u4e8e\u6d88\u606f\u53bb\u91cd\u4e0e\u8ffd\u8e2a\u3002 <\/li>\n<li>  sender  &#xff1a;\u53d1\u9001\u8005ID\u3002 <\/li>\n<li>  receiver  &#xff1a;\u63a5\u6536\u8005ID\u3002 <\/li>\n<li>  type  &#xff1a;\u6d88\u606f\u7c7b\u578b&#xff0c;\u5982  text  \u3001  image  \u3001  voice  \u3001  video  \u7b49\u3002 <\/li>\n<li>  content  &#xff1a;\u6d88\u606f\u5185\u5bb9&#xff0c;\u6839\u636e\u7c7b\u578b\u4e0d\u540c&#xff0c;\u7ed3\u6784\u4e5f\u4e0d\u540c\u3002 <\/li>\n<li>  timestamp  &#xff1a;\u6d88\u606f\u53d1\u9001\u65f6\u95f4\u6233\u3002 <\/li>\n<\/ul>\n<p>  \u903b\u8f91\u5206\u6790&#xff1a;  <\/p>\n<p> \u8be5\u7ed3\u6784\u8bbe\u8ba1\u5177\u5907\u826f\u597d\u7684\u6269\u5c55\u6027&#xff0c;\u4fbf\u4e8e\u540e\u7eed\u6dfb\u52a0\u65b0\u7684\u6d88\u606f\u7c7b\u578b\u6216\u6269\u5c55\u5b57\u6bb5\u3002\u540c\u65f6&#xff0c;\u7ed3\u6784\u5316\u8bbe\u8ba1\u6709\u52a9\u4e8e\u524d\u7aef\u5feb\u901f\u89e3\u6790\u4e0e\u5c55\u793a&#xff0c;\u4e5f\u4fbf\u4e8e\u65e5\u5fd7\u8bb0\u5f55\u4e0e\u6d88\u606f\u5ba1\u8ba1\u3002 <\/p>\n<h4> 4.1.2 \u56fe\u7247\u3001\u8bed\u97f3\u3001\u89c6\u9891\u7684\u6d88\u606f\u5c01\u88c5\u65b9\u5f0f <\/h4>\n<p> \u5bf9\u4e8e\u591a\u5a92\u4f53\u6d88\u606f&#xff0c;Fchat\u91c7\u7528\u201c\u5143\u6570\u636e&#043;URL\u201d\u7684\u65b9\u5f0f&#xff0c;\u5c06\u5b9e\u9645\u6587\u4ef6\u5b58\u50a8\u5728CDN\u6216\u5bf9\u8c61\u5b58\u50a8\u4e2d&#xff0c;\u6d88\u606f\u4f53\u4e2d\u4ec5\u5305\u542b\u5143\u4fe1\u606f\u548c\u6587\u4ef6\u8bbf\u95ee\u5730\u5740\u3002 <\/p>\n<p>  \u56fe\u7247\u6d88\u606f\u793a\u4f8b&#xff1a;  <\/p>\n<p>{<br \/>\n  &#034;msgId&#034;: &#034;20250405-123456-002&#034;,<br \/>\n  &#034;sender&#034;: &#034;user123&#034;,<br \/>\n  &#034;receiver&#034;: &#034;user456&#034;,<br \/>\n  &#034;type&#034;: &#034;image&#034;,<br \/>\n  &#034;content&#034;: {<br \/>\n    &#034;url&#034;: &#034;https:\/\/cdn.example.com\/images\/20250405-123456-002.jpg&#034;,<br \/>\n    &#034;thumbnail&#034;: &#034;https:\/\/cdn.example.com\/images\/thumb_20250405-123456-002.jpg&#034;,<br \/>\n    &#034;width&#034;: 800,<br \/>\n    &#034;height&#034;: 600,<br \/>\n    &#034;size&#034;: 204800<br \/>\n  },<br \/>\n  &#034;timestamp&#034;: 1743623460<br \/>\n}<\/p>\n<p>  \u8bed\u97f3\u6d88\u606f\u793a\u4f8b&#xff1a;  <\/p>\n<p>{<br \/>\n  &#034;msgId&#034;: &#034;20250405-123456-003&#034;,<br \/>\n  &#034;sender&#034;: &#034;user123&#034;,<br \/>\n  &#034;receiver&#034;: &#034;user456&#034;,<br \/>\n  &#034;type&#034;: &#034;voice&#034;,<br \/>\n  &#034;content&#034;: {<br \/>\n    &#034;url&#034;: &#034;https:\/\/cdn.example.com\/voices\/20250405-123456-003.mp3&#034;,<br \/>\n    &#034;duration&#034;: 60,<br \/>\n    &#034;size&#034;: 102400<br \/>\n  },<br \/>\n  &#034;timestamp&#034;: 1743623465<br \/>\n}<\/p>\n<p>  \u89c6\u9891\u6d88\u606f\u793a\u4f8b&#xff1a;  <\/p>\n<p>{<br \/>\n  &#034;msgId&#034;: &#034;20250405-123456-004&#034;,<br \/>\n  &#034;sender&#034;: &#034;user123&#034;,<br \/>\n  &#034;receiver&#034;: &#034;user456&#034;,<br \/>\n  &#034;type&#034;: &#034;video&#034;,<br \/>\n  &#034;content&#034;: {<br \/>\n    &#034;url&#034;: &#034;https:\/\/cdn.example.com\/videos\/20250405-123456-004.mp4&#034;,<br \/>\n    &#034;thumbnail&#034;: &#034;https:\/\/cdn.example.com\/videos\/thumb_20250405-123456-004.jpg&#034;,<br \/>\n    &#034;duration&#034;: 120,<br \/>\n    &#034;width&#034;: 1280,<br \/>\n    &#034;height&#034;: 720,<br \/>\n    &#034;size&#034;: 512000<br \/>\n  },<br \/>\n  &#034;timestamp&#034;: 1743623470<br \/>\n}<\/p>\n<p>  \u903b\u8f91\u5206\u6790&#xff1a;  <\/p>\n<p> \u901a\u8fc7\u5c06\u591a\u5a92\u4f53\u6587\u4ef6\u4e0a\u4f20\u81f3CDN\u5e76\u4ec5\u5728\u6d88\u606f\u4e2d\u4fdd\u5b58\u5143\u6570\u636e\u4e0e\u8bbf\u95eeURL&#xff0c;Fchat\u6709\u6548\u964d\u4f4e\u4e86\u6d88\u606f\u4f20\u8f93\u8fc7\u7a0b\u4e2d\u7684\u5e26\u5bbd\u538b\u529b\u548c\u670d\u52a1\u5668\u8d1f\u8f7d&#xff0c;\u540c\u65f6\u63d0\u5347\u4e86\u6d88\u606f\u7684\u4f20\u8f93\u6548\u7387\u548c\u53ef\u6269\u5c55\u6027\u3002 <\/p>\n<h3> 4.2 \u6d88\u606f\u4e0a\u4f20\u4e0e\u5206\u53d1\u673a\u5236 <\/h3>\n<p> \u4e3a\u4e86\u652f\u6301\u591a\u5a92\u4f53\u6d88\u606f\u7684\u9ad8\u6548\u4f20\u8f93&#xff0c;Fchat\u8bbe\u8ba1\u4e86\u4e00\u5957\u5b8c\u5584\u7684\u4e0a\u4f20\u4e0e\u5206\u53d1\u673a\u5236&#xff0c;\u7ed3\u5408CDN\u4e0e\u7f13\u5b58\u7b56\u7565&#xff0c;\u5b9e\u73b0\u6d88\u606f\u7684\u5feb\u901f\u54cd\u5e94\u4e0e\u5168\u7403\u5206\u53d1\u3002 <\/p>\n<h4> 4.2.1 \u6587\u4ef6\u4e0a\u4f20\u63a5\u53e3\u8bbe\u8ba1 <\/h4>\n<p> Fchat\u63d0\u4f9b\u7edf\u4e00\u7684\u6587\u4ef6\u4e0a\u4f20\u63a5\u53e3&#xff0c;\u652f\u6301\u591a\u7c7b\u578b\u6587\u4ef6\u4e0a\u4f20\u3002\u63a5\u53e3\u8bbe\u8ba1\u5982\u4e0b&#xff1a; <\/p>\n<p>POST \/api\/v1\/upload<br \/>\nContent-Type: multipart\/form-data<\/p>\n<p>Form Data:<br \/>\n&#8211; file: &lt;binary file&gt;<br \/>\n&#8211; type: image | voice | video<br \/>\n&#8211; userId: user123<\/p>\n<p>  \u54cd\u5e94\u793a\u4f8b&#xff1a;  <\/p>\n<p>{<br \/>\n  &#034;code&#034;: 200,<br \/>\n  &#034;data&#034;: {<br \/>\n    &#034;url&#034;: &#034;https:\/\/cdn.example.com\/files\/20250405-123456-002.jpg&#034;,<br \/>\n    &#034;fileId&#034;: &#034;20250405-123456-002&#034;<br \/>\n  }<br \/>\n}<\/p>\n<p>  \u53c2\u6570\u8bf4\u660e&#xff1a;  <\/p>\n<ul>\n<li>  file  &#xff1a;\u4e0a\u4f20\u7684\u6587\u4ef6\u4e8c\u8fdb\u5236\u6570\u636e\u3002 <\/li>\n<li>  type  &#xff1a;\u6587\u4ef6\u7c7b\u578b\u3002 <\/li>\n<li>  userId  &#xff1a;\u4e0a\u4f20\u7528\u6237ID&#xff0c;\u7528\u4e8e\u6743\u9650\u9a8c\u8bc1\u3002 <\/li>\n<li>  url  &#xff1a;\u8fd4\u56de\u6587\u4ef6\u7684\u8bbf\u95ee\u5730\u5740\u3002 <\/li>\n<li>  fileId  &#xff1a;\u6587\u4ef6\u552f\u4e00\u6807\u8bc6\u7b26\u3002 <\/li>\n<\/ul>\n<p>  \u903b\u8f91\u5206\u6790&#xff1a;  <\/p>\n<p> \u4e0a\u4f20\u63a5\u53e3\u91c7\u7528\u6807\u51c6\u7684HTTP\u534f\u8bae&#xff0c;\u652f\u6301\u591a\u79cd\u5ba2\u6237\u7aef\u8bbf\u95ee\u3002\u4e0a\u4f20\u6210\u529f\u540e\u8fd4\u56de\u7684URL\u53ef\u76f4\u63a5\u7528\u4e8e\u6784\u5efa\u6d88\u606f\u4f53&#xff0c;\u786e\u4fdd\u524d\u7aef\u53ef\u4ee5\u7acb\u5373\u5c55\u793a\u6587\u4ef6\u5185\u5bb9\u3002 <\/p>\n<h4> 4.2.2 CDN\u52a0\u901f\u4e0e\u8fb9\u7f18\u8282\u70b9\u7f13\u5b58 <\/h4>\n<p> Fchat\u91c7\u7528CDN&#xff08;\u5185\u5bb9\u5206\u53d1\u7f51\u7edc&#xff09;\u4f5c\u4e3a\u591a\u5a92\u4f53\u8d44\u6e90\u7684\u5b58\u50a8\u4e0e\u5206\u53d1\u65b9\u6848&#xff0c;\u63d0\u5347\u8bbf\u95ee\u901f\u5ea6\u548c\u5e76\u53d1\u80fd\u529b\u3002\u67b6\u6784\u5982\u4e0b&#xff1a; <\/p>\n<p>graph TD<br \/>\n    A[\u5ba2\u6237\u7aef] &#8211;&gt; B[\u4e0a\u4f20\u63a5\u53e3]<br \/>\n    B &#8211;&gt; C[\u5bf9\u8c61\u5b58\u50a8]<br \/>\n    C &#8211;&gt; D[CDN\u7f13\u5b58\u8282\u70b9]<br \/>\n    A &#8211;&gt; E[\u6d88\u606f\u63a5\u6536\u65b9]<br \/>\n    E &#8211;&gt; F[CDN\u8fb9\u7f18\u8282\u70b9]<br \/>\n    F &#8211;&gt; G[\u7528\u6237\u8bbe\u5907]<\/p>\n<p>  \u6d41\u7a0b\u8bf4\u660e&#xff1a;  <\/p>\n<li> \u5ba2\u6237\u7aef\u4e0a\u4f20\u6587\u4ef6\u81f3Fchat\u670d\u52a1\u5668&#xff1b; <\/li>\n<li> \u670d\u52a1\u5668\u5c06\u6587\u4ef6\u4e0a\u4f20\u81f3\u5bf9\u8c61\u5b58\u50a8&#xff08;\u5982AWS S3\u3001\u963f\u91cc\u4e91OSS&#xff09;&#xff1b; <\/li>\n<li> \u6587\u4ef6\u540c\u6b65\u81f3CDN\u7f51\u7edc&#xff1b; <\/li>\n<li> \u63a5\u6536\u65b9\u901a\u8fc7CDN\u83b7\u53d6\u6587\u4ef6&#xff0c;\u51cf\u5c11\u6e90\u7ad9\u538b\u529b&#xff1b; <\/li>\n<li> \u8fb9\u7f18\u8282\u70b9\u7f13\u5b58\u6587\u4ef6&#xff0c;\u63d0\u5347\u54cd\u5e94\u901f\u5ea6\u3002 <\/li>\n<p>  \u4f18\u52bf\u5206\u6790&#xff1a;  <\/p>\n<ul>\n<li> \u63d0\u9ad8\u6587\u4ef6\u8bbf\u95ee\u901f\u5ea6&#xff1b; <\/li>\n<li> \u964d\u4f4e\u670d\u52a1\u5668\u5e26\u5bbd\u538b\u529b&#xff1b; <\/li>\n<li> \u652f\u6301\u5168\u7403\u7528\u6237\u8bbf\u95ee&#xff1b; <\/li>\n<li> \u63d0\u5347\u5e76\u53d1\u8bbf\u95ee\u80fd\u529b\u3002 <\/li>\n<\/ul>\n<h3> 4.3 \u6d88\u606f\u5185\u5bb9\u7684\u89e3\u6790\u4e0e\u6e32\u67d3 <\/h3>\n<p> \u5728\u524d\u7aef&#xff0c;Fchat\u901a\u8fc7\u7edf\u4e00\u7684\u6d88\u606f\u89e3\u6790\u7ec4\u4ef6\u548c\u5bcc\u5a92\u4f53\u6e32\u67d3\u5f15\u64ce&#xff0c;\u5b9e\u73b0\u5bf9\u591a\u79cd\u6d88\u606f\u7c7b\u578b\u7684\u53cb\u597d\u5c55\u793a&#xff0c;\u63d0\u5347\u7528\u6237\u4f53\u9a8c\u3002 <\/p>\n<h4> 4.3.1 \u524d\u7aef\u6d88\u606f\u5c55\u793a\u7ec4\u4ef6\u5f00\u53d1 <\/h4>\n<p> Fchat\u524d\u7aef\u91c7\u7528React\u6846\u67b6\u5f00\u53d1\u6d88\u606f\u5c55\u793a\u7ec4\u4ef6&#xff0c;\u6838\u5fc3\u7ed3\u6784\u5982\u4e0b&#xff1a; <\/p>\n<p>function MessageItem({ message }) {<br \/>\n  switch (message.type) {<br \/>\n    case &#039;text&#039;:<br \/>\n      return &lt;TextMessage message&#061;{message} \/&gt;;<br \/>\n    case &#039;image&#039;:<br \/>\n      return &lt;ImageMessage message&#061;{message} \/&gt;;<br \/>\n    case &#039;voice&#039;:<br \/>\n      return &lt;VoiceMessage message&#061;{message} \/&gt;;<br \/>\n    case &#039;video&#039;:<br \/>\n      return &lt;VideoMessage message&#061;{message} \/&gt;;<br \/>\n    default:<br \/>\n      return &lt;UnknownMessage \/&gt;;<br \/>\n  }<br \/>\n}<\/p>\n<p>  \u903b\u8f91\u5206\u6790&#xff1a;  <\/p>\n<p> \u8be5\u7ec4\u4ef6\u901a\u8fc7\u5224\u65ad\u6d88\u606f\u7c7b\u578b\u52a8\u6001\u6e32\u67d3\u4e0d\u540c\u7684\u5b50\u7ec4\u4ef6&#xff0c;\u5b9e\u73b0\u5bf9\u591a\u79cd\u6d88\u606f\u7684\u7edf\u4e00\u5904\u7406\u4e0e\u5c55\u793a\u3002\u6bcf\u4e2a\u5b50\u7ec4\u4ef6\u5185\u90e8\u8d1f\u8d23\u5177\u4f53\u7c7b\u578b\u7684\u6e32\u67d3\u903b\u8f91\u548c\u7528\u6237\u4ea4\u4e92\u5904\u7406\u3002 <\/p>\n<h4> 4.3.2 \u5bcc\u6587\u672c\u4e0e\u8868\u60c5\u652f\u6301\u5b9e\u73b0 <\/h4>\n<p> Fchat\u652f\u6301\u5bcc\u6587\u672c\u6d88\u606f\u548c\u8868\u60c5\u7b26\u53f7&#xff0c;\u91c7\u7528Markdown\u89e3\u6790\u5668\u7ed3\u5408\u81ea\u5b9a\u4e49\u8868\u60c5\u5e93\u5b9e\u73b0&#xff1a; <\/p>\n<p>import ReactMarkdown from &#039;react-markdown&#039;;<br \/>\nimport emoji from &#039;remark-emoji&#039;;<\/p>\n<p>function TextMessage({ message }) {<br \/>\n  return (<br \/>\n    &lt;div className&#061;&#034;text-message&#034;&gt;<br \/>\n      &lt;ReactMarkdown remarkPlugins&#061;{[emoji]}&gt;<br \/>\n        {message.content.text}<br \/>\n      &lt;\/ReactMarkdown&gt;<br \/>\n    &lt;\/div&gt;<br \/>\n  );<br \/>\n}<\/p>\n<p>  \u53c2\u6570\u8bf4\u660e&#xff1a;  <\/p>\n<ul>\n<li>  ReactMarkdown  &#xff1a;\u5c06Markdown\u683c\u5f0f\u6587\u672c\u89e3\u6790\u4e3aHTML\u3002 <\/li>\n<li>  remarkPlugins  &#xff1a;\u63d2\u4ef6\u7cfb\u7edf&#xff0c;\u6dfb\u52a0\u8868\u60c5\u652f\u6301\u3002 <\/li>\n<li>  emoji  &#xff1a;\u5c06  \ud83d\ude42  \u7b49\u7b26\u53f7\u8f6c\u6362\u4e3a\u8868\u60c5\u56fe\u50cf\u3002 <\/li>\n<\/ul>\n<p>  \u903b\u8f91\u5206\u6790&#xff1a;  <\/p>\n<p> \u901a\u8fc7Markdown\u89e3\u6790\u5668&#xff0c;\u7528\u6237\u53ef\u4ee5\u5728\u804a\u5929\u4e2d\u4f7f\u7528\u52a0\u7c97\u3001\u659c\u4f53\u3001\u94fe\u63a5\u3001\u8868\u60c5\u7b49\u4e30\u5bcc\u683c\u5f0f&#xff0c;\u63d0\u5347\u4ea4\u6d41\u4f53\u9a8c\u3002\u540c\u65f6&#xff0c;\u4ee3\u7801\u7ed3\u6784\u6e05\u6670&#xff0c;\u6613\u4e8e\u6269\u5c55\u65b0\u7684\u63d2\u4ef6\u529f\u80fd\u3002 <\/p>\n<h4> 4.3.3 \u89c6\u9891\u64ad\u653e\u5668\u4e0e\u97f3\u9891\u64ad\u653e\u5668\u96c6\u6210 <\/h4>\n<p> Fchat\u96c6\u6210HTML5\u7684  &lt;video&gt;  \u548c  &lt;audio&gt;  \u6807\u7b7e&#xff0c;\u7ed3\u5408\u7b2c\u4e09\u65b9\u64ad\u653e\u5668\u5e93&#xff08;\u5982video.js\u3001wavesurfer.js&#xff09;\u5b9e\u73b0\u591a\u5a92\u4f53\u64ad\u653e\u3002 <\/p>\n<p>  \u89c6\u9891\u64ad\u653e\u5668\u793a\u4f8b&#xff1a;  <\/p>\n<p>import React from &#039;react&#039;;<\/p>\n<p>function VideoMessage({ message }) {<br \/>\n  return (<br \/>\n    &lt;div className&#061;&#034;video-message&#034;&gt;<br \/>\n      &lt;video controls width&#061;&#034;320&#034; height&#061;&#034;240&#034; src&#061;{message.content.url}&gt;&lt;\/video&gt;<br \/>\n      &lt;p&gt;\u65f6\u957f&#xff1a;{message.content.duration}\u79d2&lt;\/p&gt;<br \/>\n    &lt;\/div&gt;<br \/>\n  );<br \/>\n}<\/p>\n<p>  \u97f3\u9891\u64ad\u653e\u5668\u793a\u4f8b&#xff1a;  <\/p>\n<p>function VoiceMessage({ message }) {<br \/>\n  return (<br \/>\n    &lt;div className&#061;&#034;voice-message&#034;&gt;<br \/>\n      &lt;audio controls src&#061;{message.content.url}&gt;&lt;\/audio&gt;<br \/>\n      &lt;p&gt;\u65f6\u957f&#xff1a;{message.content.duration}\u79d2&lt;\/p&gt;<br \/>\n    &lt;\/div&gt;<br \/>\n  );<br \/>\n}<\/p>\n<p>  \u903b\u8f91\u5206\u6790&#xff1a;  <\/p>\n<ul>\n<li> \u4f7f\u7528\u539f\u751fHTML5\u63a7\u4ef6&#xff0c;\u517c\u5bb9\u6027\u5f3a&#xff1b; <\/li>\n<li> \u7ed3\u5408\u81ea\u5b9a\u4e49UI\u53ef\u5b9e\u73b0\u66f4\u4e30\u5bcc\u7684\u64ad\u653e\u63a7\u5236&#xff1b; <\/li>\n<li> \u652f\u6301\u9884\u52a0\u8f7d\u3001\u8fdb\u5ea6\u6761\u3001\u64ad\u653e\u6682\u505c\u7b49\u57fa\u7840\u529f\u80fd\u3002 <\/li>\n<\/ul>\n<p> \u6b64\u5916&#xff0c;Fchat\u8fd8\u652f\u6301\u7f29\u7565\u56fe\u70b9\u51fb\u64ad\u653e\u3001\u81ea\u52a8\u52a0\u8f7d\u9884\u89c8\u56fe\u7b49\u4f18\u5316\u7b56\u7565&#xff0c;\u63d0\u5347\u7528\u6237\u4f53\u9a8c\u3002 <\/p>\n<h3> \u603b\u7ed3\u4e0e\u5c55\u671b <\/h3>\n<p> Fchat\u901a\u8fc7\u5bf9\u591a\u5a92\u4f53\u6d88\u606f\u7684\u7edf\u4e00\u7ed3\u6784\u8bbe\u8ba1\u3001\u9ad8\u6548\u7684\u4e0a\u4f20\u4e0e\u5206\u53d1\u673a\u5236\u4ee5\u53ca\u524d\u7aef\u5bcc\u5a92\u4f53\u6e32\u67d3\u7684\u652f\u6301&#xff0c;\u5b9e\u73b0\u4e86\u5bf9\u6587\u672c\u3001\u56fe\u7247\u3001\u8bed\u97f3\u3001\u89c6\u9891\u7b49\u591a\u79cd\u6d88\u606f\u7c7b\u578b\u7684\u5168\u9762\u652f\u6301\u3002\u4e0b\u4e00\u7ae0\u6211\u4eec\u5c06\u6df1\u5165\u63a2\u8ba8Fchat\u5982\u4f55\u901a\u8fc7SSL\/TLS\u52a0\u5bc6\u901a\u4fe1\u4fdd\u969c\u6d88\u606f\u4f20\u8f93\u7684\u5b89\u5168\u6027\u3002 <\/p>\n<h2> 5. SSL\/TLS\u52a0\u5bc6\u901a\u4fe1\u5b9e\u73b0 <\/h2>\n<p> \u5728\u73b0\u4ee3\u901a\u4fe1\u7cfb\u7edf\u4e2d&#xff0c;\u6570\u636e\u7684\u5b89\u5168\u6027\u4e0e\u5b8c\u6574\u6027\u81f3\u5173\u91cd\u8981\u3002Fchat \u4f5c\u4e3a\u4e00\u4e2a\u9ad8\u6027\u80fd\u7684\u5373\u65f6\u901a\u8baf\u670d\u52a1\u5668&#xff0c;\u91c7\u7528 SSL\/TLS \u534f\u8bae\u5b9e\u73b0\u52a0\u5bc6\u901a\u4fe1&#xff0c;\u786e\u4fdd\u7528\u6237\u4e4b\u95f4\u7684\u6d88\u606f\u5728\u4f20\u8f93\u8fc7\u7a0b\u4e2d\u4e0d\u88ab\u7a83\u53d6\u6216\u7be1\u6539\u3002\u672c\u7ae0\u5c06\u6df1\u5165\u5256\u6790 SSL\/TLS \u7684\u901a\u4fe1\u673a\u5236&#xff0c;\u7ed3\u5408 Fchat \u7684\u5b9e\u73b0\u65b9\u5f0f&#xff0c;\u8be6\u7ec6\u8bb2\u89e3\u52a0\u5bc6\u901a\u4fe1\u7684\u539f\u7406\u3001\u914d\u7f6e\u4e0e\u5904\u7406\u6d41\u7a0b\u3002 <\/p>\n<h3> 5.1 \u52a0\u5bc6\u901a\u4fe1\u7684\u57fa\u672c\u539f\u7406 <\/h3>\n<h4> 5.1.1 SSL\/TLS\u63e1\u624b\u6d41\u7a0b\u8be6\u89e3 <\/h4>\n<p> SSL\/TLS \u63e1\u624b\u662f\u5efa\u7acb\u52a0\u5bc6\u901a\u4fe1\u7684\u524d\u63d0&#xff0c;\u5b83\u4e0d\u4ec5\u7528\u4e8e\u8eab\u4efd\u9a8c\u8bc1&#xff0c;\u8fd8\u8d1f\u8d23\u534f\u5546\u540e\u7eed\u901a\u4fe1\u6240\u4f7f\u7528\u7684\u52a0\u5bc6\u7b97\u6cd5\u548c\u5bc6\u94a5\u3002Fchat \u4f7f\u7528 TLS 1.2 \u6216\u66f4\u9ad8\u7248\u672c&#xff0c;\u786e\u4fdd\u901a\u4fe1\u8fc7\u7a0b\u7684\u5b89\u5168\u6027\u3002 <\/p>\n<p>  TLS \u63e1\u624b\u6d41\u7a0b\u56fe\u5982\u4e0b&#xff1a;  <\/p>\n<p>sequenceDiagram<br \/>\n    participant Client<br \/>\n    participant Server<br \/>\n    Client-&gt;&gt;Server: ClientHello<br \/>\n    Server-&gt;&gt;Client: ServerHello, Certificate, ServerKeyExchange, ServerHelloDone<br \/>\n    Client-&gt;&gt;Server: ClientKeyExchange, ChangeCipherSpec, Finished<br \/>\n    Server-&gt;&gt;Client: ChangeCipherSpec, Finished<br \/>\n    Client&lt;-&gt;&gt;Server: Encrypted Application Data<\/p>\n<h5> \u63e1\u624b\u6d41\u7a0b\u8be6\u89e3&#xff1a; <\/h5>\n<li>  ClientHello  &#xff1a;\u5ba2\u6237\u7aef\u53d1\u9001\u4e00\u4e2a\u5305\u542b\u652f\u6301\u7684 TLS \u7248\u672c\u3001\u52a0\u5bc6\u5957\u4ef6&#xff08;Cipher Suites&#xff09;\u548c\u968f\u673a\u6570\u7684 ClientHello \u6d88\u606f\u3002 <\/li>\n<li>  ServerHello  &#xff1a;\u670d\u52a1\u5668\u9009\u62e9\u4e00\u4e2a\u52a0\u5bc6\u5957\u4ef6\u5e76\u8fd4\u56de ServerHello \u6d88\u606f&#xff0c;\u540c\u65f6\u53d1\u9001\u81ea\u5df1\u7684\u8bc1\u4e66&#xff08;\u901a\u5e38\u4e3a X.509 \u8bc1\u4e66&#xff09;\u3002 <\/li>\n<li>  \u5bc6\u94a5\u4ea4\u6362  &#xff1a;  &#8211; \u5982\u679c\u4f7f\u7528 RSA \u5bc6\u94a5\u4ea4\u6362&#xff0c;\u5ba2\u6237\u7aef\u4f7f\u7528\u670d\u52a1\u5668\u8bc1\u4e66\u4e2d\u7684\u516c\u94a5\u52a0\u5bc6\u9884\u4e3b\u5bc6\u94a5&#xff08;Pre-Master Secret&#xff09;&#xff0c;\u53d1\u9001\u7ed9\u670d\u52a1\u5668\u3002  &#8211; \u5982\u679c\u4f7f\u7528 ECDHE \u7b49\u524d\u5411\u5b89\u5168\u7b97\u6cd5&#xff0c;\u53cc\u65b9\u901a\u8fc7\u5bc6\u94a5\u4ea4\u6362\u534f\u8bae&#xff08;\u5982 Diffie-Hellman&#xff09;\u751f\u6210\u5171\u4eab\u5bc6\u94a5\u3002 <\/li>\n<li>  ChangeCipherSpec  &#xff1a;\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u7aef\u90fd\u5207\u6362\u5230\u52a0\u5bc6\u6a21\u5f0f\u3002 <\/li>\n<li>  Finished  &#xff1a;\u53cc\u65b9\u53d1\u9001 Finished \u6d88\u606f&#xff0c;\u9a8c\u8bc1\u63e1\u624b\u8fc7\u7a0b\u7684\u5b8c\u6574\u6027\u3002 <\/li>\n<li>  Encrypted Application Data  &#xff1a;\u4e4b\u540e\u6240\u6709\u7684\u901a\u4fe1\u90fd\u7ecf\u8fc7\u52a0\u5bc6\u4f20\u8f93\u3002 <\/li>\n<p>  \u6ce8\u610f  &#xff1a;Fchat \u670d\u52a1\u5668\u9ed8\u8ba4\u542f\u7528\u524d\u5411\u5b89\u5168&#xff08;Forward Secrecy&#xff09;\u673a\u5236&#xff0c;\u91c7\u7528 ECDHE \u5bc6\u94a5\u4ea4\u6362\u7b97\u6cd5&#xff0c;\u5373\u4f7f\u957f\u671f\u5bc6\u94a5\u6cc4\u9732\u4e5f\u4e0d\u4f1a\u5f71\u54cd\u8fc7\u53bb\u901a\u4fe1\u7684\u5b89\u5168\u6027\u3002 <\/p>\n<h4> 5.1.2 \u6570\u5b57\u8bc1\u4e66\u4e0e\u5bc6\u94a5\u7ba1\u7406 <\/h4>\n<p> Fchat \u91c7\u7528\u57fa\u4e8e X.509 \u6807\u51c6\u7684\u6570\u5b57\u8bc1\u4e66\u8fdb\u884c\u8eab\u4efd\u8ba4\u8bc1\u548c\u5bc6\u94a5\u4ea4\u6362\u3002\u8bc1\u4e66\u901a\u5e38\u7531\u53ef\u4fe1\u7684\u8bc1\u4e66\u9881\u53d1\u673a\u6784&#xff08;CA&#xff09;\u7b7e\u53d1&#xff0c;\u6216\u5728\u6d4b\u8bd5\u73af\u5883\u4e2d\u4f7f\u7528\u81ea\u7b7e\u540d\u8bc1\u4e66\u3002 <\/p>\n<h5> \u8bc1\u4e66\u4e0e\u5bc6\u94a5\u6587\u4ef6\u8bf4\u660e&#xff1a; <\/h5>\n<table>\n<tr> \u6587\u4ef6\u540d  \u5185\u5bb9\u63cf\u8ff0 <\/tr>\n<tbody>\n<tr>\n<td>  server.crt  <\/td>\n<td> \u670d\u52a1\u5668\u8bc1\u4e66&#xff0c;\u5305\u542b\u516c\u94a5\u548c\u8eab\u4efd\u4fe1\u606f <\/td>\n<\/tr>\n<tr>\n<td>  server.key  <\/td>\n<td> \u670d\u52a1\u5668\u79c1\u94a5&#xff0c;\u7528\u4e8e\u89e3\u5bc6\u5ba2\u6237\u7aef\u4fe1\u606f <\/td>\n<\/tr>\n<tr>\n<td>  ca.crt  <\/td>\n<td> \u6839\u8bc1\u4e66&#xff0c;\u7528\u4e8e\u9a8c\u8bc1\u670d\u52a1\u5668\u8bc1\u4e66\u5408\u6cd5\u6027 <\/td>\n<\/tr>\n<tr>\n<td>  dhparams.pem  <\/td>\n<td> DH \u53c2\u6570\u6587\u4ef6&#xff0c;\u7528\u4e8e\u589e\u5f3a\u5bc6\u94a5\u4ea4\u6362\u5b89\u5168\u6027 <\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h5> \u751f\u6210\u81ea\u7b7e\u540d\u8bc1\u4e66\u793a\u4f8b&#xff08;OpenSSL&#xff09;&#xff1a; <\/h5>\n<p># \u751f\u6210\u79c1\u94a5<br \/>\nopenssl genrsa -out server.key 2048<\/p>\n<p># \u751f\u6210\u8bc1\u4e66\u8bf7\u6c42<br \/>\nopenssl req -new -key server.key -out server.csr<\/p>\n<p># \u81ea\u7b7e\u540d\u8bc1\u4e66<br \/>\nopenssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt<\/p>\n<p>  \u9010\u884c\u89e3\u91ca&#xff1a;   &#8211;  genrsa  : \u751f\u6210 RSA \u79c1\u94a5&#xff0c;2048 \u4f4d\u957f\u5ea6&#xff0c;\u5b89\u5168\u6027\u9ad8\u3002  &#8211;  req -new  : \u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u8bc1\u4e66\u8bf7\u6c42\u6587\u4ef6&#xff08;CSR&#xff09;&#xff0c;\u9700\u8981\u586b\u5199\u7ec4\u7ec7\u4fe1\u606f\u3002  &#8211;  x509 -req  : \u81ea\u7b7e\u540d\u751f\u6210 X.509 \u8bc1\u4e66&#xff0c;\u6709\u6548\u671f\u4e3a 365 \u5929\u3002 <\/p>\n<p> Fchat \u652f\u6301\u914d\u7f6e\u591a\u4e2a\u8bc1\u4e66\u4ee5\u5b9e\u73b0\u591a\u57df\u540d\u652f\u6301&#xff08;SNI&#xff09;&#xff0c;\u5e76\u53ef\u901a\u8fc7\u8bc1\u4e66\u540a\u9500\u5217\u8868&#xff08;CRL&#xff09;\u6216 OCSP \u534f\u8bae\u8fdb\u884c\u8bc1\u4e66\u72b6\u6001\u68c0\u67e5&#xff0c;\u9632\u6b62\u4f7f\u7528\u5df2\u540a\u9500\u7684\u8bc1\u4e66\u3002 <\/p>\n<h3> 5.2 Fchat\u4e2d\u7684\u52a0\u5bc6\u901a\u4fe1\u914d\u7f6e <\/h3>\n<h4> 5.2.1 OpenSSL\u914d\u7f6e\u4e0e\u8bc1\u4e66\u751f\u6210 <\/h4>\n<p> Fchat \u670d\u52a1\u7aef\u4f7f\u7528 OpenSSL \u5e93\u5b9e\u73b0 TLS \u52a0\u5bc6\u529f\u80fd\u3002\u5728\u914d\u7f6e\u6587\u4ef6\u4e2d&#xff0c;\u9700\u6307\u5b9a\u8bc1\u4e66\u8def\u5f84\u3001\u79c1\u94a5\u8def\u5f84\u4ee5\u53ca TLS \u534f\u8bae\u7248\u672c\u548c\u52a0\u5bc6\u5957\u4ef6\u3002 <\/p>\n<h5> \u793a\u4f8b\u914d\u7f6e&#xff08;fchat.conf&#xff09;&#xff1a; <\/h5>\n<p>ssl:<br \/>\n  enable: true<br \/>\n  cert_path: &#034;\/etc\/fchat\/ssl\/server.crt&#034;<br \/>\n  key_path: &#034;\/etc\/fchat\/ssl\/server.key&#034;<br \/>\n  ca_path: &#034;\/etc\/fchat\/ssl\/ca.crt&#034;<br \/>\n  dhparams_path: &#034;\/etc\/fchat\/ssl\/dhparams.pem&#034;<br \/>\n  protocols: [&#034;TLSv1.2&#034;, &#034;TLSv1.3&#034;]<br \/>\n  ciphers: &#034;ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384&#034;<\/p>\n<p>  \u53c2\u6570\u8bf4\u660e&#xff1a;   &#8211;  cert_path  &#xff1a;\u670d\u52a1\u5668\u8bc1\u4e66\u8def\u5f84\u3002  &#8211;  key_path  &#xff1a;\u79c1\u94a5\u8def\u5f84&#xff0c;\u5fc5\u987b\u4e3a PEM \u683c\u5f0f\u3002  &#8211;  ca_path  &#xff1a;\u6839\u8bc1\u4e66\u8def\u5f84&#xff0c;\u7528\u4e8e\u5ba2\u6237\u7aef\u9a8c\u8bc1\u670d\u52a1\u5668\u8eab\u4efd\u3002  &#8211;  dhparams_path  &#xff1a;DH \u53c2\u6570\u6587\u4ef6&#xff0c;\u7528\u4e8e\u524d\u5411\u5b89\u5168\u7684\u5bc6\u94a5\u4ea4\u6362\u3002  &#8211;  protocols  &#xff1a;\u5141\u8bb8\u7684 TLS \u534f\u8bae\u7248\u672c\u3002  &#8211;  ciphers  &#xff1a;\u52a0\u5bc6\u5957\u4ef6\u4f18\u5148\u7ea7\u5217\u8868&#xff0c;\u5efa\u8bae\u4f18\u5148\u4f7f\u7528\u524d\u5411\u5b89\u5168\u7b97\u6cd5\u3002 <\/p>\n<h5> \u914d\u7f6e\u670d\u52a1\u7aef\u542f\u7528 TLS \u7684\u4ee3\u7801\u7247\u6bb5&#xff08;\u4f2a\u4ee3\u7801&#xff09;&#xff1a; <\/h5>\n<p>import ssl<br \/>\nfrom fchat.server import TCPServer<\/p>\n<p>context &#061; ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)<br \/>\ncontext.load_cert_chain(certfile&#061;&#034;server.crt&#034;, keyfile&#061;&#034;server.key&#034;)<br \/>\ncontext.verify_mode &#061; ssl.CERT_REQUIRED<br \/>\ncontext.load_verify_locations(cafile&#061;&#034;ca.crt&#034;)<br \/>\ncontext.options |&#061; ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1  # \u7981\u7528\u4f4e\u7248\u672c\u534f\u8bae<br \/>\ncontext.set_ciphers(&#034;ECDHE-ECDSA-AES256-GCM-SHA384&#034;)<\/p>\n<p>server &#061; TCPServer(&#034;0.0.0.0&#034;, 8080, ssl_context&#061;context)<br \/>\nserver.start()<\/p>\n<p>  \u9010\u884c\u89e3\u91ca&#xff1a;   &#8211;  create_default_context  &#xff1a;\u521b\u5efa\u4e00\u4e2a\u7528\u4e8e\u5ba2\u6237\u7aef\u8ba4\u8bc1\u7684 SSL \u4e0a\u4e0b\u6587\u3002  &#8211;  load_cert_chain  &#xff1a;\u52a0\u8f7d\u670d\u52a1\u5668\u8bc1\u4e66\u548c\u79c1\u94a5\u3002  &#8211;  verify_mode &#061; ssl.CERT_REQUIRED  &#xff1a;\u8981\u6c42\u5ba2\u6237\u7aef\u63d0\u4f9b\u8bc1\u4e66\u8fdb\u884c\u53cc\u5411\u8ba4\u8bc1\u3002  &#8211;  set_ciphers  &#xff1a;\u8bbe\u7f6e\u52a0\u5bc6\u5957\u4ef6&#xff0c;\u4f18\u5148\u4f7f\u7528 ECDHE \u524d\u5411\u5b89\u5168\u7b97\u6cd5\u3002 <\/p>\n<h4> 5.2.2 \u670d\u52a1\u7aef\u4e0e\u5ba2\u6237\u7aef\u8bc1\u4e66\u9a8c\u8bc1\u673a\u5236 <\/h4>\n<p> Fchat \u652f\u6301\u53cc\u5411 TLS&#xff08;Mutual TLS&#xff09;\u8ba4\u8bc1&#xff0c;\u5373\u670d\u52a1\u7aef\u9a8c\u8bc1\u5ba2\u6237\u7aef\u8bc1\u4e66&#xff0c;\u5ba2\u6237\u7aef\u4e5f\u9a8c\u8bc1\u670d\u52a1\u7aef\u8bc1\u4e66\u3002 <\/p>\n<h5> \u5ba2\u6237\u7aef\u914d\u7f6e&#xff08;Python \u793a\u4f8b&#xff09;&#xff1a; <\/h5>\n<p>import ssl<br \/>\nimport socket<\/p>\n<p>context &#061; ssl.create_default_context()<br \/>\ncontext.check_hostname &#061; True<br \/>\ncontext.verify_mode &#061; ssl.CERT_REQUIRED<br \/>\ncontext.load_cert_chain(certfile&#061;&#034;client.crt&#034;, keyfile&#061;&#034;client.key&#034;)<br \/>\ncontext.load_verify_locations(cafile&#061;&#034;ca.crt&#034;)<\/p>\n<p>with socket.create_connection((&#034;fchat.example.com&#034;, 8080)) as sock:<br \/>\n    with context.wrap_socket(sock, server_hostname&#061;&#034;fchat.example.com&#034;) as ssock:<br \/>\n        print(ssock.version())<br \/>\n        print(ssock.getpeercert())  # \u83b7\u53d6\u670d\u52a1\u5668\u8bc1\u4e66\u4fe1\u606f<\/p>\n<p>  \u53c2\u6570\u8bf4\u660e&#xff1a;   &#8211;  check_hostname  &#xff1a;\u542f\u7528\u4e3b\u673a\u540d\u9a8c\u8bc1&#xff0c;\u9632\u6b62\u4e2d\u95f4\u4eba\u653b\u51fb\u3002  &#8211;  verify_mode &#061; ssl.CERT_REQUIRED  &#xff1a;\u5ba2\u6237\u7aef\u5fc5\u987b\u9a8c\u8bc1\u670d\u52a1\u5668\u8bc1\u4e66\u3002  &#8211;  load_cert_chain  &#xff1a;\u5ba2\u6237\u7aef\u8bc1\u4e66\u548c\u79c1\u94a5\u8def\u5f84&#xff0c;\u7528\u4e8e\u670d\u52a1\u7aef\u9a8c\u8bc1\u3002 <\/p>\n<p> Fchat \u670d\u52a1\u7aef\u5728\u63a5\u6536\u5230\u5ba2\u6237\u7aef\u8fde\u63a5\u65f6&#xff0c;\u4f1a\u8c03\u7528  getpeercert()  \u65b9\u6cd5\u83b7\u53d6\u5ba2\u6237\u7aef\u8bc1\u4e66&#xff0c;\u5e76\u901a\u8fc7 CA \u6839\u8bc1\u4e66\u8fdb\u884c\u9a8c\u8bc1\u3002\u5982\u679c\u9a8c\u8bc1\u5931\u8d25&#xff0c;\u5219\u62d2\u7edd\u8fde\u63a5\u3002 <\/p>\n<h3> 5.3 \u52a0\u5bc6\u6d88\u606f\u7684\u4f20\u8f93\u4e0e\u89e3\u5bc6\u5904\u7406 <\/h3>\n<h4> 5.3.1 \u6d88\u606f\u52a0\u5bc6\u7b97\u6cd5\u9009\u578b&#xff08;AES\u3001RSA&#xff09; <\/h4>\n<p> Fchat \u91c7\u7528\u5206\u5c42\u52a0\u5bc6\u7b56\u7565&#xff1a; <\/p>\n<ul>\n<li>  \u4f20\u8f93\u5c42\u52a0\u5bc6  &#xff1a;\u4f7f\u7528 TLS \u534f\u8bae\u5b9e\u73b0\u7aef\u5230\u7aef\u52a0\u5bc6&#xff0c;\u9632\u6b62\u4e2d\u95f4\u4eba\u7a83\u542c\u3002 <\/li>\n<li>  \u5e94\u7528\u5c42\u52a0\u5bc6  &#xff1a;\u5bf9\u654f\u611f\u6d88\u606f&#xff08;\u5982\u79c1\u804a\u6d88\u606f\u3001\u6587\u4ef6\u94fe\u63a5&#xff09;\u8fdb\u884c\u4e8c\u6b21\u52a0\u5bc6&#xff0c;\u4f7f\u7528 AES-256-GCM \u7b97\u6cd5\u3002 <\/li>\n<\/ul>\n<h5> AES-256-GCM \u52a0\u5bc6\u793a\u4f8b&#xff08;Python&#xff09;&#xff1a; <\/h5>\n<p>from Crypto.Cipher import AES<br \/>\nfrom Crypto.Random import get_random_bytes<br \/>\nfrom Crypto.Util.Padding import pad<\/p>\n<p>key &#061; get_random_bytes(32)  # 256-bit key<br \/>\niv &#061; get_random_bytes(12)   # GCM mode requires 96-bit IV<\/p>\n<p>cipher &#061; AES.new(key, AES.MODE_GCM, iv)<br \/>\nplaintext &#061; b&#034;Secret message to encrypt&#034;<br \/>\nciphertext, tag &#061; cipher.encrypt_and_digest(pad(plaintext, AES.block_size))<\/p>\n<p># \u53d1\u9001 ciphertext &#043; iv &#043; tag<\/p>\n<p>  \u9010\u884c\u89e3\u91ca&#xff1a;   &#8211;  AES.new()  &#xff1a;\u521b\u5efa AES-GCM \u6a21\u5f0f\u52a0\u5bc6\u5668\u3002  &#8211;  encrypt_and_digest()  &#xff1a;\u52a0\u5bc6\u6570\u636e\u5e76\u751f\u6210\u8ba4\u8bc1\u6807\u7b7e&#xff08;tag&#xff09;&#xff0c;\u9632\u6b62\u7be1\u6539\u3002  &#8211;  pad()  &#xff1a;\u586b\u5145\u6570\u636e\u5757&#xff0c;\u786e\u4fdd\u660e\u6587\u957f\u5ea6\u4e3a\u5757\u5927\u5c0f\u7684\u6574\u6570\u500d\u3002 <\/p>\n<p> \u5728\u63a5\u6536\u7aef&#xff0c;\u4f7f\u7528\u76f8\u540c\u7684 key\u3001iv \u548c tag \u8fdb\u884c\u89e3\u5bc6\u548c\u5b8c\u6574\u6027\u6821\u9a8c&#xff1a; <\/p>\n<p>cipher &#061; AES.new(key, AES.MODE_GCM, iv)<br \/>\ndecrypted &#061; cipher.decrypt_and_verify(ciphertext, tag)<\/p>\n<h5> RSA \u7528\u4e8e\u5bc6\u94a5\u4ea4\u6362&#xff08;\u975e\u5bf9\u79f0\u52a0\u5bc6&#xff09;&#xff1a; <\/h5>\n<p> Fchat \u5728\u67d0\u4e9b\u573a\u666f\u4e0b\u4f7f\u7528 RSA \u4f5c\u4e3a\u5bc6\u94a5\u4ea4\u6362\u624b\u6bb5&#xff0c;\u4f8b\u5982\u5728\u4f1a\u8bdd\u521d\u59cb\u5316\u65f6\u52a0\u5bc6\u4f20\u8f93 AES \u5bc6\u94a5\u3002 <\/p>\n<p># \u751f\u6210 RSA \u5bc6\u94a5\u5bf9<br \/>\nopenssl genrsa -out private.pem 2048<br \/>\nopenssl rsa -in private.pem -pubout -out public.pem<\/p>\n<p>  \u4f7f\u7528 RSA \u52a0\u5bc6 AES \u5bc6\u94a5&#xff08;\u4f2a\u4ee3\u7801&#xff09;&#xff1a;  <\/p>\n<p>from Crypto.Cipher import PKCS1_OAEP<br \/>\nfrom Crypto.PublicKey import RSA<\/p>\n<p>public_key &#061; RSA.import_key(open(&#034;public.pem&#034;).read())<br \/>\ncipher_rsa &#061; PKCS1_OAEP.new(public_key)<br \/>\nencrypted_key &#061; cipher_rsa.encrypt(key)<\/p>\n<p>  \u8bf4\u660e&#xff1a;   &#8211;  PKCS1_OAEP  &#xff1a;RSA \u52a0\u5bc6\u586b\u5145\u65b9\u6848&#xff0c;\u9632\u6b62\u660e\u6587\u653b\u51fb\u3002  &#8211;  encrypt()  &#xff1a;\u4f7f\u7528\u516c\u94a5\u52a0\u5bc6 AES \u5bc6\u94a5&#xff0c;\u4ec5\u6301\u6709\u79c1\u94a5\u7684\u4e00\u65b9\u53ef\u89e3\u5bc6\u3002 <\/p>\n<h4> 5.3.2 \u4f1a\u8bdd\u5bc6\u94a5\u52a8\u6001\u751f\u6210\u4e0e\u4ea4\u6362 <\/h4>\n<p> \u4e3a\u589e\u5f3a\u5b89\u5168\u6027&#xff0c;Fchat \u5728\u6bcf\u6b21\u4f1a\u8bdd\u5efa\u7acb\u65f6\u52a8\u6001\u751f\u6210\u65b0\u7684\u4f1a\u8bdd\u5bc6\u94a5&#xff08;Session Key&#xff09;&#xff0c;\u5e76\u901a\u8fc7 ECDHE \u7b97\u6cd5\u5b9e\u73b0\u5bc6\u94a5\u4ea4\u6362\u3002 <\/p>\n<h5> ECDHE \u5bc6\u94a5\u4ea4\u6362\u6d41\u7a0b&#xff08;\u4f2a\u4ee3\u7801&#xff09;&#xff1a; <\/h5>\n<p>from cryptography.hazmat.primitives.asymmetric import ec<br \/>\nfrom cryptography.hazmat.primitives.kdf.hkdf import HKDF<br \/>\nfrom cryptography.hazmat.primitives import hashes<\/p>\n<p># \u5ba2\u6237\u7aef\u751f\u6210\u4e34\u65f6\u5bc6\u94a5\u5bf9<br \/>\nclient_private_key &#061; ec.generate_private_key(ec.SECP384R1())<br \/>\nclient_public_key &#061; client_private_key.public_key()<\/p>\n<p># \u670d\u52a1\u7aef\u751f\u6210\u4e34\u65f6\u5bc6\u94a5\u5bf9<br \/>\nserver_private_key &#061; ec.generate_private_key(ec.SECP384R1())<br \/>\nserver_public_key &#061; server_private_key.public_key()<\/p>\n<p># \u5ba2\u6237\u7aef\u8ba1\u7b97\u5171\u4eab\u5bc6\u94a5<br \/>\nshared_key &#061; client_private_key.exchange(ec.ECDH(), server_public_key)<\/p>\n<p># \u4f7f\u7528 HKDF \u884d\u751f\u4f1a\u8bdd\u5bc6\u94a5<br \/>\nhkdf &#061; HKDF(<br \/>\n    algorithm&#061;hashes.SHA256(),<br \/>\n    length&#061;32,<br \/>\n    salt&#061;None,<br \/>\n    info&#061;b&#039;handshake data&#039;,<br \/>\n)<br \/>\nsession_key &#061; hkdf.derive(shared_key)<\/p>\n<p>  \u8bf4\u660e&#xff1a;   &#8211;  ec.generate_private_key()  &#xff1a;\u751f\u6210\u692d\u5706\u66f2\u7ebf\u5bc6\u94a5\u5bf9\u3002  &#8211;  exchange()  &#xff1a;\u4f7f\u7528 ECDH \u7b97\u6cd5\u8ba1\u7b97\u5171\u4eab\u5bc6\u94a5\u3002  &#8211;  HKDF  &#xff1a;\u5bc6\u94a5\u6d3e\u751f\u51fd\u6570&#xff0c;\u5c06\u5171\u4eab\u5bc6\u94a5\u6269\u5c55\u4e3a\u4f1a\u8bdd\u5bc6\u94a5\u3002 <\/p>\n<h5> \u4f1a\u8bdd\u5bc6\u94a5\u4f7f\u7528\u6d41\u7a0b\u56fe&#xff1a; <\/h5>\n<p>graph TD<br \/>\n    A[\u5ba2\u6237\u7aef\u53d1\u8d77\u8fde\u63a5] &#8211;&gt; B[\u670d\u52a1\u7aef\u54cd\u5e94\u5e76\u4ea4\u6362\u516c\u94a5]<br \/>\n    B &#8211;&gt; C[\u53cc\u65b9\u8ba1\u7b97\u5171\u4eab\u5bc6\u94a5]<br \/>\n    C &#8211;&gt; D[\u901a\u8fc7 HKDF \u884d\u751f\u4f1a\u8bdd\u5bc6\u94a5]<br \/>\n    D &#8211;&gt; E[\u4f7f\u7528\u4f1a\u8bdd\u5bc6\u94a5\u52a0\u5bc6\u901a\u4fe1]<\/p>\n<p> \u901a\u8fc7\u52a8\u6001\u751f\u6210\u4f1a\u8bdd\u5bc6\u94a5\u5e76\u7ed3\u5408\u524d\u5411\u5b89\u5168\u7b97\u6cd5&#xff0c;Fchat \u5b9e\u73b0\u4e86\u5373\u4f7f\u957f\u671f\u5bc6\u94a5\u6cc4\u9732\u4e5f\u4e0d\u4f1a\u5f71\u54cd\u5386\u53f2\u901a\u4fe1\u5b89\u5168\u7684\u52a0\u5bc6\u673a\u5236\u3002 <\/p>\n<p> \u672c\u7ae0\u4ece SSL\/TLS \u63e1\u624b\u6d41\u7a0b\u5165\u624b&#xff0c;\u8be6\u7ec6\u8bb2\u89e3\u4e86 Fchat \u5982\u4f55\u914d\u7f6e\u52a0\u5bc6\u901a\u4fe1\u3001\u7ba1\u7406\u8bc1\u4e66\u3001\u5b9e\u73b0\u53cc\u5411\u8ba4\u8bc1&#xff0c;\u5e76\u4ecb\u7ecd\u4e86\u5e94\u7528\u5c42\u52a0\u5bc6\u7b56\u7565\u548c\u4f1a\u8bdd\u5bc6\u94a5\u7684\u52a8\u6001\u751f\u6210\u673a\u5236\u3002\u901a\u8fc7\u4ee3\u7801\u793a\u4f8b\u4e0e\u6d41\u7a0b\u56fe\u7684\u7ed3\u5408&#xff0c;\u8bfb\u8005\u53ef\u6e05\u6670\u7406\u89e3 Fchat \u5728\u4fdd\u969c\u901a\u4fe1\u5b89\u5168\u65b9\u9762\u7684\u5b9e\u73b0\u7ec6\u8282\u3002 <\/p>\n<h2> 6. \u6743\u9650\u63a7\u5236\u4e0e\u8bbf\u95ee\u5ba1\u8ba1\u673a\u5236 <\/h2>\n<p> \u5728\u73b0\u4ee3\u4f01\u4e1a\u7ea7\u5373\u65f6\u901a\u8baf\u7cfb\u7edf\u4e2d&#xff0c;\u6743\u9650\u63a7\u5236\u4e0e\u8bbf\u95ee\u5ba1\u8ba1\u662f\u4fdd\u969c\u7cfb\u7edf\u5b89\u5168\u3001\u9632\u6b62\u654f\u611f\u4fe1\u606f\u6cc4\u9732\u3001\u5b9e\u73b0\u7ec6\u7c92\u5ea6\u7ba1\u7406\u7684\u6838\u5fc3\u673a\u5236\u3002Fchat \u901a\u8fc7\u57fa\u4e8e\u89d2\u8272\u7684\u8bbf\u95ee\u63a7\u5236&#xff08;RBAC&#xff09;\u6a21\u578b&#xff0c;\u7ed3\u5408\u7075\u6d3b\u7684\u63a5\u53e3\u6743\u9650\u7b56\u7565\u4e0e\u8be6\u5c3d\u7684\u64cd\u4f5c\u65e5\u5fd7\u5ba1\u8ba1\u4f53\u7cfb&#xff0c;\u6784\u5efa\u4e86\u4e00\u5957\u5b8c\u6574\u800c\u9ad8\u6548\u7684\u5b89\u5168\u63a7\u5236\u4f53\u7cfb\u3002\u672c\u7ae0\u5c06\u6df1\u5165\u89e3\u6790 Fchat \u4e2d\u7684\u6743\u9650\u63a7\u5236\u6a21\u578b\u8bbe\u8ba1\u3001\u8bbf\u95ee\u63a7\u5236\u7b56\u7565\u5b9e\u65bd\u4ee5\u53ca\u64cd\u4f5c\u65e5\u5fd7\u4e0e\u5ba1\u8ba1\u8ffd\u8e2a\u673a\u5236&#xff0c;\u5e2e\u52a9\u5f00\u53d1\u8005\u548c\u7cfb\u7edf\u7ba1\u7406\u5458\u5168\u9762\u7406\u89e3\u5176\u5185\u90e8\u5b9e\u73b0\u539f\u7406\u4e0e\u4f7f\u7528\u65b9\u5f0f\u3002 <\/p>\n<h3> 6.1 \u6743\u9650\u63a7\u5236\u6a21\u578b\u8bbe\u8ba1 <\/h3>\n<p> Fchat \u7684\u6743\u9650\u63a7\u5236\u6a21\u578b\u91c7\u7528\u7ecf\u5178\u7684 RBAC&#xff08;Role-Based Access Control&#xff09;\u6a21\u578b&#xff0c;\u7ed3\u5408\u7528\u6237\u3001\u89d2\u8272\u3001\u6743\u9650\u4e09\u8005\u4e4b\u95f4\u7684\u6620\u5c04\u5173\u7cfb&#xff0c;\u5b9e\u73b0\u7075\u6d3b\u7684\u6743\u9650\u7ba1\u7406\u3002\u8fd9\u79cd\u6a21\u578b\u7684\u4f18\u52bf\u5728\u4e8e\u80fd\u591f\u5feb\u901f\u54cd\u5e94\u7ec4\u7ec7\u67b6\u6784\u53d8\u5316&#xff0c;\u964d\u4f4e\u6743\u9650\u7ef4\u62a4\u7684\u590d\u6742\u5ea6\u3002 <\/p>\n<h4> 6.1.1 RBAC\u6a21\u578b\u5728Fchat\u4e2d\u7684\u5b9e\u73b0 <\/h4>\n<p> RBAC \u6a21\u578b\u7684\u6838\u5fc3\u5728\u4e8e\u89d2\u8272&#xff08;Role&#xff09;\u4f5c\u4e3a\u6743\u9650\u7684\u8f7d\u4f53&#xff0c;\u7528\u6237\u901a\u8fc7\u88ab\u5206\u914d\u5230\u4e00\u4e2a\u6216\u591a\u4e2a\u89d2\u8272\u6765\u83b7\u5f97\u76f8\u5e94\u7684\u6743\u9650\u3002\u8fd9\u79cd\u8bbe\u8ba1\u53ef\u4ee5\u907f\u514d\u76f4\u63a5\u5bf9\u7528\u6237\u5206\u914d\u6743\u9650\u5e26\u6765\u7684\u6df7\u4e71\u548c\u7ef4\u62a4\u56f0\u96be\u3002 <\/p>\n<p> \u5728 Fchat \u4e2d&#xff0c;RBAC \u6a21\u578b\u7684\u5b9e\u73b0\u7ed3\u6784\u5982\u4e0b&#xff1a; <\/p>\n<p>graph TD<br \/>\n    A[\u7528\u6237 User] &#8211;&gt;|\u5c5e\u4e8e| B(\u89d2\u8272 Role)<br \/>\n    B &#8211;&gt;|\u62e5\u6709| C[\u6743\u9650 Permission]<br \/>\n    D[\u8d44\u6e90 Resource] &#8211;&gt; C<\/p>\n<p>  \u5b9e\u73b0\u8bf4\u660e&#xff1a;  <\/p>\n<ul>\n<li>  User&#xff08;\u7528\u6237&#xff09;  &#xff1a;\u7cfb\u7edf\u4e2d\u7684\u5b9e\u9645\u4f7f\u7528\u8005&#xff0c;\u5982\u5458\u5de5\u3001\u5ba2\u670d\u3001\u7ba1\u7406\u5458\u7b49\u3002 <\/li>\n<li>  Role&#xff08;\u89d2\u8272&#xff09;  &#xff1a;\u6743\u9650\u7684\u96c6\u5408&#xff0c;\u4f8b\u5982  \u7ba1\u7406\u5458  \u3001  \u5ba2\u670d  \u3001  \u8bbf\u5ba2  \u7b49\u3002 <\/li>\n<li>  Permission&#xff08;\u6743\u9650&#xff09;  &#xff1a;\u5bf9\u67d0\u4e2a\u8d44\u6e90&#xff08;\u5982\u6d88\u606f\u53d1\u9001\u3001\u7fa4\u7ec4\u7ba1\u7406&#xff09;\u7684\u5177\u4f53\u64cd\u4f5c\u6743\u9650&#xff0c;\u4f8b\u5982  \u53d1\u9001\u6d88\u606f  \u3001  \u8e22\u51fa\u7fa4\u6210\u5458  \u3002 <\/li>\n<li>  Resource&#xff08;\u8d44\u6e90&#xff09;  &#xff1a;\u7cfb\u7edf\u4e2d\u9700\u8981\u88ab\u4fdd\u62a4\u7684\u5bf9\u8c61&#xff0c;\u5982\u804a\u5929\u5ba4\u3001\u7fa4\u7ec4\u3001API \u63a5\u53e3\u7b49\u3002 <\/li>\n<\/ul>\n<h4> 6.1.2 \u7528\u6237\u3001\u89d2\u8272\u3001\u6743\u9650\u4e09\u7ea7\u7ed3\u6784 <\/h4>\n<p> Fchat \u4e2d\u7684\u6743\u9650\u4f53\u7cfb\u91c7\u7528\u4e09\u7ea7\u7ed3\u6784\u7ba1\u7406&#xff1a;\u7528\u6237 \u2192 \u89d2\u8272 \u2192 \u6743\u9650\u3002\u8fd9\u79cd\u7ed3\u6784\u4fbf\u4e8e\u6743\u9650\u7684\u96c6\u4e2d\u7ba1\u7406\u4e0e\u7075\u6d3b\u5206\u914d\u3002 <\/p>\n<p>  \u6743\u9650\u7ed3\u6784\u8868\u5982\u4e0b&#xff1a;  <\/p>\n<table>\n<tr> \u7528\u6237ID  \u7528\u6237\u540d  \u89d2\u8272\u5217\u8868  \u6743\u9650\u96c6\u5408 <\/tr>\n<tbody>\n<tr>\n<td> U001 <\/td>\n<td> Alice <\/td>\n<td> \u7ba1\u7406\u5458 <\/td>\n<td> \u53d1\u9001\u6d88\u606f\u3001\u8e22\u51fa\u6210\u5458\u3001\u67e5\u770b\u65e5\u5fd7\u3001\u5c01\u7981\u8d26\u53f7 <\/td>\n<\/tr>\n<tr>\n<td> U002 <\/td>\n<td> Bob <\/td>\n<td> \u5ba2\u670d <\/td>\n<td> \u53d1\u9001\u6d88\u606f\u3001\u67e5\u770b\u804a\u5929\u8bb0\u5f55 <\/td>\n<\/tr>\n<tr>\n<td> U003 <\/td>\n<td> Charlie <\/td>\n<td> \u666e\u901a\u7528\u6237 <\/td>\n<td> \u53d1\u9001\u6d88\u606f\u3001\u67e5\u770b\u81ea\u5df1\u7684\u804a\u5929\u8bb0\u5f55 <\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>  \u4ee3\u7801\u793a\u4f8b&#xff1a;\u6743\u9650\u9a8c\u8bc1\u903b\u8f91&#xff08;\u4f2a\u4ee3\u7801&#xff09;  <\/p>\n<p>def check_permission(user, resource, action):<br \/>\n    # \u83b7\u53d6\u7528\u6237\u7684\u6240\u6709\u89d2\u8272<br \/>\n    roles &#061; user.get_roles()<br \/>\n    # \u904d\u5386\u89d2\u8272&#xff0c;\u68c0\u67e5\u662f\u5426\u62e5\u6709\u5bf9\u5e94\u6743\u9650<br \/>\n    for role in roles:<br \/>\n        if role.has_permission(resource, action):<br \/>\n            return True<br \/>\n    return False<\/p>\n<p>  \u4ee3\u7801\u5206\u6790&#xff1a;  <\/p>\n<ul>\n<li>  user.get_roles()  &#xff1a;\u83b7\u53d6\u7528\u6237\u6240\u5c5e\u7684\u6240\u6709\u89d2\u8272\u3002 <\/li>\n<li>  role.has_permission(resource, action)  &#xff1a;\u68c0\u67e5\u89d2\u8272\u662f\u5426\u62e5\u6709\u5bf9\u8d44\u6e90\u7684\u6307\u5b9a\u64cd\u4f5c\u6743\u9650\u3002 <\/li>\n<li> \u82e5\u4efb\u610f\u89d2\u8272\u62e5\u6709\u8be5\u6743\u9650&#xff0c;\u5219\u8fd4\u56de  True  &#xff0c;\u5426\u5219\u8fd4\u56de  False  \u3002 <\/li>\n<\/ul>\n<p> \u8be5\u6743\u9650\u6a21\u578b\u652f\u6301\u52a8\u6001\u6dfb\u52a0\u89d2\u8272\u548c\u6743\u9650&#xff0c;\u9002\u5408\u4f01\u4e1a\u5185\u90e8\u7ec4\u7ec7\u7ed3\u6784\u9891\u7e41\u8c03\u6574\u7684\u573a\u666f\u3002 <\/p>\n<h3> 6.2 \u8bbf\u95ee\u63a7\u5236\u7b56\u7565\u4e0e\u5b9e\u65bd <\/h3>\n<p> \u8bbf\u95ee\u63a7\u5236\u662f\u6743\u9650\u6a21\u578b\u5728\u5b9e\u9645\u4e1a\u52a1\u573a\u666f\u4e2d\u7684\u5177\u4f53\u4f53\u73b0\u3002Fchat \u652f\u6301\u591a\u79cd\u8bbf\u95ee\u63a7\u5236\u7b56\u7565&#xff0c;\u5305\u62ec\u63a5\u53e3\u7ea7\u522b\u7684\u6743\u9650\u63a7\u5236\u3001\u7fa4\u7ec4\u804a\u5929\u6743\u9650\u7ba1\u7406\u7b49&#xff0c;\u4ee5\u786e\u4fdd\u4e0d\u540c\u89d2\u8272\u7528\u6237\u5728\u7cfb\u7edf\u4e2d\u7684\u884c\u4e3a\u7b26\u5408\u5b89\u5168\u7b56\u7565\u3002 <\/p>\n<h4> 6.2.1 \u63a5\u53e3\u6743\u9650\u63a7\u5236\u4e0e\u9274\u6743\u673a\u5236 <\/h4>\n<p> Fchat \u7684 RESTful API \u63a5\u53e3\u91c7\u7528 Token &#043; \u6743\u9650\u63a7\u5236\u7684\u53cc\u91cd\u9274\u6743\u673a\u5236\u3002\u7528\u6237\u5728\u8c03\u7528\u63a5\u53e3\u65f6&#xff0c;\u5fc5\u987b\u643a\u5e26\u6709\u6548\u7684 Token&#xff0c;\u5e76\u4e14\u8be5\u7528\u6237\u5fc5\u987b\u62e5\u6709\u5bf9\u5e94\u63a5\u53e3\u7684\u8bbf\u95ee\u6743\u9650\u3002 <\/p>\n<p>  \u63a5\u53e3\u8bbf\u95ee\u6d41\u7a0b\u5982\u4e0b&#xff1a;  <\/p>\n<p>sequenceDiagram<br \/>\n    \u7528\u6237-&gt;&gt;\u8ba4\u8bc1\u670d\u52a1: \u767b\u5f55\u83b7\u53d6 Token<br \/>\n    \u8ba4\u8bc1\u670d\u52a1&#8211;&gt;&gt;\u7528\u6237: \u8fd4\u56de Token<br \/>\n    \u7528\u6237-&gt;&gt;API\u670d\u52a1: \u8c03\u7528\u63a5\u53e3 &#043; Token<br \/>\n    API\u670d\u52a1-&gt;&gt;\u6743\u9650\u670d\u52a1: \u9a8c\u8bc1 Token &amp; \u6743\u9650<br \/>\n    \u6743\u9650\u670d\u52a1&#8211;&gt;&gt;API\u670d\u52a1: \u8fd4\u56de\u6743\u9650\u9a8c\u8bc1\u7ed3\u679c<br \/>\n    API\u670d\u52a1&#8211;&gt;&gt;\u7528\u6237: \u54cd\u5e94\u7ed3\u679c<\/p>\n<p>  Token \u9a8c\u8bc1\u6d41\u7a0b\u4ee3\u7801\u7247\u6bb5&#xff08;Python Flask \u793a\u4f8b&#xff09;  <\/p>\n<p>&#064;app.before_request<br \/>\ndef validate_token():<br \/>\n    token &#061; request.headers.get(&#039;Authorization&#039;)<br \/>\n    if not token:<br \/>\n        return jsonify({&#039;error&#039;: &#039;Missing token&#039;}), 401<\/p>\n<p>    try:<br \/>\n        payload &#061; jwt.decode(token, SECRET_KEY, algorithms&#061;[&#039;HS256&#039;])<br \/>\n        current_user &#061; User.get_by_id(payload[&#039;user_id&#039;])<br \/>\n    except jwt.ExpiredSignatureError:<br \/>\n        return jsonify({&#039;error&#039;: &#039;Token expired&#039;}), 401<br \/>\n    except jwt.InvalidTokenError:<br \/>\n        return jsonify({&#039;error&#039;: &#039;Invalid token&#039;}), 401<\/p>\n<p>    g.user &#061; current_user<\/p>\n<p>  \u53c2\u6570\u8bf4\u660e&#xff1a;  <\/p>\n<ul>\n<li>  Authorization  &#xff1a;\u8bf7\u6c42\u5934\u4e2d\u643a\u5e26\u7684 Token\u3002 <\/li>\n<li>  jwt.decode()  &#xff1a;\u4f7f\u7528\u6307\u5b9a\u5bc6\u94a5\u89e3\u7801 Token&#xff0c;\u9a8c\u8bc1\u5176\u5408\u6cd5\u6027\u3002 <\/li>\n<li>  SECRET_KEY  &#xff1a;\u670d\u52a1\u7aef\u7528\u4e8e\u7b7e\u540d\u548c\u9a8c\u8bc1 Token \u7684\u5bc6\u94a5\u3002 <\/li>\n<li>  g.user  &#xff1a;Flask \u4e0a\u4e0b\u6587\u53d8\u91cf&#xff0c;\u7528\u4e8e\u4fdd\u5b58\u5f53\u524d\u7528\u6237\u5bf9\u8c61\u3002 <\/li>\n<\/ul>\n<p>  \u6743\u9650\u9a8c\u8bc1\u903b\u8f91&#xff1a;  <\/p>\n<p>def require_permission(permission):<br \/>\n    def decorator(f):<br \/>\n        &#064;wraps(f)<br \/>\n        def wrapped(*args, **kwargs):<br \/>\n            if not g.user.has_permission(permission):<br \/>\n                return jsonify({&#039;error&#039;: &#039;Permission denied&#039;}), 403<br \/>\n            return f(*args, **kwargs)<br \/>\n        return wrapped<br \/>\n    return decorator<\/p>\n<p> \u8be5\u88c5\u9970\u5668\u7528\u4e8e\u88c5\u9970 API \u63a5\u53e3\u51fd\u6570&#xff0c;\u786e\u4fdd\u53ea\u6709\u62e5\u6709\u5bf9\u5e94\u6743\u9650\u7684\u7528\u6237\u624d\u80fd\u8bbf\u95ee\u3002 <\/p>\n<h4> 6.2.2 \u7fa4\u7ec4\u4e0e\u79c1\u804a\u6743\u9650\u7ba1\u7406 <\/h4>\n<p> Fchat \u652f\u6301\u7fa4\u7ec4\u548c\u79c1\u804a\u6d88\u606f\u7684\u6743\u9650\u63a7\u5236&#xff0c;\u7ba1\u7406\u5458\u53ef\u4ee5\u914d\u7f6e\u54ea\u4e9b\u89d2\u8272\u53ef\u4ee5\u52a0\u5165\u7fa4\u7ec4\u3001\u53d1\u9001\u6d88\u606f\u3001\u8e22\u51fa\u6210\u5458\u7b49\u3002 <\/p>\n<p>  \u6743\u9650\u63a7\u5236\u5b57\u6bb5\u793a\u4f8b&#xff08;\u6570\u636e\u5e93\u8868\u8bbe\u8ba1&#xff09;&#xff1a;  <\/p>\n<p>CREATE TABLE group_permissions (<br \/>\n    group_id VARCHAR(36) NOT NULL,<br \/>\n    role_id VARCHAR(36) NOT NULL,<br \/>\n    can_send_message BOOLEAN DEFAULT TRUE,<br \/>\n    can_kick_member BOOLEAN DEFAULT FALSE,<br \/>\n    can_invite_member BOOLEAN DEFAULT FALSE,<br \/>\n    PRIMARY KEY (group_id, role_id)<br \/>\n);<\/p>\n<p>  \u5b57\u6bb5\u8bf4\u660e&#xff1a;  <\/p>\n<ul>\n<li>  can_send_message  &#xff1a;\u662f\u5426\u5141\u8bb8\u53d1\u9001\u6d88\u606f\u3002 <\/li>\n<li>  can_kick_member  &#xff1a;\u662f\u5426\u5141\u8bb8\u8e22\u51fa\u6210\u5458\u3002 <\/li>\n<li>  can_invite_member  &#xff1a;\u662f\u5426\u5141\u8bb8\u9080\u8bf7\u65b0\u6210\u5458\u3002 <\/li>\n<\/ul>\n<p>  \u6743\u9650\u9a8c\u8bc1\u903b\u8f91\u4ee3\u7801&#xff08;\u4f2a\u4ee3\u7801&#xff09;  <\/p>\n<p>def check_group_permission(user, group_id, action):<br \/>\n    roles &#061; user.get_roles_in_group(group_id)<br \/>\n    for role in roles:<br \/>\n        permission &#061; get_group_role_permission(group_id, role.id)<br \/>\n        if permission.get(action, False):<br \/>\n            return True<br \/>\n    return False<\/p>\n<p> \u6b64\u903b\u8f91\u786e\u4fdd\u7528\u6237\u5728\u7279\u5b9a\u7fa4\u7ec4\u4e2d\u53ea\u80fd\u6267\u884c\u88ab\u6388\u6743\u7684\u64cd\u4f5c\u3002 <\/p>\n<h3> 6.3 \u64cd\u4f5c\u65e5\u5fd7\u4e0e\u5ba1\u8ba1\u8ffd\u8e2a <\/h3>\n<p> \u64cd\u4f5c\u65e5\u5fd7\u662f\u7cfb\u7edf\u5b89\u5168\u5ba1\u8ba1\u548c\u6545\u969c\u6392\u67e5\u7684\u91cd\u8981\u4f9d\u636e\u3002Fchat \u63d0\u4f9b\u5b8c\u6574\u7684\u64cd\u4f5c\u65e5\u5fd7\u8bb0\u5f55\u673a\u5236&#xff0c;\u6db5\u76d6\u7528\u6237\u884c\u4e3a\u3001\u6743\u9650\u53d8\u66f4\u3001\u63a5\u53e3\u8c03\u7528\u7b49\u5173\u952e\u64cd\u4f5c&#xff0c;\u5e76\u652f\u6301\u65e5\u5fd7\u67e5\u8be2\u4e0e\u5b89\u5168\u4e8b\u4ef6\u54cd\u5e94\u3002 <\/p>\n<h4> 6.3.1 \u65e5\u5fd7\u8bb0\u5f55\u5185\u5bb9\u4e0e\u683c\u5f0f\u89c4\u8303 <\/h4>\n<p> Fchat \u7684\u64cd\u4f5c\u65e5\u5fd7\u8bb0\u5f55\u91c7\u7528\u7edf\u4e00\u7684\u7ed3\u6784\u5316\u683c\u5f0f&#xff0c;\u4fbf\u4e8e\u540e\u7eed\u5206\u6790\u4e0e\u67e5\u8be2\u3002 <\/p>\n<p>  \u65e5\u5fd7\u7ed3\u6784\u793a\u4f8b&#xff1a;  <\/p>\n<p>{<br \/>\n  &#034;timestamp&#034;: &#034;2025-04-05T10:23:15Z&#034;,<br \/>\n  &#034;user_id&#034;: &#034;U001&#034;,<br \/>\n  &#034;username&#034;: &#034;Alice&#034;,<br \/>\n  &#034;action&#034;: &#034;kick_member&#034;,<br \/>\n  &#034;target_user_id&#034;: &#034;U003&#034;,<br \/>\n  &#034;group_id&#034;: &#034;G001&#034;,<br \/>\n  &#034;ip_address&#034;: &#034;192.168.1.100&#034;,<br \/>\n  &#034;user_agent&#034;: &#034;Mozilla\/5.0&#034;,<br \/>\n  &#034;status&#034;: &#034;success&#034;<br \/>\n}<\/p>\n<p>  \u5b57\u6bb5\u8bf4\u660e&#xff1a;  <\/p>\n<ul>\n<li>  timestamp  &#xff1a;\u64cd\u4f5c\u65f6\u95f4\u6233\u3002 <\/li>\n<li>  action  &#xff1a;\u64cd\u4f5c\u7c7b\u578b&#xff0c;\u5982  login  ,  send_message  ,  kick_member  \u3002 <\/li>\n<li>  group_id  &#xff1a;\u64cd\u4f5c\u6d89\u53ca\u7684\u7fa4\u7ec4 ID\u3002 <\/li>\n<li>  ip_address  \u548c  user_agent  &#xff1a;\u5ba2\u6237\u7aef\u4fe1\u606f&#xff0c;\u7528\u4e8e\u5b89\u5168\u5206\u6790\u3002 <\/li>\n<li>  status  &#xff1a;\u64cd\u4f5c\u662f\u5426\u6210\u529f\u3002 <\/li>\n<\/ul>\n<h4> 6.3.2 \u65e5\u5fd7\u5b58\u50a8\u4e0e\u67e5\u8be2\u4f18\u5316 <\/h4>\n<p> Fchat \u4f7f\u7528 ELK&#xff08;Elasticsearch\u3001Logstash\u3001Kibana&#xff09;\u6280\u672f\u6808\u8fdb\u884c\u65e5\u5fd7\u5b58\u50a8\u4e0e\u5206\u6790&#xff0c;\u63d0\u5347\u65e5\u5fd7\u5904\u7406\u6548\u7387\u548c\u53ef\u89c6\u5316\u80fd\u529b\u3002 <\/p>\n<p>  \u65e5\u5fd7\u5199\u5165\u6d41\u7a0b\u5982\u4e0b&#xff1a;  <\/p>\n<p>graph LR<br \/>\n    A[\u4e1a\u52a1\u7cfb\u7edf] &#8211;&gt; B[\u65e5\u5fd7\u91c7\u96c6\u5668 Logstash]<br \/>\n    B &#8211;&gt; C[Elasticsearch \u5b58\u50a8]<br \/>\n    C &#8211;&gt; D[Kibana \u5c55\u793a]<\/p>\n<p>  \u67e5\u8be2\u4f18\u5316\u7b56\u7565&#xff1a;  <\/p>\n<ul>\n<li>  \u6309\u65f6\u95f4\u8303\u56f4\u7d22\u5f15  &#xff1a;\u5c06\u65e5\u5fd7\u6309\u65f6\u95f4\u5206\u7247\u5b58\u50a8&#xff0c;\u63d0\u9ad8\u67e5\u8be2\u6548\u7387\u3002 <\/li>\n<li>  \u6309\u7528\u6237ID\u6216\u64cd\u4f5c\u7c7b\u578b\u5efa\u7acb\u7d22\u5f15  &#xff1a;\u652f\u6301\u5feb\u901f\u5b9a\u4f4d\u7279\u5b9a\u7528\u6237\u6216\u64cd\u4f5c\u8bb0\u5f55\u3002 <\/li>\n<li>  \u65e5\u5fd7\u538b\u7f29\u5f52\u6863  &#xff1a;\u5bf9\u5386\u53f2\u65e5\u5fd7\u8fdb\u884c\u538b\u7f29\u5b58\u50a8&#xff0c;\u8282\u7701\u78c1\u76d8\u7a7a\u95f4\u3002 <\/li>\n<\/ul>\n<p>  Elasticsearch \u67e5\u8be2\u793a\u4f8b&#xff08;DSL&#xff09;&#xff1a;  <\/p>\n<p>GET logs\/_search<br \/>\n{<br \/>\n  &#034;query&#034;: {<br \/>\n    &#034;range&#034;: {<br \/>\n      &#034;timestamp&#034;: {<br \/>\n        &#034;gte&#034;: &#034;2025-04-01T00:00:00Z&#034;,<br \/>\n        &#034;lte&#034;: &#034;2025-04-05T23:59:59Z&#034;<br \/>\n      }<br \/>\n    }<br \/>\n  },<br \/>\n  &#034;sort&#034;: [<br \/>\n    {&#034;timestamp&#034;: &#034;desc&#034;}<br \/>\n  ]<br \/>\n}<\/p>\n<p>  \u529f\u80fd\u8bf4\u660e&#xff1a;  <\/p>\n<ul>\n<li> \u67e5\u8be2 2025 \u5e74 4 \u6708 1 \u65e5\u81f3 4 \u6708 5 \u65e5\u4e4b\u95f4\u7684\u65e5\u5fd7\u3002 <\/li>\n<li> \u6309\u65f6\u95f4\u5012\u5e8f\u6392\u5217\u3002 <\/li>\n<\/ul>\n<h4> 6.3.3 \u5b89\u5168\u4e8b\u4ef6\u9884\u8b66\u4e0e\u54cd\u5e94\u673a\u5236 <\/h4>\n<p> Fchat \u914d\u5408 ELK \u4e0e Prometheus &#043; Grafana \u5b9e\u73b0\u5b89\u5168\u4e8b\u4ef6\u7684\u5b9e\u65f6\u76d1\u63a7\u4e0e\u9884\u8b66\u3002 <\/p>\n<p>  \u5b89\u5168\u4e8b\u4ef6\u7c7b\u578b&#xff1a;  <\/p>\n<ul>\n<li> \u5f02\u5e38\u767b\u5f55&#xff08;\u5982\u77ed\u65f6\u95f4\u5185\u591a\u6b21\u5931\u8d25&#xff09; <\/li>\n<li> \u6743\u9650\u5f02\u5e38\u64cd\u4f5c&#xff08;\u5982\u975e\u7ba1\u7406\u5458\u8e22\u51fa\u6210\u5458&#xff09; <\/li>\n<li> \u5927\u91cf\u63a5\u53e3\u8c03\u7528&#xff08;\u7591\u4f3c\u722c\u866b\u6216\u653b\u51fb&#xff09; <\/li>\n<\/ul>\n<p>  \u76d1\u63a7\u89c4\u5219\u793a\u4f8b&#xff08;Prometheus &#043; Alertmanager&#xff09;&#xff1a;  <\/p>\n<p>groups:<br \/>\n  &#8211; name: security-alerts<br \/>\n    rules:<br \/>\n      &#8211; alert: HighLoginFailures<br \/>\n        expr: rate(login_attempts_failed[5m]) &gt; 10<br \/>\n        for: 2m<br \/>\n        labels:<br \/>\n          severity: warning<br \/>\n        annotations:<br \/>\n          summary: &#034;High number of login failures&#034;<br \/>\n          description: &#034;More than 10 failed login attempts in 5 minutes&#034;<\/p>\n<p>  \u54cd\u5e94\u673a\u5236&#xff1a;  <\/p>\n<ul>\n<li> \u89e6\u53d1\u544a\u8b66\u540e&#xff0c;\u901a\u8fc7\u90ae\u4ef6\u3001\u4f01\u4e1a\u5fae\u4fe1\u6216\u9489\u9489\u901a\u77e5\u7ba1\u7406\u5458\u3002 <\/li>\n<li> \u81ea\u52a8\u8bb0\u5f55\u65e5\u5fd7\u5e76\u9501\u5b9a\u53ef\u7591 IP \u6216\u7528\u6237\u8d26\u6237\u3002 <\/li>\n<li> \u63d0\u4f9b\u65e5\u5fd7\u94fe\u63a5\u4f9b\u7ba1\u7406\u5458\u8fdb\u4e00\u6b65\u5206\u6790\u3002 <\/li>\n<\/ul>\n<p> \u672c\u7ae0\u7cfb\u7edf\u9610\u8ff0\u4e86 Fchat \u5728\u6743\u9650\u63a7\u5236\u4e0e\u8bbf\u95ee\u5ba1\u8ba1\u65b9\u9762\u7684\u6838\u5fc3\u8bbe\u8ba1\u4e0e\u5b9e\u73b0\u673a\u5236\u3002\u4ece RBAC \u6a21\u578b\u5230\u63a5\u53e3\u9274\u6743&#xff0c;\u518d\u5230\u65e5\u5fd7\u8bb0\u5f55\u4e0e\u5b89\u5168\u9884\u8b66&#xff0c;Fchat \u63d0\u4f9b\u4e86\u4e00\u5957\u5b8c\u6574\u3001\u5b89\u5168\u3001\u53ef\u6269\u5c55\u7684\u6743\u9650\u7ba1\u7406\u4f53\u7cfb&#xff0c;\u4e3a\u4f01\u4e1a\u7ea7\u5373\u65f6\u901a\u8baf\u7cfb\u7edf\u7684\u7a33\u5b9a\u8fd0\u884c\u548c\u5b89\u5168\u7ba1\u7406\u63d0\u4f9b\u4e86\u575a\u5b9e\u4fdd\u969c\u3002 <\/p>\n<h2> 7. API\u63a5\u53e3\u5f00\u53d1\u4e0e\u96c6\u6210 <\/h2>\n<p> API\u63a5\u53e3\u4f5c\u4e3aFchat\u7cfb\u7edf\u4e0e\u5916\u90e8\u7cfb\u7edf\u8fdb\u884c\u6570\u636e\u4ea4\u4e92\u7684\u6838\u5fc3\u6865\u6881&#xff0c;\u5176\u8bbe\u8ba1\u8d28\u91cf\u76f4\u63a5\u51b3\u5b9a\u4e86\u7cfb\u7edf\u7684\u53ef\u6269\u5c55\u6027\u3001\u5b89\u5168\u6027\u548c\u96c6\u6210\u6548\u7387\u3002\u672c\u7ae0\u5c06\u4ece\u63a5\u53e3\u8bbe\u8ba1\u539f\u5219\u5165\u624b&#xff0c;\u7ed3\u5408\u5177\u4f53\u793a\u4f8b\u8bf4\u660e\u5e38\u7528API\u7684\u4f7f\u7528\u65b9\u5f0f&#xff0c;\u5e76\u63a2\u8ba8\u5982\u4f55\u4e0e\u7b2c\u4e09\u65b9\u7cfb\u7edf&#xff08;\u5982OA\u3001CRM\u7b49&#xff09;\u8fdb\u884c\u9ad8\u6548\u96c6\u6210\u3002 <\/p>\n<h3> 7.1 API\u63a5\u53e3\u8bbe\u8ba1\u539f\u5219 <\/h3>\n<h4> 7.1.1 RESTful\u98ce\u683c\u4e0e\u63a5\u53e3\u6807\u51c6\u5316 <\/h4>\n<p> Fchat\u91c7\u7528  RESTful\u98ce\u683c  \u8fdb\u884cAPI\u8bbe\u8ba1&#xff0c;\u9075\u5faaHTTP\u65b9\u6cd5&#xff08;GET\u3001POST\u3001PUT\u3001DELETE&#xff09;\u4e0e\u8d44\u6e90\u8def\u5f84\u7684\u7edf\u4e00\u89c4\u8303&#xff0c;\u786e\u4fdd\u63a5\u53e3\u8bed\u4e49\u6e05\u6670\u4e14\u6613\u4e8e\u7406\u89e3\u3002\u4f8b\u5982&#xff1a; <\/p>\n<p>GET \/api\/v1\/users\/{userId}<\/p>\n<p> \u8868\u793a\u83b7\u53d6\u67d0\u4e2a\u7528\u6237\u7684\u4fe1\u606f&#xff0c;\u800c&#xff1a; <\/p>\n<p>POST \/api\/v1\/messages<\/p>\n<p> \u8868\u793a\u53d1\u9001\u4e00\u6761\u6d88\u606f\u3002 <\/p>\n<p> \u6807\u51c6\u5316\u8bbe\u8ba1\u4f53\u73b0\u5728\u4ee5\u4e0b\u51e0\u70b9&#xff1a; <\/p>\n<ul>\n<li>  \u7edf\u4e00\u7684URL\u7ed3\u6784  &#xff1a;\u4ee5\u8d44\u6e90\u4e3a\u4e2d\u5fc3&#xff0c;\u4f7f\u7528\u590d\u6570\u540d\u8bcd\u8868\u793a\u8d44\u6e90\u96c6\u5408\u3002 <\/li>\n<li>  \u7edf\u4e00\u7684\u72b6\u6001\u7801\u8fd4\u56de  &#xff1a;\u5982200\u8868\u793a\u6210\u529f&#xff0c;400\u8868\u793a\u8bf7\u6c42\u9519\u8bef&#xff0c;401\u8868\u793a\u672a\u6388\u6743&#xff0c;500\u8868\u793a\u670d\u52a1\u5668\u5185\u90e8\u9519\u8bef\u3002 <\/li>\n<li>  \u7edf\u4e00\u7684\u54cd\u5e94\u683c\u5f0f  &#xff1a; <\/li>\n<\/ul>\n<p>{<br \/>\n  &#034;code&#034;: 200,<br \/>\n  &#034;message&#034;: &#034;Success&#034;,<br \/>\n  &#034;data&#034;: {<br \/>\n    &#034;userId&#034;: &#034;123&#034;,<br \/>\n    &#034;username&#034;: &#034;john_doe&#034;<br \/>\n  }<br \/>\n}<\/p>\n<h4> 7.1.2 \u63a5\u53e3\u5b89\u5168\u6027\u8bbe\u8ba1&#xff08;Token\u3001\u7b7e\u540d&#xff09; <\/h4>\n<p> \u4e3a\u4e86\u786e\u4fddAPI\u8c03\u7528\u7684\u5b89\u5168\u6027&#xff0c;Fchat\u91c7\u7528\u4e86  Token&#043;\u7b7e\u540d  \u7684\u53cc\u91cd\u9a8c\u8bc1\u673a\u5236&#xff1a; <\/p>\n<ul>\n<li>  Token\u673a\u5236  &#xff1a;\u5ba2\u6237\u7aef\u5728\u767b\u5f55\u6210\u529f\u540e\u83b7\u53d6\u4e00\u4e2a\u6709\u6548\u671f\u4e3aN\u5c0f\u65f6\u7684\u8bbf\u95eeToken&#xff08;\u5982JWT&#xff09;&#xff0c;\u540e\u7eed\u8bf7\u6c42\u9700\u643a\u5e26\u8be5Token\u3002 <\/li>\n<li>  \u7b7e\u540d\u673a\u5236  &#xff1a;\u5bf9\u8bf7\u6c42\u53c2\u6570\u8fdb\u884c\u7b7e\u540d&#xff08;\u5982HMAC-SHA256&#xff09;&#xff0c;\u9632\u6b62\u53c2\u6570\u88ab\u7be1\u6539\u3002 <\/li>\n<\/ul>\n<p> \u7b7e\u540d\u6d41\u7a0b\u793a\u4f8b\u5982\u4e0b&#xff1a; <\/p>\n<li> \u5ba2\u6237\u7aef\u5c06\u8bf7\u6c42\u53c2\u6570\u6309ASCII\u987a\u5e8f\u6392\u5e8f&#xff1b; <\/li>\n<li> \u62fc\u63a5\u53c2\u6570\u952e\u503c\u5bf9\u5e76\u9644\u52a0\u5bc6\u94a5&#xff08;secret&#xff09;&#xff1b; <\/li>\n<li> \u4f7f\u7528HMAC-SHA256\u7b97\u6cd5\u751f\u6210\u7b7e\u540d\u503c&#xff1b; <\/li>\n<li> \u5c06\u7b7e\u540d\u503c\u4f5c\u4e3a\u53c2\u6570\u52a0\u5165\u8bf7\u6c42\u5934\u6216\u67e5\u8be2\u53c2\u6570\u4e2d\u53d1\u9001\u3002 <\/li>\n<p> \u670d\u52a1\u7aef\u6536\u5230\u8bf7\u6c42\u540e\u91cd\u590d\u7b7e\u540d\u6d41\u7a0b&#xff0c;\u82e5\u7b7e\u540d\u4e00\u81f4\u5219\u5141\u8bb8\u8bbf\u95ee\u3002 <\/p>\n<h3> 7.2 \u5e38\u7528API\u63a5\u53e3\u793a\u4f8b <\/h3>\n<h4> 7.2.1 \u7528\u6237\u7ba1\u7406\u63a5\u53e3 <\/h4>\n<p>  \u63a5\u53e3&#xff1a;\u521b\u5efa\u7528\u6237  <\/p>\n<p>POST \/api\/v1\/users<\/p>\n<p>  \u8bf7\u6c42\u4f53\u793a\u4f8b&#xff1a;  <\/p>\n<p>{<br \/>\n  &#034;username&#034;: &#034;john_doe&#034;,<br \/>\n  &#034;email&#034;: &#034;john&#064;example.com&#034;,<br \/>\n  &#034;password&#034;: &#034;hashed_password&#034;<br \/>\n}<\/p>\n<p>  \u54cd\u5e94\u793a\u4f8b&#xff1a;  <\/p>\n<p>{<br \/>\n  &#034;code&#034;: 201,<br \/>\n  &#034;message&#034;: &#034;User created successfully&#034;,<br \/>\n  &#034;data&#034;: {<br \/>\n    &#034;userId&#034;: &#034;U123456&#034;<br \/>\n  }<br \/>\n}<\/p>\n<h4> 7.2.2 \u6d88\u606f\u53d1\u9001\u4e0e\u63a5\u6536\u63a5\u53e3 <\/h4>\n<p>  \u63a5\u53e3&#xff1a;\u53d1\u9001\u6d88\u606f  <\/p>\n<p>POST \/api\/v1\/messages<\/p>\n<p>  \u8bf7\u6c42\u53c2\u6570&#xff1a;  <\/p>\n<p>{<br \/>\n  &#034;from&#034;: &#034;U123456&#034;,<br \/>\n  &#034;to&#034;: &#034;U789012&#034;,<br \/>\n  &#034;type&#034;: &#034;text&#034;,<br \/>\n  &#034;content&#034;: &#034;Hello, how are you?&#034;,<br \/>\n  &#034;timestamp&#034;: 1712345678<br \/>\n}<\/p>\n<p>  \u63a5\u53e3&#xff1a;\u63a5\u6536\u6d88\u606f&#xff08;\u957f\u8f6e\u8be2&#xff09;  <\/p>\n<p>GET \/api\/v1\/messages?userId&#061;U123456<\/p>\n<p> \u652f\u6301\u957f\u8f6e\u8be2\u673a\u5236&#xff0c;\u5ba2\u6237\u7aef\u5728\u65e0\u65b0\u6d88\u606f\u65f6\u4fdd\u6301\u8fde\u63a5\u7b49\u5f85&#xff0c;\u76f4\u5230\u6709\u65b0\u6d88\u606f\u5230\u8fbe\u6216\u8d85\u65f6\u3002 <\/p>\n<h4> 7.2.3 \u7fa4\u7ec4\u7ba1\u7406\u4e0e\u6d88\u606f\u5e7f\u64ad\u63a5\u53e3 <\/h4>\n<p>  \u63a5\u53e3&#xff1a;\u521b\u5efa\u7fa4\u7ec4  <\/p>\n<p>POST \/api\/v1\/groups<\/p>\n<p>  \u8bf7\u6c42\u53c2\u6570&#xff1a;  <\/p>\n<p>{<br \/>\n  &#034;groupName&#034;: &#034;Project Alpha&#034;,<br \/>\n  &#034;members&#034;: [&#034;U123456&#034;, &#034;U789012&#034;]<br \/>\n}<\/p>\n<p>  \u63a5\u53e3&#xff1a;\u7fa4\u7ec4\u5e7f\u64ad\u6d88\u606f  <\/p>\n<p>POST \/api\/v1\/groups\/{groupId}\/messages<\/p>\n<p>  \u8bf7\u6c42\u4f53&#xff1a;  <\/p>\n<p>{<br \/>\n  &#034;sender&#034;: &#034;U123456&#034;,<br \/>\n  &#034;content&#034;: &#034;Meeting scheduled for tomorrow at 10 AM.&#034;<br \/>\n}<\/p>\n<h3> 7.3 \u7b2c\u4e09\u65b9\u7cfb\u7edf\u96c6\u6210\u5b9e\u8df5 <\/h3>\n<h4> 7.3.1 \u4e0eOA\u3001CRM\u7cfb\u7edf\u7684\u96c6\u6210\u65b9\u6848 <\/h4>\n<p> Fchat\u652f\u6301\u4e0e\u4f01\u4e1a\u5185\u90e8\u7cfb\u7edf\u5982OA\u3001CRM\u7b49\u65e0\u7f1d\u96c6\u6210&#xff0c;\u4e3b\u8981\u901a\u8fc7\u4ee5\u4e0b\u65b9\u5f0f\u5b9e\u73b0&#xff1a; <\/p>\n<ul>\n<li>  OAuth2.0\u5355\u70b9\u767b\u5f55\u96c6\u6210  &#xff1a;\u7b2c\u4e09\u65b9\u7cfb\u7edf\u53ef\u901a\u8fc7OAuth2.0\u534f\u8bae\u83b7\u53d6Fchat\u7684\u8bbf\u95eeToken&#xff0c;\u5b9e\u73b0\u7528\u6237\u514d\u767b\u5f55\u8bbf\u95ee\u3002 <\/li>\n<li>  API\u7f51\u5173\u5bf9\u63a5  &#xff1a;\u901a\u8fc7API\u7f51\u5173\u7edf\u4e00\u7ba1\u7406\u6743\u9650\u3001\u9650\u6d41\u3001\u7b7e\u540d\u9a8c\u8bc1\u7b49&#xff0c;\u786e\u4fdd\u7cfb\u7edf\u95f4\u8c03\u7528\u7684\u5b89\u5168\u6027\u3002 <\/li>\n<li>  Webhook\u4e8b\u4ef6\u8ba2\u9605  &#xff1a;Fchat\u652f\u6301\u5c06\u7528\u6237\u4e0a\u7ebf\u3001\u6d88\u606f\u63a5\u6536\u3001\u7fa4\u7ec4\u53d8\u52a8\u7b49\u4e8b\u4ef6\u63a8\u9001\u7ed9\u7b2c\u4e09\u65b9\u7cfb\u7edf&#xff0c;\u5b9e\u73b0\u5b9e\u65f6\u8054\u52a8\u3002 <\/li>\n<\/ul>\n<p> \u4f8b\u5982&#xff0c;CRM\u7cfb\u7edf\u8ba2\u9605Fchat\u7528\u6237\u4e0a\u7ebf\u4e8b\u4ef6&#xff1a; <\/p>\n<p>POST \/api\/v1\/webhooks<\/p>\n<p>  \u8bf7\u6c42\u4f53&#xff1a;  <\/p>\n<p>{<br \/>\n  &#034;eventType&#034;: &#034;user_online&#034;,<br \/>\n  &#034;callbackUrl&#034;: &#034;https:\/\/crm.example.com\/hooks\/user_online&#034;<br \/>\n}<\/p>\n<h4> 7.3.2 \u63a5\u53e3\u8c03\u8bd5\u4e0e\u81ea\u52a8\u5316\u6d4b\u8bd5\u65b9\u6cd5 <\/h4>\n<p> \u4e3a\u4e86\u63d0\u5347\u63a5\u53e3\u5f00\u53d1\u6548\u7387\u4e0e\u8d28\u91cf&#xff0c;Fchat\u63a8\u8350\u4f7f\u7528\u4ee5\u4e0b\u5de5\u5177\u8fdb\u884c\u63a5\u53e3\u8c03\u8bd5\u4e0e\u6d4b\u8bd5&#xff1a; <\/p>\n<ul>\n<li>  Postman  &#xff1a;\u652f\u6301\u63a5\u53e3\u8bf7\u6c42\u6a21\u62df\u3001\u53c2\u6570\u7ba1\u7406\u3001\u81ea\u52a8\u5316\u6d4b\u8bd5\u811a\u672c\u7f16\u5199\u3002 <\/li>\n<li>  Swagger UI  &#xff1a;\u81ea\u52a8\u751f\u6210API\u6587\u6863\u5e76\u63d0\u4f9b\u4ea4\u4e92\u5f0f\u8c03\u8bd5\u754c\u9762\u3002 <\/li>\n<li>  \u81ea\u52a8\u5316\u6d4b\u8bd5\u6846\u67b6&#xff08;\u5982JUnit &#043; RestAssured&#xff09;  &#xff1a; <\/li>\n<\/ul>\n<p> \u793a\u4f8b\u6d4b\u8bd5\u4ee3\u7801&#xff08;Java&#xff09;&#xff1a; <\/p>\n<p>&#064;Test<br \/>\npublic void testSendMessage() {<br \/>\n    String jsonBody &#061; &#034;{ \\\\&#034;from\\\\&#034;: \\\\&#034;U123456\\\\&#034;, \\\\&#034;to\\\\&#034;: \\\\&#034;U789012\\\\&#034;, \\\\&#034;type\\\\&#034;: \\\\&#034;text\\\\&#034;, \\\\&#034;content\\\\&#034;: \\\\&#034;Test message\\\\&#034; }&#034;;<br \/>\n    given()<br \/>\n        .header(&#034;Authorization&#034;, &#034;Bearer &#034; &#043; validToken)<br \/>\n        .contentType(ContentType.JSON)<br \/>\n        .body(jsonBody)<br \/>\n    .when()<br \/>\n        .post(&#034;\/api\/v1\/messages&#034;)<br \/>\n    .then()<br \/>\n        .statusCode(200)<br \/>\n        .body(&#034;code&#034;, equalTo(200));<br \/>\n}<\/p>\n<p> \u6b64\u5916&#xff0c;\u5efa\u8bae\u7ed3\u5408CI\/CD\u6d41\u7a0b&#xff0c;\u5728\u4ee3\u7801\u63d0\u4ea4\u540e\u81ea\u52a8\u8fd0\u884c\u63a5\u53e3\u6d4b\u8bd5&#xff0c;\u786e\u4fdd\u63a5\u53e3\u53d8\u66f4\u4e0d\u4f1a\u7834\u574f\u73b0\u6709\u529f\u80fd\u3002 <\/p>\n<p> \u901a\u8fc7\u4e0a\u8ff0\u63a5\u53e3\u8bbe\u8ba1\u4e0e\u96c6\u6210\u5b9e\u8df5&#xff0c;Fchat\u4e0d\u4ec5\u4e3a\u5f00\u53d1\u8005\u63d0\u4f9b\u4e86\u7075\u6d3b\u7684\u5f00\u53d1\u63a5\u53e3&#xff0c;\u4e5f\u4e3a\u7cfb\u7edf\u7684\u53ef\u6269\u5c55\u6027\u548c\u751f\u6001\u6574\u5408\u80fd\u529b\u6253\u4e0b\u4e86\u575a\u5b9e\u57fa\u7840\u3002 <\/p>\n<p>  \u672c\u6587\u8fd8\u6709\u914d\u5957\u7684\u7cbe\u54c1\u8d44\u6e90&#xff0c;\u70b9\u51fb\u83b7\u53d6  <img decoding=\"async\" alt=\"menu-r.4af5f7ec.gif\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122150439-69723c87ed57a.gif\" style=\"width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text\" \/> <\/p>\n<p> \u7b80\u4ecb&#xff1a;Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u662f\u4e00\u6b3e\u4e13\u4e3a\u6784\u5efa\u7a33\u5b9a\u3001\u5b89\u5168\u3001\u53ef\u6269\u5c55\u7684\u5b9e\u65f6\u901a\u8baf\u7cfb\u7edf\u800c\u8bbe\u8ba1\u7684\u9ad8\u6027\u80fd\u670d\u52a1\u5668\u8f6f\u4ef6&#xff0c;\u9002\u7528\u4e8e\u4f01\u4e1a\u6c9f\u901a\u3001\u5728\u7ebf\u5ba2\u670d\u3001\u793e\u4ea4\u5e94\u7528\u7b49\u591a\u573a\u666f\u3002\u5176\u5177\u5907\u5f3a\u5927\u7684\u6d88\u606f\u5904\u7406\u80fd\u529b&#xff0c;\u652f\u6301\u6587\u672c\u3001\u56fe\u7247\u3001\u8bed\u97f3\u3001\u89c6\u9891\u7b49\u591a\u79cd\u6d88\u606f\u7c7b\u578b&#xff0c;\u5e76\u91c7\u7528SSL\/TLS\u52a0\u5bc6\u6280\u672f\u4fdd\u969c\u901a\u4fe1\u5b89\u5168\u3002\u63d0\u4f9b\u5b8c\u5584\u7684API\u548cSDK&#xff0c;\u4fbf\u4e8e\u5f00\u53d1\u8005\u5feb\u901f\u96c6\u6210\u4e0e\u5b9a\u5236\u3002\u540c\u65f6\u652f\u6301\u96c6\u7fa4\u90e8\u7f72\u4e0e\u8d1f\u8f7d\u5747\u8861&#xff0c;\u5177\u5907\u826f\u597d\u7684\u5f39\u6027\u4f38\u7f29\u80fd\u529b&#xff0c;\u9002\u5408\u9ad8\u5e76\u53d1\u73af\u5883\u4e0b\u7684\u7a33\u5b9a\u8fd0\u884c\u3002 <\/p>\n<p>   \u672c\u6587\u8fd8\u6709\u914d\u5957\u7684\u7cbe\u54c1\u8d44\u6e90&#xff0c;\u70b9\u51fb\u83b7\u53d6   <img decoding=\"async\" alt=\"menu-r.4af5f7ec.gif\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122150439-69723c87ed57a.gif\" style=\"width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text\" \/>  <\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u672c\u6587\u8fd8\u6709\u914d\u5957\u7684\u7cbe\u54c1\u8d44\u6e90&#xff0c;\u70b9\u51fb\u83b7\u53d6    \u7b80\u4ecb&#xff1a;Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u662f\u4e00\u6b3e\u4e13\u4e3a\u6784\u5efa\u7a33\u5b9a\u3001\u5b89\u5168\u3001\u53ef\u6269\u5c55\u7684\u5b9e\u65f6\u901a\u8baf\u7cfb\u7edf\u800c\u8bbe\u8ba1\u7684\u9ad8\u6027\u80fd\u670d\u52a1\u5668\u8f6f\u4ef6&#xff0c;\u9002\u7528\u4e8e\u4f01\u4e1a\u6c9f\u901a\u3001\u5728\u7ebf\u5ba2\u670d\u3001\u793e\u4ea4\u5e94\u7528\u7b49\u591a\u573a\u666f\u3002\u5176\u5177\u5907\u5f3a\u5927\u7684\u6d88\u606f\u5904\u7406\u80fd\u529b&#xff0c;\u652f\u6301\u6587\u672c\u3001\u56fe\u7247\u3001\u8bed\u97f3\u3001\u89c6\u9891\u7b49\u591a\u79cd\u6d88\u606f\u7c7b\u578b&#xff0c;\u5e76\u91c7\u7528SSL\/TLS\u52a0\u5bc6\u6280\u672f\u4fdd\u969c\u901a\u4fe1\u5b89\u5168\u3002\u63d0\u4f9b\u5b8c\u5584\u7684API\u548cSDK&#xff0c;\u4fbf\u4e8e\u5f00\u53d1\u8005\u5feb\u901f\u96c6\u6210\u4e0e\u5b9a\u5236\u3002\u540c\u65f6\u652f\u6301\u96c6\u7fa4\u90e8\u7f72\u4e0e\u8d1f\u8f7d\u5747\u8861&#xff0c;\u5177\u5907\u826f<\/p>\n","protected":false},"author":2,"featured_media":64185,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"topic":[],"class_list":["post-64186","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-server"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u2014\u2014\u6253\u9020\u9ad8\u6548\u5b9e\u65f6\u901a\u8baf\u5e73\u53f0\u7684\u5229\u5668 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/64186.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u2014\u2014\u6253\u9020\u9ad8\u6548\u5b9e\u65f6\u901a\u8baf\u5e73\u53f0\u7684\u5229\u5668 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"\u672c\u6587\u8fd8\u6709\u914d\u5957\u7684\u7cbe\u54c1\u8d44\u6e90&#xff0c;\u70b9\u51fb\u83b7\u53d6  \u7b80\u4ecb&#xff1a;Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u662f\u4e00\u6b3e\u4e13\u4e3a\u6784\u5efa\u7a33\u5b9a\u3001\u5b89\u5168\u3001\u53ef\u6269\u5c55\u7684\u5b9e\u65f6\u901a\u8baf\u7cfb\u7edf\u800c\u8bbe\u8ba1\u7684\u9ad8\u6027\u80fd\u670d\u52a1\u5668\u8f6f\u4ef6&#xff0c;\u9002\u7528\u4e8e\u4f01\u4e1a\u6c9f\u901a\u3001\u5728\u7ebf\u5ba2\u670d\u3001\u793e\u4ea4\u5e94\u7528\u7b49\u591a\u573a\u666f\u3002\u5176\u5177\u5907\u5f3a\u5927\u7684\u6d88\u606f\u5904\u7406\u80fd\u529b&#xff0c;\u652f\u6301\u6587\u672c\u3001\u56fe\u7247\u3001\u8bed\u97f3\u3001\u89c6\u9891\u7b49\u591a\u79cd\u6d88\u606f\u7c7b\u578b&#xff0c;\u5e76\u91c7\u7528SSL\/TLS\u52a0\u5bc6\u6280\u672f\u4fdd\u969c\u901a\u4fe1\u5b89\u5168\u3002\u63d0\u4f9b\u5b8c\u5584\u7684API\u548cSDK&#xff0c;\u4fbf\u4e8e\u5f00\u53d1\u8005\u5feb\u901f\u96c6\u6210\u4e0e\u5b9a\u5236\u3002\u540c\u65f6\u652f\u6301\u96c6\u7fa4\u90e8\u7f72\u4e0e\u8d1f\u8f7d\u5747\u8861&#xff0c;\u5177\u5907\u826f\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/64186.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-01-22T15:04:41+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122150439-69723c87ed57a.gif\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"19 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/64186.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/64186.html\",\"name\":\"Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u2014\u2014\u6253\u9020\u9ad8\u6548\u5b9e\u65f6\u901a\u8baf\u5e73\u53f0\u7684\u5229\u5668 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-01-22T15:04:41+00:00\",\"dateModified\":\"2026-01-22T15:04:41+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/64186.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/64186.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/64186.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u2014\u2014\u6253\u9020\u9ad8\u6548\u5b9e\u65f6\u901a\u8baf\u5e73\u53f0\u7684\u5229\u5668\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u2014\u2014\u6253\u9020\u9ad8\u6548\u5b9e\u65f6\u901a\u8baf\u5e73\u53f0\u7684\u5229\u5668 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/64186.html","og_locale":"zh_CN","og_type":"article","og_title":"Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u2014\u2014\u6253\u9020\u9ad8\u6548\u5b9e\u65f6\u901a\u8baf\u5e73\u53f0\u7684\u5229\u5668 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"\u672c\u6587\u8fd8\u6709\u914d\u5957\u7684\u7cbe\u54c1\u8d44\u6e90&#xff0c;\u70b9\u51fb\u83b7\u53d6  \u7b80\u4ecb&#xff1a;Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u662f\u4e00\u6b3e\u4e13\u4e3a\u6784\u5efa\u7a33\u5b9a\u3001\u5b89\u5168\u3001\u53ef\u6269\u5c55\u7684\u5b9e\u65f6\u901a\u8baf\u7cfb\u7edf\u800c\u8bbe\u8ba1\u7684\u9ad8\u6027\u80fd\u670d\u52a1\u5668\u8f6f\u4ef6&#xff0c;\u9002\u7528\u4e8e\u4f01\u4e1a\u6c9f\u901a\u3001\u5728\u7ebf\u5ba2\u670d\u3001\u793e\u4ea4\u5e94\u7528\u7b49\u591a\u573a\u666f\u3002\u5176\u5177\u5907\u5f3a\u5927\u7684\u6d88\u606f\u5904\u7406\u80fd\u529b&#xff0c;\u652f\u6301\u6587\u672c\u3001\u56fe\u7247\u3001\u8bed\u97f3\u3001\u89c6\u9891\u7b49\u591a\u79cd\u6d88\u606f\u7c7b\u578b&#xff0c;\u5e76\u91c7\u7528SSL\/TLS\u52a0\u5bc6\u6280\u672f\u4fdd\u969c\u901a\u4fe1\u5b89\u5168\u3002\u63d0\u4f9b\u5b8c\u5584\u7684API\u548cSDK&#xff0c;\u4fbf\u4e8e\u5f00\u53d1\u8005\u5feb\u901f\u96c6\u6210\u4e0e\u5b9a\u5236\u3002\u540c\u65f6\u652f\u6301\u96c6\u7fa4\u90e8\u7f72\u4e0e\u8d1f\u8f7d\u5747\u8861&#xff0c;\u5177\u5907\u826f","og_url":"https:\/\/www.wsisp.com\/helps\/64186.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-01-22T15:04:41+00:00","og_image":[{"url":"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122150439-69723c87ed57a.gif"}],"author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"19 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/64186.html","url":"https:\/\/www.wsisp.com\/helps\/64186.html","name":"Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u2014\u2014\u6253\u9020\u9ad8\u6548\u5b9e\u65f6\u901a\u8baf\u5e73\u53f0\u7684\u5229\u5668 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-01-22T15:04:41+00:00","dateModified":"2026-01-22T15:04:41+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/64186.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/64186.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/64186.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"Fchat\u4e13\u4e1a\u804a\u5929\u670d\u52a1\u5668\u2014\u2014\u6253\u9020\u9ad8\u6548\u5b9e\u65f6\u901a\u8baf\u5e73\u53f0\u7684\u5229\u5668"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/64186","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=64186"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/64186\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media\/64185"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=64186"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=64186"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=64186"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=64186"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}