{"id":85162,"date":"2026-07-27T02:17:05","date_gmt":"2026-07-26T18:17:05","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/85162.html"},"modified":"2026-07-27T02:17:05","modified_gmt":"2026-07-26T18:17:05","slug":"http-%e7%8a%b6%e6%80%81%e7%a0%81%ef%bc%9a%e5%ae%a2%e6%88%b7%e7%ab%af%e4%b8%8e%e6%9c%8d%e5%8a%a1%e5%99%a8%e7%9a%84%e9%80%9a%e4%bf%a1%e8%af%ad%e8%a8%80-%e7%ac%ac%e4%ba%94%e9%83%a8","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/85162.html","title":{"rendered":"HTTP \u72b6\u6001\u7801\uff1a\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u5668\u7684\u901a\u4fe1\u8bed\u8a00\u2014\u2014\u7b2c\u4e94\u90e8\u5206\uff1a\u670d\u52a1\u5668\u9519\u8bef\u72b6\u6001\u7801\uff085xx\uff09\u7cfb\u7edf\u5206\u6790"},"content":{"rendered":"<h3>\u7b2c24\u7ae0&#xff1a;500 Internal Server Error &#8211; \u5185\u90e8\u670d\u52a1\u5668\u9519\u8bef<\/h3>\n<h4>24.1 \u6df1\u5ea6\u6280\u672f\u89e3\u6790&#xff1a;500\u9519\u8bef\u7684\u672c\u8d28<\/h4>\n<p>500 Internal Server Error\u00a0\u662fHTTP\u534f\u8bae\u4e2d\u6700\u901a\u7528\u3001\u6700\u4ee4\u4eba\u56f0\u60d1\u7684\u670d\u52a1\u5668\u9519\u8bef\u72b6\u6001\u7801\u3002\u4e0e\u5ba2\u6237\u7aef\u9519\u8bef&#xff08;4xx&#xff09;\u4e0d\u540c&#xff0c;500\u9519\u8bef\u660e\u786e\u8868\u793a\u95ee\u9898\u51fa\u5728\u670d\u52a1\u5668\u7aef&#xff0c;\u4f46\u670d\u52a1\u5668\u65e0\u6cd5\u6216\u4e0d\u613f\u63d0\u4f9b\u66f4\u5177\u4f53\u7684\u4fe1\u606f\u3002<\/p>\n<h5>24.1.1 \u6280\u672f\u89c4\u683c\u4e0e\u534f\u8bae\u5b9a\u4e49<\/h5>\n<ul>\n<li>\n<p>HTTP\/1.1 RFC 7231\u5b9a\u4e49&#xff1a;\u670d\u52a1\u5668\u9047\u5230\u4e86\u610f\u5916\u60c5\u51b5&#xff0c;\u963b\u6b62\u5176\u5b8c\u6210\u8bf7\u6c42<\/p>\n<\/li>\n<li>\n<p>\u72b6\u6001\u7801\u8bed\u4e49&#xff1a;\u901a\u7528\u9519\u8bef\u54cd\u5e94&#xff0c;\u5f53\u6ca1\u6709\u66f4\u5177\u4f53\u6d88\u606f\u5408\u9002\u65f6\u4f7f\u7528<\/p>\n<\/li>\n<li>\n<p>\u5173\u952e\u7279\u5f81&#xff1a;<\/p>\n<ul>\n<li>\n<p>\u670d\u52a1\u5668\u7aef\u6545\u969c\u7684&#034;\u515c\u5e95&#034;\u72b6\u6001\u7801<\/p>\n<\/li>\n<li>\n<p>\u901a\u5e38\u4f34\u968f\u670d\u52a1\u5668\u7aef\u5f02\u5e38\u5806\u6808\u6216\u65e5\u5fd7<\/p>\n<\/li>\n<li>\n<p>\u5ba2\u6237\u7aef\u65e0\u6cd5\u901a\u8fc7\u4fee\u6539\u8bf7\u6c42\u89e3\u51b3\u6b64\u95ee\u9898<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h5>24.1.2 \u4e0e\u76f8\u5173\u72b6\u6001\u7801\u7684\u533a\u5206<img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1196\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/07\/20260726181654-6a664f16b62ae.png\" width=\"3086\" \/><\/h5>\n<\/p>\n<h4>24.2 \u5178\u578b\u89e6\u53d1\u573a\u666f\u4e0e\u6848\u4f8b\u5206\u6790<\/h4>\n<h5>24.2.1 \u4ee3\u7801\u7ea7\u5f02\u5e38&#xff08;\u6700\u5e38\u89c1\u573a\u666f&#xff09;<\/h5>\n<p>\u6848\u4f8b\u4e00&#xff1a;\u672a\u6355\u83b7\u7684\u8fd0\u884c\u65f6\u5f02\u5e38<\/p>\n<p>python<\/p>\n<p># \u9519\u8bef\u793a\u4f8b&#xff1a;\u7f3a\u4e4f\u5f02\u5e38\u5904\u7406\u7684\u5371\u9669\u4ee3\u7801<br \/>\n&#064;app.route(&#039;\/process-data&#039;)<br \/>\ndef process_data():<br \/>\n    # \u672a\u9a8c\u8bc1\u8f93\u5165\u53ef\u80fd\u5bfc\u81f4\u5404\u79cd\u5f02\u5e38<br \/>\n    data &#061; request.json[&#039;data&#039;]  # KeyError\u5982\u679c&#039;data&#039;\u4e0d\u5b58\u5728<br \/>\n    result &#061; complex_processing(data)  # \u53ef\u80fd\u629b\u51fa\u5404\u79cd\u5f02\u5e38<br \/>\n    return jsonify(result)<\/p>\n<p># \u6b63\u786e\u793a\u4f8b&#xff1a;\u9632\u5fa1\u6027\u7f16\u7a0b<br \/>\n&#064;app.route(&#039;\/process-data&#039;)<br \/>\ndef process_data():<br \/>\n    try:<br \/>\n        data &#061; request.json.get(&#039;data&#039;)<br \/>\n        if not data:<br \/>\n            return jsonify({&#039;error&#039;: &#039;Missing data field&#039;}), 400<\/p>\n<p>        # \u8f93\u5165\u9a8c\u8bc1<br \/>\n        if not validate_input(data):<br \/>\n            return jsonify({&#039;error&#039;: &#039;Invalid input format&#039;}), 422<\/p>\n<p>        result &#061; safe_processing(data)<br \/>\n        return jsonify(result)<\/p>\n<p>    except SpecificException as e:<br \/>\n        logger.error(f&#034;Processing failed: {str(e)}&#034;)<br \/>\n        return jsonify({&#039;error&#039;: &#039;Processing failed&#039;}), 500<\/p>\n<p>    except Exception as e:<br \/>\n        # \u5168\u5c40\u5f02\u5e38\u5904\u7406<br \/>\n        logger.critical(f&#034;Unexpected error: {str(e)}&#034;, exc_info&#061;True)<br \/>\n        # \u53ef\u4ee5\u8003\u8651\u8fd4\u56de\u66f4\u53cb\u597d\u7684\u9519\u8bef\u4fe1\u606f<br \/>\n        return jsonify({&#039;error&#039;: &#039;Internal server error&#039;}), 500<\/p>\n<p>\u6848\u4f8b\u4e8c&#xff1a;\u8d44\u6e90\u6cc4\u6f0f\u5bfc\u81f4\u7684\u7cfb\u7edf\u5d29\u6e83<\/p>\n<p>java<\/p>\n<p>\/\/ \u6570\u636e\u5e93\u8fde\u63a5\u6cc4\u6f0f\u793a\u4f8b<br \/>\npublic class UserService {<br \/>\n    public User getUser(String userId) {<br \/>\n        Connection conn &#061; null;<br \/>\n        try {<br \/>\n            conn &#061; dataSource.getConnection();<br \/>\n            \/\/ \u6267\u884c\u67e5\u8be2<br \/>\n            return executeQuery(conn, userId);<br \/>\n        } catch (SQLException e) {<br \/>\n            \/\/ \u9519\u8bef&#xff1a;\u8fde\u63a5\u672a\u5728finally\u5757\u4e2d\u5173\u95ed<br \/>\n            throw new RuntimeException(&#034;Query failed&#034;, e);<br \/>\n        }<br \/>\n        \/\/ \u7f3a\u5c11finally\u5757\u5173\u95ed\u8fde\u63a5<br \/>\n    }<br \/>\n}<\/p>\n<p>\/\/ \u6539\u8fdb\u65b9\u6848&#xff1a;\u4f7f\u7528try-with-resources<br \/>\npublic User getUser(String userId) {<br \/>\n    try (Connection conn &#061; dataSource.getConnection();<br \/>\n         PreparedStatement stmt &#061; conn.prepareStatement(&#034;SELECT * FROM users WHERE id&#061;?&#034;)) {<\/p>\n<p>        stmt.setString(1, userId);<br \/>\n        try (ResultSet rs &#061; stmt.executeQuery()) {<br \/>\n            if (rs.next()) {<br \/>\n                return mapToUser(rs);<br \/>\n            }<br \/>\n        }<br \/>\n    } catch (SQLException e) {<br \/>\n        logger.error(&#034;Database error&#034;, e);<br \/>\n        throw new ServiceException(&#034;Failed to retrieve user&#034;, e);<br \/>\n    }<br \/>\n    return null;<br \/>\n}<\/p>\n<h5>24.2.2 \u914d\u7f6e\u9519\u8bef\u573a\u666f<\/h5>\n<p>Nginx &#043; PHP-FPM\u914d\u7f6e\u95ee\u9898\u5206\u6790&#xff1a;<\/p>\n<p>nginx<\/p>\n<p># \u9519\u8bef\u914d\u7f6e\u793a\u4f8b<br \/>\nserver {<br \/>\n    listen 80;<br \/>\n    server_name example.com;<\/p>\n<p>    location ~ \\\\.php$ {<br \/>\n        fastcgi_pass unix:\/var\/run\/php\/php7.4-fpm.sock;<br \/>\n        # \u9519\u8bef\u7684socket\u8def\u5f84\u6216\u6743\u9650\u95ee\u9898<br \/>\n        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;<br \/>\n        include fastcgi_params;<br \/>\n    }<br \/>\n}<\/p>\n<p># \u5e38\u89c1\u914d\u7f6e\u95ee\u9898\u68c0\u67e5\u6e05\u5355&#xff1a;<br \/>\n# 1. Socket\u6587\u4ef6\u6743\u9650&#xff1a;ls -l \/var\/run\/php\/php7.4-fpm.sock<br \/>\n# 2. PHP-FPM\u8fdb\u7a0b\u7528\u6237\u4e0eNginx\u7528\u6237\u662f\u5426\u5339\u914d<br \/>\n# 3. SCRIPT_FILENAME\u53c2\u6570\u662f\u5426\u6b63\u786e\u8bbe\u7f6e<br \/>\n# 4. \u6587\u4ef6\u7cfb\u7edf\u6743\u9650\u95ee\u9898<\/p>\n<h5>24.2.3 \u7b2c\u4e09\u65b9\u4f9d\u8d56\u6545\u969c<\/h5>\n<p>python<\/p>\n<p># \u5916\u90e8API\u8c03\u7528\u5bfc\u81f4\u7684\u7ea7\u8054\u6545\u969c<br \/>\nclass PaymentService:<br \/>\n    def __init__(self):<br \/>\n        self.gateway_url &#061; os.getenv(&#039;PAYMENT_GATEWAY_URL&#039;)<br \/>\n        self.timeout &#061; int(os.getenv(&#039;PAYMENT_TIMEOUT&#039;, 5))<\/p>\n<p>    def process_payment(self, order):<br \/>\n        try:<br \/>\n            response &#061; requests.post(<br \/>\n                f&#034;{self.gateway_url}\/charge&#034;,<br \/>\n                json&#061;order.to_dict(),<br \/>\n                timeout&#061;self.timeout<br \/>\n            )<br \/>\n            response.raise_for_status()<br \/>\n            return response.json()<\/p>\n<p>        except requests.exceptions.Timeout:<br \/>\n            # \u8d85\u65f6\u5904\u7406\u7b56\u7565<br \/>\n            logger.error(f&#034;Payment gateway timeout after {self.timeout}s&#034;)<br \/>\n            raise PaymentGatewayTimeout(&#034;Payment service unavailable&#034;)<\/p>\n<p>        except requests.exceptions.ConnectionError:<br \/>\n            # \u8fde\u63a5\u5931\u8d25\u5904\u7406<br \/>\n            logger.error(&#034;Cannot connect to payment gateway&#034;)<br \/>\n            raise PaymentGatewayError(&#034;Payment service connection failed&#034;)<\/p>\n<p>        except requests.exceptions.RequestException as e:<br \/>\n            # \u5176\u4ed6\u8bf7\u6c42\u5f02\u5e38<br \/>\n            logger.error(f&#034;Payment gateway error: {str(e)}&#034;)<br \/>\n            raise PaymentGatewayError(&#034;Payment processing failed&#034;)<\/p>\n<h4>24.3 \u7cfb\u7edf\u5316\u8bca\u65ad\u65b9\u6cd5\u8bba<\/h4>\n<h5>24.3.1 \u5206\u5c42\u8bca\u65ad\u6846\u67b6<\/h5>\n<p>\u8bca\u65ad\u91d1\u5b57\u5854\u6a21\u578b&#xff1a;<\/p>\n<p>text<\/p>\n<p>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502          \u4e1a\u52a1\u5c42\u9762\u76d1\u63a7               \u2502<br \/>\n\u2502  \u2022 \u7528\u6237\u6295\u8bc9                         \u2502<br \/>\n\u2502  \u2022 \u4e1a\u52a1\u6307\u6807\u5f02\u5e38                    \u2502<br \/>\n\u2502  \u2022 \u4ea4\u6613\u5931\u8d25\u7387\u4e0a\u5347                  \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<br \/>\n               \u25bc<br \/>\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502          \u5e94\u7528\u5c42\u9762\u8bca\u65ad               \u2502<br \/>\n\u2502  \u2022 \u9519\u8bef\u65e5\u5fd7\u5206\u6790                    \u2502<br \/>\n\u2502  \u2022 \u5e94\u7528\u6027\u80fd\u76d1\u63a7(APM)              \u2502<br \/>\n\u2502  \u2022 \u5806\u6808\u8ddf\u8e2a\u89e3\u6790                    \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<br \/>\n               \u25bc<br \/>\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502          \u7cfb\u7edf\u5c42\u9762\u68c0\u67e5               \u2502<br \/>\n\u2502  \u2022 \u7cfb\u7edf\u65e5\u5fd7(\/var\/log\/)             \u2502<br \/>\n\u2502  \u2022 \u8d44\u6e90\u4f7f\u7528\u7387(CPU\/\u5185\u5b58\/\u78c1\u76d8)       \u2502<br \/>\n\u2502  \u2022 \u8fdb\u7a0b\u72b6\u6001\u76d1\u63a7                    \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<br \/>\n               \u25bc<br \/>\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502          \u57fa\u7840\u8bbe\u65bd\u5c42                 \u2502<br \/>\n\u2502  \u2022 \u7f51\u7edc\u8fde\u901a\u6027                      \u2502<br \/>\n\u2502  \u2022 \u8d1f\u8f7d\u5747\u8861\u72b6\u6001                    \u2502<br \/>\n\u2502  \u2022 \u6570\u636e\u5e93\u8fde\u63a5\u6c60                    \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/p>\n<h5>24.3.2 \u8bca\u65ad\u547d\u4ee4\u4e0e\u5de5\u5177\u96c6<\/h5>\n<p>\u5b9e\u65f6\u8bca\u65ad\u5de5\u5177\u7bb1&#xff1a;<\/p>\n<p>bash<\/p>\n<p>#!\/bin\/bash<br \/>\n# 500\u9519\u8bef\u8bca\u65ad\u811a\u672c\u793a\u4f8b<\/p>\n<p># 1. \u68c0\u67e5Web\u670d\u52a1\u5668\u9519\u8bef\u65e5\u5fd7<br \/>\ntail -100 \/var\/log\/nginx\/error.log | grep -A5 -B5 &#034;500&#034;<br \/>\ntail -100 \/var\/log\/apache2\/error.log | grep -i &#034;internal&#034;<\/p>\n<p># 2. \u68c0\u67e5\u5e94\u7528\u65e5\u5fd7<br \/>\njournalctl -u your-application.service &#8211;since &#034;10 minutes ago&#034; | tail -50<\/p>\n<p># 3. \u7cfb\u7edf\u8d44\u6e90\u68c0\u67e5<br \/>\ntop -b -n 1 | head -20<br \/>\nfree -h<br \/>\ndf -h<\/p>\n<p># 4. \u7f51\u7edc\u8fde\u63a5\u72b6\u6001<br \/>\nnetstat -tulpn | grep -E &#034;(80|443)&#034;<br \/>\nss -tulpn | grep LISTEN<\/p>\n<p># 5. \u8fdb\u7a0b\u68c0\u67e5<br \/>\nps aux | grep -E &#034;(nginx|apache|php|python|java)&#034; | head -20<\/p>\n<p># 6. \u6570\u636e\u5e93\u8fde\u63a5\u68c0\u67e5<br \/>\n# MySQL<br \/>\nmysqladmin -u root -p status<br \/>\n# PostgreSQL<br \/>\npg_isready -h localhost<\/p>\n<p># 7. \u78c1\u76d8I\/O\u68c0\u67e5<br \/>\niostat -x 1 5<\/p>\n<p># 8. \u5185\u5b58\u6cc4\u6f0f\u68c0\u67e5<br \/>\ncat \/proc\/meminfo | grep -E &#034;(MemFree|Cached|Swap)&#034;<\/p>\n<p># 9. \u81ea\u52a8\u751f\u6210\u8bca\u65ad\u62a5\u544a<br \/>\necho &#034;&#061;&#061;&#061; 500\u9519\u8bef\u8bca\u65ad\u62a5\u544a &#061;&#061;&#061;&#034; &gt; \/tmp\/diagnosis_$(date &#043;%s).txt<br \/>\necho &#034;\u65f6\u95f4: $(date)&#034; &gt;&gt; \/tmp\/diagnosis.txt<br \/>\ndmesg | tail -20 &gt;&gt; \/tmp\/diagnosis.txt<\/p>\n<h4>24.4 \u9ad8\u7ea7\u89e3\u51b3\u65b9\u6848\u4e0e\u6700\u4f73\u5b9e\u8df5<\/h4>\n<h5>24.4.1 \u4f18\u96c5\u964d\u7ea7\u4e0e\u6545\u969c\u9694\u79bb<\/h5>\n<p>java<\/p>\n<p>\/\/ \u4f7f\u7528\u65ad\u8def\u5668\u6a21\u5f0f\u7684\u4f18\u96c5\u964d\u7ea7<br \/>\n&#064;Service<br \/>\npublic class RecommendationService {<\/p>\n<p>    private final CircuitBreaker circuitBreaker;<br \/>\n    private final CacheService cacheService;<\/p>\n<p>    public RecommendationService() {<br \/>\n        \/\/ \u914d\u7f6e\u65ad\u8def\u5668&#xff1a;10\u79d2\u518550%\u5931\u8d25\u89e6\u53d1\u6253\u5f00\u72b6\u6001<br \/>\n        CircuitBreakerConfig config &#061; CircuitBreakerConfig.custom()<br \/>\n            .failureRateThreshold(50)<br \/>\n            .waitDurationInOpenState(Duration.ofSeconds(30))<br \/>\n            .slidingWindowSize(10)<br \/>\n            .build();<\/p>\n<p>        this.circuitBreaker &#061; CircuitBreaker.of(&#034;recommendation-service&#034;, config);<br \/>\n    }<\/p>\n<p>    public List&lt;Product&gt; getRecommendations(String userId) {<br \/>\n        return circuitBreaker.executeSupplier(() -&gt; {<br \/>\n            \/\/ \u4e3b\u903b\u8f91&#xff1a;\u8c03\u7528\u63a8\u8350\u5f15\u64ce<br \/>\n            return callRecommendationEngine(userId);<br \/>\n        }, throwable -&gt; {<br \/>\n            \/\/ \u964d\u7ea7\u903b\u8f91&#xff1a;\u8fd4\u56de\u7f13\u5b58\u6216\u9ed8\u8ba4\u63a8\u8350<br \/>\n            logger.warn(&#034;Recommendation engine failed, using fallback&#034;, throwable);<br \/>\n            return getCachedRecommendations(userId);<br \/>\n        });<br \/>\n    }<\/p>\n<p>    private List&lt;Product&gt; getCachedRecommendations(String userId) {<br \/>\n        \/\/ \u4ece\u7f13\u5b58\u83b7\u53d6\u6216\u8fd4\u56de\u9ed8\u8ba4\u5217\u8868<br \/>\n        List&lt;Product&gt; cached &#061; cacheService.get(&#034;rec:&#034; &#043; userId);<br \/>\n        return cached !&#061; null ? cached : getDefaultRecommendations();<br \/>\n    }<br \/>\n}<\/p>\n<h5>24.4.2 \u5168\u9762\u76d1\u63a7\u4e0e\u544a\u8b66\u4f53\u7cfb<\/h5>\n<p>Prometheus &#043; Grafana\u76d1\u63a7\u914d\u7f6e\u793a\u4f8b&#xff1a;<\/p>\n<p>yaml<\/p>\n<p># prometheus.yml &#8211; 500\u9519\u8bef\u76d1\u63a7\u914d\u7f6e<br \/>\nscrape_configs:<br \/>\n  &#8211; job_name: &#039;webapp&#039;<br \/>\n    static_configs:<br \/>\n      &#8211; targets: [&#039;localhost:8080&#039;]<\/p>\n<p>    # \u81ea\u5b9a\u4e49500\u9519\u8bef\u6307\u6807<br \/>\n    metric_relabel_configs:<br \/>\n    &#8211; source_labels: [code]<br \/>\n      regex: &#039;5..&#039;<br \/>\n      action: keep<\/p>\n<p># \u544a\u8b66\u89c4\u5219\u914d\u7f6e<br \/>\ngroups:<br \/>\n  &#8211; name: http_errors<br \/>\n    rules:<br \/>\n      &#8211; alert: High500ErrorRate<br \/>\n        expr: |<br \/>\n          rate(<br \/>\n            http_requests_total{status&#061;&#034;500&#034;}[5m]<br \/>\n          ) \/ rate(<br \/>\n            http_requests_total[5m]<br \/>\n          ) &gt; 0.05  # 5%\u7684500\u9519\u8bef\u7387<br \/>\n        for: 2m<br \/>\n        labels:<br \/>\n          severity: critical<br \/>\n        annotations:<br \/>\n          summary: &#034;High rate of 500 errors detected&#034;<br \/>\n          description: |<br \/>\n            500\u9519\u8bef\u7387\u8d85\u8fc75%&#xff0c;\u5f53\u524d\u503c: {{ $value }}<br \/>\n            \u5f71\u54cd\u670d\u52a1: {{ $labels.service }}<\/p>\n<h5>24.4.3 \u81ea\u52a8\u5316\u6062\u590d\u673a\u5236<\/h5>\n<p>Kubernetes\u5065\u5eb7\u68c0\u67e5\u4e0e\u81ea\u6108&#xff1a;<\/p>\n<p>yaml<\/p>\n<p># deployment.yaml<br \/>\napiVersion: apps\/v1<br \/>\nkind: Deployment<br \/>\nmetadata:<br \/>\n  name: webapp-deployment<br \/>\nspec:<br \/>\n  replicas: 3<br \/>\n  selector:<br \/>\n    matchLabels:<br \/>\n      app: webapp<br \/>\n  template:<br \/>\n    metadata:<br \/>\n      labels:<br \/>\n        app: webapp<br \/>\n    spec:<br \/>\n      containers:<br \/>\n      &#8211; name: webapp<br \/>\n        image: your-webapp:latest<br \/>\n        ports:<br \/>\n        &#8211; containerPort: 8080<\/p>\n<p>        # \u6d3b\u6027\u63a2\u9488 &#8211; \u68c0\u67e5\u5bb9\u5668\u662f\u5426\u5b58\u6d3b<br \/>\n        livenessProbe:<br \/>\n          httpGet:<br \/>\n            path: \/health\/live<br \/>\n            port: 8080<br \/>\n          initialDelaySeconds: 30<br \/>\n          periodSeconds: 10<br \/>\n          failureThreshold: 3  # \u8fde\u7eed3\u6b21\u5931\u8d25\u540e\u91cd\u542f\u5bb9\u5668<\/p>\n<p>        # \u5c31\u7eea\u63a2\u9488 &#8211; \u68c0\u67e5\u5bb9\u5668\u662f\u5426\u51c6\u5907\u597d\u63a5\u6536\u6d41\u91cf<br \/>\n        readinessProbe:<br \/>\n          httpGet:<br \/>\n            path: \/health\/ready<br \/>\n            port: 8080<br \/>\n          initialDelaySeconds: 5<br \/>\n          periodSeconds: 5<br \/>\n          failureThreshold: 2<\/p>\n<p>        # \u8d44\u6e90\u9650\u5236\u9632\u6b62OOM<br \/>\n        resources:<br \/>\n          limits:<br \/>\n            memory: &#034;512Mi&#034;<br \/>\n            cpu: &#034;500m&#034;<br \/>\n          requests:<br \/>\n            memory: &#034;256Mi&#034;<br \/>\n            cpu: &#034;250m&#034;<\/p>\n<h4>24.5 \u9884\u9632\u6027\u67b6\u6784\u8bbe\u8ba1<\/h4>\n<h5>24.5.1 \u5bb9\u9519\u67b6\u6784\u6a21\u5f0f<\/h5>\n<p>\u5fae\u670d\u52a1\u67b6\u6784\u4e2d\u7684\u9519\u8bef\u4f20\u64ad\u63a7\u5236&#xff1a;<\/p>\n<p>python<\/p>\n<p># \u4f7f\u7528\u5f02\u6b65\u6d88\u606f\u961f\u5217\u89e3\u8026\u670d\u52a1<br \/>\nimport asyncio<br \/>\nfrom contextlib import asynccontextmanager<br \/>\nfrom typing import Optional<\/p>\n<p>class ResilientService:<br \/>\n    def __init__(self):<br \/>\n        self.retry_policy &#061; ExponentialBackoffRetry(<br \/>\n            max_retries&#061;3,<br \/>\n            base_delay&#061;1.0,<br \/>\n            max_delay&#061;10.0<br \/>\n        )<\/p>\n<p>    async def process_with_retry(self, task, task_id: str):<br \/>\n        &#034;&#034;&#034;\u5e26\u91cd\u8bd5\u548c\u6b7b\u4fe1\u961f\u5217\u7684\u5904\u7406&#034;&#034;&#034;<br \/>\n        for attempt in range(self.retry_policy.max_retries):<br \/>\n            try:<br \/>\n                return await task()<\/p>\n<p>            except TransientError as e:<br \/>\n                if attempt &#061;&#061; self.retry_policy.max_retries &#8211; 1:<br \/>\n                    # \u6700\u7ec8\u5931\u8d25&#xff0c;\u8fdb\u5165\u6b7b\u4fe1\u961f\u5217<br \/>\n                    await self.send_to_dead_letter_queue(task_id, str(e))<br \/>\n                    raise<\/p>\n<p>                delay &#061; self.retry_policy.get_delay(attempt)<br \/>\n                logger.warning(f&#034;Attempt {attempt&#043;1} failed, retrying in {delay}s&#034;)<br \/>\n                await asyncio.sleep(delay)<\/p>\n<p>            except PermanentError as e:<br \/>\n                # \u6c38\u4e45\u6027\u9519\u8bef&#xff0c;\u4e0d\u91cd\u8bd5<br \/>\n                logger.error(f&#034;Permanent error: {str(e)}&#034;)<br \/>\n                await self.send_to_dead_letter_queue(task_id, str(e))<br \/>\n                raise<\/p>\n<h5>24.5.2 \u6df7\u6c8c\u5de5\u7a0b\u4e0e\u97e7\u6027\u6d4b\u8bd5<\/h5>\n<p>python<\/p>\n<p># \u4f7f\u7528Chaos Toolkit\u8fdb\u884c\u6545\u969c\u6ce8\u5165\u6d4b\u8bd5<br \/>\nimport chaos<br \/>\nfrom chaos import experiment<\/p>\n<p>&#064;experiment<br \/>\ndef test_database_failure_resilience():<br \/>\n    &#034;&#034;&#034;\u6d4b\u8bd5\u6570\u636e\u5e93\u6545\u969c\u65f6\u7684\u670d\u52a1\u884c\u4e3a&#034;&#034;&#034;<\/p>\n<p>    # 1. \u5efa\u7acb\u5065\u5eb7\u57fa\u51c6<br \/>\n    baseline &#061; get_system_health()<\/p>\n<p>    # 2. \u6ce8\u5165\u6545\u969c&#xff1a;\u6a21\u62df\u6570\u636e\u5e93\u8fde\u63a5\u5931\u8d25<br \/>\n    with chaos.inject_fault(<br \/>\n        target&#061;&#034;database&#034;,<br \/>\n        fault_type&#061;&#034;network_latency&#034;,<br \/>\n        parameters&#061;{&#034;latency&#034;: 5000, &#034;duration&#034;: &#034;30s&#034;}<br \/>\n    ):<br \/>\n        # 3. \u76d1\u63a7\u7cfb\u7edf\u54cd\u5e94<br \/>\n        response &#061; simulate_user_workflow()<\/p>\n<p>        # 4. \u9a8c\u8bc1\u7cfb\u7edf\u662f\u5426\u4f18\u96c5\u964d\u7ea7<br \/>\n        assert response.status_code !&#061; 500, &#034;\u7cfb\u7edf\u4e0d\u5e94\u8fd4\u56de500\u9519\u8bef&#034;<br \/>\n        assert has_fallback_content(response), &#034;\u5e94\u663e\u793a\u964d\u7ea7\u5185\u5bb9&#034;<\/p>\n<p>        # 5. \u6536\u96c6\u6307\u6807<br \/>\n        metrics &#061; collect_performance_metrics()<\/p>\n<p>    # 6. \u6062\u590d\u5e76\u9a8c\u8bc1<br \/>\n    recovery_time &#061; measure_recovery_time()<br \/>\n    assert recovery_time &lt; 60, &#034;\u6062\u590d\u65f6\u95f4\u5e94\u5c0f\u4e8e60\u79d2&#034;<\/p>\n<p>    return {<br \/>\n        &#034;baseline&#034;: baseline,<br \/>\n        &#034;under_fault&#034;: metrics,<br \/>\n        &#034;recovery_time&#034;: recovery_time<br \/>\n    }<\/p>\n<h4>24.6 \u603b\u7ed3&#xff1a;\u4ece\u88ab\u52a8\u54cd\u5e94\u5230\u4e3b\u52a8\u9884\u9632<\/h4>\n<p>500 Internal Server Error \u867d\u7136\u662f\u4e00\u4e2a\u901a\u7528\u9519\u8bef&#xff0c;\u4f46\u5176\u80cc\u540e\u7684\u539f\u56e0\u5343\u5dee\u4e07\u522b\u3002\u6709\u6548\u7684500\u9519\u8bef\u7ba1\u7406\u9700\u8981&#xff1a;<\/p>\n<li>\n<p>\u591a\u5c42\u9632\u5fa1\u4f53\u7cfb&#xff1a;\u4ece\u4ee3\u7801\u7ea7\u5f02\u5e38\u5904\u7406\u5230\u67b6\u6784\u7ea7\u5bb9\u9519\u8bbe\u8ba1<\/p>\n<\/li>\n<li>\n<p>\u5168\u9762\u53ef\u89c2\u6d4b\u6027&#xff1a;\u65e5\u5fd7\u3001\u6307\u6807\u3001\u8ffd\u8e2a\u4e09\u4f4d\u4e00\u4f53\u7684\u76d1\u63a7\u4f53\u7cfb<\/p>\n<\/li>\n<li>\n<p>\u81ea\u52a8\u5316\u6062\u590d&#xff1a;\u57fa\u4e8e\u5065\u5eb7\u68c0\u67e5\u7684\u81ea\u52a8\u91cd\u542f\u548c\u6d41\u91cf\u5207\u6362<\/p>\n<\/li>\n<li>\n<p>\u9884\u9632\u6027\u6d4b\u8bd5&#xff1a;\u6df7\u6c8c\u5de5\u7a0b\u3001\u8d1f\u8f7d\u6d4b\u8bd5\u3001\u6545\u969c\u6ce8\u5165<\/p>\n<\/li>\n<li>\n<p>\u6301\u7eed\u6539\u8fdb&#xff1a;\u5efa\u7acb\u6545\u969c\u590d\u76d8\u6587\u5316&#xff0c;\u5c06\u6bcf\u6b21500\u9519\u8bef\u8f6c\u5316\u4e3a\u7cfb\u7edf\u52a0\u56fa\u7684\u673a\u4f1a<\/p>\n<\/li>\n<p>\u901a\u8fc7\u7cfb\u7edf\u5316\u7684\u65b9\u6cd5\u5904\u7406500\u9519\u8bef&#xff0c;\u53ef\u4ee5\u663e\u8457\u63d0\u5347\u7cfb\u7edf\u7684\u53ef\u7528\u6027\u548c\u53ef\u9760\u6027&#xff0c;\u5c06\u4e0d\u53ef\u9884\u77e5\u7684\u670d\u52a1\u5668\u9519\u8bef\u8f6c\u5316\u4e3a\u53ef\u7ba1\u7406\u3001\u53ef\u9884\u9632\u7684\u7cfb\u7edf\u884c\u4e3a\u3002<\/p>\n<hr \/>\n<h3>\u7b2c25\u7ae0&#xff1a;501 Not Implemented &#8211; \u672a\u5b9e\u73b0\u529f\u80fd<\/h3>\n<h4>25.1 \u534f\u8bae\u89c4\u8303\u6df1\u5ea6\u89e3\u8bfb<\/h4>\n<p>501 Not Implemented\u00a0\u662f\u4e00\u4e2a\u7ecf\u5e38\u88ab\u8bef\u89e3\u6216\u8bef\u7528\u7684HTTP\u72b6\u6001\u7801\u3002\u5b83\u660e\u786e\u8868\u793a\u670d\u52a1\u5668\u4e0d\u652f\u6301\u5b8c\u6210\u8bf7\u6c42\u6240\u9700\u7684\u529f\u80fd\u3002<\/p>\n<h5>25.1.1 RFC 7231 \u6b63\u5f0f\u5b9a\u4e49<\/h5>\n<ul>\n<li>\n<p>\u539f\u6587&#xff1a;&#034;The server does not support the functionality required to fulfill the request.&#034;<\/p>\n<\/li>\n<li>\n<p>\u5173\u952e\u89e3\u8bfb&#xff1a;<\/p>\n<ul>\n<li>\n<p>\u670d\u52a1\u5668\u7406\u89e3\u8bf7\u6c42&#xff0c;\u4f46\u65e0\u6cd5\u6267\u884c<\/p>\n<\/li>\n<li>\n<p>\u901a\u5e38\u4e0eHTTP\u65b9\u6cd5\u76f8\u5173&#xff08;\u5982\u670d\u52a1\u5668\u4e0d\u652f\u6301PATCH\u65b9\u6cd5&#xff09;<\/p>\n<\/li>\n<li>\n<p>\u662f\u6c38\u4e45\u6027\u9519\u8bef&#xff0c;\u9664\u975e\u670d\u52a1\u5668\u5347\u7ea7<\/p>\n<\/li>\n<li>\n<p>\u5fc5\u987b\u5305\u542b\u9002\u5f53\u7684Allow\u5934\u90e8&#xff08;\u5982\u679c\u9002\u7528&#xff09;<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h5>25.1.2 \u4e0e405 Method Not Allowed\u7684\u533a\u522b<img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1724\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/07\/20260726181656-6a664f18606e1.png\" width=\"2102\" \/><\/h5>\n<h4>25.2 \u5b9e\u9645\u5e94\u7528\u573a\u666f\u5206\u6790<\/h4>\n<h5>25.2.1 REST API\u8bbe\u8ba1\u4e2d\u7684\u6b63\u786e\u4f7f\u7528<\/h5>\n<p>python<\/p>\n<p># Flask REST API\u793a\u4f8b &#8211; \u6b63\u786e\u5b9e\u73b0501\u54cd\u5e94<br \/>\nfrom flask import Flask, jsonify, request<br \/>\nfrom functools import wraps<\/p>\n<p>app &#061; Flask(__name__)<\/p>\n<p>def require_feature(feature_name):<br \/>\n    &#034;&#034;&#034;\u88c5\u9970\u5668&#xff1a;\u68c0\u67e5\u529f\u80fd\u662f\u5426\u5df2\u5b9e\u73b0&#034;&#034;&#034;<br \/>\n    def decorator(f):<br \/>\n        &#064;wraps(f)<br \/>\n        def decorated_function(*args, **kwargs):<br \/>\n            if not is_feature_enabled(feature_name):<br \/>\n                # \u8fd4\u56de501&#xff0c;\u8868\u793a\u529f\u80fd\u672a\u5b9e\u73b0<br \/>\n                return jsonify({<br \/>\n                    &#034;error&#034;: &#034;Feature not implemented&#034;,<br \/>\n                    &#034;feature&#034;: feature_name,<br \/>\n                    &#034;documentation&#034;: &#034;https:\/\/api.example.com\/docs\/features&#034;<br \/>\n                }), 501<br \/>\n            return f(*args, **kwargs)<br \/>\n        return decorated_function<br \/>\n    return decorator<\/p>\n<p>&#064;app.route(&#039;\/api\/v1\/users\/&lt;user_id&gt;&#039;, methods&#061;[&#039;GET&#039;, &#039;PATCH&#039;, &#039;DELETE&#039;])<br \/>\ndef user_operations(user_id):<br \/>\n    if request.method &#061;&#061; &#039;PATCH&#039;:<br \/>\n        # PATCH\u65b9\u6cd5\u5df2\u8ba1\u5212\u4f46\u672a\u5b9e\u73b0<br \/>\n        return jsonify({<br \/>\n            &#034;error&#034;: &#034;PATCH method not yet implemented&#034;,<br \/>\n            &#034;message&#034;: &#034;Use PUT for full updates or check roadmap&#034;,<br \/>\n            &#034;roadmap&#034;: &#034;https:\/\/api.example.com\/roadmap#patch-support&#034;,<br \/>\n            &#034;available_methods&#034;: [&#034;GET&#034;, &#034;PUT&#034;, &#034;DELETE&#034;]<br \/>\n        }), 501<\/p>\n<p>    elif request.method &#061;&#061; &#039;DELETE&#039;:<br \/>\n        if not is_deletion_enabled():<br \/>\n            return jsonify({<br \/>\n                &#034;error&#034;: &#034;User deletion not implemented&#034;,<br \/>\n                &#034;message&#034;: &#034;Contact admin for account deletion&#034;,<br \/>\n                &#034;contact&#034;: &#034;support&#064;example.com&#034;<br \/>\n            }), 501<\/p>\n<p>    # \u6b63\u5e38\u5904\u7406GET\u548c\u5df2\u5b9e\u73b0\u7684DELETE<br \/>\n    return handle_user_request(user_id, request.method)<\/p>\n<p># \u4e3aOPTIONS\u8bf7\u6c42\u6b63\u786e\u8fd4\u56deAllow\u5934\u90e8<br \/>\n&#064;app.route(&#039;\/api\/v1\/users\/&lt;user_id&gt;&#039;, methods&#061;[&#039;OPTIONS&#039;])<br \/>\ndef user_options(user_id):<br \/>\n    response &#061; jsonify({})<br \/>\n    response.headers[&#039;Allow&#039;] &#061; &#039;GET, PUT, DELETE&#039;  # \u4e0d\u5305\u62ecPATCH<br \/>\n    response.headers[&#039;Accept-Patch&#039;] &#061; &#039;application\/json-patch&#043;json&#039;<br \/>\n    return response<\/p>\n<h5>25.2.2 WebDAV\u6269\u5c55\u534f\u8bae\u573a\u666f<\/h5>\n<p>http<\/p>\n<p># WebDAV\u5ba2\u6237\u7aef\u8bf7\u6c42\u793a\u4f8b<br \/>\nPROPFIND \/remote.php\/dav\/files\/user\/documents\/ HTTP\/1.1<br \/>\nHost: cloud.example.com<br \/>\nDepth: 1<br \/>\nContent-Type: application\/xml; charset&#061;utf-8<br \/>\nContent-Length: 173<\/p>\n<p>&lt;?xml version&#061;&#034;1.0&#034; encoding&#061;&#034;utf-8&#034; ?&gt;<br \/>\n&lt;D:propfind xmlns:D&#061;&#034;DAV:&#034;&gt;<br \/>\n    &lt;D:prop&gt;<br \/>\n        &lt;D:getlastmodified\/&gt;<br \/>\n        &lt;D:getcontentlength\/&gt;<br \/>\n        &lt;D:creationdate\/&gt;<br \/>\n        &lt;D:resourcetype\/&gt;<br \/>\n    &lt;\/D:prop&gt;<br \/>\n&lt;\/D:propfind&gt;<\/p>\n<p># \u670d\u52a1\u5668\u54cd\u5e94&#xff08;\u5982\u679cPROPFIND\u672a\u5b9e\u73b0&#xff09;<br \/>\nHTTP\/1.1 501 Not Implemented<br \/>\nAllow: GET, HEAD, POST, PUT, DELETE, OPTIONS<br \/>\nContent-Type: application\/json<\/p>\n<p>{<br \/>\n    &#034;error&#034;: &#034;PROPFIND method not supported&#034;,<br \/>\n    &#034;supported_methods&#034;: [&#034;GET&#034;, &#034;HEAD&#034;, &#034;POST&#034;, &#034;PUT&#034;, &#034;DELETE&#034;, &#034;OPTIONS&#034;],<br \/>\n    &#034;webdav_support&#034;: false,<br \/>\n    &#034;alternative&#034;: &#034;\/api\/v2\/files\/metadata&#034;<br \/>\n}<\/p>\n<h4>25.3 \u4f01\u4e1a\u7ea7\u89e3\u51b3\u65b9\u6848\u8bbe\u8ba1<\/h4>\n<h5>25.3.1 API\u7248\u672c\u7ba1\u7406\u4e0e\u529f\u80fd\u6807\u8bb0<\/h5>\n<p>yaml<\/p>\n<p># OpenAPI 3.0\u89c4\u8303\u4e2d\u7684\u529f\u80fd\u6807\u8bb0<br \/>\nopenapi: 3.0.3<br \/>\ninfo:<br \/>\n  title: User Management API<br \/>\n  version: 1.5.0<br \/>\n  description: |<br \/>\n    \u6ce8\u610f&#xff1a;\u67d0\u4e9b\u529f\u80fd\u53ef\u80fd\u5904\u4e8ebeta\u72b6\u6001\u6216\u672a\u5b8c\u5168\u5b9e\u73b0\u3002<br \/>\n    \u4f7f\u7528&#096;X-Feature-Flags&#096;\u5934\u90e8\u8bf7\u6c42\u7279\u5b9a\u529f\u80fd\u3002<\/p>\n<p>paths:<br \/>\n  \/users\/{id}:<br \/>\n    patch:<br \/>\n      summary: Partially update a user<br \/>\n      description: |<br \/>\n        \u6b64\u529f\u80fd\u5f53\u524d\u4e3a**\u5b9e\u9a8c\u6027**\u3002<br \/>\n        \u9700\u8981\u8bbe\u7f6e&#096;X-Feature-Flags: partial-update&#096;\u3002<br \/>\n        \u5b8c\u6574\u5b9e\u73b0\u8ba1\u5212\u5728v2.0.0\u3002<br \/>\n      operationId: patchUser<br \/>\n      parameters:<br \/>\n        &#8211; name: X-Feature-Flags<br \/>\n          in: header<br \/>\n          required: true<br \/>\n          schema:<br \/>\n            type: string<br \/>\n            enum: [partial-update]<br \/>\n      responses:<br \/>\n        &#039;200&#039;:<br \/>\n          description: Successfully updated<br \/>\n        &#039;501&#039;:<br \/>\n          description: |<br \/>\n            PATCH not fully implemented for this resource.<br \/>\n            Current support limited to email field only.<br \/>\n            Full PATCH support coming in v2.0.0.<br \/>\n          content:<br \/>\n            application\/json:<br \/>\n              schema:<br \/>\n                $ref: &#039;#\/components\/schemas\/NotImplementedError&#039;<\/p>\n<h5>25.3.2 \u6e10\u8fdb\u5f0f\u529f\u80fd\u53d1\u5e03\u7b56\u7565<\/h5>\n<p>python<\/p>\n<p># \u529f\u80fd\u6807\u8bb0\u4e0e\u6e10\u8fdb\u5f0f\u53d1\u5e03\u7cfb\u7edf<br \/>\nfrom typing import Dict, Optional<br \/>\nfrom enum import Enum<br \/>\nimport redis<\/p>\n<p>class FeatureStatus(Enum):<br \/>\n    NOT_IMPLEMENTED &#061; &#034;not_implemented&#034;<br \/>\n    ALPHA &#061; &#034;alpha&#034;<br \/>\n    BETA &#061; &#034;beta&#034;<br \/>\n    GA &#061; &#034;general_availability&#034;<br \/>\n    DEPRECATED &#061; &#034;deprecated&#034;<\/p>\n<p>class FeatureManager:<br \/>\n    def __init__(self):<br \/>\n        self.redis &#061; redis.Redis(host&#061;&#039;localhost&#039;, port&#061;6379, db&#061;0)<br \/>\n        self.feature_registry &#061; self._load_feature_registry()<\/p>\n<p>    def _load_feature_registry(self) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u52a0\u8f7d\u529f\u80fd\u5b9a\u4e49&#034;&#034;&#034;<br \/>\n        return {<br \/>\n            &#034;user_partial_update&#034;: {<br \/>\n                &#034;status&#034;: FeatureStatus.BETA,<br \/>\n                &#034;description&#034;: &#034;PATCH support for user resources&#034;,<br \/>\n                &#034;since_version&#034;: &#034;1.4.0&#034;,<br \/>\n                &#034;planned_ga&#034;: &#034;2.0.0&#034;,<br \/>\n                &#034;required_headers&#034;: [&#034;X-Feature-Flags&#034;],<br \/>\n                &#034;documentation&#034;: &#034;\/docs\/features\/partial-update&#034;<br \/>\n            },<br \/>\n            &#034;bulk_operations&#034;: {<br \/>\n                &#034;status&#034;: FeatureStatus.NOT_IMPLEMENTED,<br \/>\n                &#034;description&#034;: &#034;Bulk create\/update\/delete operations&#034;,<br \/>\n                &#034;planned_version&#034;: &#034;2.1.0&#034;,<br \/>\n                &#034;roadmap_url&#034;: &#034;\/roadmap#bulk-operations&#034;<br \/>\n            }<br \/>\n        }<\/p>\n<p>    def check_feature_access(self, feature_name: str,<br \/>\n                           user_id: Optional[str] &#061; None) -&gt; bool:<br \/>\n        &#034;&#034;&#034;\u68c0\u67e5\u7528\u6237\u662f\u5426\u53ef\u4ee5\u8bbf\u95ee\u7279\u5b9a\u529f\u80fd&#034;&#034;&#034;<br \/>\n        feature &#061; self.feature_registry.get(feature_name)<\/p>\n<p>        if not feature:<br \/>\n            return False<\/p>\n<p>        status &#061; feature[&#034;status&#034;]<\/p>\n<p>        # \u6839\u636e\u529f\u80fd\u72b6\u6001\u51b3\u5b9a\u8bbf\u95ee\u6743\u9650<br \/>\n        if status &#061;&#061; FeatureStatus.NOT_IMPLEMENTED:<br \/>\n            return False<br \/>\n        elif status &#061;&#061; FeatureStatus.ALPHA:<br \/>\n            # \u4ec5\u9650\u5185\u90e8\u6d4b\u8bd5\u7528\u6237<br \/>\n            return self._is_internal_user(user_id)<br \/>\n        elif status &#061;&#061; FeatureStatus.BETA:<br \/>\n            # Beta\u6d4b\u8bd5\u7528\u6237\u6216\u901a\u8fc7\u529f\u80fd\u6807\u8bb0\u8bf7\u6c42<br \/>\n            return self._is_beta_user(user_id) or self._has_feature_flag(feature_name)<br \/>\n        elif status &#061;&#061; FeatureStatus.GA:<br \/>\n            return True<br \/>\n        elif status &#061;&#061; FeatureStatus.DEPRECATED:<br \/>\n            # \u5df2\u5f03\u7528\u529f\u80fd\u53ef\u80fd\u4ecd\u7136\u53ef\u7528<br \/>\n            return self._has_legacy_access(user_id)<\/p>\n<p>        return False<\/p>\n<p>    def handle_not_implemented(self, feature_name: str, request) -&gt; tuple:<br \/>\n        &#034;&#034;&#034;\u751f\u6210\u6807\u51c6\u5316\u7684501\u54cd\u5e94&#034;&#034;&#034;<br \/>\n        feature &#061; self.feature_registry.get(feature_name, {})<\/p>\n<p>        response_data &#061; {<br \/>\n            &#034;error&#034;: &#034;Feature not implemented&#034;,<br \/>\n            &#034;feature&#034;: feature_name,<br \/>\n            &#034;current_status&#034;: feature.get(&#034;status&#034;, &#034;unknown&#034;),<br \/>\n            &#034;message&#034;: feature.get(&#034;description&#034;, &#034;&#034;)<br \/>\n        }<\/p>\n<p>        # \u6dfb\u52a0\u6709\u7528\u7684\u5143\u6570\u636e<br \/>\n        if &#034;planned_version&#034; in feature:<br \/>\n            response_data[&#034;planned_release&#034;] &#061; feature[&#034;planned_version&#034;]<br \/>\n        if &#034;documentation&#034; in feature:<br \/>\n            response_data[&#034;documentation_url&#034;] &#061; f&#034;https:\/\/api.example.com{feature[&#039;documentation&#039;]}&#034;<br \/>\n        if &#034;roadmap_url&#034; in feature:<br \/>\n            response_data[&#034;roadmap_url&#034;] &#061; f&#034;https:\/\/api.example.com{feature[&#039;roadmap_url&#039;]}&#034;<\/p>\n<p>        # \u6839\u636e\u8bf7\u6c42Accept\u5934\u90e8\u8fd4\u56de\u4e0d\u540c\u683c\u5f0f<br \/>\n        accept_header &#061; request.headers.get(&#039;Accept&#039;, &#039;application\/json&#039;)<br \/>\n        if &#039;text\/html&#039; in accept_header:<br \/>\n            return self._render_feature_roadmap_html(feature_name), 501<br \/>\n        elif &#039;application\/xml&#039; in accept_header:<br \/>\n            return self._render_feature_roadmap_xml(feature_name), 501<br \/>\n        else:<br \/>\n            return jsonify(response_data), 501<\/p>\n<h4>25.4 \u5ba2\u6237\u7aef\u5904\u7406\u7b56\u7565<\/h4>\n<h5>25.4.1 \u4f18\u96c5\u7684\u529f\u80fd\u68c0\u6d4b\u4e0e\u964d\u7ea7<\/h5>\n<p>javascript<\/p>\n<p>\/\/ \u73b0\u4ee3JavaScript\u5ba2\u6237\u7aef\u5b9e\u73b0<br \/>\nclass APIClient {<br \/>\n    constructor(baseURL) {<br \/>\n        this.baseURL &#061; baseURL;<br \/>\n        this.capabilities &#061; new Map();<br \/>\n        this.featureDetectionDone &#061; false;<br \/>\n    }<\/p>\n<p>    async detectCapabilities() {<br \/>\n        try {<br \/>\n            \/\/ \u9996\u5148\u5c1d\u8bd5OPTIONS\u8bf7\u6c42\u83b7\u53d6\u652f\u6301\u7684\u65b9\u6cd5<br \/>\n            const optionsResponse &#061; await fetch(&#096;${this.baseURL}\/api\/v1&#096;, {<br \/>\n                method: &#039;OPTIONS&#039;<br \/>\n            });<\/p>\n<p>            if (optionsResponse.headers.has(&#039;Allow&#039;)) {<br \/>\n                const allowedMethods &#061; optionsResponse.headers.get(&#039;Allow&#039;)<br \/>\n                    .split(&#039;,&#039;)<br \/>\n                    .map(m &#061;&gt; m.trim());<\/p>\n<p>                this.capabilities.set(&#039;methods&#039;, allowedMethods);<br \/>\n            }<\/p>\n<p>            \/\/ \u68c0\u67e5\u7279\u5b9a\u529f\u80fd<br \/>\n            await this.checkFeature(&#039;partial-update&#039;);<br \/>\n            await this.checkFeature(&#039;bulk-operations&#039;);<\/p>\n<p>            this.featureDetectionDone &#061; true;<br \/>\n            this.saveCapabilitiesToStorage();<\/p>\n<p>        } catch (error) {<br \/>\n            console.warn(&#039;Capability detection failed, using defaults&#039;, error);<br \/>\n            this.setDefaultCapabilities();<br \/>\n        }<br \/>\n    }<\/p>\n<p>    async checkFeature(featureName) {<br \/>\n        const testEndpoint &#061; &#096;${this.baseURL}\/api\/v1\/feature-check\/${featureName}&#096;;<\/p>\n<p>        try {<br \/>\n            const response &#061; await fetch(testEndpoint, {<br \/>\n                method: &#039;HEAD&#039;,<br \/>\n                headers: {<br \/>\n                    &#039;X-Feature-Check&#039;: &#039;true&#039;<br \/>\n                }<br \/>\n            });<\/p>\n<p>            if (response.status &#061;&#061;&#061; 200) {<br \/>\n                this.capabilities.set(featureName, true);<\/p>\n<p>                \/\/ \u5982\u679c\u6709\u529f\u80fd\u7248\u672c\u4fe1\u606f<br \/>\n                const version &#061; response.headers.get(&#039;X-Feature-Version&#039;);<br \/>\n                if (version) {<br \/>\n                    this.capabilities.set(&#096;${featureName}.version&#096;, version);<br \/>\n                }<br \/>\n            } else if (response.status &#061;&#061;&#061; 501) {<br \/>\n                this.capabilities.set(featureName, false);<\/p>\n<p>                \/\/ \u89e3\u6790\u54cd\u5e94\u83b7\u53d6\u66f4\u591a\u4fe1\u606f<br \/>\n                const errorData &#061; await response.json();<br \/>\n                this.capabilities.set(&#096;${featureName}.info&#096;, errorData);<br \/>\n            }<br \/>\n        } catch (error) {<br \/>\n            \/\/ \u7f51\u7edc\u9519\u8bef&#xff0c;\u529f\u80fd\u72b6\u6001\u672a\u77e5<br \/>\n            this.capabilities.set(featureName, &#039;unknown&#039;);<br \/>\n        }<br \/>\n    }<\/p>\n<p>    async updateUser(userId, data, partial &#061; false) {<br \/>\n        \/\/ \u6839\u636e\u529f\u80fd\u652f\u6301\u60c5\u51b5\u9009\u62e9\u65b9\u6cd5<br \/>\n        if (partial &amp;&amp; this.capabilities.get(&#039;partial-update&#039;)) {<br \/>\n            try {<br \/>\n                return await this.patchUser(userId, data);<br \/>\n            } catch (error) {<br \/>\n                if (error.status &#061;&#061;&#061; 501) {<br \/>\n                    \/\/ \u529f\u80fd\u68c0\u6d4b\u53ef\u80fd\u8fc7\u65f6&#xff0c;\u66f4\u65b0\u5e76\u964d\u7ea7<br \/>\n                    await this.detectCapabilities();<br \/>\n                    return await this.putUser(userId, data);<br \/>\n                }<br \/>\n                throw error;<br \/>\n            }<br \/>\n        } else {<br \/>\n            \/\/ \u4f7f\u7528\u5b8c\u6574\u7684PUT\u66f4\u65b0<br \/>\n            return await this.putUser(userId, data);<br \/>\n        }<br \/>\n    }<\/p>\n<p>    async patchUser(userId, data) {<br \/>\n        const response &#061; await fetch(&#096;${this.baseURL}\/api\/v1\/users\/${userId}&#096;, {<br \/>\n            method: &#039;PATCH&#039;,<br \/>\n            headers: {<br \/>\n                &#039;Content-Type&#039;: &#039;application\/json-patch&#043;json&#039;,<br \/>\n                &#039;X-Feature-Flags&#039;: &#039;partial-update&#039;<br \/>\n            },<br \/>\n            body: JSON.stringify(data)<br \/>\n        });<\/p>\n<p>        if (response.status &#061;&#061;&#061; 501) {<br \/>\n            const error &#061; new Error(&#039;Partial update not implemented&#039;);<br \/>\n            error.status &#061; 501;<br \/>\n            error.details &#061; await response.json();<br \/>\n            throw error;<br \/>\n        }<\/p>\n<p>        return response.json();<br \/>\n    }<br \/>\n}<\/p>\n<h5>25.4.2 \u7528\u6237\u754c\u9762\u7684\u4f18\u96c5\u5904\u7406<\/h5>\n<p>vue<\/p>\n<p>&lt;!&#8211; Vue.js\u7ec4\u4ef6&#xff1a;\u529f\u80fd\u4e0d\u53ef\u7528\u7684\u4f18\u96c5UI\u5904\u7406 &#8211;&gt;<br \/>\n&lt;template&gt;<br \/>\n  &lt;div class&#061;&#034;feature-unavailable&#034;&gt;<br \/>\n    &lt;div v-if&#061;&#034;isLoading&#034; class&#061;&#034;loading&#034;&gt;<br \/>\n      &lt;span class&#061;&#034;spinner&#034;&gt;&lt;\/span&gt;<br \/>\n      \u68c0\u67e5\u529f\u80fd\u53ef\u7528\u6027&#8230;<br \/>\n    &lt;\/div&gt;<\/p>\n<p>    &lt;div v-else-if&#061;&#034;!isSupported&#034; class&#061;&#034;unsupported-feature&#034;&gt;<br \/>\n      &lt;div class&#061;&#034;feature-header&#034;&gt;<br \/>\n        &lt;icon name&#061;&#034;construction&#034; size&#061;&#034;48&#034; \/&gt;<br \/>\n        &lt;h2&gt;{{ featureName }} \u529f\u80fd\u6682\u65f6\u4e0d\u53ef\u7528&lt;\/h2&gt;<br \/>\n      &lt;\/div&gt;<\/p>\n<p>      &lt;div class&#061;&#034;feature-details&#034;&gt;<br \/>\n        &lt;p v-if&#061;&#034;featureInfo.message&#034;&gt;{{ featureInfo.message }}&lt;\/p&gt;<\/p>\n<p>        &lt;div v-if&#061;&#034;featureInfo.planned_release&#034; class&#061;&#034;roadmap-info&#034;&gt;<br \/>\n          &lt;h3&gt;\u8ba1\u5212\u53d1\u5e03\u7248\u672c&lt;\/h3&gt;<br \/>\n          &lt;p&gt;\u9884\u8ba1\u5728 &lt;strong&gt;{{ featureInfo.planned_release }}&lt;\/strong&gt; \u7248\u672c\u4e2d\u63d0\u4f9b&lt;\/p&gt;<br \/>\n          &lt;a :href&#061;&#034;featureInfo.roadmap_url&#034; target&#061;&#034;_blank&#034;&gt;\u67e5\u770b\u8be6\u7ec6\u8def\u7ebf\u56fe&lt;\/a&gt;<br \/>\n        &lt;\/div&gt;<\/p>\n<p>        &lt;div v-if&#061;&#034;hasAlternatives&#034; class&#061;&#034;alternatives&#034;&gt;<br \/>\n          &lt;h3&gt;\u66ff\u4ee3\u65b9\u6848&lt;\/h3&gt;<br \/>\n          &lt;ul&gt;<br \/>\n            &lt;li v-for&#061;&#034;alt in alternatives&#034; :key&#061;&#034;alt.method&#034;&gt;<br \/>\n              &lt;button &#064;click&#061;&#034;useAlternative(alt)&#034;&gt;<br \/>\n                \u4f7f\u7528 {{ alt.name }}<br \/>\n              &lt;\/button&gt;<br \/>\n            &lt;\/li&gt;<br \/>\n          &lt;\/ul&gt;<br \/>\n        &lt;\/div&gt;<\/p>\n<p>        &lt;div class&#061;&#034;actions&#034;&gt;<br \/>\n          &lt;button &#064;click&#061;&#034;retryDetection&#034; class&#061;&#034;btn-secondary&#034;&gt;<br \/>\n            \u91cd\u65b0\u68c0\u67e5\u529f\u80fd<br \/>\n          &lt;\/button&gt;<br \/>\n          &lt;a :href&#061;&#034;featureInfo.documentation_url&#034;<br \/>\n             target&#061;&#034;_blank&#034;<br \/>\n             class&#061;&#034;btn-primary&#034;&gt;<br \/>\n            \u67e5\u770b\u6587\u6863<br \/>\n          &lt;\/a&gt;<br \/>\n        &lt;\/div&gt;<br \/>\n      &lt;\/div&gt;<br \/>\n    &lt;\/div&gt;<\/p>\n<p>    &lt;slot v-else&gt;&lt;\/slot&gt;<br \/>\n  &lt;\/div&gt;<br \/>\n&lt;\/template&gt;<\/p>\n<p>&lt;script&gt;<br \/>\nexport default {<br \/>\n  name: &#039;FeatureGuard&#039;,<br \/>\n  props: {<br \/>\n    featureName: {<br \/>\n      type: String,<br \/>\n      required: true<br \/>\n    },<br \/>\n    required: {<br \/>\n      type: Boolean,<br \/>\n      default: false<br \/>\n    }<br \/>\n  },<\/p>\n<p>  data() {<br \/>\n    return {<br \/>\n      isLoading: true,<br \/>\n      isSupported: false,<br \/>\n      featureInfo: {},<br \/>\n      alternatives: []<br \/>\n    };<br \/>\n  },<\/p>\n<p>  async created() {<br \/>\n    await this.checkFeatureSupport();<br \/>\n  },<\/p>\n<p>  methods: {<br \/>\n    async checkFeatureSupport() {<br \/>\n      this.isLoading &#061; true;<\/p>\n<p>      try {<br \/>\n        const response &#061; await this.$api.checkFeature(this.featureName);<\/p>\n<p>        if (response.supported) {<br \/>\n          this.isSupported &#061; true;<br \/>\n        } else {<br \/>\n          this.featureInfo &#061; response.details || {};<br \/>\n          this.findAlternatives();<br \/>\n        }<br \/>\n      } catch (error) {<br \/>\n        console.error(&#039;Feature check failed:&#039;, error);<br \/>\n        \/\/ \u9ed8\u8ba4\u964d\u7ea7\u5904\u7406<br \/>\n        this.findAlternatives();<br \/>\n      } finally {<br \/>\n        this.isLoading &#061; false;<br \/>\n      }<br \/>\n    },<\/p>\n<p>    findAlternatives() {<br \/>\n      \/\/ \u6839\u636e\u529f\u80fd\u540d\u67e5\u627e\u66ff\u4ee3\u65b9\u6848<br \/>\n      const alternativeMap &#061; {<br \/>\n        &#039;partial-update&#039;: [<br \/>\n          { name: &#039;\u5b8c\u6574\u66f4\u65b0&#039;, method: &#039;fullUpdate&#039; },<br \/>\n          { name: &#039;\u8868\u5355\u7f16\u8f91&#039;, method: &#039;formEdit&#039; }<br \/>\n        ],<br \/>\n        &#039;bulk-operations&#039;: [<br \/>\n          { name: &#039;\u5355\u4e2a\u64cd\u4f5c&#039;, method: &#039;singleOperation&#039; },<br \/>\n          { name: &#039;\u5bfc\u5165\/\u5bfc\u51fa&#039;, method: &#039;importExport&#039; }<br \/>\n        ]<br \/>\n      };<\/p>\n<p>      this.alternatives &#061; alternativeMap[this.featureName] || [];<br \/>\n    },<\/p>\n<p>    useAlternative(alternative) {<br \/>\n      this.$emit(&#039;use-alternative&#039;, alternative.method);<br \/>\n    },<\/p>\n<p>    async retryDetection() {<br \/>\n      await this.checkFeatureSupport();<br \/>\n    }<br \/>\n  }<br \/>\n};<br \/>\n&lt;\/script&gt;<\/p>\n<h4>25.5 \u76d1\u63a7\u4e0e\u6f14\u8fdb\u7ba1\u7406<\/h4>\n<h5>25.5.1 \u529f\u80fd\u4f7f\u7528\u7387\u8ffd\u8e2a<\/h5>\n<p>python<\/p>\n<p># \u529f\u80fd\u4f7f\u7528\u7387\u76d1\u63a7\u7cfb\u7edf<br \/>\nfrom dataclasses import dataclass<br \/>\nfrom datetime import datetime<br \/>\nfrom collections import defaultdict<br \/>\nimport statistics<br \/>\nfrom typing import Dict, List, Optional<\/p>\n<p>&#064;dataclass<br \/>\nclass FeatureMetric:<br \/>\n    &#034;&#034;&#034;\u529f\u80fd\u4f7f\u7528\u6307\u6807&#034;&#034;&#034;<br \/>\n    feature_name: str<br \/>\n    requests_total: int &#061; 0<br \/>\n    requests_successful: int &#061; 0<br \/>\n    requests_failed: int &#061; 0<br \/>\n    requests_not_implemented: int &#061; 0<br \/>\n    average_response_time: float &#061; 0.0<br \/>\n    p95_response_time: float &#061; 0.0<\/p>\n<p>    &#064;property<br \/>\n    def success_rate(self) -&gt; float:<br \/>\n        if self.requests_total &#061;&#061; 0:<br \/>\n            return 0.0<br \/>\n        return self.requests_successful \/ self.requests_total<\/p>\n<p>    &#064;property<br \/>\n    def not_implemented_rate(self) -&gt; float:<br \/>\n        if self.requests_total &#061;&#061; 0:<br \/>\n            return 0.0<br \/>\n        return self.requests_not_implemented \/ self.requests_total<\/p>\n<p>class FeatureAnalytics:<br \/>\n    def __init__(self):<br \/>\n        self.metrics: Dict[str, FeatureMetric] &#061; defaultdict(FeatureMetric)<br \/>\n        self.response_times: Dict[str, List[float]] &#061; defaultdict(list)<br \/>\n        self.daily_requests: Dict[str, Dict[str, int]] &#061; defaultdict(<br \/>\n            lambda: defaultdict(int)<br \/>\n        )<\/p>\n<p>    def track_request(self, feature_name: str, status_code: int,<br \/>\n                     response_time: float):<br \/>\n        &#034;&#034;&#034;\u8ffd\u8e2a\u529f\u80fd\u8bf7\u6c42&#034;&#034;&#034;<br \/>\n        metric &#061; self.metrics[feature_name]<br \/>\n        metric.feature_name &#061; feature_name<br \/>\n        metric.requests_total &#043;&#061; 1<\/p>\n<p>        if 200 &lt;&#061; status_code &lt; 300:<br \/>\n            metric.requests_successful &#043;&#061; 1<br \/>\n        elif status_code &#061;&#061; 501:<br \/>\n            metric.requests_not_implemented &#043;&#061; 1<br \/>\n        else:<br \/>\n            metric.requests_failed &#043;&#061; 1<\/p>\n<p>        # \u8bb0\u5f55\u54cd\u5e94\u65f6\u95f4<br \/>\n        self.response_times[feature_name].append(response_time)<\/p>\n<p>        # \u66f4\u65b0\u7edf\u8ba1<br \/>\n        times &#061; self.response_times[feature_name]<br \/>\n        if times:<br \/>\n            metric.average_response_time &#061; statistics.mean(times)<br \/>\n            if len(times) &gt;&#061; 5:<br \/>\n                metric.p95_response_time &#061; statistics.quantiles(times, n&#061;20)[18]<\/p>\n<p>        # \u8bb0\u5f55\u6bcf\u65e5\u8bf7\u6c42<br \/>\n        today &#061; datetime.now().strftime(&#039;%Y-%m-%d&#039;)<br \/>\n        self.daily_requests[feature_name][today] &#043;&#061; 1<\/p>\n<p>    def get_feature_priority_score(self, feature_name: str) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u8ba1\u7b97\u529f\u80fd\u5b9e\u73b0\u7684\u4f18\u5148\u7ea7\u5206\u6570&#034;&#034;&#034;<br \/>\n        metric &#061; self.metrics.get(feature_name)<br \/>\n        if not metric or metric.requests_total &#061;&#061; 0:<br \/>\n            return 0.0<\/p>\n<p>        # \u57fa\u4e8e\u8bf7\u6c42\u91cf\u3001\u5931\u8d25\u7387\u548c\u4e1a\u52a1\u91cd\u8981\u6027\u8ba1\u7b97\u5206\u6570<br \/>\n        request_volume_score &#061; min(metric.requests_total \/ 1000, 1.0)<br \/>\n        not_implemented_score &#061; metric.not_implemented_rate<\/p>\n<p>        # \u4e1a\u52a1\u91cd\u8981\u6027\u6743\u91cd&#xff08;\u53ef\u4ece\u914d\u7f6e\u83b7\u53d6&#xff09;<br \/>\n        business_importance &#061; self.get_business_importance(feature_name)<\/p>\n<p>        # \u8ba1\u7b97\u7efc\u5408\u5206\u6570<br \/>\n        priority_score &#061; (<br \/>\n            request_volume_score * 0.4 &#043;<br \/>\n            not_implemented_score * 0.4 &#043;<br \/>\n            business_importance * 0.2<br \/>\n        )<\/p>\n<p>        return priority_score<\/p>\n<p>    def generate_roadmap_recommendations(self) -&gt; List[Dict]:<br \/>\n        &#034;&#034;&#034;\u751f\u6210\u8def\u7ebf\u56fe\u5efa\u8bae&#034;&#034;&#034;<br \/>\n        recommendations &#061; []<\/p>\n<p>        for feature_name, metric in self.metrics.items():<br \/>\n            if metric.requests_not_implemented &gt; 0:<br \/>\n                score &#061; self.get_feature_priority_score(feature_name)<\/p>\n<p>                recommendation &#061; {<br \/>\n                    &#039;feature&#039;: feature_name,<br \/>\n                    &#039;priority_score&#039;: round(score, 2),<br \/>\n                    &#039;total_requests&#039;: metric.requests_total,<br \/>\n                    &#039;not_implemented_requests&#039;: metric.requests_not_implemented,<br \/>\n                    &#039;not_implemented_rate&#039;: round(metric.not_implemented_rate, 3),<br \/>\n                    &#039;recommendation&#039;: self.get_implementation_recommendation(score),<br \/>\n                    &#039;estimated_effort&#039;: self.estimate_implementation_effort(feature_name)<br \/>\n                }<\/p>\n<p>                recommendations.append(recommendation)<\/p>\n<p>        # \u6309\u4f18\u5148\u7ea7\u6392\u5e8f<br \/>\n        recommendations.sort(key&#061;lambda x: x[&#039;priority_score&#039;], reverse&#061;True)<br \/>\n        return recommendations<\/p>\n<h4>25.6 \u6700\u4f73\u5b9e\u8df5\u603b\u7ed3<\/h4>\n<h5>25.6.1 Do&#039;s and Don&#039;ts<\/h5>\n<p>\u5e94\u8be5\u505a&#xff1a;<\/p>\n<ul>\n<li>\n<p>\u2705 \u4e3a\u6240\u6709\u672a\u5b9e\u73b0\u7684\u529f\u80fd\u8fd4\u56de\u4e00\u81f4\u7684501\u54cd\u5e94<\/p>\n<\/li>\n<li>\n<p>\u2705 \u5728OPTIONS\u54cd\u5e94\u4e2d\u51c6\u786e\u5217\u51fa\u652f\u6301\u7684\u65b9\u6cd5<\/p>\n<\/li>\n<li>\n<p>\u2705 \u63d0\u4f9b\u6e05\u6670\u7684\u9519\u8bef\u4fe1\u606f\u548c\u6587\u6863\u94fe\u63a5<\/p>\n<\/li>\n<li>\n<p>\u2705 \u4f7f\u7528\u529f\u80fd\u6807\u8bb0\u7ba1\u7406\u5b9e\u9a8c\u6027\u529f\u80fd<\/p>\n<\/li>\n<li>\n<p>\u2705 \u8ffd\u8e2a501\u9519\u8bef\u7387\u4ee5\u6307\u5bfc\u4ea7\u54c1\u8def\u7ebf\u56fe<\/p>\n<\/li>\n<\/ul>\n<p>\u4e0d\u5e94\u8be5\u505a&#xff1a;<\/p>\n<ul>\n<li>\n<p>\u274c \u7528501\u54cd\u5e94\u66ff\u4ee3400\u3001404\u6216405<\/p>\n<\/li>\n<li>\n<p>\u274c \u5728\u672a\u5b9e\u73b0\u529f\u80fd\u4e0a\u4e0d\u63d0\u4f9b\u4efb\u4f55\u54cd\u5e94<\/p>\n<\/li>\n<li>\n<p>\u274c \u6df7\u6dc6&#034;\u672a\u5b9e\u73b0&#034;\u548c&#034;\u6682\u65f6\u4e0d\u53ef\u7528&#034;&#xff08;\u5e94\u8be5\u7528503&#xff09;<\/p>\n<\/li>\n<li>\n<p>\u274c \u5ffd\u7565Allow\u5934\u90e8\u7684\u51c6\u786e\u6027<\/p>\n<\/li>\n<li>\n<p>\u274c \u4e0d\u63d0\u4f9b\u529f\u80fd\u6f14\u8fdb\u7684\u65f6\u95f4\u8868<\/p>\n<\/li>\n<\/ul>\n<h5>25.6.2 \u6f14\u8fdb\u7b56\u7565\u5efa\u8bae<\/h5>\n<li>\n<p>\u900f\u660e\u6c9f\u901a&#xff1a;\u5411\u7528\u6237\u660e\u786e\u8bf4\u660e\u529f\u80fd\u72b6\u6001\u548c\u8ba1\u5212<\/p>\n<\/li>\n<li>\n<p>\u6e10\u8fdb\u5f0f\u53d1\u5e03&#xff1a;\u4f7f\u7528\u529f\u80fd\u6807\u8bb0\u63a7\u5236\u529f\u80fd\u66dd\u5149\u5ea6<\/p>\n<\/li>\n<li>\n<p>\u53cd\u9988\u5faa\u73af&#xff1a;\u57fa\u4e8e501\u8bf7\u6c42\u91cf\u8c03\u6574\u5f00\u53d1\u4f18\u5148\u7ea7<\/p>\n<\/li>\n<li>\n<p>\u5411\u540e\u517c\u5bb9&#xff1a;\u786e\u4fddAPI\u6f14\u8fdb\u4e0d\u5f71\u54cd\u73b0\u6709\u5ba2\u6237\u7aef<\/p>\n<\/li>\n<li>\n<p>\u76d1\u63a7\u9a71\u52a8&#xff1a;\u7528\u6570\u636e\u6307\u5bfc\u529f\u80fd\u5b9e\u73b0\u51b3\u7b56<\/p>\n<\/li>\n<p>\u901a\u8fc7\u7cfb\u7edf\u5316\u5730\u7ba1\u7406501\u72b6\u6001\u7801&#xff0c;API\u53ef\u4ee5\u63d0\u4f9b\u66f4\u597d\u7684\u5f00\u53d1\u8005\u4f53\u9a8c&#xff0c;\u540c\u65f6\u4e3a\u4ea7\u54c1\u56e2\u961f\u63d0\u4f9b\u6709\u4ef7\u503c\u7684\u6570\u636e\u6765\u6307\u5bfc\u529f\u80fd\u5f00\u53d1\u4f18\u5148\u7ea7\u3002<\/p>\n<hr \/>\n<h3>\u7b2c26\u7ae0&#xff1a;502 Bad Gateway &#8211; \u7f51\u5173\u9519\u8bef<\/h3>\n<h4>26.1 \u67b6\u6784\u89c6\u89d2\u6df1\u5ea6\u89e3\u6790<\/h4>\n<p>502 Bad Gateway\u00a0\u662f\u5206\u5e03\u5f0f\u7cfb\u7edf\u4e2d\u5e38\u89c1\u4f46\u590d\u6742\u7684\u9519\u8bef&#xff0c;\u8868\u660e\u4f5c\u4e3a\u7f51\u5173\u6216\u4ee3\u7406\u7684\u670d\u52a1\u5668\u4ece\u4e0a\u6e38\u670d\u52a1\u5668\u63a5\u6536\u5230\u65e0\u6548\u54cd\u5e94\u3002<\/p>\n<h5>26.1.1 \u7f51\u5173\u67b6\u6784\u4e2d\u7684\u89d2\u8272\u5b9a\u4f4d<\/h5>\n<p>text<\/p>\n<p>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502                    \u5ba2\u6237\u7aef\u8bf7\u6c42\u6d41                          \u2502<br \/>\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524<br \/>\n\u2502 1. \u5ba2\u6237\u7aef \u2192 \u8d1f\u8f7d\u5747\u8861\u5668 \u2192 \u53cd\u5411\u4ee3\u7406(Nginx) \u2192 \u5e94\u7528\u670d\u52a1\u5668    \u2502<br \/>\n\u2502    \u2191          \u2191              \u2191              \u2191           \u2502<br \/>\n\u2502    \u2502          \u2502              \u2502              \u2502           \u2502<br \/>\n\u2502 2. \u54cd\u5e94 \u2190    \u2190 502\u9519\u8bef\u53ef\u80fd\u53d1\u751f\u5728\u4efb\u610f \u2192 \u4e4b\u95f4 \u2192           \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/p>\n<p>\u5e38\u89c1502\u4ea7\u751f\u70b9&#xff1a;<br \/>\n\u2022 \u8d1f\u8f7d\u5747\u8861\u5668 \u2194 \u53cd\u5411\u4ee3\u7406 \u901a\u4fe1\u5931\u8d25<br \/>\n\u2022 \u53cd\u5411\u4ee3\u7406 \u2194 \u5e94\u7528\u670d\u52a1\u5668 \u8fde\u63a5\u95ee\u9898<br \/>\n\u2022 \u5e94\u7528\u670d\u52a1\u5668 \u2194 \u5fae\u670d\u52a1\/API \u8c03\u7528\u8d85\u65f6<br \/>\n\u2022 \u5fae\u670d\u52a1 \u2194 \u6570\u636e\u5e93\/\u7f13\u5b58 \u8fde\u63a5\u5f02\u5e38<\/p>\n<h5>26.1.2 \u4e0e\u76f8\u5173\u9519\u8bef\u7684\u7cbe\u786e\u533a\u5206<img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1510\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/07\/20260726181658-6a664f1a20358.png\" width=\"3056\" \/><\/h5>\n<h4>26.2 \u751f\u4ea7\u73af\u5883\u6545\u969c\u8bca\u65ad<\/h4>\n<h5>26.2.1 Nginx\u4f5c\u4e3a\u53cd\u5411\u4ee3\u7406\u7684\u5178\u578b\u573a\u666f<\/h5>\n<p>nginx<\/p>\n<p># Nginx\u914d\u7f6e\u793a\u4f8b\u53ca\u6f5c\u5728\u95ee\u9898\u70b9<br \/>\nupstream backend {<br \/>\n    # \u95ee\u98981&#xff1a;\u4e0d\u6070\u5f53\u7684\u5065\u5eb7\u68c0\u67e5<br \/>\n    server 10.0.1.1:8080 max_fails&#061;3 fail_timeout&#061;30s;<br \/>\n    server 10.0.1.2:8080 max_fails&#061;3 fail_timeout&#061;30s;<\/p>\n<p>    # \u5efa\u8bae\u914d\u7f6e&#xff1a;<br \/>\n    # server 10.0.1.1:8080 max_fails&#061;3 fail_timeout&#061;30s slow_start&#061;30s;<br \/>\n    # server 10.0.1.2:8080 backup;  # \u5907\u4efd\u670d\u52a1\u5668<br \/>\n}<\/p>\n<p>server {<br \/>\n    listen 80;<br \/>\n    server_name api.example.com;<\/p>\n<p>    # \u95ee\u98982&#xff1a;\u4ee3\u7406\u7f13\u51b2\u8bbe\u7f6e\u4e0d\u5f53<br \/>\n    proxy_buffering on;<br \/>\n    proxy_buffer_size 4k;<br \/>\n    proxy_buffers 8 4k;<br \/>\n    proxy_busy_buffers_size 8k;<\/p>\n<p>    # \u95ee\u98983&#xff1a;\u8d85\u65f6\u8bbe\u7f6e\u4e0d\u5408\u7406<br \/>\n    proxy_connect_timeout 5s;      # \u8fde\u63a5\u4e0a\u6e38\u8d85\u65f6<br \/>\n    proxy_send_timeout 60s;        # \u53d1\u9001\u8bf7\u6c42\u8d85\u65f6<br \/>\n    proxy_read_timeout 60s;        # \u8bfb\u53d6\u54cd\u5e94\u8d85\u65f6<\/p>\n<p>    # \u5173\u952e\u6539\u8fdb&#xff1a;\u542f\u7528\u8be6\u7ec6\u9519\u8bef\u65e5\u5fd7<br \/>\n    error_log \/var\/log\/nginx\/502_errors.log debug;<\/p>\n<p>    location \/api\/ {<br \/>\n        proxy_pass http:\/\/backend;<\/p>\n<p>        # \u6dfb\u52a0\u8bca\u65ad\u5934\u90e8<br \/>\n        proxy_set_header X-Real-IP $remote_addr;<br \/>\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br \/>\n        proxy_set_header X-Forwarded-Proto $scheme;<br \/>\n        proxy_set_header X-Request-ID $request_id;<\/p>\n<p>        # \u9519\u8bef\u9875\u9762\u5904\u7406<br \/>\n        error_page 502 &#061;503 \/maintenance.html;<\/p>\n<p>        # \u91cd\u8bd5\u673a\u5236<br \/>\n        proxy_next_upstream error timeout invalid_header http_502;<br \/>\n        proxy_next_upstream_tries 3;<br \/>\n        proxy_next_upstream_timeout 10s;<br \/>\n    }<\/p>\n<p>    # \u81ea\u5b9a\u4e49502\u9519\u8bef\u9875\u9762<br \/>\n    location &#061; \/maintenance.html {<br \/>\n        internal;<br \/>\n        root \/usr\/share\/nginx\/html;<br \/>\n    }<br \/>\n}<\/p>\n<h5>26.2.2 \u7cfb\u7edf\u5316\u8bca\u65ad\u811a\u672c<\/h5>\n<p>bash<\/p>\n<p>#!\/bin\/bash<br \/>\n# 502\u9519\u8bef\u5168\u65b9\u4f4d\u8bca\u65ad\u5de5\u5177<\/p>\n<p>echo &#034;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; 502 Bad Gateway \u8bca\u65ad\u62a5\u544a &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#034;<br \/>\necho &#034;\u751f\u6210\u65f6\u95f4: $(date)&#034;<br \/>\necho &#034;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#034;<\/p>\n<p># 1. \u7cfb\u7edf\u7ea7\u68c0\u67e5<br \/>\necho -e &#034;\\\\n1. \u7cfb\u7edf\u8d44\u6e90\u68c0\u67e5:&#034;<br \/>\necho &#034;\u5185\u5b58\u4f7f\u7528:&#034;<br \/>\nfree -h | grep -E &#034;^(Mem|Swap)&#034;<\/p>\n<p>echo -e &#034;\\\\nCPU\u8d1f\u8f7d:&#034;<br \/>\nuptime<br \/>\nmpstat -P ALL 1 1 | tail -n &#043;4<\/p>\n<p>echo -e &#034;\\\\n\u78c1\u76d8\u7a7a\u95f4:&#034;<br \/>\ndf -h | grep -E &#034;^\/dev&#034;<\/p>\n<p># 2. \u7f51\u7edc\u8fde\u63a5\u68c0\u67e5<br \/>\necho -e &#034;\\\\n2. \u7f51\u7edc\u8fde\u63a5\u72b6\u6001:&#034;<br \/>\necho &#034;\u8fde\u63a5\u6570\u7edf\u8ba1:&#034;<br \/>\nss -s | head -5<\/p>\n<p>echo -e &#034;\\\\nNginx\u8fde\u63a5\u72b6\u6001:&#034;<br \/>\nnetstat -an | grep &#039;:80&#039; | awk &#039;{print $6}&#039; | sort | uniq -c | sort -rn<\/p>\n<p># 3. Nginx\u7279\u5b9a\u68c0\u67e5<br \/>\necho -e &#034;\\\\n3. Nginx\u72b6\u6001\u68c0\u67e5:&#034;<br \/>\nif systemctl is-active nginx &gt;\/dev\/null 2&gt;&amp;1; then<br \/>\n    echo &#034;Nginx\u8fd0\u884c\u72b6\u6001: ACTIVE&#034;<\/p>\n<p>    # \u68c0\u67e5Nginx\u9519\u8bef\u65e5\u5fd7\u4e2d\u7684502\u9519\u8bef<br \/>\n    echo -e &#034;\\\\n\u6700\u8fd1502\u9519\u8bef:&#034;<br \/>\n    tail -100 \/var\/log\/nginx\/error.log | grep -i &#034;502&#034; | head -10<\/p>\n<p>    # \u68c0\u67e5\u4e0a\u6e38\u670d\u52a1\u5668\u72b6\u6001<br \/>\n    echo -e &#034;\\\\n\u4e0a\u6e38\u670d\u52a1\u5668\u68c0\u67e5:&#034;<br \/>\n    upstream_servers&#061;$(grep -r &#034;server &#034; \/etc\/nginx\/conf.d\/* | grep -v &#034;#&#034; | awk &#039;{print $2}&#039;)<br \/>\n    for server in $upstream_servers; do<br \/>\n        echo -n &#034;\u68c0\u67e5 $server &#8230; &#034;<br \/>\n        if timeout 2 nc -z ${server%:*} ${server#*:} 2&gt;\/dev\/null; then<br \/>\n            echo &#034;\u2713 \u53ef\u8fbe&#034;<br \/>\n        else<br \/>\n            echo &#034;\u2717 \u4e0d\u53ef\u8fbe&#034;<br \/>\n        fi<br \/>\n    done<\/p>\n<p>    # Nginx\u6d3b\u52a8\u8fde\u63a5<br \/>\n    echo -e &#034;\\\\nNginx\u6d3b\u52a8\u8fde\u63a5\u7edf\u8ba1:&#034;<br \/>\n    curl -s http:\/\/127.0.0.1\/nginx_status 2&gt;\/dev\/null || \\\\<br \/>\n    echo &#034;Nginx\u72b6\u6001\u9875\u9762\u672a\u542f\u7528&#034;<br \/>\nelse<br \/>\n    echo &#034;Nginx\u8fd0\u884c\u72b6\u6001: INACTIVE&#034;<br \/>\nfi<\/p>\n<p># 4. \u5e94\u7528\u670d\u52a1\u5668\u68c0\u67e5<br \/>\necho -e &#034;\\\\n4. \u5e94\u7528\u670d\u52a1\u5668\u68c0\u67e5:&#034;<br \/>\ncheck_service() {<br \/>\n    local service&#061;$1<br \/>\n    local port&#061;$2<\/p>\n<p>    echo -n &#034;\u68c0\u67e5 $service (\u7aef\u53e3 $port) &#8230; &#034;<br \/>\n    if systemctl is-active $service &gt;\/dev\/null 2&gt;&amp;1; then<br \/>\n        echo -n &#034;\u670d\u52a1\u6d3b\u8dc3 &#034;<br \/>\n        if ss -tln | grep &#034;:$port &#034; &gt;\/dev\/null; then<br \/>\n            echo &#034;\u2713 \u76d1\u542c\u4e2d&#034;<br \/>\n        else<br \/>\n            echo &#034;\u2717 \u672a\u76d1\u542c\u7aef\u53e3&#034;<br \/>\n        fi<br \/>\n    else<br \/>\n        echo &#034;\u2717 \u670d\u52a1\u672a\u8fd0\u884c&#034;<br \/>\n    fi<br \/>\n}<\/p>\n<p># \u5e38\u89c1\u5e94\u7528\u670d\u52a1\u5668\u68c0\u67e5<br \/>\ncheck_service &#034;php-fpm&#034; 9000<br \/>\ncheck_service &#034;tomcat&#034; 8080<br \/>\ncheck_service &#034;node&#034; 3000<br \/>\ncheck_service &#034;gunicorn&#034; 8000<\/p>\n<p># 5. \u9632\u706b\u5899\u68c0\u67e5<br \/>\necho -e &#034;\\\\n5. \u9632\u706b\u5899\u89c4\u5219\u68c0\u67e5:&#034;<br \/>\nif command -v ufw &gt;\/dev\/null 2&gt;&amp;1; then<br \/>\n    echo &#034;UFW\u72b6\u6001:&#034;<br \/>\n    ufw status verbose | head -10<br \/>\nelif command -v firewall-cmd &gt;\/dev\/null 2&gt;&amp;1; then<br \/>\n    echo &#034;FirewallD\u72b6\u6001:&#034;<br \/>\n    firewall-cmd &#8211;list-all | head -20<br \/>\nelse<br \/>\n    echo &#034;\u4f7f\u7528iptables:&#034;<br \/>\n    iptables -L -n | grep -E &#034;(80|443|8080|9000)&#034; | head -10<br \/>\nfi<\/p>\n<p># 6. DNS\u89e3\u6790\u68c0\u67e5<br \/>\necho -e &#034;\\\\n6. DNS\u89e3\u6790\u68c0\u67e5:&#034;<br \/>\nupstream_hosts&#061;$(grep -r &#034;proxy_pass&#034; \/etc\/nginx\/conf.d\/* | grep -v &#034;#&#034; | awk &#039;{print $2}&#039; | cut -d&#039;\/&#039; -f3 | cut -d&#039;:&#039; -f1 | sort -u)<br \/>\nfor host in $upstream_hosts; do<br \/>\n    if [[ $host &#061;~ ^[0-9]&#043;\\\\.[0-9]&#043;\\\\.[0-9]&#043;\\\\.[0-9]&#043;$ ]]; then<br \/>\n        continue<br \/>\n    fi<br \/>\n    echo -n &#034;\u89e3\u6790 $host &#8230; &#034;<br \/>\n    dig &#043;short $host | head -1 | xargs echo<br \/>\ndone<\/p>\n<p># 7. SSL\/TLS\u68c0\u67e5&#xff08;\u5982\u679c\u4f7f\u7528HTTPS&#xff09;<br \/>\necho -e &#034;\\\\n7. SSL\/TLS\u68c0\u67e5:&#034;<br \/>\nif grep -r &#034;ssl_certificate&#034; \/etc\/nginx\/conf.d\/* &gt;\/dev\/null 2&gt;&amp;1; then<br \/>\n    echo &#034;\u68c0\u6d4b\u5230SSL\u914d\u7f6e&#034;<br \/>\n    for cert in $(grep -r &#034;ssl_certificate &#034; \/etc\/nginx\/conf.d\/* | awk &#039;{print $2}&#039; | tr -d &#039;;&#039;); do<br \/>\n        if [ -f &#034;$cert&#034; ]; then<br \/>\n            echo &#034;\u8bc1\u4e66 $cert \u6709\u6548\u671f:&#034;<br \/>\n            openssl x509 -in &#034;$cert&#034; -noout -dates 2&gt;\/dev\/null || echo &#034;\u65e0\u6548\u8bc1\u4e66&#034;<br \/>\n        fi<br \/>\n    done<br \/>\nfi<\/p>\n<p>echo -e &#034;\\\\n&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#034;<br \/>\necho &#034;\u8bca\u65ad\u5b8c\u6210\u3002\u68c0\u67e5\u4ee5\u4e0a\u8f93\u51fa\u5bfb\u627e\u6f5c\u5728\u95ee\u9898\u3002&#034;<\/p>\n<h4>26.3 \u9ad8\u53ef\u7528\u67b6\u6784\u89e3\u51b3\u65b9\u6848<\/h4>\n<h5>26.3.1 \u667a\u80fd\u5065\u5eb7\u68c0\u67e5\u914d\u7f6e<\/h5>\n<p>yaml<\/p>\n<p># Kubernetes Ingress\u5065\u5eb7\u68c0\u67e5\u914d\u7f6e\u793a\u4f8b<br \/>\napiVersion: networking.k8s.io\/v1<br \/>\nkind: Ingress<br \/>\nmetadata:<br \/>\n  name: api-ingress<br \/>\n  annotations:<br \/>\n    # Nginx Ingress\u63a7\u5236\u5668\u914d\u7f6e<br \/>\n    nginx.ingress.kubernetes.io\/upstream-hash-by: &#034;$request_uri&#034;<br \/>\n    nginx.ingress.kubernetes.io\/load-balance: &#034;ewma&#034;<\/p>\n<p>    # \u5065\u5eb7\u68c0\u67e5\u914d\u7f6e<br \/>\n    nginx.ingress.kubernetes.io\/health-check: &#034;true&#034;<br \/>\n    nginx.ingress.kubernetes.io\/health-check-path: &#034;\/health&#034;<br \/>\n    nginx.ingress.kubernetes.io\/health-check-interval: &#034;30s&#034;<br \/>\n    nginx.ingress.kubernetes.io\/health-check-timeout: &#034;5s&#034;<br \/>\n    nginx.ingress.kubernetes.io\/health-check-expected-statuses: &#034;200,204&#034;<br \/>\n    nginx.ingress.kubernetes.io\/health-check-max-fails: &#034;3&#034;<br \/>\n    nginx.ingress.kubernetes.io\/health-check-fail-timeout: &#034;60s&#034;<\/p>\n<p>    # \u6162\u542f\u52a8\u914d\u7f6e<br \/>\n    nginx.ingress.kubernetes.io\/upstream-slow-start: &#034;30s&#034;<\/p>\n<p>    # \u8fde\u63a5\u7ba1\u7406<br \/>\n    nginx.ingress.kubernetes.io\/upstream-keepalive-connections: &#034;100&#034;<br \/>\n    nginx.ingress.kubernetes.io\/upstream-keepalive-timeout: &#034;60s&#034;<br \/>\n    nginx.ingress.kubernetes.io\/upstream-keepalive-requests: &#034;1000&#034;<\/p>\n<p>spec:<br \/>\n  ingressClassName: nginx<br \/>\n  rules:<br \/>\n  &#8211; host: api.example.com<br \/>\n    http:<br \/>\n      paths:<br \/>\n      &#8211; path: \/<br \/>\n        pathType: Prefix<br \/>\n        backend:<br \/>\n          service:<br \/>\n            name: api-service<br \/>\n            port:<br \/>\n              number: 8080<\/p>\n<h5>26.3.2 \u591a\u7ea7\u6545\u969c\u8f6c\u79fb\u7b56\u7565<\/h5>\n<p>python<\/p>\n<p># Python\u7f51\u5173\u6545\u969c\u8f6c\u79fb\u5b9e\u73b0<br \/>\nimport asyncio<br \/>\nimport random<br \/>\nfrom typing import List, Optional<br \/>\nfrom dataclasses import dataclass<br \/>\nfrom enum import Enum<br \/>\nimport aiohttp<br \/>\nfrom statsd import StatsClient<br \/>\nimport redis<\/p>\n<p>class ServerHealth(Enum):<br \/>\n    HEALTHY &#061; &#034;healthy&#034;<br \/>\n    UNHEALTHY &#061; &#034;unhealthy&#034;<br \/>\n    DEGRADED &#061; &#034;degraded&#034;<br \/>\n    UNKNOWN &#061; &#034;unknown&#034;<\/p>\n<p>&#064;dataclass<br \/>\nclass UpstreamServer:<br \/>\n    url: str<br \/>\n    weight: int &#061; 1<br \/>\n    current_connections: int &#061; 0<br \/>\n    health: ServerHealth &#061; ServerHealth.UNKNOWN<br \/>\n    failure_count: int &#061; 0<br \/>\n    last_failure: Optional[float] &#061; None<br \/>\n    response_time_avg: float &#061; 0.0<br \/>\n    success_rate: float &#061; 1.0<\/p>\n<p>class IntelligentLoadBalancer:<br \/>\n    def __init__(self, upstreams: List[UpstreamServer]):<br \/>\n        self.upstreams &#061; upstreams<br \/>\n        self.statsd &#061; StatsClient()<br \/>\n        self.redis &#061; redis.Redis(host&#061;&#039;localhost&#039;, port&#061;6379, db&#061;0)<br \/>\n        self.circuit_breaker_threshold &#061; 5<br \/>\n        self.recovery_time &#061; 300  # 5\u5206\u949f<\/p>\n<p>    async def health_check(self):<br \/>\n        &#034;&#034;&#034;\u5b9a\u671f\u5065\u5eb7\u68c0\u67e5&#034;&#034;&#034;<br \/>\n        for server in self.upstreams:<br \/>\n            try:<br \/>\n                async with aiohttp.ClientSession() as session:<br \/>\n                    start_time &#061; asyncio.get_event_loop().time()<\/p>\n<p>                    async with session.get(<br \/>\n                        f&#034;{server.url}\/health&#034;,<br \/>\n                        timeout&#061;aiohttp.ClientTimeout(total&#061;5)<br \/>\n                    ) as response:<br \/>\n                        response_time &#061; asyncio.get_event_loop().time() &#8211; start_time<\/p>\n<p>                        if response.status &#061;&#061; 200:<br \/>\n                            health_data &#061; await response.json()<\/p>\n<p>                            # \u57fa\u4e8e\u54cd\u5e94\u66f4\u65b0\u670d\u52a1\u5668\u72b6\u6001<br \/>\n                            self.update_server_health(<br \/>\n                                server,<br \/>\n                                healthy&#061;True,<br \/>\n                                response_time&#061;response_time,<br \/>\n                                load&#061;health_data.get(&#039;load&#039;, 0)<br \/>\n                            )<br \/>\n                        else:<br \/>\n                            self.record_failure(server)<\/p>\n<p>            except (aiohttp.ClientError, asyncio.TimeoutError):<br \/>\n                self.record_failure(server)<\/p>\n<p>    def record_failure(self, server: UpstreamServer):<br \/>\n        &#034;&#034;&#034;\u8bb0\u5f55\u670d\u52a1\u5668\u6545\u969c&#034;&#034;&#034;<br \/>\n        server.failure_count &#043;&#061; 1<br \/>\n        server.last_failure &#061; asyncio.get_event_loop().time()<\/p>\n<p>        # \u66f4\u65b0\u6210\u529f\u7387<br \/>\n        total_requests &#061; self.redis.incr(f&#034;server:{server.url}:total&#034;)<br \/>\n        failures &#061; self.redis.incr(f&#034;server:{server.url}:failures&#034;)<br \/>\n        server.success_rate &#061; 1 &#8211; (failures \/ total_requests)<\/p>\n<p>        # \u68c0\u67e5\u662f\u5426\u9700\u8981\u7194\u65ad<br \/>\n        if server.failure_count &gt;&#061; self.circuit_breaker_threshold:<br \/>\n            server.health &#061; ServerHealth.UNHEALTHY<br \/>\n            self.statsd.incr(f&#034;servers.circuit_open.{server.url}&#034;)<\/p>\n<p>            # \u8bbe\u7f6e\u6062\u590d\u5b9a\u65f6\u5668<br \/>\n            asyncio.create_task(self.attempt_recovery(server))<\/p>\n<p>    async def attempt_recovery(self, server: UpstreamServer):<br \/>\n        &#034;&#034;&#034;\u5c1d\u8bd5\u6062\u590d\u6545\u969c\u670d\u52a1\u5668&#034;&#034;&#034;<br \/>\n        await asyncio.sleep(self.recovery_time)<\/p>\n<p>        # \u534a\u5f00\u72b6\u6001\u6d4b\u8bd5<br \/>\n        try:<br \/>\n            async with aiohttp.ClientSession() as session:<br \/>\n                async with session.get(<br \/>\n                    f&#034;{server.url}\/health\/light&#034;,<br \/>\n                    timeout&#061;aiohttp.ClientTimeout(total&#061;2)<br \/>\n                ) as response:<br \/>\n                    if response.status &#061;&#061; 200:<br \/>\n                        server.failure_count &#061; 0<br \/>\n                        server.health &#061; ServerHealth.HEALTHY<br \/>\n                        self.statsd.incr(f&#034;servers.circuit_closed.{server.url}&#034;)<br \/>\n        except:<br \/>\n            # \u6d4b\u8bd5\u5931\u8d25&#xff0c;\u4fdd\u6301\u7194\u65ad<br \/>\n            pass<\/p>\n<p>    def select_server(self) -&gt; Optional[UpstreamServer]:<br \/>\n        &#034;&#034;&#034;\u667a\u80fd\u9009\u62e9\u670d\u52a1\u5668&#034;&#034;&#034;<br \/>\n        candidates &#061; []<\/p>\n<p>        for server in self.upstreams:<br \/>\n            # \u8df3\u8fc7\u4e0d\u5065\u5eb7\u7684\u670d\u52a1\u5668<br \/>\n            if server.health &#061;&#061; ServerHealth.UNHEALTHY:<br \/>\n                continue<\/p>\n<p>            # \u6839\u636e\u6743\u91cd\u3001\u8d1f\u8f7d\u548c\u6210\u529f\u7387\u8ba1\u7b97\u9009\u62e9\u6982\u7387<br \/>\n            base_weight &#061; server.weight<\/p>\n<p>            # \u6210\u529f\u7387\u8c03\u6574&#xff08;\u6210\u529f\u7387\u4f4e\u5219\u964d\u4f4e\u6743\u91cd&#xff09;<br \/>\n            success_adjustment &#061; server.success_rate<\/p>\n<p>            # \u8fde\u63a5\u6570\u8c03\u6574&#xff08;\u8fde\u63a5\u6570\u591a\u5219\u964d\u4f4e\u6743\u91cd&#xff09;<br \/>\n            connection_adjustment &#061; 1 \/ (1 &#043; server.current_connections * 0.1)<\/p>\n<p>            # \u54cd\u5e94\u65f6\u95f4\u8c03\u6574&#xff08;\u54cd\u5e94\u6162\u5219\u964d\u4f4e\u6743\u91cd&#xff09;<br \/>\n            response_adjustment &#061; 1 \/ (1 &#043; server.response_time_avg * 0.1)<\/p>\n<p>            effective_weight &#061; (<br \/>\n                base_weight *<br \/>\n                success_adjustment *<br \/>\n                connection_adjustment *<br \/>\n                response_adjustment<br \/>\n            )<\/p>\n<p>            if effective_weight &gt; 0:<br \/>\n                candidates.append((server, effective_weight))<\/p>\n<p>        if not candidates:<br \/>\n            return None<\/p>\n<p>        # \u52a0\u6743\u968f\u673a\u9009\u62e9<br \/>\n        total_weight &#061; sum(w for _, w in candidates)<br \/>\n        r &#061; random.uniform(0, total_weight)<br \/>\n        cumulative &#061; 0<\/p>\n<p>        for server, weight in candidates:<br \/>\n            cumulative &#043;&#061; weight<br \/>\n            if r &lt;&#061; cumulative:<br \/>\n                return server<\/p>\n<p>        return candidates[0][0]<\/p>\n<p>    async def proxy_request(self, request):<br \/>\n        &#034;&#034;&#034;\u4ee3\u7406\u8bf7\u6c42\u5230\u9009\u4e2d\u7684\u670d\u52a1\u5668&#034;&#034;&#034;<br \/>\n        server &#061; self.select_server()<\/p>\n<p>        if not server:<br \/>\n            # \u6240\u6709\u670d\u52a1\u5668\u90fd\u4e0d\u53ef\u7528<br \/>\n            self.statsd.incr(&#034;proxy.all_servers_unavailable&#034;)<br \/>\n            return self.create_502_response()<\/p>\n<p>        try:<br \/>\n            server.current_connections &#043;&#061; 1<br \/>\n            self.statsd.incr(f&#034;server.connections.active.{server.url}&#034;)<\/p>\n<p>            # \u8f6c\u53d1\u8bf7\u6c42<br \/>\n            response &#061; await self.forward_request(server, request)<\/p>\n<p>            # \u8bb0\u5f55\u6210\u529f<br \/>\n            self.record_success(server)<br \/>\n            return response<\/p>\n<p>        except Exception as e:<br \/>\n            # \u8bb0\u5f55\u5931\u8d25<br \/>\n            self.record_failure(server)<br \/>\n            self.statsd.incr(f&#034;proxy.errors.{type(e).__name__}&#034;)<\/p>\n<p>            # \u5c1d\u8bd5\u6545\u969c\u8f6c\u79fb<br \/>\n            return await self.failover_request(request, server)<\/p>\n<p>        finally:<br \/>\n            server.current_connections -&#061; 1<\/p>\n<p>    async def failover_request(self, request, failed_server):<br \/>\n        &#034;&#034;&#034;\u6545\u969c\u8f6c\u79fb\u903b\u8f91&#034;&#034;&#034;<br \/>\n        # \u6807\u8bb0\u539f\u59cb\u670d\u52a1\u5668\u4e3a\u6682\u65f6\u4e0d\u53ef\u7528<br \/>\n        failed_server.health &#061; ServerHealth.DEGRADED<\/p>\n<p>        # \u91cd\u8bd5\u903b\u8f91<br \/>\n        for attempt in range(2):  # \u6700\u591a\u91cd\u8bd52\u6b21<br \/>\n            server &#061; self.select_server()<\/p>\n<p>            if server and server !&#061; failed_server:<br \/>\n                try:<br \/>\n                    return await self.forward_request(server, request)<br \/>\n                except Exception:<br \/>\n                    continue<\/p>\n<p>        # \u6240\u6709\u91cd\u8bd5\u5931\u8d25<br \/>\n        return self.create_502_response()<\/p>\n<p>    def create_502_response(self):<br \/>\n        &#034;&#034;&#034;\u521b\u5efa\u6807\u51c6\u5316\u7684502\u54cd\u5e94&#034;&#034;&#034;<br \/>\n        return {<br \/>\n            &#034;status&#034;: 502,<br \/>\n            &#034;headers&#034;: {<br \/>\n                &#034;Content-Type&#034;: &#034;application\/json&#034;,<br \/>\n                &#034;Retry-After&#034;: &#034;30&#034;<br \/>\n            },<br \/>\n            &#034;body&#034;: {<br \/>\n                &#034;error&#034;: {<br \/>\n                    &#034;code&#034;: &#034;bad_gateway&#034;,<br \/>\n                    &#034;message&#034;: &#034;Unable to connect to upstream server&#034;,<br \/>\n                    &#034;details&#034;: {<br \/>\n                        &#034;timestamp&#034;: asyncio.get_event_loop().time(),<br \/>\n                        &#034;healthy_servers&#034;: len([s for s in self.upstreams<br \/>\n                                              if s.health &#061;&#061; ServerHealth.HEALTHY]),<br \/>\n                        &#034;suggested_actions&#034;: [<br \/>\n                            &#034;Please try again in 30 seconds&#034;,<br \/>\n                            &#034;Check service status at status.example.com&#034;<br \/>\n                        ]<br \/>\n                    }<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<h4>26.4 \u76d1\u63a7\u4e0e\u544a\u8b66\u4f53\u7cfb<\/h4>\n<h5>26.4.1 \u5168\u9762\u7684\u6307\u6807\u6536\u96c6<\/h5>\n<p>yaml<\/p>\n<p># Prometheus\u76d1\u63a7\u914d\u7f6e<br \/>\nscrape_configs:<br \/>\n  &#8211; job_name: &#039;nginx&#039;<br \/>\n    static_configs:<br \/>\n      &#8211; targets: [&#039;nginx:9113&#039;]<\/p>\n<p>  &#8211; job_name: &#039;upstream_servers&#039;<br \/>\n    static_configs:<br \/>\n      &#8211; targets:<br \/>\n        &#8211; &#039;app1:8080&#039;<br \/>\n        &#8211; &#039;app2:8080&#039;<br \/>\n        &#8211; &#039;app3:8080&#039;<br \/>\n    metrics_path: &#039;\/metrics&#039;<\/p>\n<p>  &#8211; job_name: &#039;gateway&#039;<br \/>\n    static_configs:<br \/>\n      &#8211; targets: [&#039;gateway:9090&#039;]<\/p>\n<p># \u544a\u8b66\u89c4\u5219<br \/>\ngroups:<br \/>\n  &#8211; name: gateway_alerts<br \/>\n    rules:<br \/>\n      &#8211; alert: High502ErrorRate<br \/>\n        expr: |<br \/>\n          rate(<br \/>\n            nginx_http_requests_total{status&#061;&#034;502&#034;}[5m]<br \/>\n          ) \/ rate(<br \/>\n            nginx_http_requests_total[5m]<br \/>\n          ) &gt; 0.01<br \/>\n        for: 2m<br \/>\n        labels:<br \/>\n          severity: critical<br \/>\n          component: gateway<br \/>\n        annotations:<br \/>\n          summary: &#034;High rate of 502 errors&#034;<br \/>\n          description: |<br \/>\n            502\u9519\u8bef\u7387\u8d85\u8fc71%&#xff0c;\u5f53\u524d\u503c: {{ $value | humanizePercentage }}<br \/>\n            \u53d7\u5f71\u54cd\u7684upstream: {{ $labels.upstream }}<\/p>\n<p>      &#8211; alert: UpstreamServerDown<br \/>\n        expr: |<br \/>\n          up{job&#061;&#034;upstream_servers&#034;} &#061;&#061; 0<br \/>\n        for: 1m<br \/>\n        labels:<br \/>\n          severity: warning<br \/>\n          component: upstream<br \/>\n        annotations:<br \/>\n          summary: &#034;Upstream server is down&#034;<br \/>\n          description: &#034;{{ $labels.instance }} is not responding&#034;<\/p>\n<p>      &#8211; alert: HighUpstreamResponseTime<br \/>\n        expr: |<br \/>\n          histogram_quantile(0.95,<br \/>\n            rate(upstream_response_time_seconds_bucket[5m])<br \/>\n          ) &gt; 2<br \/>\n        for: 5m<br \/>\n        labels:<br \/>\n          severity: warning<br \/>\n          component: upstream<br \/>\n        annotations:<br \/>\n          summary: &#034;High upstream response time&#034;<br \/>\n          description: |<br \/>\n            95%\u7684\u54cd\u5e94\u65f6\u95f4\u8d85\u8fc72\u79d2<br \/>\n            \u5f53\u524d\u503c: {{ $value }}\u79d2<\/p>\n<h5>26.4.2 \u5206\u5e03\u5f0f\u8ffd\u8e2a\u96c6\u6210<\/h5>\n<p>python<\/p>\n<p># OpenTelemetry\u8ffd\u8e2a\u96c6\u6210<br \/>\nfrom opentelemetry import trace<br \/>\nfrom opentelemetry.exporter.jaeger.thrift import JaegerExporter<br \/>\nfrom opentelemetry.sdk.trace import TracerProvider<br \/>\nfrom opentelemetry.sdk.trace.export import BatchSpanProcessor<br \/>\nfrom opentelemetry.instrumentation.requests import RequestsInstrumentor<\/p>\n<p># \u8bbe\u7f6e\u8ffd\u8e2a<br \/>\ntrace.set_tracer_provider(TracerProvider())<br \/>\ntracer &#061; trace.get_tracer(__name__)<\/p>\n<p># Jaeger\u5bfc\u51fa\u5668<br \/>\njaeger_exporter &#061; JaegerExporter(<br \/>\n    agent_host_name&#061;&#034;jaeger&#034;,<br \/>\n    agent_port&#061;6831,<br \/>\n)<br \/>\ntrace.get_tracer_provider().add_span_processor(<br \/>\n    BatchSpanProcessor(jaeger_exporter)<br \/>\n)<\/p>\n<p># \u81ea\u52a8instrument\u8bf7\u6c42\u5e93<br \/>\nRequestsInstrumentor().instrument()<\/p>\n<p>class TracedGateway:<br \/>\n    def __init__(self):<br \/>\n        self.tracer &#061; trace.get_tracer(&#034;gateway.service&#034;)<\/p>\n<p>    async def handle_request(self, request):<br \/>\n        # \u521b\u5efa\u5206\u5e03\u5f0f\u8ffd\u8e2aspan<br \/>\n        with self.tracer.start_as_current_span(&#034;gateway.proxy&#034;) as span:<br \/>\n            span.set_attribute(&#034;http.method&#034;, request.method)<br \/>\n            span.set_attribute(&#034;http.url&#034;, request.url)<br \/>\n            span.set_attribute(&#034;http.user_agent&#034;, request.headers.get(&#039;User-Agent&#039;))<\/p>\n<p>            try:<br \/>\n                # \u6dfb\u52a0\u8ffd\u8e2a\u5934\u90e8<br \/>\n                headers &#061; dict(request.headers)<br \/>\n                trace.instrumentation.utils._add_header(<br \/>\n                    headers,<br \/>\n                    span.get_span_context()<br \/>\n                )<\/p>\n<p>                # \u8f6c\u53d1\u8bf7\u6c42<br \/>\n                response &#061; await self.proxy_request(request, headers)<\/p>\n<p>                span.set_attribute(&#034;http.status_code&#034;, response.status)<br \/>\n                span.set_status(trace.Status(trace.StatusCode.OK))<\/p>\n<p>                return response<\/p>\n<p>            except Exception as e:<br \/>\n                span.set_status(trace.Status(<br \/>\n                    trace.StatusCode.ERROR,<br \/>\n                    str(e)<br \/>\n                ))<br \/>\n                span.record_exception(e)<\/p>\n<p>                # \u8bb0\u5f55502\u9519\u8bef<br \/>\n                span.set_attribute(&#034;error.type&#034;, &#034;bad_gateway&#034;)<br \/>\n                span.set_attribute(&#034;error.retryable&#034;, True)<\/p>\n<p>                raise<\/p>\n<h4>26.5 \u9884\u9632\u4e0e\u4f18\u5316\u7b56\u7565<\/h4>\n<h5>26.5.1 \u8fde\u63a5\u6c60\u4f18\u5316\u914d\u7f6e<\/h5>\n<p>java<\/p>\n<p>\/\/ Java\u8fde\u63a5\u6c60\u4f18\u5316\u793a\u4f8b<br \/>\n&#064;Configuration<br \/>\npublic class ConnectionPoolConfig {<\/p>\n<p>    &#064;Bean<br \/>\n    public HttpClient httpClient() {<br \/>\n        return HttpClient.create()<br \/>\n            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)<br \/>\n            .option(ChannelOption.SO_KEEPALIVE, true)<\/p>\n<p>            \/\/ \u8fde\u63a5\u6c60\u914d\u7f6e<br \/>\n            .connectionProvider(<br \/>\n                ConnectionProvider.builder(&#034;custom&#034;)<br \/>\n                    .maxConnections(500)                    \/\/ \u6700\u5927\u8fde\u63a5\u6570<br \/>\n                    .pendingAcquireTimeout(Duration.ofSeconds(60))  \/\/ \u83b7\u53d6\u8fde\u63a5\u8d85\u65f6<br \/>\n                    .pendingAcquireMaxCount(-1)             \/\/ \u65e0\u9650\u5236\u7b49\u5f85\u961f\u5217<br \/>\n                    .maxIdleTime(Duration.ofSeconds(30))    \/\/ \u6700\u5927\u7a7a\u95f2\u65f6\u95f4<br \/>\n                    .maxLifeTime(Duration.ofMinutes(5))     \/\/ \u8fde\u63a5\u6700\u5927\u751f\u5b58\u65f6\u95f4<br \/>\n                    .evictInBackground(Duration.ofSeconds(120)) \/\/ \u540e\u53f0\u6e05\u7406\u95f4\u9694<br \/>\n                    .metrics(true)                          \/\/ \u542f\u7528\u6307\u6807<br \/>\n                    .build()<br \/>\n            )<\/p>\n<p>            \/\/ \u54cd\u5e94\u8d85\u65f6<br \/>\n            .responseTimeout(Duration.ofSeconds(30))<\/p>\n<p>            \/\/ \u91cd\u8bd5\u7b56\u7565<br \/>\n            .doOnConnected(conn -&gt;<br \/>\n                conn.addHandlerLast(new ReadTimeoutHandler(30))<br \/>\n            );<br \/>\n    }<\/p>\n<p>    &#064;Bean<br \/>\n    public WebClient webClient(HttpClient httpClient) {<br \/>\n        return WebClient.builder()<br \/>\n            .clientConnector(new ReactorClientHttpConnector(httpClient))<\/p>\n<p>            \/\/ \u9ed8\u8ba4\u8fc7\u6ee4\u5668<br \/>\n            .filter((request, next) -&gt; {<br \/>\n                long startTime &#061; System.nanoTime();<\/p>\n<p>                return next.exchange(request)<br \/>\n                    .doOnSuccess(response -&gt; {<br \/>\n                        long duration &#061; System.nanoTime() &#8211; startTime;<br \/>\n                        logMetric(request, response, duration);<br \/>\n                    })<br \/>\n                    .doOnError(error -&gt; {<br \/>\n                        long duration &#061; System.nanoTime() &#8211; startTime;<br \/>\n                        logError(request, error, duration);<br \/>\n                    });<br \/>\n            })<br \/>\n            .build();<br \/>\n    }<br \/>\n}<\/p>\n<h5>26.5.2 \u5bb9\u91cf\u89c4\u5212\u4e0e\u81ea\u52a8\u6269\u5c55<\/h5>\n<p>python<\/p>\n<p># \u57fa\u4e8e\u9884\u6d4b\u7684\u81ea\u52a8\u6269\u5c55\u7b56\u7565<br \/>\nfrom sklearn.ensemble import RandomForestRegressor<br \/>\nimport numpy as np<br \/>\nfrom datetime import datetime, timedelta<\/p>\n<p>class PredictiveScaler:<br \/>\n    def __init__(self):<br \/>\n        self.model &#061; RandomForestRegressor(n_estimators&#061;100)<br \/>\n        self.historical_data &#061; []<br \/>\n        self.retrain_interval &#061; 3600  # \u6bcf\u5c0f\u65f6\u91cd\u8bad\u7ec3\u4e00\u6b21<br \/>\n        self.last_retrain &#061; 0<\/p>\n<p>    def collect_metrics(self, timestamp, metrics):<br \/>\n        &#034;&#034;&#034;\u6536\u96c6\u6027\u80fd\u6307\u6807&#034;&#034;&#034;<br \/>\n        data_point &#061; {<br \/>\n            &#039;timestamp&#039;: timestamp,<br \/>\n            &#039;request_rate&#039;: metrics[&#039;requests_per_second&#039;],<br \/>\n            &#039;avg_response_time&#039;: metrics[&#039;avg_response_time_ms&#039;],<br \/>\n            &#039;error_rate&#039;: metrics[&#039;error_rate&#039;],<br \/>\n            &#039;active_connections&#039;: metrics[&#039;active_connections&#039;],<br \/>\n            &#039;cpu_usage&#039;: metrics[&#039;cpu_percent&#039;],<br \/>\n            &#039;memory_usage&#039;: metrics[&#039;memory_percent&#039;]<br \/>\n        }<br \/>\n        self.historical_data.append(data_point)<\/p>\n<p>        # \u4fdd\u6301\u6700\u8fd124\u5c0f\u65f6\u6570\u636e<br \/>\n        cutoff &#061; timestamp &#8211; timedelta(hours&#061;24)<br \/>\n        self.historical_data &#061; [<br \/>\n            d for d in self.historical_data<br \/>\n            if d[&#039;timestamp&#039;] &gt; cutoff<br \/>\n        ]<\/p>\n<p>    def predict_load(self, lookahead_minutes&#061;30):<br \/>\n        &#034;&#034;&#034;\u9884\u6d4b\u672a\u6765\u8d1f\u8f7d&#034;&#034;&#034;<br \/>\n        current_time &#061; datetime.now()<\/p>\n<p>        # \u51c6\u5907\u8bad\u7ec3\u6570\u636e<br \/>\n        X &#061; []<br \/>\n        y &#061; []<\/p>\n<p>        for i in range(len(self.historical_data) &#8211; 1):<br \/>\n            current &#061; self.historical_data[i]<br \/>\n            next_point &#061; self.historical_data[i &#043; 1]<\/p>\n<p>            features &#061; self.extract_features(current)<br \/>\n            target &#061; next_point[&#039;request_rate&#039;]<\/p>\n<p>            X.append(features)<br \/>\n            y.append(target)<\/p>\n<p>        if len(X) &lt; 100:<br \/>\n            # \u6570\u636e\u4e0d\u8db3&#xff0c;\u4f7f\u7528\u7b80\u5355\u9884\u6d4b<br \/>\n            return self.simple_prediction()<\/p>\n<p>        # \u5b9a\u671f\u91cd\u8bad\u7ec3\u6a21\u578b<br \/>\n        if current_time.timestamp() &#8211; self.last_retrain &gt; self.retrain_interval:<br \/>\n            self.model.fit(X, y)<br \/>\n            self.last_retrain &#061; current_time.timestamp()<\/p>\n<p>        # \u9884\u6d4b<br \/>\n        current_features &#061; self.extract_features(self.historical_data[-1])<br \/>\n        predicted_load &#061; self.model.predict([current_features])[0]<\/p>\n<p>        return max(0, predicted_load)<\/p>\n<p>    def calculate_desired_instances(self, current_instances):<br \/>\n        &#034;&#034;&#034;\u8ba1\u7b97\u6240\u9700\u5b9e\u4f8b\u6570&#034;&#034;&#034;<br \/>\n        predicted_load &#061; self.predict_load()<br \/>\n        current_capacity &#061; current_instances * 1000  # \u5047\u8bbe\u6bcf\u4e2a\u5b9e\u4f8b\u5904\u74061000 RPS<\/p>\n<p>        if predicted_load &gt; current_capacity * 0.8:  # 80%\u9608\u503c<br \/>\n            # \u9700\u8981\u6269\u5bb9<br \/>\n            desired_instances &#061; int(np.ceil(predicted_load \/ 1000))<br \/>\n            buffer &#061; int(np.ceil(desired_instances * 0.2))  # 20%\u7f13\u51b2<br \/>\n            return desired_instances &#043; buffer<\/p>\n<p>        elif predicted_load &lt; current_capacity * 0.3:  # 30%\u9608\u503c<br \/>\n            # \u53ef\u4ee5\u7f29\u5bb9<br \/>\n            desired_instances &#061; int(np.ceil(predicted_load \/ 1000))<br \/>\n            return max(1, desired_instances)  # \u81f3\u5c11\u4fdd\u75591\u4e2a\u5b9e\u4f8b<\/p>\n<p>        return current_instances<\/p>\n<p>    def extract_features(self, data_point):<br \/>\n        &#034;&#034;&#034;\u4ece\u6570\u636e\u70b9\u63d0\u53d6\u7279\u5f81&#034;&#034;&#034;<br \/>\n        hour &#061; data_point[&#039;timestamp&#039;].hour<br \/>\n        day_of_week &#061; data_point[&#039;timestamp&#039;].weekday()<\/p>\n<p>        return [<br \/>\n            hour,<br \/>\n            day_of_week,<br \/>\n            data_point[&#039;request_rate&#039;],<br \/>\n            data_point[&#039;avg_response_time&#039;],<br \/>\n            data_point[&#039;error_rate&#039;],<br \/>\n            data_point[&#039;active_connections&#039;],<br \/>\n            data_point[&#039;cpu_usage&#039;],<br \/>\n            data_point[&#039;memory_usage&#039;]<br \/>\n        ]<\/p>\n<h4>26.6 \u6700\u4f73\u5b9e\u8df5\u603b\u7ed3<\/h4>\n<h5>26.6.1 \u914d\u7f6e\u68c0\u67e5\u6e05\u5355<\/h5>\n<p>Nginx\u914d\u7f6e\u4f18\u5316&#xff1a;<\/p>\n<p>text<\/p>\n<p>\u2705 proxy_connect_timeout: 5-10\u79d2<br \/>\n\u2705 proxy_read_timeout: \u6839\u636e\u4e1a\u52a1\u8c03\u6574&#xff08;\u901a\u5e3830-60\u79d2&#xff09;<br \/>\n\u2705 proxy_send_timeout: 30-60\u79d2<br \/>\n\u2705 proxy_buffer_size: 4k\u62168k<br \/>\n\u2705 proxy_buffers: 8 4k\u62168k<br \/>\n\u2705 proxy_next_upstream: error timeout invalid_header http_502<br \/>\n\u2705 proxy_next_upstream_tries: 2-3\u6b21<br \/>\n\u2705 keepalive_connections: 32-64<\/p>\n<p>\u5e94\u7528\u670d\u52a1\u5668\u914d\u7f6e&#xff1a;<\/p>\n<p>text<\/p>\n<p>\u2705 \u8fde\u63a5\u6c60\u5927\u5c0f&#xff1a;\u6839\u636e\u8d1f\u8f7d\u8c03\u6574<br \/>\n\u2705 \u7ebf\u7a0b\u6c60\u914d\u7f6e&#xff1a;\u907f\u514d\u8d44\u6e90\u8017\u5c3d<br \/>\n\u2705 \u5185\u5b58\u9650\u5236&#xff1a;\u9632\u6b62OOM<br \/>\n\u2705 \u5065\u5eb7\u68c0\u67e5\u7aef\u70b9&#xff1a;\/health, \/ready, \/live<br \/>\n\u2705 \u4f18\u96c5\u5173\u95ed&#xff1a;\u5904\u7406SIGTERM\u4fe1\u53f7<\/p>\n<h5>26.6.2 \u76d1\u63a7\u6307\u6807\u5173\u952e\u70b9<\/h5>\n<li>\n<p>\u7f51\u5173\u5c42\u6307\u6807&#xff1a;<\/p>\n<ul>\n<li>\n<p>502\u9519\u8bef\u7387&#xff08;\u76ee\u6807&#xff1a;&lt; 0.1%&#xff09;<\/p>\n<\/li>\n<li>\n<p>\u5e73\u5747\u54cd\u5e94\u65f6\u95f4&#xff08;\u76ee\u6807&#xff1a;&lt; 200ms&#xff09;<\/p>\n<\/li>\n<li>\n<p>\u8fde\u63a5\u6c60\u4f7f\u7528\u7387&#xff08;\u76ee\u6807&#xff1a;&lt; 80%&#xff09;<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u4e0a\u6e38\u670d\u52a1\u6307\u6807&#xff1a;<\/p>\n<ul>\n<li>\n<p>\u670d\u52a1\u53ef\u7528\u6027&#xff08;\u76ee\u6807&#xff1a;&gt; 99.9%&#xff09;<\/p>\n<\/li>\n<li>\n<p>\u9519\u8bef\u7387&#xff08;\u76ee\u6807&#xff1a;&lt; 0.5%&#xff09;<\/p>\n<\/li>\n<li>\n<p>\u8d44\u6e90\u4f7f\u7528\u7387&#xff08;CPU\u3001\u5185\u5b58\u3001\u8fde\u63a5&#xff09;<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u7f51\u7edc\u6307\u6807&#xff1a;<\/p>\n<ul>\n<li>\n<p>\u5ef6\u8fdf&#xff08;\u76ee\u6807&#xff1a;&lt; 50ms&#xff09;<\/p>\n<\/li>\n<li>\n<p>\u4e22\u5305\u7387&#xff08;\u76ee\u6807&#xff1a;&lt; 0.1%&#xff09;<\/p>\n<\/li>\n<li>\n<p>\u5e26\u5bbd\u4f7f\u7528\u7387&#xff08;\u76ee\u6807&#xff1a;&lt; 70%&#xff09;<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<p>\u901a\u8fc7\u5b9e\u65bd\u8fd9\u4e9b\u7b56\u7565&#xff0c;\u53ef\u4ee5\u663e\u8457\u964d\u4f4e502\u9519\u8bef\u7684\u53d1\u751f\u7387&#xff0c;\u63d0\u9ad8\u7cfb\u7edf\u7684\u6574\u4f53\u53ef\u9760\u6027\u3002<\/p>\n<hr \/>\n<h3>\u7b2c27\u7ae0&#xff1a;503 Service Unavailable &#8211; \u670d\u52a1\u4e0d\u53ef\u7528<\/h3>\n<h4>27.1 \u6df1\u5165\u89e3\u6790\u670d\u52a1\u4e0d\u53ef\u7528\u72b6\u6001<\/h4>\n<p>503 Service Unavailable\u00a0\u8868\u793a\u670d\u52a1\u5668\u6682\u65f6\u65e0\u6cd5\u5904\u7406\u8bf7\u6c42&#xff0c;\u901a\u5e38\u662f\u7531\u4e8e\u8fc7\u8f7d\u6216\u7ef4\u62a4\u3002\u4e0e502\u4e0d\u540c&#xff0c;503\u8868\u793a\u670d\u52a1\u5668\u672c\u8eab\u77e5\u9053\u5b83\u6682\u65f6\u65e0\u6cd5\u63d0\u4f9b\u670d\u52a1\u3002<\/p>\n<h5>27.1.1 \u534f\u8bae\u89c4\u8303\u4e0e\u8bed\u4e49<\/h5>\n<ul>\n<li>\n<p>RFC 7231\u5b9a\u4e49&#xff1a;\u670d\u52a1\u5668\u5f53\u524d\u65e0\u6cd5\u5904\u7406\u8bf7\u6c42&#xff0c;\u56e0\u4e3a\u4e34\u65f6\u7684\u8fc7\u8f7d\u6216\u7cfb\u7edf\u7ef4\u62a4<\/p>\n<\/li>\n<li>\n<p>\u5173\u952e\u7279\u6027&#xff1a;<\/p>\n<ul>\n<li>\n<p>\u4e34\u65f6\u6027\u9519\u8bef&#xff08;\u5bf9\u6bd4501\u7684\u6c38\u4e45\u6027&#xff09;<\/p>\n<\/li>\n<li>\n<p>\u901a\u5e38\u5e94\u5305\u542bRetry-After\u5934\u90e8<\/p>\n<\/li>\n<li>\n<p>\u53ef\u80fd\u7531\u4e8e\u8ba1\u5212\u7ef4\u62a4\u3001\u8fc7\u8f7d\u6216\u4f9d\u8d56\u670d\u52a1\u6545\u969c<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h5>27.1.2 \u4e0e\u76f8\u5173\u72b6\u6001\u7801\u7684\u7cbe\u786e\u533a\u5206<img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1040\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/07\/20260726181700-6a664f1c2aef5.png\" width=\"3094\" \/><\/h5>\n<h4>27.2 \u5bb9\u91cf\u7ba1\u7406\u4e0e\u8fc7\u8f7d\u4fdd\u62a4<\/h4>\n<h5>27.2.1 \u57fa\u4e8e\u961f\u5217\u7406\u8bba\u7684\u5bb9\u91cf\u6a21\u578b<\/h5>\n<p>python<\/p>\n<p># \u670d\u52a1\u5bb9\u91cf\u7ba1\u7406\u4e0e\u8fc7\u8f7d\u4fdd\u62a4\u7cfb\u7edf<br \/>\nimport asyncio<br \/>\nimport time<br \/>\nfrom collections import deque<br \/>\nfrom dataclasses import dataclass<br \/>\nfrom typing import Optional, Deque<br \/>\nimport statistics<\/p>\n<p>&#064;dataclass<br \/>\nclass Request:<br \/>\n    id: str<br \/>\n    arrival_time: float<br \/>\n    priority: int &#061; 1<br \/>\n    timeout: float &#061; 30.0<\/p>\n<p>&#064;dataclass<br \/>\nclass CapacityMetrics:<br \/>\n    &#034;&#034;&#034;\u5bb9\u91cf\u6307\u6807&#034;&#034;&#034;<br \/>\n    arrival_rate: float &#061; 0.0      # \u8bf7\u6c42\u5230\u8fbe\u7387 (requests\/second)<br \/>\n    service_rate: float &#061; 0.0      # \u670d\u52a1\u7387 (requests\/second)<br \/>\n    queue_length: int &#061; 0          # \u961f\u5217\u957f\u5ea6<br \/>\n    utilization: float &#061; 0.0       # \u5229\u7528\u7387 (arrival_rate \/ service_rate)<br \/>\n    response_time_95: float &#061; 0.0  # 95%\u54cd\u5e94\u65f6\u95f4<br \/>\n    error_rate: float &#061; 0.0        # \u9519\u8bef\u7387<\/p>\n<p>class AdaptiveRateLimiter:<br \/>\n    &#034;&#034;&#034;\u81ea\u9002\u5e94\u901f\u7387\u9650\u5236\u5668&#034;&#034;&#034;<\/p>\n<p>    def __init__(self, initial_capacity: int &#061; 100):<br \/>\n        self.max_capacity &#061; initial_capacity<br \/>\n        self.current_capacity &#061; initial_capacity<br \/>\n        self.queue: Deque[Request] &#061; deque()<br \/>\n        self.in_progress &#061; 0<br \/>\n        self.metrics_history &#061; deque(maxlen&#061;1000)<\/p>\n<p>        # \u63a7\u5236\u53c2\u6570<br \/>\n        self.target_response_time &#061; 0.2  # \u76ee\u6807\u54cd\u5e94\u65f6\u95f4200ms<br \/>\n        self.target_utilization &#061; 0.7    # \u76ee\u6807\u5229\u7528\u738770%<br \/>\n        self.min_capacity &#061; 10           # \u6700\u5c0f\u5bb9\u91cf<br \/>\n        self.adjustment_cooldown &#061; 5.0   # \u8c03\u6574\u51b7\u5374\u65f6\u95f4<\/p>\n<p>        self.last_adjustment &#061; 0.0<br \/>\n        self.last_rejection &#061; 0.0<\/p>\n<p>    def should_accept(self, request: Request) -&gt; bool:<br \/>\n        &#034;&#034;&#034;\u51b3\u5b9a\u662f\u5426\u63a5\u53d7\u65b0\u8bf7\u6c42&#034;&#034;&#034;<br \/>\n        current_time &#061; time.time()<\/p>\n<p>        # \u8ba1\u7b97\u5f53\u524d\u6307\u6807<br \/>\n        metrics &#061; self._calculate_metrics(current_time)<\/p>\n<p>        # \u68c0\u67e5\u662f\u5426\u8fc7\u8f7d<br \/>\n        if self._is_overloaded(metrics, current_time):<br \/>\n            return False<\/p>\n<p>        # \u57fa\u4e8e\u961f\u5217\u957f\u5ea6\u9650\u5236<br \/>\n        if len(self.queue) &gt;&#061; self.current_capacity * 2:<br \/>\n            return False<\/p>\n<p>        # \u57fa\u4e8e\u54cd\u5e94\u65f6\u95f4\u9884\u6d4b<br \/>\n        predicted_response_time &#061; self._predict_response_time(metrics)<br \/>\n        if predicted_response_time &gt; request.timeout * 0.8:<br \/>\n            return False<\/p>\n<p>        return True<\/p>\n<p>    def _is_overloaded(self, metrics: CapacityMetrics, current_time: float) -&gt; bool:<br \/>\n        &#034;&#034;&#034;\u5224\u65ad\u7cfb\u7edf\u662f\u5426\u8fc7\u8f7d&#034;&#034;&#034;<\/p>\n<p>        # \u6807\u51c61&#xff1a;\u54cd\u5e94\u65f6\u95f4\u8d85\u8fc7\u9608\u503c<br \/>\n        if metrics.response_time_95 &gt; self.target_response_time * 3:<br \/>\n            return True<\/p>\n<p>        # \u6807\u51c62&#xff1a;\u9519\u8bef\u7387\u8fc7\u9ad8<br \/>\n        if metrics.error_rate &gt; 0.1:  # 10%\u9519\u8bef\u7387<br \/>\n            return True<\/p>\n<p>        # \u6807\u51c63&#xff1a;\u961f\u5217\u8fc7\u957f<br \/>\n        if metrics.queue_length &gt; self.current_capacity * 3:<br \/>\n            return True<\/p>\n<p>        # \u6807\u51c64&#xff1a;\u8fd1\u671f\u6709\u592a\u591a\u62d2\u7edd<br \/>\n        if (current_time &#8211; self.last_rejection &lt; 1.0 and<br \/>\n            metrics.arrival_rate &gt; self.current_capacity * 2):<br \/>\n            return True<\/p>\n<p>        return False<\/p>\n<p>    def _calculate_metrics(self, current_time: float) -&gt; CapacityMetrics:<br \/>\n        &#034;&#034;&#034;\u8ba1\u7b97\u5f53\u524d\u6027\u80fd\u6307\u6807&#034;&#034;&#034;<br \/>\n        metrics &#061; CapacityMetrics()<\/p>\n<p>        # \u8ba1\u7b97\u5230\u8fbe\u7387&#xff08;\u57fa\u4e8e\u6700\u8fd110\u79d2&#xff09;<br \/>\n        recent_arrivals &#061; [<br \/>\n            r for r in self.metrics_history<br \/>\n            if current_time &#8211; r[&#039;timestamp&#039;] &lt; 10<br \/>\n        ]<\/p>\n<p>        if recent_arrivals:<br \/>\n            arrival_times &#061; [r[&#039;timestamp&#039;] for r in recent_arrivals]<br \/>\n            metrics.arrival_rate &#061; len(recent_arrivals) \/ 10.0<\/p>\n<p>            # \u8ba1\u7b97\u670d\u52a1\u7387<br \/>\n            completed &#061; [r for r in recent_arrivals if r[&#039;completed&#039;]]<br \/>\n            if completed:<br \/>\n                service_times &#061; [r[&#039;service_time&#039;] for r in completed]<br \/>\n                metrics.service_rate &#061; 1.0 \/ statistics.mean(service_times)<\/p>\n<p>        # \u961f\u5217\u957f\u5ea6<br \/>\n        metrics.queue_length &#061; len(self.queue)<\/p>\n<p>        # \u5229\u7528\u7387<br \/>\n        if metrics.service_rate &gt; 0:<br \/>\n            metrics.utilization &#061; metrics.arrival_rate \/ metrics.service_rate<\/p>\n<p>        # \u54cd\u5e94\u65f6\u95f4\u767e\u5206\u4f4d<br \/>\n        response_times &#061; [r[&#039;response_time&#039;] for r in recent_arrivals<br \/>\n                         if &#039;response_time&#039; in r]<br \/>\n        if response_times:<br \/>\n            metrics.response_time_95 &#061; statistics.quantiles(<br \/>\n                response_times, n&#061;20<br \/>\n            )[18] if len(response_times) &gt;&#061; 5 else response_times[-1]<\/p>\n<p>        # \u9519\u8bef\u7387<br \/>\n        errors &#061; [r for r in recent_arrivals if r.get(&#039;error&#039;, False)]<br \/>\n        if recent_arrivals:<br \/>\n            metrics.error_rate &#061; len(errors) \/ len(recent_arrivals)<\/p>\n<p>        return metrics<\/p>\n<p>    def _predict_response_time(self, metrics: CapacityMetrics) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u9884\u6d4b\u54cd\u5e94\u65f6\u95f4&#xff08;\u57fa\u4e8eM\/M\/1\u961f\u5217\u6a21\u578b&#xff09;&#034;&#034;&#034;<br \/>\n        if metrics.utilization &gt;&#061; 1.0:<br \/>\n            # \u7cfb\u7edf\u9971\u548c&#xff0c;\u54cd\u5e94\u65f6\u95f4\u8d8b\u4e8e\u65e0\u9650<br \/>\n            return float(&#039;inf&#039;)<\/p>\n<p>        if metrics.service_rate &#061;&#061; 0:<br \/>\n            return 0.0<\/p>\n<p>        # M\/M\/1\u961f\u5217\u516c\u5f0f&#xff1a;\u54cd\u5e94\u65f6\u95f4 &#061; 1\/\u03bc \/ (1 &#8211; \u03c1)<br \/>\n        # \u5176\u4e2d\u03bc\u662f\u670d\u52a1\u7387&#xff0c;\u03c1\u662f\u5229\u7528\u7387<br \/>\n        if metrics.utilization &lt; 0.95:<br \/>\n            expected_service_time &#061; 1.0 \/ metrics.service_rate<br \/>\n            predicted &#061; expected_service_time \/ (1 &#8211; metrics.utilization)<br \/>\n            return predicted<br \/>\n        else:<br \/>\n            return float(&#039;inf&#039;)<\/p>\n<p>    async def adjust_capacity(self, current_time: float):<br \/>\n        &#034;&#034;&#034;\u81ea\u9002\u5e94\u8c03\u6574\u5bb9\u91cf&#034;&#034;&#034;<br \/>\n        if current_time &#8211; self.last_adjustment &lt; self.adjustment_cooldown:<br \/>\n            return<\/p>\n<p>        metrics &#061; self._calculate_metrics(current_time)<\/p>\n<p>        # \u57fa\u4e8e\u54cd\u5e94\u65f6\u95f4\u8c03\u6574<br \/>\n        if metrics.response_time_95 &gt; self.target_response_time * 1.5:<br \/>\n            # \u54cd\u5e94\u65f6\u95f4\u8fc7\u9ad8&#xff0c;\u964d\u4f4e\u5bb9\u91cf<br \/>\n            reduction &#061; self._calculate_reduction(metrics)<br \/>\n            self.current_capacity &#061; max(<br \/>\n                self.min_capacity,<br \/>\n                int(self.current_capacity * reduction)<br \/>\n            )<\/p>\n<p>        elif (metrics.utilization &lt; self.target_utilization * 0.8 and<br \/>\n              metrics.response_time_95 &lt; self.target_response_time * 0.8):<br \/>\n            # \u5229\u7528\u7387\u4f4e\u4e14\u54cd\u5e94\u65f6\u95f4\u597d&#xff0c;\u53ef\u4ee5\u589e\u52a0\u5bb9\u91cf<br \/>\n            increase &#061; self._calculate_increase(metrics)<br \/>\n            self.current_capacity &#061; min(<br \/>\n                self.max_capacity,<br \/>\n                int(self.current_capacity * increase)<br \/>\n            )<\/p>\n<p>        self.last_adjustment &#061; current_time<\/p>\n<p>    def _calculate_reduction(self, metrics: CapacityMetrics) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u8ba1\u7b97\u5bb9\u91cf\u51cf\u5c11\u6bd4\u4f8b&#034;&#034;&#034;<br \/>\n        # \u54cd\u5e94\u65f6\u95f4\u8d85\u8fc7\u76ee\u6807\u7684\u500d\u6570<br \/>\n        overshoot_ratio &#061; metrics.response_time_95 \/ self.target_response_time<\/p>\n<p>        if overshoot_ratio &gt; 3.0:<br \/>\n            # \u4e25\u91cd\u8fc7\u8f7d&#xff0c;\u5927\u5e45\u51cf\u5c11<br \/>\n            return 0.5<br \/>\n        elif overshoot_ratio &gt; 2.0:<br \/>\n            # \u4e2d\u5ea6\u8fc7\u8f7d<br \/>\n            return 0.7<br \/>\n        else:<br \/>\n            # \u8f7b\u5fae\u8fc7\u8f7d<br \/>\n            return 0.9<\/p>\n<p>    def create_503_response(self, request: Request,<br \/>\n                           metrics: CapacityMetrics) -&gt; dict:<br \/>\n        &#034;&#034;&#034;\u521b\u5efa\u667a\u80fd\u7684503\u54cd\u5e94&#034;&#034;&#034;<br \/>\n        current_time &#061; time.time()<\/p>\n<p>        # \u8ba1\u7b97\u5efa\u8bae\u7684\u91cd\u8bd5\u65f6\u95f4<br \/>\n        if self.queue:<br \/>\n            avg_service_time &#061; 1.0 \/ metrics.service_rate if metrics.service_rate &gt; 0 else 1.0<br \/>\n            queue_wait &#061; len(self.queue) * avg_service_time<br \/>\n            retry_after &#061; min(30, max(1, int(queue_wait)))<br \/>\n        else:<br \/>\n            retry_after &#061; 5  # \u9ed8\u8ba45\u79d2<\/p>\n<p>        response &#061; {<br \/>\n            &#034;status&#034;: 503,<br \/>\n            &#034;headers&#034;: {<br \/>\n                &#034;Content-Type&#034;: &#034;application\/json&#034;,<br \/>\n                &#034;Retry-After&#034;: str(retry_after)<br \/>\n            },<br \/>\n            &#034;body&#034;: {<br \/>\n                &#034;error&#034;: {<br \/>\n                    &#034;code&#034;: &#034;service_unavailable&#034;,<br \/>\n                    &#034;message&#034;: &#034;Service is temporarily overloaded&#034;,<br \/>\n                    &#034;details&#034;: {<br \/>\n                        &#034;request_id&#034;: request.id,<br \/>\n                        &#034;timestamp&#034;: current_time,<br \/>\n                        &#034;queue_position&#034;: len(self.queue) if request in self.queue else None,<br \/>\n                        &#034;estimated_wait_time&#034;: retry_after,<br \/>\n                        &#034;current_metrics&#034;: {<br \/>\n                            &#034;arrival_rate&#034;: round(metrics.arrival_rate, 2),<br \/>\n                            &#034;utilization&#034;: round(metrics.utilization, 3),<br \/>\n                            &#034;queue_length&#034;: metrics.queue_length,<br \/>\n                            &#034;response_time_95&#034;: round(metrics.response_time_95, 3)<br \/>\n                        },<br \/>\n                        &#034;suggestions&#034;: [<br \/>\n                            f&#034;Please retry after {retry_after} seconds&#034;,<br \/>\n                            &#034;Use exponential backoff for retries&#034;,<br \/>\n                            &#034;Check service status at status.example.com&#034;<br \/>\n                        ]<br \/>\n                    }<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>        # \u8bb0\u5f55\u62d2\u7edd<br \/>\n        self.last_rejection &#061; current_time<br \/>\n        self.metrics_history.append({<br \/>\n            &#034;timestamp&#034;: current_time,<br \/>\n            &#034;request_id&#034;: request.id,<br \/>\n            &#034;rejected&#034;: True,<br \/>\n            &#034;queue_length&#034;: metrics.queue_length,<br \/>\n            &#034;arrival_rate&#034;: metrics.arrival_rate<br \/>\n        })<\/p>\n<p>        return response<\/p>\n<h5>27.2.2 \u5206\u5e03\u5f0f\u9650\u6d41\u4e0e\u914d\u989d\u7ba1\u7406<\/h5>\n<p>java<\/p>\n<p>\/\/ \u57fa\u4e8eRedis\u7684\u5206\u5e03\u5f0f\u9650\u6d41\u5668<br \/>\n&#064;Slf4j<br \/>\n&#064;Component<br \/>\npublic class DistributedRateLimiter {<\/p>\n<p>    private final RedisTemplate&lt;String, String&gt; redisTemplate;<br \/>\n    private final ObjectMapper objectMapper;<\/p>\n<p>    \/\/ \u9650\u6d41\u914d\u7f6e<br \/>\n    private final Map&lt;String, RateLimitConfig&gt; rateLimitConfigs;<\/p>\n<p>    &#064;Data<br \/>\n    &#064;AllArgsConstructor<br \/>\n    static class RateLimitConfig {<br \/>\n        private int requestsPerSecond;<br \/>\n        private int burstCapacity;<br \/>\n        private Duration windowSize;<br \/>\n        private boolean enabled;<br \/>\n    }<\/p>\n<p>    public DistributedRateLimiter(RedisTemplate&lt;String, String&gt; redisTemplate,<br \/>\n                                 ObjectMapper objectMapper) {<br \/>\n        this.redisTemplate &#061; redisTemplate;<br \/>\n        this.objectMapper &#061; objectMapper;<br \/>\n        this.rateLimitConfigs &#061; loadRateLimitConfigs();<br \/>\n    }<\/p>\n<p>    \/**<br \/>\n     * \u68c0\u67e5\u8bf7\u6c42\u662f\u5426\u5e94\u8be5\u88ab\u9650\u6d41<br \/>\n     *\/<br \/>\n    public RateLimitResult checkRateLimit(String clientId, String endpoint) {<br \/>\n        String key &#061; String.format(&#034;rate_limit:%s:%s&#034;, clientId, endpoint);<br \/>\n        RateLimitConfig config &#061; rateLimitConfigs.getOrDefault(endpoint,<br \/>\n            new RateLimitConfig(100, 200, Duration.ofSeconds(1), true));<\/p>\n<p>        if (!config.isEnabled()) {<br \/>\n            return RateLimitResult.allowed();<br \/>\n        }<\/p>\n<p>        long currentTime &#061; System.currentTimeMillis();<br \/>\n        long windowStart &#061; currentTime &#8211; config.getWindowSize().toMillis();<\/p>\n<p>        \/\/ \u4f7f\u7528Redis sorted set\u5b9e\u73b0\u6ed1\u52a8\u7a97\u53e3<br \/>\n        String windowKey &#061; key &#043; &#034;:window&#034;;<\/p>\n<p>        \/\/ \u79fb\u9664\u7a97\u53e3\u5916\u7684\u8bf7\u6c42<br \/>\n        redisTemplate.opsForZSet().removeRangeByScore(<br \/>\n            windowKey, 0, windowStart &#8211; 1<br \/>\n        );<\/p>\n<p>        \/\/ \u83b7\u53d6\u5f53\u524d\u7a97\u53e3\u5185\u7684\u8bf7\u6c42\u6570<br \/>\n        Long requestCount &#061; redisTemplate.opsForZSet().zCard(windowKey);<\/p>\n<p>        if (requestCount &#061;&#061; null) {<br \/>\n            requestCount &#061; 0L;<br \/>\n        }<\/p>\n<p>        \/\/ \u68c0\u67e5\u662f\u5426\u8d85\u8fc7\u9650\u5236<br \/>\n        if (requestCount &gt;&#061; config.getRequestsPerSecond()) {<br \/>\n            \/\/ \u8ba1\u7b97\u4e0b\u4e00\u4e2a\u53ef\u7528\u65f6\u95f4<br \/>\n            Double oldestScore &#061; redisTemplate.opsForZSet()<br \/>\n                .rangeWithScores(windowKey, 0, 0)<br \/>\n                .stream()<br \/>\n                .findFirst()<br \/>\n                .map(TypedTuple::getScore)<br \/>\n                .orElse((double) currentTime);<\/p>\n<p>            long retryAfter &#061; (long) (oldestScore &#043; 1000) &#8211; currentTime;<br \/>\n            retryAfter &#061; Math.max(1, retryAfter \/ 1000);<\/p>\n<p>            return RateLimitResult.rateLimited(retryAfter);<br \/>\n        }<\/p>\n<p>        \/\/ \u6dfb\u52a0\u5f53\u524d\u8bf7\u6c42\u5230\u7a97\u53e3<br \/>\n        redisTemplate.opsForZSet().add(<br \/>\n            windowKey,<br \/>\n            UUID.randomUUID().toString(),<br \/>\n            currentTime<br \/>\n        );<\/p>\n<p>        \/\/ \u8bbe\u7f6ekey\u7684\u8fc7\u671f\u65f6\u95f4<br \/>\n        redisTemplate.expire(windowKey, config.getWindowSize().plusSeconds(10));<\/p>\n<p>        \/\/ \u8ba1\u7b97\u5269\u4f59\u914d\u989d<br \/>\n        long remaining &#061; config.getRequestsPerSecond() &#8211; requestCount &#8211; 1;<\/p>\n<p>        return RateLimitResult.allowed(remaining);<br \/>\n    }<\/p>\n<p>    \/**<br \/>\n     * \u81ea\u9002\u5e94\u8c03\u6574\u9650\u6d41\u914d\u7f6e<br \/>\n     *\/<br \/>\n    public void adjustRateLimits(SystemMetrics metrics) {<br \/>\n        for (Map.Entry&lt;String, RateLimitConfig&gt; entry : rateLimitConfigs.entrySet()) {<br \/>\n            String endpoint &#061; entry.getKey();<br \/>\n            RateLimitConfig config &#061; entry.getValue();<\/p>\n<p>            \/\/ \u57fa\u4e8e\u7cfb\u7edf\u6307\u6807\u52a8\u6001\u8c03\u6574<br \/>\n            if (metrics.getErrorRate() &gt; 0.1) {<br \/>\n                \/\/ \u9519\u8bef\u7387\u9ad8&#xff0c;\u964d\u4f4e\u9650\u6d41\u9608\u503c<br \/>\n                int newLimit &#061; (int) (config.getRequestsPerSecond() * 0.8);<br \/>\n                config.setRequestsPerSecond(Math.max(10, newLimit));<br \/>\n                log.info(&#034;Reduced rate limit for {} to {}&#034;, endpoint, newLimit);<\/p>\n<p>            } else if (metrics.getCpuUsage() &gt; 0.8) {<br \/>\n                \/\/ CPU\u4f7f\u7528\u7387\u9ad8&#xff0c;\u964d\u4f4e\u9650\u6d41\u9608\u503c<br \/>\n                int newLimit &#061; (int) (config.getRequestsPerSecond() * 0.9);<br \/>\n                config.setRequestsPerSecond(Math.max(10, newLimit));<br \/>\n                log.info(&#034;Reduced rate limit for {} due to high CPU&#034;, endpoint);<\/p>\n<p>            } else if (metrics.getErrorRate() &lt; 0.01 &amp;&amp;<br \/>\n                      metrics.getCpuUsage() &lt; 0.6 &amp;&amp;<br \/>\n                      metrics.getResponseTime95() &lt; 200) {<br \/>\n                \/\/ \u7cfb\u7edf\u5065\u5eb7&#xff0c;\u53ef\u4ee5\u9002\u5f53\u63d0\u9ad8\u9650\u6d41\u9608\u503c<br \/>\n                int newLimit &#061; (int) (config.getRequestsPerSecond() * 1.1);<br \/>\n                config.setRequestsPerSecond(Math.min(1000, newLimit));<br \/>\n                log.info(&#034;Increased rate limit for {} to {}&#034;, endpoint, newLimit);<br \/>\n            }<br \/>\n        }<br \/>\n    }<\/p>\n<p>    &#064;Data<br \/>\n    &#064;AllArgsConstructor<br \/>\n    static class RateLimitResult {<br \/>\n        private boolean allowed;<br \/>\n        private long remainingRequests;<br \/>\n        private long retryAfterSeconds;<br \/>\n        private String message;<\/p>\n<p>        public static RateLimitResult allowed() {<br \/>\n            return new RateLimitResult(true, -1, 0, null);<br \/>\n        }<\/p>\n<p>        public static RateLimitResult allowed(long remaining) {<br \/>\n            return new RateLimitResult(true, remaining, 0, null);<br \/>\n        }<\/p>\n<p>        public static RateLimitResult rateLimited(long retryAfter) {<br \/>\n            return new RateLimitResult(false, 0, retryAfter,<br \/>\n                &#034;Rate limit exceeded. Please retry after &#034; &#043; retryAfter &#043; &#034; seconds.&#034;);<br \/>\n        }<br \/>\n    }<br \/>\n}<\/p>\n<h4>27.3 \u4f18\u96c5\u7684\u670d\u52a1\u964d\u7ea7<\/h4>\n<h5>27.3.1 \u591a\u7ea7\u964d\u7ea7\u7b56\u7565\u5b9e\u73b0<\/h5>\n<p>python<\/p>\n<p># \u670d\u52a1\u964d\u7ea7\u7ba1\u7406\u5668<br \/>\nfrom enum import Enum<br \/>\nfrom typing import Dict, Any, Optional, Callable<br \/>\nimport time<br \/>\nfrom dataclasses import dataclass<br \/>\nfrom functools import wraps<\/p>\n<p>class DegradationLevel(Enum):<br \/>\n    &#034;&#034;&#034;\u964d\u7ea7\u7ea7\u522b&#034;&#034;&#034;<br \/>\n    NORMAL &#061; &#034;normal&#034;           # \u6b63\u5e38\u6a21\u5f0f<br \/>\n    DEGRADED &#061; &#034;degraded&#034;       # \u964d\u7ea7\u6a21\u5f0f<br \/>\n    MINIMAL &#061; &#034;minimal&#034;         # \u6700\u5c0f\u529f\u80fd\u6a21\u5f0f<br \/>\n    EMERGENCY &#061; &#034;emergency&#034;     # \u7d27\u6025\u6a21\u5f0f<\/p>\n<p>&#064;dataclass<br \/>\nclass DegradationRule:<br \/>\n    &#034;&#034;&#034;\u964d\u7ea7\u89c4\u5219&#034;&#034;&#034;<br \/>\n    metric_name: str           # \u6307\u6807\u540d\u79f0<br \/>\n    threshold: float           # \u9608\u503c<br \/>\n    duration: float           # \u6301\u7eed\u65f6\u95f4&#xff08;\u79d2&#xff09;<br \/>\n    target_level: DegradationLevel  # \u76ee\u6807\u964d\u7ea7\u7ea7\u522b<br \/>\n    cooldown: float &#061; 300      # \u51b7\u5374\u65f6\u95f4&#xff08;\u79d2&#xff09;<\/p>\n<p>class ServiceDegrader:<br \/>\n    &#034;&#034;&#034;\u670d\u52a1\u964d\u7ea7\u7ba1\u7406\u5668&#034;&#034;&#034;<\/p>\n<p>    def __init__(self):<br \/>\n        self.current_level &#061; DegradationLevel.NORMAL<br \/>\n        self.rules: Dict[str, DegradationRule] &#061; {}<br \/>\n        self.metrics_history &#061; {}<br \/>\n        self.last_level_change &#061; time.time()<\/p>\n<p>        # \u9ed8\u8ba4\u964d\u7ea7\u89c4\u5219<br \/>\n        self._setup_default_rules()<\/p>\n<p>        # \u964d\u7ea7\u5904\u7406\u5668\u6620\u5c04<br \/>\n        self.degradation_handlers &#061; {<br \/>\n            DegradationLevel.NORMAL: self._handle_normal,<br \/>\n            DegradationLevel.DEGRADED: self._handle_degraded,<br \/>\n            DegradationLevel.MINIMAL: self._handle_minimal,<br \/>\n            DegradationLevel.EMERGENCY: self._handle_emergency<br \/>\n        }<\/p>\n<p>    def _setup_default_rules(self):<br \/>\n        &#034;&#034;&#034;\u8bbe\u7f6e\u9ed8\u8ba4\u964d\u7ea7\u89c4\u5219&#034;&#034;&#034;<br \/>\n        self.rules &#061; {<br \/>\n            # CPU\u4f7f\u7528\u7387\u89c4\u5219<br \/>\n            &#034;high_cpu&#034;: DegradationRule(<br \/>\n                metric_name&#061;&#034;cpu_usage&#034;,<br \/>\n                threshold&#061;0.8,  # 80%<br \/>\n                duration&#061;30,    # \u6301\u7eed30\u79d2<br \/>\n                target_level&#061;DegradationLevel.DEGRADED<br \/>\n            ),<\/p>\n<p>            # \u5185\u5b58\u4f7f\u7528\u7387\u89c4\u5219<br \/>\n            &#034;high_memory&#034;: DegradationRule(<br \/>\n                metric_name&#061;&#034;memory_usage&#034;,<br \/>\n                threshold&#061;0.9,  # 90%<br \/>\n                duration&#061;10,<br \/>\n                target_level&#061;DegradationLevel.MINIMAL<br \/>\n            ),<\/p>\n<p>            # \u9519\u8bef\u7387\u89c4\u5219<br \/>\n            &#034;high_error_rate&#034;: DegradationRule(<br \/>\n                metric_name&#061;&#034;error_rate&#034;,<br \/>\n                threshold&#061;0.1,  # 10%<br \/>\n                duration&#061;60,<br \/>\n                target_level&#061;DegradationLevel.DEGRADED<br \/>\n            ),<\/p>\n<p>            # \u54cd\u5e94\u65f6\u95f4\u89c4\u5219<br \/>\n            &#034;slow_response&#034;: DegradationRule(<br \/>\n                metric_name&#061;&#034;response_time_95&#034;,<br \/>\n                threshold&#061;2.0,  # 2\u79d2<br \/>\n                duration&#061;30,<br \/>\n                target_level&#061;DegradationLevel.DEGRADED<br \/>\n            ),<\/p>\n<p>            # \u961f\u5217\u957f\u5ea6\u89c4\u5219<br \/>\n            &#034;long_queue&#034;: DegradationRule(<br \/>\n                metric_name&#061;&#034;queue_length&#034;,<br \/>\n                threshold&#061;1000,<br \/>\n                duration&#061;10,<br \/>\n                target_level&#061;DegradationLevel.MINIMAL<br \/>\n            )<br \/>\n        }<\/p>\n<p>    def update_metrics(self, metrics: Dict[str, float]):<br \/>\n        &#034;&#034;&#034;\u66f4\u65b0\u6307\u6807\u5e76\u68c0\u67e5\u662f\u5426\u9700\u8981\u964d\u7ea7&#034;&#034;&#034;<br \/>\n        current_time &#061; time.time()<\/p>\n<p>        # \u66f4\u65b0\u6307\u6807\u5386\u53f2<br \/>\n        for name, value in metrics.items():<br \/>\n            if name not in self.metrics_history:<br \/>\n                self.metrics_history[name] &#061; []<\/p>\n<p>            self.metrics_history[name].append({<br \/>\n                &#034;timestamp&#034;: current_time,<br \/>\n                &#034;value&#034;: value<br \/>\n            })<\/p>\n<p>            # \u4fdd\u7559\u6700\u8fd15\u5206\u949f\u6570\u636e<br \/>\n            cutoff &#061; current_time &#8211; 300<br \/>\n            self.metrics_history[name] &#061; [<br \/>\n                m for m in self.metrics_history[name]<br \/>\n                if m[&#034;timestamp&#034;] &gt; cutoff<br \/>\n            ]<\/p>\n<p>        # \u68c0\u67e5\u964d\u7ea7\u89c4\u5219<br \/>\n        new_level &#061; self._evaluate_rules(current_time)<\/p>\n<p>        # \u5982\u679c\u68c0\u6d4b\u5230\u9700\u8981\u964d\u7ea7<br \/>\n        if new_level !&#061; self.current_level:<br \/>\n            # \u68c0\u67e5\u51b7\u5374\u65f6\u95f4<br \/>\n            if current_time &#8211; self.last_level_change &lt; 60:<br \/>\n                # \u907f\u514d\u9891\u7e41\u5207\u6362<br \/>\n                return<\/p>\n<p>            old_level &#061; self.current_level<br \/>\n            self.current_level &#061; new_level<br \/>\n            self.last_level_change &#061; current_time<\/p>\n<p>            # \u8bb0\u5f55\u72b6\u6001\u53d8\u5316<br \/>\n            self._log_degradation_change(old_level, new_level, metrics)<\/p>\n<p>            # \u6267\u884c\u964d\u7ea7\/\u6062\u590d\u64cd\u4f5c<br \/>\n            self._execute_degradation_actions(old_level, new_level)<\/p>\n<p>    def _evaluate_rules(self, current_time: float) -&gt; DegradationLevel:<br \/>\n        &#034;&#034;&#034;\u8bc4\u4f30\u6240\u6709\u964d\u7ea7\u89c4\u5219&#034;&#034;&#034;<br \/>\n        target_level &#061; self.current_level<\/p>\n<p>        for rule_name, rule in self.rules.items():<br \/>\n            metric_history &#061; self.metrics_history.get(rule.metric_name, [])<\/p>\n<p>            if not metric_history:<br \/>\n                continue<\/p>\n<p>            # \u68c0\u67e5\u6700\u8fd1duration\u79d2\u5185\u7684\u6307\u6807<br \/>\n            recent_metrics &#061; [<br \/>\n                m for m in metric_history<br \/>\n                if current_time &#8211; m[&#034;timestamp&#034;] &lt;&#061; rule.duration<br \/>\n            ]<\/p>\n<p>            if not recent_metrics:<br \/>\n                continue<\/p>\n<p>            # \u68c0\u67e5\u662f\u5426\u8d85\u8fc7\u9608\u503c<br \/>\n            values &#061; [m[&#034;value&#034;] for m in recent_metrics]<br \/>\n            avg_value &#061; sum(values) \/ len(values)<\/p>\n<p>            if avg_value &gt;&#061; rule.threshold:<br \/>\n                # \u9700\u8981\u964d\u7ea7<br \/>\n                if rule.target_level.value &gt; target_level.value:<br \/>\n                    target_level &#061; rule.target_level<\/p>\n<p>        return target_level<\/p>\n<p>    def _handle_normal(self, request, **kwargs):<br \/>\n        &#034;&#034;&#034;\u6b63\u5e38\u6a21\u5f0f\u5904\u7406&#034;&#034;&#034;<br \/>\n        return self._process_full_features(request, **kwargs)<\/p>\n<p>    def _handle_degraded(self, request, **kwargs):<br \/>\n        &#034;&#034;&#034;\u964d\u7ea7\u6a21\u5f0f\u5904\u7406&#034;&#034;&#034;<br \/>\n        # \u5173\u95ed\u975e\u6838\u5fc3\u529f\u80fd<br \/>\n        features &#061; kwargs.get(&#039;features&#039;, {})<\/p>\n<p>        # \u7981\u7528\u9ad8\u6210\u672c\u529f\u80fd<br \/>\n        if features.get(&#039;enable_ai_analysis&#039;, False):<br \/>\n            features[&#039;enable_ai_analysis&#039;] &#061; False<\/p>\n<p>        if features.get(&#039;enable_realtime_processing&#039;, False):<br \/>\n            features[&#039;enable_realtime_processing&#039;] &#061; False<\/p>\n<p>        # \u4f7f\u7528\u7f13\u5b58\u800c\u4e0d\u662f\u5b9e\u65f6\u8ba1\u7b97<br \/>\n        use_cache &#061; True<\/p>\n<p>        return self._process_basic_features(request,<br \/>\n                                           use_cache&#061;use_cache,<br \/>\n                                           **kwargs)<\/p>\n<p>    def _handle_minimal(self, request, **kwargs):<br \/>\n        &#034;&#034;&#034;\u6700\u5c0f\u529f\u80fd\u6a21\u5f0f&#034;&#034;&#034;<br \/>\n        # \u53ea\u63d0\u4f9b\u6838\u5fc3\u529f\u80fd<br \/>\n        features &#061; {<br \/>\n            &#039;enable_cache&#039;: True,<br \/>\n            &#039;enable_basic_processing&#039;: True,<br \/>\n            &#039;enable_advanced_features&#039;: False,<br \/>\n            &#039;enable_external_calls&#039;: False<br \/>\n        }<\/p>\n<p>        # \u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4<br \/>\n        kwargs[&#039;timeout&#039;] &#061; min(kwargs.get(&#039;timeout&#039;, 30), 5)<\/p>\n<p>        return self._process_minimal_features(request, **kwargs)<\/p>\n<p>    def _handle_emergency(self, request, **kwargs):<br \/>\n        &#034;&#034;&#034;\u7d27\u6025\u6a21\u5f0f&#034;&#034;&#034;<br \/>\n        # \u8fd4\u56de\u9759\u6001\u54cd\u5e94\u6216\u9519\u8bef\u9875\u9762<br \/>\n        return {<br \/>\n            &#034;status&#034;: 503,<br \/>\n            &#034;headers&#034;: {<br \/>\n                &#034;Content-Type&#034;: &#034;application\/json&#034;,<br \/>\n                &#034;Retry-After&#034;: &#034;60&#034;<br \/>\n            },<br \/>\n            &#034;body&#034;: {<br \/>\n                &#034;error&#034;: {<br \/>\n                    &#034;code&#034;: &#034;service_emergency&#034;,<br \/>\n                    &#034;message&#034;: &#034;Service is in emergency mode&#034;,<br \/>\n                    &#034;details&#034;: {<br \/>\n                        &#034;mode&#034;: &#034;emergency&#034;,<br \/>\n                        &#034;minimal_features_only&#034;: True,<br \/>\n                        &#034;estimated_recovery_time&#034;: &#034;unknown&#034;,<br \/>\n                        &#034;status_page&#034;: &#034;https:\/\/status.example.com&#034;<br \/>\n                    }<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>    def process_request(self, request, **kwargs):<br \/>\n        &#034;&#034;&#034;\u6839\u636e\u5f53\u524d\u964d\u7ea7\u7ea7\u522b\u5904\u7406\u8bf7\u6c42&#034;&#034;&#034;<br \/>\n        handler &#061; self.degradation_handlers[self.current_level]<br \/>\n        return handler(request, **kwargs)<\/p>\n<p>    def degrade_method(self, feature_name: str):<br \/>\n        &#034;&#034;&#034;\u65b9\u6cd5\u88c5\u9970\u5668&#xff1a;\u6839\u636e\u964d\u7ea7\u7ea7\u522b\u8c03\u6574\u884c\u4e3a&#034;&#034;&#034;<br \/>\n        def decorator(func):<br \/>\n            &#064;wraps(func)<br \/>\n            def wrapper(*args, **kwargs):<br \/>\n                # \u68c0\u67e5\u529f\u80fd\u5728\u5f53\u524d\u964d\u7ea7\u7ea7\u522b\u662f\u5426\u53ef\u7528<br \/>\n                if not self._is_feature_available(feature_name):<br \/>\n                    # \u8fd4\u56de\u964d\u7ea7\u54cd\u5e94<br \/>\n                    return self._get_degraded_response(feature_name)<\/p>\n<p>                # \u6839\u636e\u964d\u7ea7\u7ea7\u522b\u8c03\u6574\u53c2\u6570<br \/>\n                if self.current_level &#061;&#061; DegradationLevel.DEGRADED:<br \/>\n                    # \u964d\u7ea7\u6a21\u5f0f&#xff1a;\u589e\u52a0\u8d85\u65f6&#xff0c;\u7981\u7528\u67d0\u4e9b\u9009\u9879<br \/>\n                    kwargs[&#039;timeout&#039;] &#061; min(kwargs.get(&#039;timeout&#039;, 30), 10)<br \/>\n                    kwargs[&#039;enable_optimizations&#039;] &#061; False<\/p>\n<p>                elif self.current_level &#061;&#061; DegradationLevel.MINIMAL:<br \/>\n                    # \u6700\u5c0f\u6a21\u5f0f&#xff1a;\u4f7f\u7528\u7b80\u5316\u7248\u672c<br \/>\n                    if hasattr(func, &#039;minimal_version&#039;):<br \/>\n                        return func.minimal_version(*args, **kwargs)<\/p>\n<p>                return func(*args, **kwargs)<\/p>\n<p>            return wrapper<br \/>\n        return decorator<\/p>\n<p>    def _is_feature_available(self, feature_name: str) -&gt; bool:<br \/>\n        &#034;&#034;&#034;\u68c0\u67e5\u529f\u80fd\u5728\u5f53\u524d\u964d\u7ea7\u7ea7\u522b\u662f\u5426\u53ef\u7528&#034;&#034;&#034;<br \/>\n        feature_availability &#061; {<br \/>\n            DegradationLevel.NORMAL: [&#039;all&#039;],<br \/>\n            DegradationLevel.DEGRADED: [&#039;core&#039;, &#039;basic&#039;, &#039;cache&#039;],<br \/>\n            DegradationLevel.MINIMAL: [&#039;core&#039;, &#039;cache&#039;],<br \/>\n            DegradationLevel.EMERGENCY: [&#039;core&#039;]<br \/>\n        }<\/p>\n<p>        available_features &#061; feature_availability.get(<br \/>\n            self.current_level, [&#039;core&#039;]<br \/>\n        )<\/p>\n<p>        return &#039;all&#039; in available_features or feature_name in available_features<\/p>\n<h4>27.4 \u667a\u80fd\u91cd\u8bd5\u4e0e\u5ba2\u6237\u7aef\u5904\u7406<\/h4>\n<h5>27.4.1 \u5ba2\u6237\u7aef\u91cd\u8bd5\u7b56\u7565<\/h5>\n<p>javascript<\/p>\n<p>\/\/ \u667a\u80fd\u91cd\u8bd5\u5ba2\u6237\u7aef\u5b9e\u73b0<br \/>\nclass ResilientHttpClient {<br \/>\n    constructor(options &#061; {}) {<br \/>\n        this.defaultOptions &#061; {<br \/>\n            maxRetries: 3,<br \/>\n            baseDelay: 1000, \/\/ 1\u79d2<br \/>\n            maxDelay: 10000, \/\/ 10\u79d2<br \/>\n            retryOnStatus: [502, 503, 504],<br \/>\n            retryOnNetworkError: true,<br \/>\n            timeout: 30000,<br \/>\n            &#8230;options<br \/>\n        };<\/p>\n<p>        this.circuitBreakers &#061; new Map();<br \/>\n        this.metrics &#061; {<br \/>\n            totalRequests: 0,<br \/>\n            successfulRequests: 0,<br \/>\n            failedRequests: 0,<br \/>\n            retriedRequests: 0,<br \/>\n            circuitBreakerTrips: 0<br \/>\n        };<br \/>\n    }<\/p>\n<p>    async request(url, options &#061; {}) {<br \/>\n        const requestOptions &#061; { &#8230;this.defaultOptions, &#8230;options };<br \/>\n        const requestId &#061; this._generateRequestId();<\/p>\n<p>        this.metrics.totalRequests&#043;&#043;;<\/p>\n<p>        \/\/ \u68c0\u67e5\u65ad\u8def\u5668<br \/>\n        const circuitBreaker &#061; this._getCircuitBreaker(url);<br \/>\n        if (circuitBreaker.state &#061;&#061;&#061; &#039;OPEN&#039;) {<br \/>\n            this.metrics.circuitBreakerTrips&#043;&#043;;<br \/>\n            throw new CircuitBreakerOpenError(<br \/>\n                &#096;Circuit breaker open for ${url}&#096;,<br \/>\n                circuitBreaker.lastFailureTime<br \/>\n            );<br \/>\n        }<\/p>\n<p>        let lastError;<br \/>\n        let attempt &#061; 0;<\/p>\n<p>        while (attempt &lt;&#061; requestOptions.maxRetries) {<br \/>\n            attempt&#043;&#043;;<\/p>\n<p>            if (attempt &gt; 1) {<br \/>\n                this.metrics.retriedRequests&#043;&#043;;<\/p>\n<p>                \/\/ \u8ba1\u7b97\u9000\u907f\u5ef6\u8fdf<br \/>\n                const delay &#061; this._calculateBackoff(<br \/>\n                    attempt,<br \/>\n                    requestOptions.baseDelay,<br \/>\n                    requestOptions.maxDelay,<br \/>\n                    lastError<br \/>\n                );<\/p>\n<p>                await this._delay(delay);<br \/>\n            }<\/p>\n<p>            try {<br \/>\n                const controller &#061; new AbortController();<br \/>\n                const timeoutId &#061; setTimeout(<br \/>\n                    () &#061;&gt; controller.abort(),<br \/>\n                    requestOptions.timeout<br \/>\n                );<\/p>\n<p>                const response &#061; await fetch(url, {<br \/>\n                    &#8230;requestOptions,<br \/>\n                    signal: controller.signal,<br \/>\n                    headers: {<br \/>\n                        &#8230;requestOptions.headers,<br \/>\n                        &#039;X-Request-ID&#039;: requestId,<br \/>\n                        &#039;X-Retry-Attempt&#039;: attempt.toString()<br \/>\n                    }<br \/>\n                });<\/p>\n<p>                clearTimeout(timeoutId);<\/p>\n<p>                \/\/ \u68c0\u67e5\u662f\u5426\u9700\u8981\u91cd\u8bd5<br \/>\n                if (this._shouldRetry(response, attempt, requestOptions)) {<br \/>\n                    lastError &#061; new HttpError(<br \/>\n                        &#096;HTTP ${response.status}&#096;,<br \/>\n                        response.status,<br \/>\n                        response<br \/>\n                    );<\/p>\n<p>                    \/\/ \u4ece\u54cd\u5e94\u4e2d\u83b7\u53d6Retry-After<br \/>\n                    const retryAfter &#061; response.headers.get(&#039;Retry-After&#039;);<br \/>\n                    if (retryAfter) {<br \/>\n                        await this._delay(parseInt(retryAfter) * 1000);<br \/>\n                    }<\/p>\n<p>                    continue;<br \/>\n                }<\/p>\n<p>                \/\/ \u6210\u529f\u54cd\u5e94<br \/>\n                circuitBreaker.recordSuccess();<br \/>\n                this.metrics.successfulRequests&#043;&#043;;<\/p>\n<p>                return response;<\/p>\n<p>            } catch (error) {<br \/>\n                clearTimeout(timeoutId);<br \/>\n                lastError &#061; error;<\/p>\n<p>                \/\/ \u8bb0\u5f55\u5931\u8d25<br \/>\n                circuitBreaker.recordFailure();<\/p>\n<p>                \/\/ \u68c0\u67e5\u662f\u5426\u5e94\u8be5\u91cd\u8bd5<br \/>\n                if (!this._shouldRetryOnError(error, attempt, requestOptions)) {<br \/>\n                    break;<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>        \/\/ \u6240\u6709\u91cd\u8bd5\u5931\u8d25<br \/>\n        this.metrics.failedRequests&#043;&#043;;<br \/>\n        throw new MaxRetriesExceededError(<br \/>\n            &#096;Max retries (${requestOptions.maxRetries}) exceeded&#096;,<br \/>\n            lastError,<br \/>\n            attempt<br \/>\n        );<br \/>\n    }<\/p>\n<p>    _shouldRetry(response, attempt, options) {<br \/>\n        if (attempt &gt;&#061; options.maxRetries) {<br \/>\n            return false;<br \/>\n        }<\/p>\n<p>        \/\/ \u68c0\u67e5\u72b6\u6001\u7801<br \/>\n        if (options.retryOnStatus.includes(response.status)) {<br \/>\n            return true;<br \/>\n        }<\/p>\n<p>        \/\/ \u7279\u6b8a\u5904\u7406503\u54cd\u5e94<br \/>\n        if (response.status &#061;&#061;&#061; 503) {<br \/>\n            const retryAfter &#061; response.headers.get(&#039;Retry-After&#039;);<br \/>\n            if (retryAfter) {<br \/>\n                \/\/ \u670d\u52a1\u5668\u660e\u786e\u544a\u8bc9\u6211\u4eec\u5e94\u8be5\u4f55\u65f6\u91cd\u8bd5<br \/>\n                return true;<br \/>\n            }<\/p>\n<p>            \/\/ \u68c0\u67e5\u54cd\u5e94\u4f53\u662f\u5426\u8868\u660e\u4e34\u65f6\u6545\u969c<br \/>\n            try {<br \/>\n                \/\/ \u53ef\u4ee5\u89e3\u6790\u54cd\u5e94\u4f53\u83b7\u53d6\u66f4\u591a\u4fe1\u606f<br \/>\n                return true;<br \/>\n            } catch {<br \/>\n                return false;<br \/>\n            }<br \/>\n        }<\/p>\n<p>        return false;<br \/>\n    }<\/p>\n<p>    _calculateBackoff(attempt, baseDelay, maxDelay, error) {<br \/>\n        \/\/ \u6307\u6570\u9000\u907f<br \/>\n        let delay &#061; baseDelay * Math.pow(2, attempt &#8211; 1);<\/p>\n<p>        \/\/ \u6dfb\u52a0\u968f\u673a\u6296\u52a8<br \/>\n        delay *&#061; 0.8 &#043; Math.random() * 0.4;<\/p>\n<p>        \/\/ \u9650\u5236\u6700\u5927\u5ef6\u8fdf<br \/>\n        delay &#061; Math.min(delay, maxDelay);<\/p>\n<p>        \/\/ \u5bf9\u4e8e503\u54cd\u5e94&#xff0c;\u5982\u679c\u63d0\u4f9b\u4e86Retry-After&#xff0c;\u4f7f\u7528\u5b83<br \/>\n        if (error &amp;&amp; error.status &#061;&#061;&#061; 503) {<br \/>\n            const retryAfter &#061; error.response?.headers?.get(&#039;Retry-After&#039;);<br \/>\n            if (retryAfter) {<br \/>\n                const serverDelay &#061; parseInt(retryAfter) * 1000;<br \/>\n                if (!isNaN(serverDelay)) {<br \/>\n                    delay &#061; Math.max(delay, serverDelay);<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>        return Math.round(delay);<br \/>\n    }<\/p>\n<p>    _getCircuitBreaker(url) {<br \/>\n        const hostname &#061; new URL(url).hostname;<\/p>\n<p>        if (!this.circuitBreakers.has(hostname)) {<br \/>\n            this.circuitBreakers.set(hostname, new CircuitBreaker());<br \/>\n        }<\/p>\n<p>        return this.circuitBreakers.get(hostname);<br \/>\n    }<br \/>\n}<\/p>\n<p>class CircuitBreaker {<br \/>\n    constructor() {<br \/>\n        this.state &#061; &#039;CLOSED&#039;;<br \/>\n        this.failureCount &#061; 0;<br \/>\n        this.successCount &#061; 0;<br \/>\n        this.lastFailureTime &#061; null;<br \/>\n        this.halfOpenTimer &#061; null;<\/p>\n<p>        this.config &#061; {<br \/>\n            failureThreshold: 5,<br \/>\n            successThreshold: 3,<br \/>\n            timeout: 30000<br \/>\n        };<br \/>\n    }<\/p>\n<p>    recordSuccess() {<br \/>\n        this.successCount&#043;&#043;;<br \/>\n        this.failureCount &#061; 0;<\/p>\n<p>        if (this.state &#061;&#061;&#061; &#039;HALF_OPEN&#039; &amp;&amp;<br \/>\n            this.successCount &gt;&#061; this.config.successThreshold) {<br \/>\n            this.state &#061; &#039;CLOSED&#039;;<br \/>\n            this.successCount &#061; 0;<br \/>\n            clearTimeout(this.halfOpenTimer);<br \/>\n        }<br \/>\n    }<\/p>\n<p>    recordFailure() {<br \/>\n        this.failureCount&#043;&#043;;<br \/>\n        this.successCount &#061; 0;<br \/>\n        this.lastFailureTime &#061; Date.now();<\/p>\n<p>        if (this.state &#061;&#061;&#061; &#039;CLOSED&#039; &amp;&amp;<br \/>\n            this.failureCount &gt;&#061; this.config.failureThreshold) {<br \/>\n            this.state &#061; &#039;OPEN&#039;;<\/p>\n<p>            \/\/ \u8bbe\u7f6e\u534a\u5f00\u72b6\u6001\u5b9a\u65f6\u5668<br \/>\n            this.halfOpenTimer &#061; setTimeout(() &#061;&gt; {<br \/>\n                this.state &#061; &#039;HALF_OPEN&#039;;<br \/>\n            }, this.config.timeout);<br \/>\n        }<br \/>\n    }<br \/>\n}<\/p>\n<h4>27.5 \u7ef4\u62a4\u7a97\u53e3\u4e0e\u8ba1\u5212\u505c\u673a\u7ba1\u7406<\/h4>\n<h5>27.5.1 \u81ea\u52a8\u5316\u7ef4\u62a4\u534f\u8c03\u7cfb\u7edf<\/h5>\n<p>python<\/p>\n<p># \u7ef4\u62a4\u7a97\u53e3\u7ba1\u7406\u5668<br \/>\nfrom datetime import datetime, timedelta<br \/>\nfrom typing import List, Dict, Optional<br \/>\nfrom enum import Enum<br \/>\nimport asyncio<br \/>\nfrom pydantic import BaseModel, validator<\/p>\n<p>class MaintenanceType(Enum):<br \/>\n    PLANNED &#061; &#034;planned&#034;<br \/>\n    EMERGENCY &#061; &#034;emergency&#034;<br \/>\n    ROLLING &#061; &#034;rolling&#034;<br \/>\n    DATABASE &#061; &#034;database&#034;<\/p>\n<p>class MaintenanceWindow(BaseModel):<br \/>\n    id: str<br \/>\n    type: MaintenanceType<br \/>\n    start_time: datetime<br \/>\n    end_time: datetime<br \/>\n    duration_minutes: int<br \/>\n    description: str<br \/>\n    affected_services: List[str]<br \/>\n    notification_channels: List[str]<br \/>\n    status: str &#061; &#034;scheduled&#034;<\/p>\n<p>    &#064;validator(&#039;end_time&#039;)<br \/>\n    def validate_duration(cls, end_time, values):<br \/>\n        if &#039;start_time&#039; in values:<br \/>\n            if end_time &lt;&#061; values[&#039;start_time&#039;]:<br \/>\n                raise ValueError(&#039;End time must be after start time&#039;)<\/p>\n<p>            duration &#061; (end_time &#8211; values[&#039;start_time&#039;]).total_seconds() \/ 60<br \/>\n            if duration &gt; 240:  # 4\u5c0f\u65f6<br \/>\n                raise ValueError(&#039;Maintenance window cannot exceed 4 hours&#039;)<\/p>\n<p>        return end_time<\/p>\n<p>class MaintenanceCoordinator:<br \/>\n    def __init__(self):<br \/>\n        self.scheduled_windows: Dict[str, MaintenanceWindow] &#061; {}<br \/>\n        self.active_windows: Dict[str, MaintenanceWindow] &#061; {}<br \/>\n        self.service_dependencies &#061; self._load_dependencies()<\/p>\n<p>    async def schedule_maintenance(self, window: MaintenanceWindow):<br \/>\n        &#034;&#034;&#034;\u8ba1\u5212\u7ef4\u62a4\u7a97\u53e3&#034;&#034;&#034;<\/p>\n<p>        # \u68c0\u67e5\u51b2\u7a81<br \/>\n        conflicts &#061; self._find_conflicts(window)<br \/>\n        if conflicts:<br \/>\n            raise ValueError(f&#034;Conflicts with existing windows: {conflicts}&#034;)<\/p>\n<p>        # \u68c0\u67e5\u4f9d\u8d56\u670d\u52a1<br \/>\n        unavailable_services &#061; self._check_dependencies(window)<br \/>\n        if unavailable_services:<br \/>\n            raise ValueError(f&#034;Dependency services unavailable: {unavailable_services}&#034;)<\/p>\n<p>        # \u5b89\u6392\u7ef4\u62a4<br \/>\n        self.scheduled_windows[window.id] &#061; window<\/p>\n<p>        # \u53d1\u9001\u901a\u77e5<br \/>\n        await self._send_notifications(window, &#034;scheduled&#034;)<\/p>\n<p>        # \u8bbe\u7f6e\u5b9a\u65f6\u5668<br \/>\n        delay &#061; (window.start_time &#8211; datetime.now()).total_seconds()<br \/>\n        if delay &gt; 0:<br \/>\n            asyncio.create_task(self._start_maintenance(window.id, delay))<\/p>\n<p>        return window<\/p>\n<p>    async def _start_maintenance(self, window_id: str, delay: float):<br \/>\n        &#034;&#034;&#034;\u5f00\u59cb\u7ef4\u62a4\u7a97\u53e3&#034;&#034;&#034;<br \/>\n        await asyncio.sleep(delay)<\/p>\n<p>        window &#061; self.scheduled_windows.get(window_id)<br \/>\n        if not window:<br \/>\n            return<\/p>\n<p>        # \u66f4\u65b0\u72b6\u6001<br \/>\n        window.status &#061; &#034;in_progress&#034;<br \/>\n        self.active_windows[window_id] &#061; window<\/p>\n<p>        # \u5f00\u59cb\u670d\u52a1\u964d\u7ea7<br \/>\n        await self._initiate_service_degradation(window)<\/p>\n<p>        # \u53d1\u9001\u5f00\u59cb\u901a\u77e5<br \/>\n        await self._send_notifications(window, &#034;started&#034;)<\/p>\n<p>        # \u8bbe\u7f6e\u7ed3\u675f\u5b9a\u65f6\u5668<br \/>\n        duration &#061; (window.end_time &#8211; window.start_time).total_seconds()<br \/>\n        asyncio.create_task(self._end_maintenance(window_id, duration))<\/p>\n<p>    async def _end_maintenance(self, window_id: str, delay: float):<br \/>\n        &#034;&#034;&#034;\u7ed3\u675f\u7ef4\u62a4\u7a97\u53e3&#034;&#034;&#034;<br \/>\n        await asyncio.sleep(delay)<\/p>\n<p>        window &#061; self.active_windows.get(window_id)<br \/>\n        if not window:<br \/>\n            return<\/p>\n<p>        # \u66f4\u65b0\u72b6\u6001<br \/>\n        window.status &#061; &#034;completed&#034;<\/p>\n<p>        # \u6062\u590d\u670d\u52a1<br \/>\n        await self._restore_services(window)<\/p>\n<p>        # \u6e05\u7406<br \/>\n        del self.active_windows[window_id]<br \/>\n        del self.scheduled_windows[window_id]<\/p>\n<p>        # \u53d1\u9001\u5b8c\u6210\u901a\u77e5<br \/>\n        await self._send_notifications(window, &#034;completed&#034;)<\/p>\n<p>        # \u8fd0\u884c\u9a8c\u8bc1\u6d4b\u8bd5<br \/>\n        await self._run_post_maintenance_tests(window)<\/p>\n<p>    async def _initiate_service_degradation(self, window: MaintenanceWindow):<br \/>\n        &#034;&#034;&#034;\u542f\u52a8\u670d\u52a1\u964d\u7ea7\u6d41\u7a0b&#034;&#034;&#034;<\/p>\n<p>        for service in window.affected_services:<br \/>\n            # \u53d1\u9001\u4f18\u96c5\u5173\u95ed\u4fe1\u53f7<br \/>\n            await self._graceful_shutdown(service)<\/p>\n<p>            # \u8bbe\u7f6e\u5065\u5eb7\u68c0\u67e5\u4e3a\u4e0d\u5065\u5eb7<br \/>\n            await self._update_health_check(service, False)<\/p>\n<p>            # \u4ece\u8d1f\u8f7d\u5747\u8861\u5668\u4e2d\u79fb\u9664<br \/>\n            await self._remove_from_load_balancer(service)<\/p>\n<p>            # \u53d1\u9001503\u54cd\u5e94<br \/>\n            await self._enable_maintenance_mode(service, window)<\/p>\n<p>    async def _enable_maintenance_mode(self, service: str, window: MaintenanceWindow):<br \/>\n        &#034;&#034;&#034;\u542f\u7528\u7ef4\u62a4\u6a21\u5f0f&#034;&#034;&#034;<\/p>\n<p>        maintenance_response &#061; {<br \/>\n            &#034;status&#034;: 503,<br \/>\n            &#034;headers&#034;: {<br \/>\n                &#034;Content-Type&#034;: &#034;application\/json&#034;,<br \/>\n                &#034;Retry-After&#034;: self._calculate_retry_after(window),<br \/>\n                &#034;X-Maintenance-ID&#034;: window.id,<br \/>\n                &#034;X-Maintenance-End&#034;: window.end_time.isoformat()<br \/>\n            },<br \/>\n            &#034;body&#034;: {<br \/>\n                &#034;error&#034;: {<br \/>\n                    &#034;code&#034;: &#034;maintenance_mode&#034;,<br \/>\n                    &#034;message&#034;: &#034;Service is undergoing maintenance&#034;,<br \/>\n                    &#034;details&#034;: {<br \/>\n                        &#034;maintenance_id&#034;: window.id,<br \/>\n                        &#034;start_time&#034;: window.start_time.isoformat(),<br \/>\n                        &#034;estimated_end_time&#034;: window.end_time.isoformat(),<br \/>\n                        &#034;description&#034;: window.description,<br \/>\n                        &#034;status_page&#034;: &#034;https:\/\/status.example.com&#034;,<br \/>\n                        &#034;updates_channel&#034;: &#034;https:\/\/updates.example.com\/maintenance&#034;<br \/>\n                    }<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>        # \u5e94\u7528\u7ef4\u62a4\u6a21\u5f0f\u54cd\u5e94<br \/>\n        await self._apply_maintenance_response(service, maintenance_response)<\/p>\n<p>    def _calculate_retry_after(self, window: MaintenanceWindow) -&gt; str:<br \/>\n        &#034;&#034;&#034;\u8ba1\u7b97Retry-After\u5934\u90e8\u503c&#034;&#034;&#034;<br \/>\n        remaining &#061; window.end_time &#8211; datetime.now()<br \/>\n        minutes &#061; max(1, int(remaining.total_seconds() \/ 60))<br \/>\n        return str(min(minutes, 60))  # \u6700\u591a60\u5206\u949f<\/p>\n<p>    async def _send_notifications(self, window: MaintenanceWindow, event: str):<br \/>\n        &#034;&#034;&#034;\u53d1\u9001\u7ef4\u62a4\u901a\u77e5&#034;&#034;&#034;<\/p>\n<p>        notifications &#061; {<br \/>\n            &#034;scheduled&#034;: {<br \/>\n                &#034;title&#034;: &#034;&#x1f6e0;\ufe0f \u8ba1\u5212\u7ef4\u62a4\u901a\u77e5&#034;,<br \/>\n                &#034;message&#034;: f&#034;\u670d\u52a1 {&#039;, &#039;.join(window.affected_services)} \u8ba1\u5212\u4e8e &#034;<br \/>\n                         f&#034;{window.start_time.strftime(&#039;%Y-%m-%d %H:%M&#039;)} \u8fdb\u884c\u7ef4\u62a4\u3002&#034;,<br \/>\n                &#034;priority&#034;: &#034;medium&#034;<br \/>\n            },<br \/>\n            &#034;started&#034;: {<br \/>\n                &#034;title&#034;: &#034;&#x1f527; \u7ef4\u62a4\u5df2\u5f00\u59cb&#034;,<br \/>\n                &#034;message&#034;: f&#034;\u7ef4\u62a4\u5df2\u5f00\u59cb&#xff0c;\u9884\u8ba1\u6301\u7eed {window.duration_minutes} \u5206\u949f\u3002&#034;,<br \/>\n                &#034;priority&#034;: &#034;high&#034;<br \/>\n            },<br \/>\n            &#034;completed&#034;: {<br \/>\n                &#034;title&#034;: &#034;\u2705 \u7ef4\u62a4\u5df2\u5b8c\u6210&#034;,<br \/>\n                &#034;message&#034;: &#034;\u7ef4\u62a4\u5df2\u5b8c\u6210&#xff0c;\u6240\u6709\u670d\u52a1\u5df2\u6062\u590d\u6b63\u5e38\u3002&#034;,<br \/>\n                &#034;priority&#034;: &#034;medium&#034;<br \/>\n            }<br \/>\n        }<\/p>\n<p>        if event not in notifications:<br \/>\n            return<\/p>\n<p>        notification &#061; notifications[event]<\/p>\n<p>        # \u53d1\u9001\u5230\u4e0d\u540c\u6e20\u9053<br \/>\n        for channel in window.notification_channels:<br \/>\n            if channel &#061;&#061; &#034;email&#034;:<br \/>\n                await self._send_email_notification(window, notification)<br \/>\n            elif channel &#061;&#061; &#034;slack&#034;:<br \/>\n                await self._send_slack_notification(window, notification)<br \/>\n            elif channel &#061;&#061; &#034;webhook&#034;:<br \/>\n                await self._send_webhook_notification(window, notification)<\/p>\n<p>    def _find_conflicts(self, new_window: MaintenanceWindow) -&gt; List[str]:<br \/>\n        &#034;&#034;&#034;\u67e5\u627e\u65f6\u95f4\u51b2\u7a81\u7684\u7ef4\u62a4\u7a97\u53e3&#034;&#034;&#034;<br \/>\n        conflicts &#061; []<\/p>\n<p>        for window_id, existing in self.scheduled_windows.items():<br \/>\n            if (new_window.start_time &lt; existing.end_time and<br \/>\n                new_window.end_time &gt; existing.start_time):<\/p>\n<p>                # \u68c0\u67e5\u662f\u5426\u6709\u670d\u52a1\u91cd\u53e0<br \/>\n                overlapping_services &#061; set(new_window.affected_services) &amp; \\\\<br \/>\n                                      set(existing.affected_services)<\/p>\n<p>                if overlapping_services:<br \/>\n                    conflicts.append(f&#034;{window_id}: {&#039;, &#039;.join(overlapping_services)}&#034;)<\/p>\n<p>        return conflicts<\/p>\n<h4>27.6 \u6700\u4f73\u5b9e\u8df5\u603b\u7ed3<\/h4>\n<h5>27.6.1 \u5bb9\u91cf\u89c4\u5212\u6307\u5357<\/h5>\n<li>\n<p>\u57fa\u51c6\u6d4b\u8bd5&#xff1a;<\/p>\n<p>bash<\/p>\n<p># \u4f7f\u7528wrk\u8fdb\u884c\u8d1f\u8f7d\u6d4b\u8bd5<br \/>\nwrk -t12 -c400 -d30s &#8211;latency https:\/\/api.example.com<\/p>\n<p># \u5173\u952e\u6307\u6807&#xff1a;<br \/>\n# &#8211; \u6700\u5927QPS&#xff08;\u6bcf\u79d2\u67e5\u8be2\u6570&#xff09;<br \/>\n# &#8211; 95%\u54cd\u5e94\u65f6\u95f4<br \/>\n# &#8211; \u9519\u8bef\u7387\n<\/li>\n<li>\n<p>\u5bb9\u91cf\u516c\u5f0f&#xff1a;<\/p>\n<p>text<\/p>\n<p>\u6240\u9700\u5b9e\u4f8b\u6570 &#061; (\u9884\u671fQPS \u00d7 \u5e73\u5747\u54cd\u5e94\u65f6\u95f4) \/ \u76ee\u6807\u5229\u7528\u7387<\/p>\n<p>\u793a\u4f8b&#xff1a;<br \/>\n\u9884\u671fQPS &#061; 1000<br \/>\n\u5e73\u5747\u54cd\u5e94\u65f6\u95f4 &#061; 0.1\u79d2<br \/>\n\u76ee\u6807\u5229\u7528\u7387 &#061; 0.7<\/p>\n<p>\u6240\u9700\u5b9e\u4f8b\u6570 &#061; (1000 \u00d7 0.1) \/ 0.7 \u2248 143\u4e2a\u8fde\u63a5\n<\/li>\n<h5>27.6.2 \u964d\u7ea7\u7b56\u7565\u77e9\u9635<\/h5>\n<table>\n<tr>\u964d\u7ea7\u7ea7\u522b\u529f\u80fd\u53ef\u7528\u6027\u54cd\u5e94\u65f6\u95f4\u7528\u6237\u4f53\u9a8c\u4e1a\u52a1\u5f71\u54cd<\/tr>\n<tbody>\n<tr>\n<td>\u6b63\u5e38<\/td>\n<td>100%\u529f\u80fd<\/td>\n<td>&lt;200ms<\/td>\n<td>\u5b8c\u6574\u4f53\u9a8c<\/td>\n<td>\u65e0\u5f71\u54cd<\/td>\n<\/tr>\n<tr>\n<td>\u964d\u7ea7<\/td>\n<td>\u6838\u5fc3\u529f\u80fd<\/td>\n<td>&lt;500ms<\/td>\n<td>\u90e8\u5206\u53d7\u9650<\/td>\n<td>\u4f4e\u5f71\u54cd<\/td>\n<\/tr>\n<tr>\n<td>\u6700\u5c0f<\/td>\n<td>\u5173\u952e\u529f\u80fd<\/td>\n<td>&lt;1000ms<\/td>\n<td>\u57fa\u672c\u53ef\u7528<\/td>\n<td>\u4e2d\u5f71\u54cd<\/td>\n<\/tr>\n<tr>\n<td>\u7d27\u6025<\/td>\n<td>\u53ea\u8bfb\u529f\u80fd<\/td>\n<td>N\/A<\/td>\n<td>\u9759\u6001\u9875\u9762<\/td>\n<td>\u9ad8\u5f71\u54cd<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h5>27.6.3 \u76d1\u63a7\u544a\u8b66\u9608\u503c<\/h5>\n<p>text<\/p>\n<p>\u2705 \u9519\u8bef\u7387\u544a\u8b66&#xff1a;&gt; 1% \u6301\u7eed5\u5206\u949f<br \/>\n\u2705 \u54cd\u5e94\u65f6\u95f4\u544a\u8b66&#xff1a;P95 &gt; 500ms \u6301\u7eed10\u5206\u949f<br \/>\n\u2705 \u961f\u5217\u957f\u5ea6\u544a\u8b66&#xff1a;&gt; 1000 \u6301\u7eed2\u5206\u949f<br \/>\n\u2705 CPU\u4f7f\u7528\u7387\u544a\u8b66&#xff1a;&gt; 80% \u6301\u7eed5\u5206\u949f<br \/>\n\u2705 \u5185\u5b58\u4f7f\u7528\u7387\u544a\u8b66&#xff1a;&gt; 90% \u6301\u7eed2\u5206\u949f<\/p>\n<p>\u901a\u8fc7\u5b9e\u65bd\u8fd9\u4e9b\u7b56\u7565&#xff0c;\u53ef\u4ee5\u6709\u6548\u5730\u7ba1\u7406\u670d\u52a1\u4e0d\u53ef\u7528\u60c5\u51b5&#xff0c;\u63d0\u4f9b\u66f4\u597d\u7684\u7528\u6237\u4f53\u9a8c&#xff0c;\u540c\u65f6\u786e\u4fdd\u7cfb\u7edf\u7684\u7a33\u5b9a\u6027\u548c\u53ef\u9760\u6027\u3002<\/p>\n<hr \/>\n<h3>\u7b2c28\u7ae0&#xff1a;504 Gateway Timeout &#8211; \u7f51\u5173\u8d85\u65f6<\/h3>\n<h4>28.1 \u6df1\u5ea6\u89e3\u6790\u7f51\u5173\u8d85\u65f6\u673a\u5236<\/h4>\n<p>504 Gateway Timeout\u00a0\u8868\u793a\u7f51\u5173\u6216\u4ee3\u7406\u670d\u52a1\u5668\u672a\u80fd\u53ca\u65f6\u4ece\u4e0a\u6e38\u670d\u52a1\u5668\u6536\u5230\u54cd\u5e94\u3002\u8fd9\u662f\u5206\u5e03\u5f0f\u7cfb\u7edf\u4e2d\u5e38\u89c1\u7684\u8d85\u65f6\u9519\u8bef&#xff0c;\u901a\u5e38\u7531\u7f51\u7edc\u5ef6\u8fdf\u6216\u4e0a\u6e38\u670d\u52a1\u5904\u7406\u7f13\u6162\u5f15\u8d77\u3002<\/p>\n<h5>28.1.1 \u534f\u8bae\u89c4\u8303\u4e0e\u8d85\u65f6\u8bed\u4e49<\/h5>\n<ul>\n<li>\n<p>RFC 7231\u5b9a\u4e49&#xff1a;\u670d\u52a1\u5668\u4f5c\u4e3a\u7f51\u5173\u6216\u4ee3\u7406&#xff0c;\u672a\u80fd\u53ca\u65f6\u4ece\u4e0a\u6e38\u670d\u52a1\u5668\u6536\u5230\u54cd\u5e94<\/p>\n<\/li>\n<li>\n<p>\u5173\u952e\u7279\u5f81&#xff1a;<\/p>\n<ul>\n<li>\n<p>\u8d85\u65f6\u53d1\u751f\u5728\u7f51\u5173\u5c42\u9762<\/p>\n<\/li>\n<li>\n<p>\u4e0a\u6e38\u670d\u52a1\u5668\u53ef\u80fd\u4ecd\u5728\u5904\u7406\u8bf7\u6c42<\/p>\n<\/li>\n<li>\n<p>\u4e0e502 Bad Gateway\u7684\u4e3b\u8981\u533a\u522b&#xff1a;502\u662f\u8fde\u63a5\u5931\u8d25&#xff0c;504\u662f\u54cd\u5e94\u8d85\u65f6<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h5>28.1.2 \u5206\u5e03\u5f0f\u7cfb\u7edf\u4e2d\u7684\u8d85\u65f6\u4f20\u64ad<img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1742\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/07\/20260726181701-6a664f1d954a1.png\" width=\"1272\" \/><\/h5>\n<h4>28.2 \u8d85\u65f6\u914d\u7f6e\u4e0e\u4f18\u5316\u7b56\u7565<\/h4>\n<h5>28.2.1 \u591a\u5c42\u8d85\u65f6\u914d\u7f6e\u6a21\u578b<\/h5>\n<p>yaml<\/p>\n<p># \u5206\u5e03\u5f0f\u8d85\u65f6\u914d\u7f6e\u7ba1\u7406<br \/>\ntimeout_config:<br \/>\n  # \u5168\u5c40\u9ed8\u8ba4\u914d\u7f6e<br \/>\n  defaults:<br \/>\n    connect_timeout: 5s<br \/>\n    read_timeout: 30s<br \/>\n    write_timeout: 30s<br \/>\n    total_timeout: 60s<\/p>\n<p>  # \u670d\u52a1\u7ea7\u914d\u7f6e<br \/>\n  services:<br \/>\n    user_service:<br \/>\n      endpoint: &#034;\/api\/v1\/users&#034;<br \/>\n      timeouts:<br \/>\n        connect: 2s<br \/>\n        read: 10s<br \/>\n        write: 10s<br \/>\n        total: 15s<br \/>\n      retry_policy:<br \/>\n        max_attempts: 3<br \/>\n        backoff_base: 1s<br \/>\n        backoff_max: 10s<\/p>\n<p>    payment_service:<br \/>\n      endpoint: &#034;\/api\/v1\/payments&#034;<br \/>\n      timeouts:<br \/>\n        connect: 5s<br \/>\n        read: 60s      # \u652f\u4ed8\u5904\u7406\u53ef\u80fd\u8f83\u957f<br \/>\n        write: 30s<br \/>\n        total: 90s<br \/>\n      circuit_breaker:<br \/>\n        failure_threshold: 5<br \/>\n        success_threshold: 3<br \/>\n        timeout: 30s<\/p>\n<p>    search_service:<br \/>\n      endpoint: &#034;\/api\/v1\/search&#034;<br \/>\n      timeouts:<br \/>\n        connect: 1s<br \/>\n        read: 5s       # \u641c\u7d22\u9700\u8981\u5feb\u901f\u54cd\u5e94<br \/>\n        write: 2s<br \/>\n        total: 10s<br \/>\n      fallback:<br \/>\n        enabled: true<br \/>\n        timeout: 2s<br \/>\n        response: &#034;cached_results&#034;<\/p>\n<p>  # \u4f9d\u8d56\u7ea7\u914d\u7f6e<br \/>\n  dependencies:<br \/>\n    database:<br \/>\n      primary:<br \/>\n        connect_timeout: 3s<br \/>\n        query_timeout: 10s<br \/>\n        transaction_timeout: 30s<br \/>\n      replica:<br \/>\n        connect_timeout: 5s<br \/>\n        query_timeout: 15s<br \/>\n        read_only: true<\/p>\n<p>    cache:<br \/>\n      redis:<br \/>\n        connect_timeout: 1s<br \/>\n        operation_timeout: 2s<br \/>\n        pool_timeout: 5s<\/p>\n<p>      memcached:<br \/>\n        connect_timeout: 1s<br \/>\n        operation_timeout: 2s<\/p>\n<p>    external_apis:<br \/>\n      payment_gateway:<br \/>\n        timeout: 30s<br \/>\n        retry_count: 2<\/p>\n<p>      email_service:<br \/>\n        timeout: 10s<br \/>\n        async: true    # \u53ef\u4ee5\u5f02\u6b65\u5904\u7406<\/p>\n<p>      analytics:<br \/>\n        timeout: 5s<br \/>\n        fire_and_forget: true  # \u975e\u5173\u952e\u8def\u5f84<\/p>\n<p>  # \u81ea\u9002\u5e94\u8d85\u65f6\u914d\u7f6e<br \/>\n  adaptive:<br \/>\n    enabled: true<br \/>\n    sampling_rate: 0.1      # 10%\u7684\u8bf7\u6c42\u7528\u4e8e\u5b66\u4e60<br \/>\n    history_window: &#034;5m&#034;<br \/>\n    percentiles:<br \/>\n      &#8211; 95    # P95\u54cd\u5e94\u65f6\u95f4<br \/>\n      &#8211; 99    # P99\u54cd\u5e94\u65f6\u95f4<\/p>\n<p>    adjustment:<br \/>\n      min_timeout: &#034;100ms&#034;<br \/>\n      max_timeout: &#034;300s&#034;<br \/>\n      adjustment_factor: 1.5  # \u57fa\u4e8eP99\u76841.5\u500d<br \/>\n      cooldown_period: &#034;30s&#034;<\/p>\n<h5>28.2.2 Nginx\u8d85\u65f6\u4f18\u5316\u914d\u7f6e<\/h5>\n<p>nginx<\/p>\n<p># Nginx\u9ad8\u7ea7\u8d85\u65f6\u914d\u7f6e<br \/>\nhttp {<br \/>\n    # \u5168\u5c40\u8d85\u65f6\u8bbe\u7f6e<br \/>\n    keepalive_timeout 75s;<br \/>\n    keepalive_requests 1000;<\/p>\n<p>    # \u89e3\u6790\u8d85\u65f6<br \/>\n    resolver 8.8.8.8 8.8.4.4 valid&#061;300s;<br \/>\n    resolver_timeout 5s;<\/p>\n<p>    # \u5ba2\u6237\u7aef\u8d85\u65f6<br \/>\n    client_body_timeout 60s;<br \/>\n    client_header_timeout 60s;<br \/>\n    send_timeout 60s;<\/p>\n<p>    # \u9650\u5236\u5ba2\u6237\u7aef\u8bf7\u6c42\u5927\u5c0f<br \/>\n    client_max_body_size 100m;<\/p>\n<p>    upstream backend {<br \/>\n        server 10.0.1.1:8080;<br \/>\n        server 10.0.1.2:8080;<\/p>\n<p>        # \u8fde\u63a5\u6c60\u914d\u7f6e<br \/>\n        keepalive 100;<br \/>\n        keepalive_timeout 60s;<br \/>\n        keepalive_requests 1000;<br \/>\n    }<\/p>\n<p>    server {<br \/>\n        listen 80;<\/p>\n<p>        location \/api\/ {<br \/>\n            proxy_pass http:\/\/backend;<\/p>\n<p>            # \u4ee3\u7406\u8d85\u65f6\u8bbe\u7f6e<br \/>\n            proxy_connect_timeout 5s;<br \/>\n            proxy_send_timeout 30s;<br \/>\n            proxy_read_timeout 30s;<\/p>\n<p>            # \u7f13\u51b2\u8bbe\u7f6e<br \/>\n            proxy_buffering on;<br \/>\n            proxy_buffer_size 8k;<br \/>\n            proxy_buffers 16 8k;<br \/>\n            proxy_busy_buffers_size 16k;<br \/>\n            proxy_temp_file_write_size 16k;<\/p>\n<p>            # \u91cd\u8bd5\u914d\u7f6e<br \/>\n            proxy_next_upstream error timeout invalid_header http_502 http_503 http_504;<br \/>\n            proxy_next_upstream_tries 3;<br \/>\n            proxy_next_upstream_timeout 10s;<\/p>\n<p>            # \u8d85\u65f6\u9519\u8bef\u5904\u7406<br \/>\n            proxy_intercept_errors on;<br \/>\n            error_page 504 &#061; &#064;gateway_timeout;<br \/>\n        }<\/p>\n<p>        # \u81ea\u5b9a\u4e49504\u5904\u7406<br \/>\n        location &#064;gateway_timeout {<br \/>\n            default_type application\/json;<\/p>\n<p>            # \u6dfb\u52a0\u91cd\u8bd5\u5934\u90e8<br \/>\n            add_header Retry-After 30;<br \/>\n            add_header X-Request-ID $request_id;<br \/>\n            add_header X-Upstream-Timeout &#034;true&#034;;<\/p>\n<p>            # \u8fd4\u56deJSON\u9519\u8bef\u54cd\u5e94<br \/>\n            return 504 &#039;{<br \/>\n                &#034;error&#034;: {<br \/>\n                    &#034;code&#034;: &#034;gateway_timeout&#034;,<br \/>\n                    &#034;message&#034;: &#034;Upstream server did not respond in time&#034;,<br \/>\n                    &#034;request_id&#034;: &#034;$request_id&#034;,<br \/>\n                    &#034;timestamp&#034;: &#034;$time_iso8601&#034;,<br \/>\n                    &#034;upstream&#034;: &#034;$proxy_host&#034;,<br \/>\n                    &#034;suggested_actions&#034;: [<br \/>\n                        &#034;Please retry your request&#034;,<br \/>\n                        &#034;Check service status at status.example.com&#034;,<br \/>\n                        &#034;Contact support if the issue persists&#034;<br \/>\n                    ]<br \/>\n                }<br \/>\n            }&#039;;<br \/>\n        }<\/p>\n<p>        # \u6162\u8bf7\u6c42\u65e5\u5fd7\u8bb0\u5f55<br \/>\n        log_format slow_requests &#039;$remote_addr &#8211; $remote_user [$time_local] &#039;<br \/>\n                                 &#039;&#034;$request&#034; $status $body_bytes_sent &#039;<br \/>\n                                 &#039;&#034;$http_referer&#034; &#034;$http_user_agent&#034; &#039;<br \/>\n                                 &#039;$request_time $upstream_response_time &#039;<br \/>\n                                 &#039;$upstream_addr $upstream_status&#039;;<\/p>\n<p>        access_log \/var\/log\/nginx\/slow_requests.log slow_requests<br \/>\n                   if&#061;$slow_request;<\/p>\n<p>        # \u5b9a\u4e49\u6162\u8bf7\u6c42&#xff08;\u8d85\u8fc75\u79d2&#xff09;<br \/>\n        map $request_time $slow_request {<br \/>\n            default 0;<br \/>\n            &#034;~^[5-9]\\\\.&#034; 1;    # 5-9\u79d2<br \/>\n            &#034;~^[1-9][0-9]&#034; 1; # 10\u79d2\u4ee5\u4e0a<br \/>\n        }<br \/>\n    }<br \/>\n}<\/p>\n<h4>28.3 \u667a\u80fd\u8d85\u65f6\u7ba1\u7406<\/h4>\n<h5>28.3.1 \u81ea\u9002\u5e94\u8d85\u65f6\u7b97\u6cd5<\/h5>\n<p>python<\/p>\n<p># \u81ea\u9002\u5e94\u8d85\u65f6\u7ba1\u7406\u7cfb\u7edf<br \/>\nimport time<br \/>\nimport statistics<br \/>\nfrom typing import List, Dict, Optional<br \/>\nfrom collections import deque<br \/>\nfrom dataclasses import dataclass<br \/>\nfrom datetime import datetime, timedelta<br \/>\nimport numpy as np<\/p>\n<p>&#064;dataclass<br \/>\nclass TimeoutMetrics:<br \/>\n    &#034;&#034;&#034;\u8d85\u65f6\u6307\u6807&#034;&#034;&#034;<br \/>\n    p50_response_time: float<br \/>\n    p95_response_time: float<br \/>\n    p99_response_time: float<br \/>\n    success_rate: float<br \/>\n    timeout_rate: float<br \/>\n    total_requests: int<br \/>\n    sample_size: int<\/p>\n<p>class AdaptiveTimeoutManager:<br \/>\n    &#034;&#034;&#034;\u81ea\u9002\u5e94\u8d85\u65f6\u7ba1\u7406\u5668&#034;&#034;&#034;<\/p>\n<p>    def __init__(self, service_name: str, initial_timeout: float &#061; 30.0):<br \/>\n        self.service_name &#061; service_name<br \/>\n        self.base_timeout &#061; initial_timeout<br \/>\n        self.current_timeout &#061; initial_timeout<br \/>\n        self.min_timeout &#061; 0.1  # 100ms<br \/>\n        self.max_timeout &#061; 300.0  # 5\u5206\u949f<\/p>\n<p>        # \u5386\u53f2\u6570\u636e\u5b58\u50a8<br \/>\n        self.response_times: deque &#061; deque(maxlen&#061;10000)<br \/>\n        self.timeout_history: deque &#061; deque(maxlen&#061;1000)<br \/>\n        self.metrics_history: deque &#061; deque(maxlen&#061;100)<\/p>\n<p>        # \u81ea\u9002\u5e94\u53c2\u6570<br \/>\n        self.percentile_target &#061; 99  # \u57fa\u4e8eP99\u8c03\u6574<br \/>\n        self.safety_factor &#061; 1.5     # \u5b89\u5168\u7cfb\u6570<br \/>\n        self.adjustment_cooldown &#061; 30  # \u8c03\u6574\u51b7\u5374\u65f6\u95f4&#xff08;\u79d2&#xff09;<br \/>\n        self.last_adjustment &#061; 0<\/p>\n<p>        # \u7edf\u8ba1\u5468\u671f<br \/>\n        self.window_size &#061; 300  # 5\u5206\u949f\u7a97\u53e3<\/p>\n<p>    def record_response(self, response_time: float, timed_out: bool &#061; False):<br \/>\n        &#034;&#034;&#034;\u8bb0\u5f55\u54cd\u5e94\u65f6\u95f4&#034;&#034;&#034;<br \/>\n        self.response_times.append({<br \/>\n            &#039;timestamp&#039;: time.time(),<br \/>\n            &#039;response_time&#039;: response_time,<br \/>\n            &#039;timed_out&#039;: timed_out<br \/>\n        })<\/p>\n<p>        if timed_out:<br \/>\n            self.timeout_history.append(time.time())<\/p>\n<p>        # \u5b9a\u671f\u8c03\u6574\u8d85\u65f6\u65f6\u95f4<br \/>\n        if time.time() &#8211; self.last_adjustment &gt; self.adjustment_cooldown:<br \/>\n            self._adjust_timeout()<\/p>\n<p>    def _adjust_timeout(self):<br \/>\n        &#034;&#034;&#034;\u8c03\u6574\u8d85\u65f6\u65f6\u95f4&#034;&#034;&#034;<br \/>\n        current_time &#061; time.time()<\/p>\n<p>        # \u83b7\u53d6\u7a97\u53e3\u5185\u7684\u6570\u636e<br \/>\n        window_start &#061; current_time &#8211; self.window_size<br \/>\n        recent_responses &#061; [<br \/>\n            r for r in self.response_times<br \/>\n            if r[&#039;timestamp&#039;] &gt; window_start<br \/>\n        ]<\/p>\n<p>        if len(recent_responses) &lt; 100:  # \u6700\u5c11100\u4e2a\u6837\u672c<br \/>\n            return<\/p>\n<p>        # \u8ba1\u7b97\u7edf\u8ba1\u6307\u6807<br \/>\n        response_times &#061; [r[&#039;response_time&#039;] for r in recent_responses]<br \/>\n        timeouts &#061; sum(1 for r in recent_responses if r[&#039;timed_out&#039;])<\/p>\n<p>        if not response_times:<br \/>\n            return<\/p>\n<p>        # \u8ba1\u7b97\u767e\u5206\u4f4d\u6570<br \/>\n        try:<br \/>\n            p95 &#061; np.percentile(response_times, 95)<br \/>\n            p99 &#061; np.percentile(response_times, 99)<\/p>\n<p>            # \u8ba1\u7b97\u6210\u529f\u7387<br \/>\n            success_rate &#061; 1 &#8211; (timeouts \/ len(recent_responses))<\/p>\n<p>            # \u57fa\u4e8eP99\u548c\u5b89\u5168\u7cfb\u6570\u8ba1\u7b97\u65b0\u8d85\u65f6\u65f6\u95f4<br \/>\n            new_timeout &#061; p99 * self.safety_factor<\/p>\n<p>            # \u5e94\u7528\u8fb9\u754c\u6761\u4ef6<br \/>\n            new_timeout &#061; max(self.min_timeout, min(new_timeout, self.max_timeout))<\/p>\n<p>            # \u907f\u514d\u9891\u7e41\u8c03\u6574&#xff08;\u53d8\u5316\u5c0f\u4e8e10%\u65f6\u4e0d\u8c03\u6574&#xff09;<br \/>\n            if abs(new_timeout &#8211; self.current_timeout) \/ self.current_timeout &gt; 0.1:<br \/>\n                old_timeout &#061; self.current_timeout<br \/>\n                self.current_timeout &#061; new_timeout<br \/>\n                self.last_adjustment &#061; current_time<\/p>\n<p>                # \u8bb0\u5f55\u8c03\u6574<br \/>\n                self._log_adjustment(old_timeout, new_timeout, p95, p99, success_rate)<\/p>\n<p>        except Exception as e:<br \/>\n            print(f&#034;Error adjusting timeout: {e}&#034;)<\/p>\n<p>    def get_timeout_for_percentile(self, percentile: int &#061; 95) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u83b7\u53d6\u7279\u5b9a\u767e\u5206\u4f4d\u7684\u63a8\u8350\u8d85\u65f6\u65f6\u95f4&#034;&#034;&#034;<br \/>\n        if not self.response_times:<br \/>\n            return self.base_timeout<\/p>\n<p>        recent_responses &#061; list(self.response_times)<br \/>\n        if len(recent_responses) &lt; 10:<br \/>\n            return self.base_timeout<\/p>\n<p>        response_times &#061; [r[&#039;response_time&#039;] for r in recent_responses<br \/>\n                         if not r[&#039;timed_out&#039;]]<\/p>\n<p>        if not response_times:<br \/>\n            return self.base_timeout<\/p>\n<p>        try:<br \/>\n            target_percentile &#061; np.percentile(response_times, percentile)<br \/>\n            return target_percentile * self.safety_factor<br \/>\n        except:<br \/>\n            return self.base_timeout<\/p>\n<p>    def should_use_percentile_timeout(self, request_type: str) -&gt; bool:<br \/>\n        &#034;&#034;&#034;\u5224\u65ad\u662f\u5426\u5e94\u8be5\u4f7f\u7528\u767e\u5206\u4f4d\u8d85\u65f6&#034;&#034;&#034;<br \/>\n        # \u67d0\u4e9b\u8bf7\u6c42\u7c7b\u578b\u4f7f\u7528\u56fa\u5b9a\u8d85\u65f6<br \/>\n        fixed_timeout_types &#061; [&#039;login&#039;, &#039;health_check&#039;, &#039;metrics&#039;]<\/p>\n<p>        if request_type in fixed_timeout_types:<br \/>\n            return False<\/p>\n<p>        # \u68c0\u67e5\u662f\u5426\u6709\u8db3\u591f\u7684\u5386\u53f2\u6570\u636e<br \/>\n        if len(self.response_times) &lt; 100:<br \/>\n            return False<\/p>\n<p>        # \u68c0\u67e5\u6570\u636e\u8d28\u91cf&#xff08;\u54cd\u5e94\u65f6\u95f4\u65b9\u5dee&#xff09;<br \/>\n        recent_responses &#061; list(self.response_times)[-100:]<br \/>\n        response_times &#061; [r[&#039;response_time&#039;] for r in recent_responses<br \/>\n                         if not r[&#039;timed_out&#039;]]<\/p>\n<p>        if len(response_times) &lt; 20:<br \/>\n            return False<\/p>\n<p>        # \u8ba1\u7b97\u53d8\u5f02\u7cfb\u6570&#xff08;\u6807\u51c6\u5dee\/\u5747\u503c&#xff09;<br \/>\n        if statistics.mean(response_times) &gt; 0:<br \/>\n            coefficient_of_variation &#061; statistics.stdev(response_times) \/ statistics.mean(response_times)<br \/>\n            # \u5982\u679c\u53d8\u5f02\u7cfb\u6570\u592a\u9ad8&#xff0c;\u4f7f\u7528\u4fdd\u5b88\u8d85\u65f6<br \/>\n            if coefficient_of_variation &gt; 2.0:<br \/>\n                return False<\/p>\n<p>        return True<\/p>\n<p>    def get_dynamic_timeout(self, request_context: Dict) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u83b7\u53d6\u52a8\u6001\u8d85\u65f6\u65f6\u95f4&#034;&#034;&#034;<br \/>\n        request_type &#061; request_context.get(&#039;type&#039;, &#039;default&#039;)<\/p>\n<p>        # \u68c0\u67e5\u662f\u5426\u5e94\u8be5\u4f7f\u7528\u767e\u5206\u4f4d\u8d85\u65f6<br \/>\n        if self.should_use_percentile_timeout(request_type):<br \/>\n            # \u6839\u636e\u8bf7\u6c42\u590d\u6742\u5ea6\u8c03\u6574\u767e\u5206\u4f4d<br \/>\n            complexity &#061; request_context.get(&#039;complexity&#039;, 1.0)<br \/>\n            adjusted_percentile &#061; min(99, 95 * complexity)<\/p>\n<p>            timeout &#061; self.get_timeout_for_percentile(int(adjusted_percentile))<br \/>\n        else:<br \/>\n            # \u4f7f\u7528\u9884\u5b9a\u4e49\u8d85\u65f6<br \/>\n            timeout_config &#061; {<br \/>\n                &#039;health_check&#039;: 5.0,<br \/>\n                &#039;login&#039;: 10.0,<br \/>\n                &#039;search&#039;: 5.0,<br \/>\n                &#039;report&#039;: 60.0,<br \/>\n                &#039;batch_processing&#039;: 300.0,<br \/>\n                &#039;default&#039;: self.current_timeout<br \/>\n            }<\/p>\n<p>            timeout &#061; timeout_config.get(request_type, self.current_timeout)<\/p>\n<p>        # \u57fa\u4e8e\u4f18\u5148\u7ea7\u8c03\u6574<br \/>\n        priority &#061; request_context.get(&#039;priority&#039;, &#039;medium&#039;)<br \/>\n        priority_factors &#061; {<br \/>\n            &#039;high&#039;: 1.0,<br \/>\n            &#039;medium&#039;: 1.0,<br \/>\n            &#039;low&#039;: 0.5<br \/>\n        }<\/p>\n<p>        timeout *&#061; priority_factors.get(priority, 1.0)<\/p>\n<p>        # \u786e\u4fdd\u5728\u5408\u7406\u8303\u56f4\u5185<br \/>\n        return max(self.min_timeout, min(timeout, self.max_timeout))<\/p>\n<h5>28.3.2 \u57fa\u4e8e\u673a\u5668\u5b66\u4e60\u7684\u8d85\u65f6\u9884\u6d4b<\/h5>\n<p>python<\/p>\n<p># \u4f7f\u7528\u673a\u5668\u5b66\u4e60\u9884\u6d4b\u8d85\u65f6<br \/>\nimport pandas as pd<br \/>\nfrom sklearn.ensemble import RandomForestRegressor<br \/>\nfrom sklearn.preprocessing import StandardScaler<br \/>\nfrom sklearn.pipeline import Pipeline<br \/>\nimport joblib<br \/>\nfrom datetime import datetime<\/p>\n<p>class TimeoutPredictor:<br \/>\n    &#034;&#034;&#034;\u57fa\u4e8e\u673a\u5668\u5b66\u4e60\u7684\u8d85\u65f6\u9884\u6d4b\u5668&#034;&#034;&#034;<\/p>\n<p>    def __init__(self, model_path: Optional[str] &#061; None):<br \/>\n        self.features &#061; [<br \/>\n            &#039;request_size_kb&#039;,<br \/>\n            &#039;request_complexity&#039;,<br \/>\n            &#039;concurrent_requests&#039;,<br \/>\n            &#039;time_of_day&#039;,<br \/>\n            &#039;day_of_week&#039;,<br \/>\n            &#039;service_load&#039;,<br \/>\n            &#039;network_latency&#039;,<br \/>\n            &#039;cache_hit_rate&#039;,<br \/>\n            &#039;database_load&#039;,<br \/>\n            &#039;previous_response_time&#039;<br \/>\n        ]<\/p>\n<p>        if model_path and os.path.exists(model_path):<br \/>\n            self.model &#061; joblib.load(model_path)<br \/>\n        else:<br \/>\n            self.model &#061; self._build_model()<\/p>\n<p>        self.training_data &#061; []<br \/>\n        self.last_training &#061; datetime.now()<\/p>\n<p>    def _build_model(self) -&gt; Pipeline:<br \/>\n        &#034;&#034;&#034;\u6784\u5efa\u673a\u5668\u5b66\u4e60\u7ba1\u9053&#034;&#034;&#034;<br \/>\n        pipeline &#061; Pipeline([<br \/>\n            (&#039;scaler&#039;, StandardScaler()),<br \/>\n            (&#039;regressor&#039;, RandomForestRegressor(<br \/>\n                n_estimators&#061;100,<br \/>\n                max_depth&#061;10,<br \/>\n                min_samples_split&#061;5,<br \/>\n                random_state&#061;42<br \/>\n            ))<br \/>\n        ])<br \/>\n        return pipeline<\/p>\n<p>    def extract_features(self, request_context: Dict) -&gt; List[float]:<br \/>\n        &#034;&#034;&#034;\u4ece\u8bf7\u6c42\u4e0a\u4e0b\u6587\u4e2d\u63d0\u53d6\u7279\u5f81&#034;&#034;&#034;<br \/>\n        features &#061; []<\/p>\n<p>        for feature_name in self.features:<br \/>\n            value &#061; request_context.get(feature_name, 0.0)<\/p>\n<p>            # \u7279\u5f81\u5de5\u7a0b<br \/>\n            if feature_name &#061;&#061; &#039;time_of_day&#039;:<br \/>\n                # \u5c06\u65f6\u95f4\u8f6c\u6362\u4e3a\u6b63\u5f26\/\u4f59\u5f26\u7279\u5f81<br \/>\n                hour &#061; value % 24<br \/>\n                features.append(np.sin(2 * np.pi * hour \/ 24))<br \/>\n                features.append(np.cos(2 * np.pi * hour \/ 24))<br \/>\n            elif feature_name &#061;&#061; &#039;day_of_week&#039;:<br \/>\n                # \u661f\u671f\u51e0\u7684\u7f16\u7801<br \/>\n                features.append(value % 7)<br \/>\n                features.append(1 if value &gt;&#061; 5 else 0)  # \u662f\u5426\u4e3a\u5468\u672b<br \/>\n            else:<br \/>\n                features.append(float(value))<\/p>\n<p>        return features<\/p>\n<p>    def predict_timeout(self, request_context: Dict) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u9884\u6d4b\u8bf7\u6c42\u7684\u8d85\u65f6\u65f6\u95f4&#034;&#034;&#034;<br \/>\n        features &#061; self.extract_features(request_context)<\/p>\n<p>        try:<br \/>\n            # \u8f6c\u6362\u4e3aDataFrame<br \/>\n            X &#061; pd.DataFrame([features], columns&#061;self.features[:len(features)])<\/p>\n<p>            # \u9884\u6d4b<br \/>\n            prediction &#061; self.model.predict(X)[0]<\/p>\n<p>            # \u5e94\u7528\u5b89\u5168\u8fb9\u754c<br \/>\n            safety_margin &#061; 1.3  # 30%\u7684\u5b89\u5168\u8fb9\u754c<br \/>\n            predicted_timeout &#061; max(0.1, prediction * safety_margin)<\/p>\n<p>            return min(predicted_timeout, 300.0)  # \u6700\u59275\u5206\u949f<\/p>\n<p>        except Exception as e:<br \/>\n            # \u5982\u679c\u9884\u6d4b\u5931\u8d25&#xff0c;\u8fd4\u56de\u4fdd\u5b88\u4f30\u8ba1<br \/>\n            print(f&#034;Prediction failed: {e}&#034;)<br \/>\n            return 30.0  # \u9ed8\u8ba430\u79d2<\/p>\n<p>    def record_training_sample(self, request_context: Dict,<br \/>\n                              actual_response_time: float):<br \/>\n        &#034;&#034;&#034;\u8bb0\u5f55\u8bad\u7ec3\u6837\u672c&#034;&#034;&#034;<br \/>\n        features &#061; self.extract_features(request_context)<br \/>\n        self.training_data.append(features &#043; [actual_response_time])<\/p>\n<p>        # \u5b9a\u671f\u91cd\u65b0\u8bad\u7ec3\u6a21\u578b<br \/>\n        if (datetime.now() &#8211; self.last_training).total_seconds() &gt; 3600:  # \u6bcf\u5c0f\u65f6<br \/>\n            self.retrain_model()<\/p>\n<p>    def retrain_model(self):<br \/>\n        &#034;&#034;&#034;\u91cd\u65b0\u8bad\u7ec3\u6a21\u578b&#034;&#034;&#034;<br \/>\n        if len(self.training_data) &lt; 100:<br \/>\n            return<\/p>\n<p>        df &#061; pd.DataFrame(self.training_data,<br \/>\n                         columns&#061;self.features &#043; [&#039;response_time&#039;])<\/p>\n<p>        X &#061; df[self.features]<br \/>\n        y &#061; df[&#039;response_time&#039;]<\/p>\n<p>        # \u79fb\u9664\u5f02\u5e38\u503c<br \/>\n        Q1 &#061; y.quantile(0.25)<br \/>\n        Q3 &#061; y.quantile(0.75)<br \/>\n        IQR &#061; Q3 &#8211; Q1<br \/>\n        mask &#061; (y &gt;&#061; Q1 &#8211; 1.5 * IQR) &amp; (y &lt;&#061; Q3 &#043; 1.5 * IQR)<\/p>\n<p>        X_clean &#061; X[mask]<br \/>\n        y_clean &#061; y[mask]<\/p>\n<p>        if len(X_clean) &lt; 50:<br \/>\n            return<\/p>\n<p>        # \u8bad\u7ec3\u6a21\u578b<br \/>\n        self.model.fit(X_clean, y_clean)<br \/>\n        self.last_training &#061; datetime.now()<\/p>\n<p>        # \u4fdd\u5b58\u6a21\u578b<br \/>\n        joblib.dump(self.model, f&#039;timeout_model_{datetime.now().timestamp()}.joblib&#039;)<\/p>\n<p>        print(f&#034;Model retrained with {len(X_clean)} samples&#034;)<\/p>\n<h4>28.4 \u5206\u5e03\u5f0f\u8ffd\u8e2a\u4e0e\u8d85\u65f6\u5206\u6790<\/h4>\n<h5>28.4.1 \u96c6\u6210\u5206\u5e03\u5f0f\u8ffd\u8e2a<\/h5>\n<p>python<\/p>\n<p># \u5206\u5e03\u5f0f\u8ffd\u8e2a\u96c6\u6210<br \/>\nfrom opentelemetry import trace<br \/>\nfrom opentelemetry.trace import Status, StatusCode<br \/>\nfrom opentelemetry.sdk.trace import TracerProvider<br \/>\nfrom opentelemetry.sdk.trace.export import BatchSpanProcessor<br \/>\nfrom opentelemetry.exporter.jaeger.thrift import JaegerExporter<br \/>\nimport time<\/p>\n<p>class TracedTimeoutManager:<br \/>\n    &#034;&#034;&#034;\u96c6\u6210\u5206\u5e03\u5f0f\u8ffd\u8e2a\u7684\u8d85\u65f6\u7ba1\u7406\u5668&#034;&#034;&#034;<\/p>\n<p>    def __init__(self, service_name: str):<br \/>\n        # \u8bbe\u7f6eOpenTelemetry<br \/>\n        trace.set_tracer_provider(TracerProvider())<br \/>\n        self.tracer &#061; trace.get_tracer(__name__)<\/p>\n<p>        # Jaeger\u5bfc\u51fa\u5668<br \/>\n        jaeger_exporter &#061; JaegerExporter(<br \/>\n            agent_host_name&#061;&#034;jaeger&#034;,<br \/>\n            agent_port&#061;6831,<br \/>\n        )<\/p>\n<p>        span_processor &#061; BatchSpanProcessor(jaeger_exporter)<br \/>\n        trace.get_tracer_provider().add_span_processor(span_processor)<\/p>\n<p>        self.service_name &#061; service_name<br \/>\n        self.timeout_thresholds &#061; {<br \/>\n            &#039;critical&#039;: 1.0,   # \u8d85\u8fc71\u79d2\u4e3a\u5173\u952e\u8def\u5f84<br \/>\n            &#039;warning&#039;: 5.0,    # \u8d85\u8fc75\u79d2\u4e3a\u8b66\u544a<br \/>\n            &#039;timeout&#039;: 30.0    # \u8d85\u65f6\u9608\u503c<br \/>\n        }<\/p>\n<p>    def instrument_request(self, request_func):<br \/>\n        &#034;&#034;&#034;\u88c5\u9970\u5668&#xff1a;\u4e3a\u8bf7\u6c42\u6dfb\u52a0\u8ffd\u8e2a\u548c\u8d85\u65f6\u76d1\u63a7&#034;&#034;&#034;<br \/>\n        def wrapper(*args, **kwargs):<br \/>\n            request_name &#061; kwargs.get(&#039;request_name&#039;, &#039;unknown&#039;)<\/p>\n<p>            with self.tracer.start_as_current_span(f&#034;{self.service_name}.{request_name}&#034;) as span:<br \/>\n                # \u6dfb\u52a0\u8bf7\u6c42\u5c5e\u6027<br \/>\n                span.set_attributes({<br \/>\n                    &#034;http.method&#034;: kwargs.get(&#039;method&#039;, &#039;GET&#039;),<br \/>\n                    &#034;http.url&#034;: kwargs.get(&#039;url&#039;, &#039;&#039;),<br \/>\n                    &#034;http.request_size&#034;: kwargs.get(&#039;content_length&#039;, 0),<br \/>\n                    &#034;timeout.threshold&#034;: kwargs.get(&#039;timeout&#039;, 30.0)<br \/>\n                })<\/p>\n<p>                start_time &#061; time.time()<\/p>\n<p>                try:<br \/>\n                    # \u6267\u884c\u8bf7\u6c42<br \/>\n                    result &#061; request_func(*args, **kwargs)<\/p>\n<p>                    # \u8ba1\u7b97\u54cd\u5e94\u65f6\u95f4<br \/>\n                    response_time &#061; time.time() &#8211; start_time<\/p>\n<p>                    # \u8bb0\u5f55\u6027\u80fd\u6307\u6807<br \/>\n                    self._record_performance_metrics(span, response_time,<br \/>\n                                                    kwargs.get(&#039;timeout&#039;, 30.0))<\/p>\n<p>                    # \u6dfb\u52a0\u54cd\u5e94\u5c5e\u6027<br \/>\n                    if hasattr(result, &#039;status_code&#039;):<br \/>\n                        span.set_attribute(&#034;http.status_code&#034;, result.status_code)<\/p>\n<p>                    span.set_status(Status(StatusCode.OK))<\/p>\n<p>                    return result<\/p>\n<p>                except TimeoutError as e:<br \/>\n                    # \u5904\u7406\u8d85\u65f6<br \/>\n                    response_time &#061; time.time() &#8211; start_time<\/p>\n<p>                    span.set_status(Status(<br \/>\n                        StatusCode.ERROR,<br \/>\n                        f&#034;Timeout after {response_time:.2f}s&#034;<br \/>\n                    ))<\/p>\n<p>                    span.set_attributes({<br \/>\n                        &#034;error.type&#034;: &#034;timeout&#034;,<br \/>\n                        &#034;error.retryable&#034;: True,<br \/>\n                        &#034;timeout.actual&#034;: response_time,<br \/>\n                        &#034;timeout.configured&#034;: kwargs.get(&#039;timeout&#039;, 30.0)<br \/>\n                    })<\/p>\n<p>                    span.record_exception(e)<\/p>\n<p>                    # \u8bb0\u5f55\u8d85\u65f6\u6307\u6807<br \/>\n                    self._record_timeout_metrics(span, response_time,<br \/>\n                                                kwargs.get(&#039;timeout&#039;, 30.0))<\/p>\n<p>                    raise<\/p>\n<p>                except Exception as e:<br \/>\n                    # \u5904\u7406\u5176\u4ed6\u9519\u8bef<br \/>\n                    span.set_status(Status(StatusCode.ERROR, str(e)))<br \/>\n                    span.record_exception(e)<br \/>\n                    raise<\/p>\n<p>        return wrapper<\/p>\n<p>    def _record_performance_metrics(self, span, response_time: float,<br \/>\n                                   timeout_threshold: float):<br \/>\n        &#034;&#034;&#034;\u8bb0\u5f55\u6027\u80fd\u6307\u6807&#034;&#034;&#034;<br \/>\n        span.set_attributes({<br \/>\n            &#034;performance.response_time&#034;: response_time,<br \/>\n            &#034;performance.timeout_ratio&#034;: response_time \/ timeout_threshold,<br \/>\n            &#034;performance.within_timeout&#034;: response_time &lt;&#061; timeout_threshold<br \/>\n        })<\/p>\n<p>        # \u6839\u636e\u54cd\u5e94\u65f6\u95f4\u8bbe\u7f6e\u4e25\u91cd\u7a0b\u5ea6<br \/>\n        if response_time &gt; self.timeout_thresholds[&#039;timeout&#039;]:<br \/>\n            span.set_attribute(&#034;performance.severity&#034;, &#034;timeout&#034;)<br \/>\n        elif response_time &gt; self.timeout_thresholds[&#039;warning&#039;]:<br \/>\n            span.set_attribute(&#034;performance.severity&#034;, &#034;warning&#034;)<br \/>\n        elif response_time &gt; self.timeout_thresholds[&#039;critical&#039;]:<br \/>\n            span.set_attribute(&#034;performance.severity&#034;, &#034;critical&#034;)<br \/>\n        else:<br \/>\n            span.set_attribute(&#034;performance.severity&#034;, &#034;normal&#034;)<\/p>\n<p>    def _record_timeout_metrics(self, span, actual_time: float,<br \/>\n                               configured_timeout: float):<br \/>\n        &#034;&#034;&#034;\u8bb0\u5f55\u8d85\u65f6\u6307\u6807&#034;&#034;&#034;<br \/>\n        timeout_exceeded_by &#061; actual_time &#8211; configured_timeout<\/p>\n<p>        span.set_attributes({<br \/>\n            &#034;timeout.exceeded_by&#034;: timeout_exceeded_by,<br \/>\n            &#034;timeout.percentage_exceeded&#034;: (timeout_exceeded_by \/ configured_timeout) * 100,<br \/>\n            &#034;timeout.suggestion&#034;: self._generate_timeout_suggestion(<br \/>\n                actual_time, configured_timeout<br \/>\n            )<br \/>\n        })<\/p>\n<p>    def _generate_timeout_suggestion(self, actual_time: float,<br \/>\n                                    configured_timeout: float) -&gt; str:<br \/>\n        &#034;&#034;&#034;\u751f\u6210\u8d85\u65f6\u914d\u7f6e\u5efa\u8bae&#034;&#034;&#034;<br \/>\n        if actual_time &lt;&#061; configured_timeout:<br \/>\n            return &#034;Timeout configuration is appropriate&#034;<\/p>\n<p>        exceed_ratio &#061; actual_time \/ configured_timeout<\/p>\n<p>        if exceed_ratio &lt; 1.1:<br \/>\n            return &#034;Consider increasing timeout by 10%&#034;<br \/>\n        elif exceed_ratio &lt; 1.5:<br \/>\n            return &#034;Consider increasing timeout by 50%&#034;<br \/>\n        elif exceed_ratio &lt; 2.0:<br \/>\n            return &#034;Consider increasing timeout by 100%&#034;<br \/>\n        else:<br \/>\n            return &#034;Investigate upstream service performance or adjust timeout significantly&#034;<\/p>\n<p>    def analyze_timeout_patterns(self, traces: List[Dict]) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u5206\u6790\u8d85\u65f6\u6a21\u5f0f&#034;&#034;&#034;<br \/>\n        analysis &#061; {<br \/>\n            &#039;total_requests&#039;: 0,<br \/>\n            &#039;timeout_requests&#039;: 0,<br \/>\n            &#039;timeout_rate&#039;: 0.0,<br \/>\n            &#039;avg_response_time&#039;: 0.0,<br \/>\n            &#039;p95_response_time&#039;: 0.0,<br \/>\n            &#039;timeout_causes&#039;: {},<br \/>\n            &#039;recommendations&#039;: []<br \/>\n        }<\/p>\n<p>        response_times &#061; []<\/p>\n<p>        for trace in traces:<br \/>\n            analysis[&#039;total_requests&#039;] &#043;&#061; 1<\/p>\n<p>            if trace.get(&#039;status&#039;) &#061;&#061; &#039;timeout&#039;:<br \/>\n                analysis[&#039;timeout_requests&#039;] &#043;&#061; 1<\/p>\n<p>                # \u5206\u6790\u8d85\u65f6\u539f\u56e0<br \/>\n                cause &#061; self._determine_timeout_cause(trace)<br \/>\n                analysis[&#039;timeout_causes&#039;][cause] &#061; \\\\<br \/>\n                    analysis[&#039;timeout_causes&#039;].get(cause, 0) &#043; 1<\/p>\n<p>            if &#039;response_time&#039; in trace:<br \/>\n                response_times.append(trace[&#039;response_time&#039;])<\/p>\n<p>        # \u8ba1\u7b97\u7edf\u8ba1\u6307\u6807<br \/>\n        if response_times:<br \/>\n            analysis[&#039;avg_response_time&#039;] &#061; statistics.mean(response_times)<br \/>\n            if len(response_times) &gt;&#061; 5:<br \/>\n                analysis[&#039;p95_response_time&#039;] &#061; np.percentile(response_times, 95)<\/p>\n<p>        if analysis[&#039;total_requests&#039;] &gt; 0:<br \/>\n            analysis[&#039;timeout_rate&#039;] &#061; \\\\<br \/>\n                analysis[&#039;timeout_requests&#039;] \/ analysis[&#039;total_requests&#039;]<\/p>\n<p>        # \u751f\u6210\u5efa\u8bae<br \/>\n        analysis[&#039;recommendations&#039;] &#061; self._generate_recommendations(analysis)<\/p>\n<p>        return analysis<\/p>\n<p>    def _determine_timeout_cause(self, trace: Dict) -&gt; str:<br \/>\n        &#034;&#034;&#034;\u786e\u5b9a\u8d85\u65f6\u539f\u56e0&#034;&#034;&#034;<br \/>\n        # \u57fa\u4e8e\u8ffd\u8e2a\u6570\u636e\u5224\u65ad\u8d85\u65f6\u539f\u56e0<br \/>\n        spans &#061; trace.get(&#039;spans&#039;, [])<\/p>\n<p>        # \u68c0\u67e5\u7f51\u7edc\u5ef6\u8fdf<br \/>\n        if any(span.get(&#039;type&#039;) &#061;&#061; &#039;network&#039; for span in spans):<br \/>\n            return &#039;network_latency&#039;<\/p>\n<p>        # \u68c0\u67e5\u6570\u636e\u5e93\u67e5\u8be2<br \/>\n        if any(span.get(&#039;type&#039;) &#061;&#061; &#039;database&#039; for span in spans):<br \/>\n            return &#039;database_query&#039;<\/p>\n<p>        # \u68c0\u67e5\u5916\u90e8API\u8c03\u7528<br \/>\n        if any(span.get(&#039;type&#039;) &#061;&#061; &#039;external_api&#039; for span in spans):<br \/>\n            return &#039;external_service&#039;<\/p>\n<p>        # \u68c0\u67e5\u4e1a\u52a1\u903b\u8f91<br \/>\n        if any(span.get(&#039;type&#039;) &#061;&#061; &#039;business_logic&#039; for span in spans):<br \/>\n            return &#039;business_logic&#039;<\/p>\n<p>        return &#039;unknown&#039;<\/p>\n<h4>28.5 \u5ba2\u6237\u7aef\u5904\u7406\u4e0e\u7528\u6237\u4f53\u9a8c\u4f18\u5316<\/h4>\n<h5>28.5.1 \u667a\u80fd\u5ba2\u6237\u7aef\u91cd\u8bd5\u7b56\u7565<\/h5>\n<p>javascript<\/p>\n<p>\/\/ \u667a\u80fd504\u5904\u7406\u5ba2\u6237\u7aef<br \/>\nclass Smart504Handler {<br \/>\n    constructor(options &#061; {}) {<br \/>\n        this.options &#061; {<br \/>\n            maxRetries: 3,<br \/>\n            baseDelay: 1000,<br \/>\n            maxDelay: 30000,<br \/>\n            jitter: 0.3,<br \/>\n            timeoutMultiplier: 1.5,<br \/>\n            circuitBreaker: {<br \/>\n                failureThreshold: 5,<br \/>\n                resetTimeout: 60000<br \/>\n            },<br \/>\n            &#8230;options<br \/>\n        };<\/p>\n<p>        this.serviceStats &#061; new Map();<br \/>\n        this.circuitBreakers &#061; new Map();<br \/>\n    }<\/p>\n<p>    async executeWithRetry(requestFn, context &#061; {}) {<br \/>\n        const requestId &#061; this._generateId();<br \/>\n        const serviceName &#061; context.serviceName || &#039;default&#039;;<\/p>\n<p>        let lastError;<br \/>\n        let attempt &#061; 0;<\/p>\n<p>        \/\/ \u83b7\u53d6\u6216\u521b\u5efa\u65ad\u8def\u5668<br \/>\n        let circuitBreaker &#061; this.circuitBreakers.get(serviceName);<br \/>\n        if (!circuitBreaker) {<br \/>\n            circuitBreaker &#061; new CircuitBreaker(this.options.circuitBreaker);<br \/>\n            this.circuitBreakers.set(serviceName, circuitBreaker);<br \/>\n        }<\/p>\n<p>        \/\/ \u68c0\u67e5\u65ad\u8def\u5668\u72b6\u6001<br \/>\n        if (circuitBreaker.state &#061;&#061;&#061; &#039;OPEN&#039;) {<br \/>\n            throw new CircuitBreakerOpenError(<br \/>\n                &#096;Circuit breaker open for ${serviceName}&#096;,<br \/>\n                circuitBreaker.lastFailureTime<br \/>\n            );<br \/>\n        }<\/p>\n<p>        while (attempt &lt;&#061; this.options.maxRetries) {<br \/>\n            attempt&#043;&#043;;<\/p>\n<p>            if (attempt &gt; 1) {<br \/>\n                \/\/ \u8ba1\u7b97\u9000\u907f\u5ef6\u8fdf<br \/>\n                const delay &#061; this._calculateBackoff(<br \/>\n                    attempt,<br \/>\n                    lastError,<br \/>\n                    context<br \/>\n                );<\/p>\n<p>                await this._sleep(delay);<\/p>\n<p>                \/\/ \u66f4\u65b0\u4e0a\u4e0b\u6587&#xff08;\u4f8b\u5982\u6dfb\u52a0\u91cd\u8bd5\u6807\u8bc6&#xff09;<br \/>\n                context.retryAttempt &#061; attempt;<br \/>\n                context.previousErrors &#061; context.previousErrors || [];<br \/>\n                context.previousErrors.push(lastError);<br \/>\n            }<\/p>\n<p>            try {<br \/>\n                \/\/ \u8bbe\u7f6e\u8d85\u65f6<br \/>\n                const timeout &#061; this._calculateTimeout(context, attempt);<\/p>\n<p>                \/\/ \u6267\u884c\u8bf7\u6c42<br \/>\n                const result &#061; await this._executeWithTimeout(<br \/>\n                    requestFn,<br \/>\n                    timeout,<br \/>\n                    context<br \/>\n                );<\/p>\n<p>                \/\/ \u8bb0\u5f55\u6210\u529f<br \/>\n                circuitBreaker.recordSuccess();<br \/>\n                this._recordSuccess(serviceName, context);<\/p>\n<p>                return result;<\/p>\n<p>            } catch (error) {<br \/>\n                lastError &#061; error;<\/p>\n<p>                \/\/ \u8bb0\u5f55\u5931\u8d25<br \/>\n                circuitBreaker.recordFailure();<br \/>\n                this._recordFailure(serviceName, error, context);<\/p>\n<p>                \/\/ \u68c0\u67e5\u662f\u5426\u5e94\u8be5\u91cd\u8bd5<br \/>\n                if (!this._shouldRetry(error, attempt, context)) {<br \/>\n                    break;<br \/>\n                }<\/p>\n<p>                \/\/ \u5982\u679c\u662f504\u9519\u8bef&#xff0c;\u68c0\u67e5\u54cd\u5e94\u5934\u90e8<br \/>\n                if (error.status &#061;&#061;&#061; 504) {<br \/>\n                    const retryAfter &#061; error.headers?.get(&#039;Retry-After&#039;);<br \/>\n                    if (retryAfter) {<br \/>\n                        await this._sleep(parseInt(retryAfter) * 1000);<br \/>\n                    }<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>        \/\/ \u6240\u6709\u91cd\u8bd5\u5931\u8d25<br \/>\n        throw new MaxRetriesExceededError(<br \/>\n            &#096;All retries failed for ${serviceName}&#096;,<br \/>\n            lastError,<br \/>\n            attempt<br \/>\n        );<br \/>\n    }<\/p>\n<p>    _calculateBackoff(attempt, lastError, context) {<br \/>\n        let delay &#061; this.options.baseDelay * Math.pow(2, attempt &#8211; 1);<\/p>\n<p>        \/\/ \u6dfb\u52a0\u6296\u52a8<br \/>\n        const jitter &#061; 1 &#8211; this.options.jitter &#043; Math.random() * this.options.jitter * 2;<br \/>\n        delay *&#061; jitter;<\/p>\n<p>        \/\/ \u9650\u5236\u6700\u5927\u5ef6\u8fdf<br \/>\n        delay &#061; Math.min(delay, this.options.maxDelay);<\/p>\n<p>        \/\/ \u5bf9\u4e8e504\u9519\u8bef&#xff0c;\u5982\u679c\u670d\u52a1\u5668\u63d0\u4f9b\u4e86Retry-After&#xff0c;\u4f7f\u7528\u5b83<br \/>\n        if (lastError &amp;&amp; lastError.status &#061;&#061;&#061; 504) {<br \/>\n            const retryAfter &#061; lastError.headers?.get(&#039;Retry-After&#039;);<br \/>\n            if (retryAfter) {<br \/>\n                const serverDelay &#061; parseInt(retryAfter) * 1000;<br \/>\n                if (!isNaN(serverDelay)) {<br \/>\n                    delay &#061; Math.max(delay, serverDelay);<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>        return Math.round(delay);<br \/>\n    }<\/p>\n<p>    _calculateTimeout(context, attempt) {<br \/>\n        \/\/ \u57fa\u4e8e\u91cd\u8bd5\u6b21\u6570\u589e\u52a0\u8d85\u65f6\u65f6\u95f4<br \/>\n        const baseTimeout &#061; context.timeout || 30000;<br \/>\n        const multiplier &#061; Math.pow(this.options.timeoutMultiplier, attempt &#8211; 1);<\/p>\n<p>        return Math.min(baseTimeout * multiplier, 300000); \/\/ \u6700\u59275\u5206\u949f<br \/>\n    }<\/p>\n<p>    _shouldRetry(error, attempt, context) {<br \/>\n        if (attempt &gt;&#061; this.options.maxRetries) {<br \/>\n            return false;<br \/>\n        }<\/p>\n<p>        \/\/ \u91cd\u8bd5504\u9519\u8bef<br \/>\n        if (error.status &#061;&#061;&#061; 504) {<br \/>\n            return true;<br \/>\n        }<\/p>\n<p>        \/\/ \u91cd\u8bd5\u7f51\u7edc\u9519\u8bef<br \/>\n        if (error.name &#061;&#061;&#061; &#039;NetworkError&#039; ||<br \/>\n            error.name &#061;&#061;&#061; &#039;TimeoutError&#039;) {<br \/>\n            return true;<br \/>\n        }<\/p>\n<p>        \/\/ \u4e0d\u91cd\u8bd5\u5ba2\u6237\u7aef\u9519\u8bef&#xff08;4xx&#xff09;<br \/>\n        if (error.status &gt;&#061; 400 &amp;&amp; error.status &lt; 500) {<br \/>\n            return false;<br \/>\n        }<\/p>\n<p>        \/\/ \u9ed8\u8ba4\u91cd\u8bd5\u670d\u52a1\u5668\u9519\u8bef&#xff08;5xx&#xff09;<br \/>\n        return error.status &gt;&#061; 500;<br \/>\n    }<\/p>\n<p>    _executeWithTimeout(requestFn, timeout, context) {<br \/>\n        return new Promise((resolve, reject) &#061;&gt; {<br \/>\n            const timeoutId &#061; setTimeout(() &#061;&gt; {<br \/>\n                reject(new TimeoutError(&#096;Request timeout after ${timeout}ms&#096;));<br \/>\n            }, timeout);<\/p>\n<p>            requestFn(context)<br \/>\n                .then(resolve)<br \/>\n                .catch(reject)<br \/>\n                .finally(() &#061;&gt; clearTimeout(timeoutId));<br \/>\n        });<br \/>\n    }<\/p>\n<p>    _recordSuccess(serviceName, context) {<br \/>\n        const stats &#061; this.serviceStats.get(serviceName) || {<br \/>\n            successes: 0,<br \/>\n            failures: 0,<br \/>\n            totalResponseTime: 0,<br \/>\n            lastSuccess: Date.now()<br \/>\n        };<\/p>\n<p>        stats.successes&#043;&#043;;<br \/>\n        stats.lastSuccess &#061; Date.now();<\/p>\n<p>        if (context.responseTime) {<br \/>\n            stats.totalResponseTime &#043;&#061; context.responseTime;<br \/>\n        }<\/p>\n<p>        this.serviceStats.set(serviceName, stats);<br \/>\n    }<\/p>\n<p>    _recordFailure(serviceName, error, context) {<br \/>\n        const stats &#061; this.serviceStats.get(serviceName) || {<br \/>\n            successes: 0,<br \/>\n            failures: 0,<br \/>\n            totalResponseTime: 0,<br \/>\n            lastFailure: Date.now()<br \/>\n        };<\/p>\n<p>        stats.failures&#043;&#043;;<br \/>\n        stats.lastFailure &#061; Date.now();<\/p>\n<p>        \/\/ \u8bb0\u5f55\u9519\u8bef\u7c7b\u578b<br \/>\n        stats.lastErrorType &#061; error.status || error.name;<\/p>\n<p>        this.serviceStats.set(serviceName, stats);<br \/>\n    }<\/p>\n<p>    getServiceHealth(serviceName) {<br \/>\n        const stats &#061; this.serviceStats.get(serviceName);<br \/>\n        const circuitBreaker &#061; this.circuitBreakers.get(serviceName);<\/p>\n<p>        if (!stats) {<br \/>\n            return { status: &#039;unknown&#039; };<br \/>\n        }<\/p>\n<p>        const totalRequests &#061; stats.successes &#043; stats.failures;<br \/>\n        const successRate &#061; totalRequests &gt; 0 ? stats.successes \/ totalRequests : 0;<\/p>\n<p>        const health &#061; {<br \/>\n            status: &#039;healthy&#039;,<br \/>\n            successRate,<br \/>\n            totalRequests,<br \/>\n            circuitBreakerState: circuitBreaker?.state || &#039;unknown&#039;,<br \/>\n            avgResponseTime: stats.successes &gt; 0 ?<br \/>\n                stats.totalResponseTime \/ stats.successes : 0<br \/>\n        };<\/p>\n<p>        \/\/ \u786e\u5b9a\u5065\u5eb7\u72b6\u6001<br \/>\n        if (circuitBreaker?.state &#061;&#061;&#061; &#039;OPEN&#039;) {<br \/>\n            health.status &#061; &#039;circuit_open&#039;;<br \/>\n        } else if (successRate &lt; 0.8) {<br \/>\n            health.status &#061; &#039;degraded&#039;;<br \/>\n        } else if (successRate &lt; 0.95) {<br \/>\n            health.status &#061; &#039;warning&#039;;<br \/>\n        }<\/p>\n<p>        return health;<br \/>\n    }<br \/>\n}<\/p>\n<h4>28.6 \u6700\u4f73\u5b9e\u8df5\u603b\u7ed3<\/h4>\n<h5>28.6.1 \u8d85\u65f6\u914d\u7f6e\u68c0\u67e5\u6e05\u5355<\/h5>\n<p>Nginx\u914d\u7f6e&#xff1a;<\/p>\n<p>text<\/p>\n<p>\u2705 proxy_connect_timeout: 2-5\u79d2<br \/>\n\u2705 proxy_send_timeout: 30-60\u79d2&#xff08;\u6839\u636e\u4e1a\u52a1\u8c03\u6574&#xff09;<br \/>\n\u2705 proxy_read_timeout: 30-60\u79d2&#xff08;\u6839\u636e\u4e1a\u52a1\u8c03\u6574&#xff09;<br \/>\n\u2705 keepalive_timeout: 15-30\u79d2<br \/>\n\u2705 resolver_timeout: 5\u79d2<\/p>\n<p>\u5e94\u7528\u670d\u52a1\u5668\u914d\u7f6e&#xff1a;<\/p>\n<p>text<\/p>\n<p>\u2705 \u6570\u636e\u5e93\u8fde\u63a5\u8d85\u65f6&#xff1a;5-10\u79d2<br \/>\n\u2705 Redis\u8d85\u65f6&#xff1a;1-2\u79d2<br \/>\n\u2705 HTTP\u5ba2\u6237\u7aef\u8d85\u65f6&#xff1a;\u5206\u5c42\u914d\u7f6e<br \/>\n\u2705 \u7ebf\u7a0b\u6c60\u7b49\u5f85\u8d85\u65f6&#xff1a;30-60\u79d2<\/p>\n<h5>28.6.2 \u76d1\u63a7\u544a\u8b66\u9608\u503c<\/h5>\n<p>yaml<\/p>\n<p># Prometheus\u544a\u8b66\u89c4\u5219<br \/>\ngroups:<br \/>\n  &#8211; name: gateway_timeout_alerts<br \/>\n    rules:<br \/>\n      &#8211; alert: High504ErrorRate<br \/>\n        expr: |<br \/>\n          rate(<br \/>\n            http_requests_total{status&#061;&#034;504&#034;}[5m]<br \/>\n          ) \/ rate(<br \/>\n            http_requests_total[5m]<br \/>\n          ) &gt; 0.01<br \/>\n        for: 2m<br \/>\n        labels:<br \/>\n          severity: critical<br \/>\n        annotations:<br \/>\n          summary: &#034;High rate of 504 gateway timeout errors&#034;<br \/>\n          description: |<br \/>\n            504\u9519\u8bef\u7387\u8d85\u8fc71%&#xff0c;\u5f53\u524d\u503c: {{ $value | humanizePercentage }}<br \/>\n            \u53d7\u5f71\u54cd\u7684upstream: {{ $labels.upstream }}<\/p>\n<p>      &#8211; alert: SlowUpstreamResponse<br \/>\n        expr: |<br \/>\n          histogram_quantile(0.95,<br \/>\n            rate(upstream_response_time_seconds_bucket[5m])<br \/>\n          ) &gt; 10<br \/>\n        for: 5m<br \/>\n        labels:<br \/>\n          severity: warning<br \/>\n        annotations:<br \/>\n          summary: &#034;Slow upstream response times&#034;<br \/>\n          description: |<br \/>\n            \u4e0a\u6e38\u670d\u52a195%\u54cd\u5e94\u65f6\u95f4\u8d85\u8fc710\u79d2<br \/>\n            \u5f53\u524d\u503c: {{ $value }}\u79d2<\/p>\n<p>      &#8211; alert: UpstreamTimeoutRatioHigh<br \/>\n        expr: |<br \/>\n          rate(<br \/>\n            http_requests_total{status&#061;&#034;504&#034;}[5m]<br \/>\n          ) \/ rate(<br \/>\n            http_requests_total{status!&#061;&#034;504&#034;}[5m]<br \/>\n          ) &gt; 0.1<br \/>\n        for: 1m<br \/>\n        labels:<br \/>\n          severity: warning<br \/>\n        annotations:<br \/>\n          summary: &#034;High ratio of timeout errors&#034;<br \/>\n          description: |<br \/>\n            \u8d85\u65f6\u9519\u8bef\u5360\u6bd4\u8d85\u8fc710%&#xff0c;\u53ef\u80fd\u9700\u8981\u8c03\u6574\u8d85\u65f6\u914d\u7f6e<\/p>\n<h5>28.6.3 \u5bb9\u91cf\u89c4\u5212\u516c\u5f0f<\/h5>\n<p>text<\/p>\n<p>\u8d85\u65f6\u914d\u7f6e &#061; \u57fa\u51c6\u54cd\u5e94\u65f6\u95f4 \u00d7 \u5b89\u5168\u7cfb\u6570 \u00d7 \u4e1a\u52a1\u91cd\u8981\u6027\u7cfb\u6570<\/p>\n<p>\u5176\u4e2d&#xff1a;<br \/>\n&#8211; \u57fa\u51c6\u54cd\u5e94\u65f6\u95f4&#xff1a;P99\u54cd\u5e94\u65f6\u95f4<br \/>\n&#8211; \u5b89\u5168\u7cfb\u6570&#xff1a;1.5-2.0&#xff08;\u6839\u636e\u670d\u52a1\u7a33\u5b9a\u6027\u8c03\u6574&#xff09;<br \/>\n&#8211; \u4e1a\u52a1\u91cd\u8981\u6027\u7cfb\u6570&#xff1a;<br \/>\n  \u2022 \u5173\u952e\u4e1a\u52a1&#xff1a;1.2<br \/>\n  \u2022 \u91cd\u8981\u4e1a\u52a1&#xff1a;1.0<br \/>\n  \u2022 \u975e\u5173\u952e\u4e1a\u52a1&#xff1a;0.8<\/p>\n<p>\u793a\u4f8b&#xff1a;<br \/>\n\u8ba2\u5355\u670d\u52a1 P99\u54cd\u5e94\u65f6\u95f4 &#061; 2\u79d2<br \/>\n\u5b89\u5168\u7cfb\u6570 &#061; 1.5<br \/>\n\u4e1a\u52a1\u91cd\u8981\u6027\u7cfb\u6570 &#061; 1.2<\/p>\n<p>\u8d85\u65f6\u914d\u7f6e &#061; 2 \u00d7 1.5 \u00d7 1.2 &#061; 3.6\u79d2<\/p>\n<p>\u901a\u8fc7\u5b9e\u65bd\u8fd9\u4e9b\u7b56\u7565&#xff0c;\u53ef\u4ee5\u663e\u8457\u964d\u4f4e504\u9519\u8bef\u7684\u53d1\u751f\u7387&#xff0c;\u63d0\u9ad8\u7cfb\u7edf\u7684\u53ef\u9760\u6027\u548c\u7528\u6237\u4f53\u9a8c\u3002<\/p>\n<hr \/>\n<h3>\u7b2c29\u7ae0&#xff1a;\u5176\u4ed65xx\u72b6\u6001\u7801&#xff08;505-511&#xff09;<\/h3>\n<h4>29.1 505 HTTP Version Not Supported<\/h4>\n<h5>29.1.1 \u534f\u8bae\u7248\u672c\u517c\u5bb9\u6027\u7ba1\u7406<\/h5>\n<p>505 HTTP Version Not Supported\u00a0\u8868\u793a\u670d\u52a1\u5668\u4e0d\u652f\u6301\u8bf7\u6c42\u4e2d\u4f7f\u7528\u7684HTTP\u534f\u8bae\u7248\u672c\u3002<\/p>\n<p>python<\/p>\n<p># HTTP\u7248\u672c\u534f\u5546\u7ba1\u7406\u5668<br \/>\nfrom typing import Dict, List, Optional<br \/>\nfrom enum import Enum<\/p>\n<p>class HTTPVersion(Enum):<br \/>\n    HTTP_0_9 &#061; &#034;HTTP\/0.9&#034;<br \/>\n    HTTP_1_0 &#061; &#034;HTTP\/1.0&#034;<br \/>\n    HTTP_1_1 &#061; &#034;HTTP\/1.1&#034;<br \/>\n    HTTP_2_0 &#061; &#034;HTTP\/2&#034;<br \/>\n    HTTP_3_0 &#061; &#034;HTTP\/3&#034;<\/p>\n<p>class HTTPVersionManager:<br \/>\n    &#034;&#034;&#034;HTTP\u7248\u672c\u7ba1\u7406\u5668&#034;&#034;&#034;<\/p>\n<p>    def __init__(self):<br \/>\n        # \u652f\u6301\u7684HTTP\u7248\u672c\u53ca\u5176\u529f\u80fd<br \/>\n        self.supported_versions &#061; {<br \/>\n            HTTPVersion.HTTP_1_1: {<br \/>\n                &#034;supported&#034;: True,<br \/>\n                &#034;features&#034;: [&#034;keep-alive&#034;, &#034;pipelining&#034;, &#034;chunked_encoding&#034;],<br \/>\n                &#034;security_level&#034;: &#034;moderate&#034;,<br \/>\n                &#034;performance_score&#034;: 7<br \/>\n            },<br \/>\n            HTTPVersion.HTTP_2_0: {<br \/>\n                &#034;supported&#034;: True,<br \/>\n                &#034;features&#034;: [&#034;multiplexing&#034;, &#034;header_compression&#034;, &#034;server_push&#034;],<br \/>\n                &#034;security_level&#034;: &#034;high&#034;,<br \/>\n                &#034;performance_score&#034;: 9<br \/>\n            },<br \/>\n            HTTPVersion.HTTP_3_0: {<br \/>\n                &#034;supported&#034;: False,  # \u5b9e\u9a8c\u6027\u652f\u6301<br \/>\n                &#034;features&#034;: [&#034;QUIC&#034;, &#034;improved_security&#034;, &#034;better_performance&#034;],<br \/>\n                &#034;security_level&#034;: &#034;very_high&#034;,<br \/>\n                &#034;performance_score&#034;: 10,<br \/>\n                &#034;experimental&#034;: True<br \/>\n            }<br \/>\n        }<\/p>\n<p>        # \u7248\u672c\u5347\u7ea7\u7b56\u7565<br \/>\n        self.upgrade_policies &#061; {<br \/>\n            &#034;aggressive&#034;: {<br \/>\n                &#034;force_upgrade&#034;: True,<br \/>\n                &#034;legacy_support_days&#034;: 30,<br \/>\n                &#034;notify_clients&#034;: True<br \/>\n            },<br \/>\n            &#034;gradual&#034;: {<br \/>\n                &#034;force_upgrade&#034;: False,<br \/>\n                &#034;legacy_support_days&#034;: 365,<br \/>\n                &#034;notify_clients&#034;: True<br \/>\n            },<br \/>\n            &#034;compatible&#034;: {<br \/>\n                &#034;force_upgrade&#034;: False,<br \/>\n                &#034;legacy_support_days&#034;: float(&#039;inf&#039;),<br \/>\n                &#034;notify_clients&#034;: False<br \/>\n            }<br \/>\n        }<\/p>\n<p>        self.current_policy &#061; &#034;gradual&#034;<\/p>\n<p>    def handle_request(self, http_version: str, request_headers: Dict) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u5904\u7406HTTP\u7248\u672c\u534f\u5546&#034;&#034;&#034;<br \/>\n        requested_version &#061; self._parse_http_version(http_version)<\/p>\n<p>        # \u68c0\u67e5\u662f\u5426\u652f\u6301\u8be5\u7248\u672c<br \/>\n        if requested_version not in self.supported_versions:<br \/>\n            return self._create_505_response(requested_version)<\/p>\n<p>        version_info &#061; self.supported_versions[requested_version]<\/p>\n<p>        # \u68c0\u67e5\u662f\u5426\u5df2\u5f03\u7528<br \/>\n        if not version_info[&#034;supported&#034;]:<br \/>\n            # \u6839\u636e\u7b56\u7565\u51b3\u5b9a\u662f\u5426\u8fd4\u56de505<br \/>\n            if self.upgrade_policies[self.current_policy][&#034;force_upgrade&#034;]:<br \/>\n                return self._create_505_response(<br \/>\n                    requested_version,<br \/>\n                    suggest_upgrade&#061;True<br \/>\n                )<\/p>\n<p>        # \u68c0\u67e5\u662f\u5426\u9700\u8981\u5347\u7ea7<br \/>\n        if self._should_suggest_upgrade(requested_version, request_headers):<br \/>\n            return self._create_upgrade_response(requested_version)<\/p>\n<p>        # \u7248\u672c\u652f\u6301&#xff0c;\u6b63\u5e38\u5904\u7406<br \/>\n        return {&#034;status&#034;: &#034;supported&#034;, &#034;version&#034;: requested_version}<\/p>\n<p>    def _create_505_response(self, requested_version: HTTPVersion,<br \/>\n                            suggest_upgrade: bool &#061; False) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u521b\u5efa505\u54cd\u5e94&#034;&#034;&#034;<br \/>\n        response &#061; {<br \/>\n            &#034;status&#034;: 505,<br \/>\n            &#034;headers&#034;: {<br \/>\n                &#034;Content-Type&#034;: &#034;application\/json&#034;<br \/>\n            },<br \/>\n            &#034;body&#034;: {<br \/>\n                &#034;error&#034;: {<br \/>\n                    &#034;code&#034;: &#034;http_version_not_supported&#034;,<br \/>\n                    &#034;message&#034;: f&#034;HTTP version {requested_version.value} is not supported&#034;,<br \/>\n                    &#034;supported_versions&#034;: [<br \/>\n                        version.value for version, info in self.supported_versions.items()<br \/>\n                        if info[&#034;supported&#034;]<br \/>\n                    ]<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>        if suggest_upgrade:<br \/>\n            latest_version &#061; self._get_latest_supported_version()<br \/>\n            response[&#034;headers&#034;][&#034;Upgrade&#034;] &#061; latest_version.value<br \/>\n            response[&#034;body&#034;][&#034;error&#034;][&#034;suggestion&#034;] &#061; {<br \/>\n                &#034;upgrade_to&#034;: latest_version.value,<br \/>\n                &#034;benefits&#034;: self.supported_versions[latest_version][&#034;features&#034;],<br \/>\n                &#034;migration_guide&#034;: &#034;https:\/\/docs.example.com\/http-upgrade&#034;<br \/>\n            }<\/p>\n<p>        return response<\/p>\n<p>    def _create_upgrade_response(self, current_version: HTTPVersion) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u521b\u5efa\u534f\u8bae\u5347\u7ea7\u54cd\u5e94&#034;&#034;&#034;<br \/>\n        latest_version &#061; self._get_latest_supported_version()<\/p>\n<p>        return {<br \/>\n            &#034;status&#034;: 426,  # Upgrade Required<br \/>\n            &#034;headers&#034;: {<br \/>\n                &#034;Content-Type&#034;: &#034;application\/json&#034;,<br \/>\n                &#034;Upgrade&#034;: latest_version.value,<br \/>\n                &#034;Connection&#034;: &#034;Upgrade&#034;<br \/>\n            },<br \/>\n            &#034;body&#034;: {<br \/>\n                &#034;info&#034;: {<br \/>\n                    &#034;message&#034;: &#034;Please upgrade your HTTP protocol&#034;,<br \/>\n                    &#034;current_version&#034;: current_version.value,<br \/>\n                    &#034;recommended_version&#034;: latest_version.value,<br \/>\n                    &#034;improvements&#034;: self._compare_versions(current_version, latest_version),<br \/>\n                    &#034;documentation&#034;: &#034;https:\/\/docs.example.com\/http-upgrade&#034;<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>    def _get_latest_supported_version(self) -&gt; HTTPVersion:<br \/>\n        &#034;&#034;&#034;\u83b7\u53d6\u6700\u65b0\u652f\u6301\u7684HTTP\u7248\u672c&#034;&#034;&#034;<br \/>\n        supported &#061; [v for v, info in self.supported_versions.items()<br \/>\n                    if info[&#034;supported&#034;]]<br \/>\n        return max(supported, key&#061;lambda x: x.value)<\/p>\n<p>    def _should_suggest_upgrade(self, current_version: HTTPVersion,<br \/>\n                               headers: Dict) -&gt; bool:<br \/>\n        &#034;&#034;&#034;\u68c0\u67e5\u662f\u5426\u5e94\u8be5\u5efa\u8bae\u5347\u7ea7&#034;&#034;&#034;<br \/>\n        # \u57fa\u4e8eUser-Agent\u5224\u65ad\u5ba2\u6237\u7aef\u80fd\u529b<br \/>\n        user_agent &#061; headers.get(&#034;User-Agent&#034;, &#034;&#034;)<\/p>\n<p>        # \u73b0\u4ee3\u6d4f\u89c8\u5668\u652f\u6301HTTP\/2\u548cHTTP\/3<br \/>\n        modern_browsers &#061; [&#034;Chrome\/&#034;, &#034;Firefox\/&#034;, &#034;Safari\/&#034;, &#034;Edge\/&#034;]<\/p>\n<p>        if any(browser in user_agent for browser in modern_browsers):<br \/>\n            # \u73b0\u4ee3\u6d4f\u89c8\u5668&#xff0c;\u53ef\u4ee5\u5efa\u8bae\u5347\u7ea7\u5230HTTP\/2\u6216HTTP\/3<br \/>\n            return current_version.value in [&#034;HTTP\/1.0&#034;, &#034;HTTP\/1.1&#034;]<\/p>\n<p>        # API\u5ba2\u6237\u7aef<br \/>\n        if &#034;python-requests&#034; in user_agent or &#034;curl&#034; in user_agent:<br \/>\n            # \u8fd9\u4e9b\u5ba2\u6237\u7aef\u901a\u5e38\u652f\u6301HTTP\/2<br \/>\n            return current_version &#061;&#061; HTTPVersion.HTTP_1_1<\/p>\n<p>        return False<\/p>\n<h5>29.1.2 Nginx\u914d\u7f6e\u793a\u4f8b<\/h5>\n<p>nginx<\/p>\n<p># Nginx HTTP\u7248\u672c\u914d\u7f6e<br \/>\nhttp {<br \/>\n    # \u652f\u6301\u7684HTTP\u7248\u672c<br \/>\n    http2 on;  # \u542f\u7528HTTP\/2<\/p>\n<p>    # \u5b9e\u9a8c\u6027HTTP\/3\u652f\u6301<br \/>\n    # listen 443 quic reuseport;<br \/>\n    # listen [::]:443 quic reuseport;<\/p>\n<p>    server {<br \/>\n        listen 80;<br \/>\n        listen 443 ssl http2;  # \u540c\u65f6\u652f\u6301HTTP\/1.1\u548cHTTP\/2<\/p>\n<p>        ssl_certificate \/etc\/nginx\/ssl\/cert.pem;<br \/>\n        ssl_certificate_key \/etc\/nginx\/ssl\/key.pem;<\/p>\n<p>        # HTTP\/2\u8bbe\u7f6e<br \/>\n        http2_push_preload on;<br \/>\n        http2_max_concurrent_streams 128;<\/p>\n<p>        # \u5904\u7406\u4e0d\u652f\u6301\u7684HTTP\u7248\u672c<br \/>\n        error_page 505 &#061; &#064;http_version_error;<\/p>\n<p>        location &#064;http_version_error {<br \/>\n            default_type application\/json;<\/p>\n<p>            # \u8fd4\u56de\u8be6\u7ec6\u7684\u9519\u8bef\u4fe1\u606f<br \/>\n            return 505 &#039;{<br \/>\n                &#034;error&#034;: {<br \/>\n                    &#034;code&#034;: &#034;unsupported_http_version&#034;,<br \/>\n                    &#034;message&#034;: &#034;The HTTP protocol version used in the request is not supported&#034;,<br \/>\n                    &#034;supported_versions&#034;: [&#034;HTTP\/1.1&#034;, &#034;HTTP\/2&#034;],<br \/>\n                    &#034;documentation&#034;: &#034;https:\/\/developer.example.com\/api\/http-versions&#034;<br \/>\n                }<br \/>\n            }&#039;;<br \/>\n        }<\/p>\n<p>        # \u5f3a\u5236HTTPS\u548cHTTP\/2\u5347\u7ea7<br \/>\n        if ($server_protocol !~* &#034;HTTP\/2&#034;) {<br \/>\n            add_header X-HTTP-Version-Upgrade &#034;Consider upgrading to HTTP\/2&#034;;<br \/>\n            add_header Alt-Svc &#039;h3&#061;&#034;:443&#034;; ma&#061;86400&#039;;  # \u5e7f\u544aHTTP\/3\u652f\u6301<br \/>\n        }<br \/>\n    }<br \/>\n}<\/p>\n<h4>29.2 506 Variant Also Negotiates<\/h4>\n<p>506 Variant Also Negotiates\u00a0\u662f\u4e00\u4e2a\u8f83\u5c11\u4f7f\u7528\u7684\u72b6\u6001\u7801&#xff0c;\u8868\u793a\u670d\u52a1\u5668\u5b58\u5728\u5185\u90e8\u914d\u7f6e\u9519\u8bef&#xff0c;\u5bfc\u81f4\u900f\u660e\u5185\u5bb9\u534f\u5546\u51fa\u73b0\u5faa\u73af\u3002<\/p>\n<h5>29.2.1 \u5185\u5bb9\u534f\u5546\u5faa\u73af\u68c0\u6d4b<\/h5>\n<p>python<\/p>\n<p># \u5185\u5bb9\u534f\u5546\u5faa\u73af\u68c0\u6d4b\u5668<br \/>\nclass ContentNegotiationManager:<br \/>\n    &#034;&#034;&#034;\u5185\u5bb9\u534f\u5546\u7ba1\u7406\u5668&#xff0c;\u9632\u6b62506\u9519\u8bef&#034;&#034;&#034;<\/p>\n<p>    def __init__(self):<br \/>\n        self.negotiation_history &#061; {}<br \/>\n        self.max_negotiation_depth &#061; 3<\/p>\n<p>        # \u652f\u6301\u7684\u5185\u5bb9\u7c7b\u578b<br \/>\n        self.supported_content_types &#061; {<br \/>\n            &#039;application\/json&#039;: {<br \/>\n                &#039;quality&#039;: 1.0,<br \/>\n                &#039;charset&#039;: [&#039;utf-8&#039;],<br \/>\n                &#039;language&#039;: [&#039;en&#039;, &#039;zh&#039;]<br \/>\n            },<br \/>\n            &#039;application\/xml&#039;: {<br \/>\n                &#039;quality&#039;: 0.9,<br \/>\n                &#039;charset&#039;: [&#039;utf-8&#039;],<br \/>\n                &#039;language&#039;: [&#039;en&#039;]<br \/>\n            },<br \/>\n            &#039;text\/html&#039;: {<br \/>\n                &#039;quality&#039;: 0.8,<br \/>\n                &#039;charset&#039;: [&#039;utf-8&#039;, &#039;iso-8859-1&#039;],<br \/>\n                &#039;language&#039;: [&#039;en&#039;, &#039;zh&#039;, &#039;ja&#039;]<br \/>\n            }<br \/>\n        }<\/p>\n<p>    def negotiate_content(self, request_headers: Dict,<br \/>\n                         available_variants: List[Dict]) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u6267\u884c\u5185\u5bb9\u534f\u5546&#xff0c;\u9632\u6b62\u5faa\u73af&#034;&#034;&#034;<br \/>\n        request_id &#061; request_headers.get(&#039;X-Request-ID&#039;)<\/p>\n<p>        if request_id:<br \/>\n            # \u68c0\u67e5\u534f\u5546\u5386\u53f2<br \/>\n            history &#061; self.negotiation_history.get(request_id, [])<\/p>\n<p>            if len(history) &gt;&#061; self.max_negotiation_depth:<br \/>\n                # \u68c0\u6d4b\u5230\u53ef\u80fd\u7684\u534f\u5546\u5faa\u73af<br \/>\n                return self._create_506_response(history)<\/p>\n<p>            # \u8bb0\u5f55\u672c\u6b21\u534f\u5546<br \/>\n            history.append({<br \/>\n                &#039;timestamp&#039;: time.time(),<br \/>\n                &#039;accept_header&#039;: request_headers.get(&#039;Accept&#039;),<br \/>\n                &#039;available_variants&#039;: available_variants<br \/>\n            })<br \/>\n            self.negotiation_history[request_id] &#061; history<\/p>\n<p>        # \u6267\u884c\u5185\u5bb9\u534f\u5546<br \/>\n        selected_variant &#061; self._select_best_variant(<br \/>\n            request_headers,<br \/>\n            available_variants<br \/>\n        )<\/p>\n<p>        if not selected_variant:<br \/>\n            # \u6ca1\u6709\u53ef\u63a5\u53d7\u7684\u53d8\u4f53<br \/>\n            return self._create_406_response(available_variants)<\/p>\n<p>        return {<br \/>\n            &#039;status&#039;: &#039;success&#039;,<br \/>\n            &#039;selected_variant&#039;: selected_variant,<br \/>\n            &#039;vary_header&#039;: self._generate_vary_header(request_headers)<br \/>\n        }<\/p>\n<p>    def _select_best_variant(self, headers: Dict,<br \/>\n                            variants: List[Dict]) -&gt; Optional[Dict]:<br \/>\n        &#034;&#034;&#034;\u9009\u62e9\u6700\u4f73\u53d8\u4f53&#034;&#034;&#034;<br \/>\n        accept_header &#061; headers.get(&#039;Accept&#039;, &#039;*\/*&#039;)<br \/>\n        accept_language &#061; headers.get(&#039;Accept-Language&#039;, &#039;en&#039;)<br \/>\n        accept_charset &#061; headers.get(&#039;Accept-Charset&#039;, &#039;utf-8&#039;)<\/p>\n<p>        # \u89e3\u6790Accept\u5934\u90e8<br \/>\n        accepted_types &#061; self._parse_accept_header(accept_header)<\/p>\n<p>        # \u4e3a\u6bcf\u4e2a\u53d8\u4f53\u8bc4\u5206<br \/>\n        scored_variants &#061; []<\/p>\n<p>        for variant in variants:<br \/>\n            score &#061; self._calculate_variant_score(<br \/>\n                variant,<br \/>\n                accepted_types,<br \/>\n                accept_language,<br \/>\n                accept_charset<br \/>\n            )<\/p>\n<p>            if score &gt; 0:<br \/>\n                scored_variants.append((score, variant))<\/p>\n<p>        if not scored_variants:<br \/>\n            return None<\/p>\n<p>        # \u9009\u62e9\u6700\u9ad8\u5206\u7684\u53d8\u4f53<br \/>\n        scored_variants.sort(reverse&#061;True)<br \/>\n        return scored_variants[0][1]<\/p>\n<p>    def _create_506_response(self, negotiation_history: List) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u521b\u5efa506\u54cd\u5e94&#034;&#034;&#034;<br \/>\n        return {<br \/>\n            &#039;status&#039;: 506,<br \/>\n            &#039;headers&#039;: {<br \/>\n                &#039;Content-Type&#039;: &#039;application\/json&#039;,<br \/>\n                &#039;Vary&#039;: &#039;Accept, Accept-Language, Accept-Charset&#039;<br \/>\n            },<br \/>\n            &#039;body&#039;: {<br \/>\n                &#039;error&#039;: {<br \/>\n                    &#039;code&#039;: &#039;variant_also_negotiates&#039;,<br \/>\n                    &#039;message&#039;: &#039;Content negotiation resulted in a circular reference&#039;,<br \/>\n                    &#039;details&#039;: {<br \/>\n                        &#039;negotiation_depth&#039;: len(negotiation_history),<br \/>\n                        &#039;negotiation_history&#039;: negotiation_history,<br \/>\n                        &#039;max_allowed_depth&#039;: self.max_negotiation_depth<br \/>\n                    },<br \/>\n                    &#039;suggestions&#039;: [<br \/>\n                        &#039;Check server content negotiation configuration&#039;,<br \/>\n                        &#039;Ensure variants have unique content types&#039;,<br \/>\n                        &#039;Review Accept headers in client requests&#039;<br \/>\n                    ]<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>    def _create_406_response(self, available_variants: List[Dict]) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u521b\u5efa406 Not Acceptable\u54cd\u5e94&#034;&#034;&#034;<br \/>\n        return {<br \/>\n            &#039;status&#039;: 406,<br \/>\n            &#039;headers&#039;: {<br \/>\n                &#039;Content-Type&#039;: &#039;application\/json&#039;,<br \/>\n                &#039;Vary&#039;: &#039;Accept, Accept-Language, Accept-Charset&#039;<br \/>\n            },<br \/>\n            &#039;body&#039;: {<br \/>\n                &#039;error&#039;: {<br \/>\n                    &#039;code&#039;: &#039;not_acceptable&#039;,<br \/>\n                    &#039;message&#039;: &#039;No acceptable variant found&#039;,<br \/>\n                    &#039;available_variants&#039;: available_variants,<br \/>\n                    &#039;supported_content_types&#039;: list(self.supported_content_types.keys())<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<h4>29.3 507 Insufficient Storage<\/h4>\n<p>507 Insufficient Storage\u00a0\u8868\u793a\u670d\u52a1\u5668\u65e0\u6cd5\u5b58\u50a8\u5b8c\u6210\u8bf7\u6c42\u6240\u9700\u7684\u5185\u5bb9&#xff0c;\u901a\u5e38\u4e0eWebDAV\u534f\u8bae\u76f8\u5173\u3002<\/p>\n<h5>29.3.1 \u5b58\u50a8\u914d\u989d\u7ba1\u7406\u7cfb\u7edf<\/h5>\n<p>python<\/p>\n<p># \u5b58\u50a8\u914d\u989d\u7ba1\u7406\u5668<br \/>\nclass StorageQuotaManager:<br \/>\n    &#034;&#034;&#034;\u5b58\u50a8\u914d\u989d\u7ba1\u7406\u5668&#xff0c;\u9632\u6b62507\u9519\u8bef&#034;&#034;&#034;<\/p>\n<p>    def __init__(self):<br \/>\n        self.user_quotas &#061; {}<br \/>\n        self.default_quota &#061; {<br \/>\n            &#039;total&#039;: 100 * 1024 * 1024,  # 100MB<br \/>\n            &#039;file_count&#039;: 1000,<br \/>\n            &#039;max_file_size&#039;: 10 * 1024 * 1024  # 10MB<br \/>\n        }<\/p>\n<p>        # \u5b58\u50a8\u4f7f\u7528\u60c5\u51b5\u7f13\u5b58<br \/>\n        self.usage_cache &#061; {}<br \/>\n        self.cache_ttl &#061; 300  # 5\u5206\u949f<\/p>\n<p>    async def check_quota(self, user_id: str,<br \/>\n                         operation: str,<br \/>\n                         size: int &#061; 0) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u68c0\u67e5\u5b58\u50a8\u914d\u989d&#034;&#034;&#034;<\/p>\n<p>        # \u83b7\u53d6\u7528\u6237\u914d\u989d<br \/>\n        quota &#061; self._get_user_quota(user_id)<\/p>\n<p>        # \u83b7\u53d6\u5f53\u524d\u4f7f\u7528\u60c5\u51b5<br \/>\n        usage &#061; await self._get_storage_usage(user_id)<\/p>\n<p>        # \u68c0\u67e5\u64cd\u4f5c\u662f\u5426\u5141\u8bb8<br \/>\n        check_result &#061; self._check_operation(operation, size, quota, usage)<\/p>\n<p>        if not check_result[&#039;allowed&#039;]:<br \/>\n            return self._create_507_response(user_id, quota, usage, check_result)<\/p>\n<p>        return {&#039;allowed&#039;: True, &#039;quota&#039;: quota, &#039;usage&#039;: usage}<\/p>\n<p>    def _check_operation(self, operation: str, size: int,<br \/>\n                        quota: Dict, usage: Dict) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u68c0\u67e5\u7279\u5b9a\u64cd\u4f5c&#034;&#034;&#034;<br \/>\n        result &#061; {<br \/>\n            &#039;allowed&#039;: True,<br \/>\n            &#039;reasons&#039;: []<br \/>\n        }<\/p>\n<p>        if operation &#061;&#061; &#039;upload&#039;:<br \/>\n            # \u68c0\u67e5\u6587\u4ef6\u5927\u5c0f\u9650\u5236<br \/>\n            if size &gt; quota[&#039;max_file_size&#039;]:<br \/>\n                result[&#039;allowed&#039;] &#061; False<br \/>\n                result[&#039;reasons&#039;].append(<br \/>\n                    f&#034;File size ({size} bytes) exceeds maximum allowed &#034;<br \/>\n                    f&#034;({quota[&#039;max_file_size&#039;]} bytes)&#034;<br \/>\n                )<\/p>\n<p>            # \u68c0\u67e5\u603b\u5b58\u50a8\u7a7a\u95f4<br \/>\n            projected_total &#061; usage[&#039;total_bytes&#039;] &#043; size<br \/>\n            if projected_total &gt; quota[&#039;total&#039;]:<br \/>\n                result[&#039;allowed&#039;] &#061; False<br \/>\n                result[&#039;reasons&#039;].append(<br \/>\n                    f&#034;Projected storage ({projected_total} bytes) exceeds &#034;<br \/>\n                    f&#034;quota ({quota[&#039;total&#039;]} bytes)&#034;<br \/>\n                )<\/p>\n<p>            # \u68c0\u67e5\u6587\u4ef6\u6570\u91cf\u9650\u5236<br \/>\n            if usage[&#039;file_count&#039;] &gt;&#061; quota[&#039;file_count&#039;]:<br \/>\n                result[&#039;allowed&#039;] &#061; False<br \/>\n                result[&#039;reasons&#039;].append(<br \/>\n                    f&#034;File count ({usage[&#039;file_count&#039;]}) exceeds limit &#034;<br \/>\n                    f&#034;({quota[&#039;file_count&#039;]})&#034;<br \/>\n                )<\/p>\n<p>        elif operation &#061;&#061; &#039;update&#039;:<br \/>\n            # \u66f4\u65b0\u73b0\u6709\u6587\u4ef6<br \/>\n            # \u8fd9\u91cc\u53ef\u4ee5\u6839\u636e\u9700\u8981\u6dfb\u52a0\u7279\u5b9a\u68c0\u67e5<br \/>\n            pass<\/p>\n<p>        return result<\/p>\n<p>    def _create_507_response(self, user_id: str, quota: Dict,<br \/>\n                            usage: Dict, check_result: Dict) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u521b\u5efa507\u54cd\u5e94&#034;&#034;&#034;<br \/>\n        return {<br \/>\n            &#039;status&#039;: 507,<br \/>\n            &#039;headers&#039;: {<br \/>\n                &#039;Content-Type&#039;: &#039;application\/json&#039;,<br \/>\n                &#039;X-Storage-Quota-Total&#039;: str(quota[&#039;total&#039;]),<br \/>\n                &#039;X-Storage-Quota-Used&#039;: str(usage[&#039;total_bytes&#039;]),<br \/>\n                &#039;X-Storage-Quota-Remaining&#039;: str(quota[&#039;total&#039;] &#8211; usage[&#039;total_bytes&#039;])<br \/>\n            },<br \/>\n            &#039;body&#039;: {<br \/>\n                &#039;error&#039;: {<br \/>\n                    &#039;code&#039;: &#039;insufficient_storage&#039;,<br \/>\n                    &#039;message&#039;: &#039;Insufficient storage to complete the operation&#039;,<br \/>\n                    &#039;details&#039;: {<br \/>\n                        &#039;user_id&#039;: user_id,<br \/>\n                        &#039;operation&#039;: check_result.get(&#039;operation&#039;),<br \/>\n                        &#039;reasons&#039;: check_result[&#039;reasons&#039;],<br \/>\n                        &#039;quota&#039;: {<br \/>\n                            &#039;total_bytes&#039;: quota[&#039;total&#039;],<br \/>\n                            &#039;max_file_size&#039;: quota[&#039;max_file_size&#039;],<br \/>\n                            &#039;max_file_count&#039;: quota[&#039;file_count&#039;]<br \/>\n                        },<br \/>\n                        &#039;usage&#039;: {<br \/>\n                            &#039;total_bytes&#039;: usage[&#039;total_bytes&#039;],<br \/>\n                            &#039;file_count&#039;: usage[&#039;file_count&#039;],<br \/>\n                            &#039;percentage_used&#039;:<br \/>\n                                (usage[&#039;total_bytes&#039;] \/ quota[&#039;total&#039;]) * 100<br \/>\n                        },<br \/>\n                        &#039;suggestions&#039;: [<br \/>\n                            &#039;Delete unused files to free up space&#039;,<br \/>\n                            &#039;Consider upgrading your storage plan&#039;,<br \/>\n                            &#039;Compress files before uploading&#039;<br \/>\n                        ],<br \/>\n                        &#039;upgrade_url&#039;: f&#039;https:\/\/example.com\/upgrade\/{user_id}&#039;<br \/>\n                    }<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>    async def _get_storage_usage(self, user_id: str) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u83b7\u53d6\u5b58\u50a8\u4f7f\u7528\u60c5\u51b5&#034;&#034;&#034;<br \/>\n        # \u68c0\u67e5\u7f13\u5b58<br \/>\n        cache_key &#061; f&#039;usage:{user_id}&#039;<br \/>\n        if cache_key in self.usage_cache:<br \/>\n            cached &#061; self.usage_cache[cache_key]<br \/>\n            if time.time() &#8211; cached[&#039;timestamp&#039;] &lt; self.cache_ttl:<br \/>\n                return cached[&#039;usage&#039;]<\/p>\n<p>        # \u4ece\u6570\u636e\u5e93\u83b7\u53d6\u4f7f\u7528\u60c5\u51b5<br \/>\n        usage &#061; await self._query_storage_usage(user_id)<\/p>\n<p>        # \u66f4\u65b0\u7f13\u5b58<br \/>\n        self.usage_cache[cache_key] &#061; {<br \/>\n            &#039;timestamp&#039;: time.time(),<br \/>\n            &#039;usage&#039;: usage<br \/>\n        }<\/p>\n<p>        return usage<\/p>\n<h4>29.4 508 Loop Detected<\/h4>\n<p>508 Loop Detected\u00a0(WebDAV\u6269\u5c55) \u8868\u793a\u670d\u52a1\u5668\u5728\u5904\u7406\u8bf7\u6c42\u65f6\u68c0\u6d4b\u5230\u65e0\u9650\u5faa\u73af\u3002<\/p>\n<h5>29.4.1 \u5faa\u73af\u68c0\u6d4b\u4e0e\u9632\u62a4<\/h5>\n<p>python<\/p>\n<p># \u8bf7\u6c42\u5faa\u73af\u68c0\u6d4b\u5668<br \/>\nclass LoopDetector:<br \/>\n    &#034;&#034;&#034;\u68c0\u6d4b\u548c\u9632\u6b62\u65e0\u9650\u5faa\u73af&#034;&#034;&#034;<\/p>\n<p>    def __init__(self, max_depth: int &#061; 10, max_iterations: int &#061; 100):<br \/>\n        self.max_depth &#061; max_depth<br \/>\n        self.max_iterations &#061; max_iterations<br \/>\n        self.active_requests &#061; {}<\/p>\n<p>        # \u5faa\u73af\u68c0\u6d4b\u6a21\u5f0f<br \/>\n        self.detection_modes &#061; {<br \/>\n            &#039;strict&#039;: {<br \/>\n                &#039;check_headers&#039;: True,<br \/>\n                &#039;check_params&#039;: True,<br \/>\n                &#039;check_body&#039;: False,<br \/>\n                &#039;threshold&#039;: 3<br \/>\n            },<br \/>\n            &#039;moderate&#039;: {<br \/>\n                &#039;check_headers&#039;: True,<br \/>\n                &#039;check_params&#039;: True,<br \/>\n                &#039;check_body&#039;: False,<br \/>\n                &#039;threshold&#039;: 5<br \/>\n            },<br \/>\n            &#039;lenient&#039;: {<br \/>\n                &#039;check_headers&#039;: False,<br \/>\n                &#039;check_params&#039;: True,<br \/>\n                &#039;check_body&#039;: False,<br \/>\n                &#039;threshold&#039;: 10<br \/>\n            }<br \/>\n        }<\/p>\n<p>        self.current_mode &#061; &#039;moderate&#039;<\/p>\n<p>    def track_request(self, request_id: str, request_data: Dict) -&gt; bool:<br \/>\n        &#034;&#034;&#034;\u8ffd\u8e2a\u8bf7\u6c42&#xff0c;\u68c0\u6d4b\u5faa\u73af&#034;&#034;&#034;<br \/>\n        if request_id not in self.active_requests:<br \/>\n            self.active_requests[request_id] &#061; {<br \/>\n                &#039;count&#039;: 1,<br \/>\n                &#039;first_seen&#039;: time.time(),<br \/>\n                &#039;last_seen&#039;: time.time(),<br \/>\n                &#039;variants&#039;: [self._create_request_signature(request_data)]<br \/>\n            }<br \/>\n            return True<\/p>\n<p>        record &#061; self.active_requests[request_id]<br \/>\n        record[&#039;count&#039;] &#043;&#061; 1<br \/>\n        record[&#039;last_seen&#039;] &#061; time.time()<\/p>\n<p>        # \u68c0\u67e5\u8bf7\u6c42\u8ba1\u6570<br \/>\n        if record[&#039;count&#039;] &gt; self.max_iterations:<br \/>\n            return False<\/p>\n<p>        # \u68c0\u67e5\u65f6\u95f4\u7a97\u53e3<br \/>\n        time_window &#061; record[&#039;last_seen&#039;] &#8211; record[&#039;first_seen&#039;]<br \/>\n        requests_per_second &#061; record[&#039;count&#039;] \/ max(time_window, 1)<\/p>\n<p>        if requests_per_second &gt; 10:  # \u6bcf\u79d210\u4e2a\u8bf7\u6c42<br \/>\n            return False<\/p>\n<p>        # \u68c0\u67e5\u8bf7\u6c42\u53d8\u4f53&#xff08;\u68c0\u6d4b\u5faa\u73af\u4e2d\u7684\u53d8\u5316&#xff09;<br \/>\n        current_signature &#061; self._create_request_signature(request_data)<\/p>\n<p>        if current_signature in record[&#039;variants&#039;]:<br \/>\n            # \u68c0\u6d4b\u5230\u76f8\u540c\u7684\u8bf7\u6c42\u53d8\u4f53<br \/>\n            variant_index &#061; record[&#039;variants&#039;].index(current_signature)<br \/>\n            loop_size &#061; len(record[&#039;variants&#039;]) &#8211; variant_index<\/p>\n<p>            if loop_size &lt;&#061; self.detection_modes[self.current_mode][&#039;threshold&#039;]:<br \/>\n                # \u68c0\u6d4b\u5230\u5c0f\u5faa\u73af<br \/>\n                return False<br \/>\n        else:<br \/>\n            record[&#039;variants&#039;].append(current_signature)<\/p>\n<p>        # \u68c0\u67e5\u53d8\u4f53\u6570\u91cf<br \/>\n        if len(record[&#039;variants&#039;]) &gt; self.max_depth:<br \/>\n            return False<\/p>\n<p>        return True<\/p>\n<p>    def _create_request_signature(self, request_data: Dict) -&gt; str:<br \/>\n        &#034;&#034;&#034;\u521b\u5efa\u8bf7\u6c42\u7b7e\u540d&#034;&#034;&#034;<br \/>\n        mode &#061; self.detection_modes[self.current_mode]<\/p>\n<p>        signature_parts &#061; []<\/p>\n<p>        if mode[&#039;check_headers&#039;]:<br \/>\n            headers &#061; request_data.get(&#039;headers&#039;, {})<br \/>\n            # \u9009\u62e9\u5173\u952e\u5934\u90e8<br \/>\n            key_headers &#061; {k: v for k, v in headers.items()<br \/>\n                          if k.lower() in [&#039;authorization&#039;, &#039;content-type&#039;, &#039;user-agent&#039;]}<br \/>\n            signature_parts.append(f&#034;headers:{hash(str(sorted(key_headers.items())))}&#034;)<\/p>\n<p>        if mode[&#039;check_params&#039;]:<br \/>\n            params &#061; request_data.get(&#039;params&#039;, {})<br \/>\n            signature_parts.append(f&#034;params:{hash(str(sorted(params.items())))}&#034;)<\/p>\n<p>        if mode[&#039;check_body&#039;] and &#039;body&#039; in request_data:<br \/>\n            body &#061; request_data[&#039;body&#039;]<br \/>\n            # \u5bf9\u4e8e\u5927\u8bf7\u6c42\u4f53&#xff0c;\u53ea\u4f7f\u7528\u54c8\u5e0c<br \/>\n            if isinstance(body, str) and len(body) &gt; 1000:<br \/>\n                signature_parts.append(f&#034;body_hash:{hash(body)}&#034;)<br \/>\n            else:<br \/>\n                signature_parts.append(f&#034;body:{hash(str(body))}&#034;)<\/p>\n<p>        return &#039;|&#039;.join(signature_parts)<\/p>\n<p>    def create_508_response(self, request_id: str,<br \/>\n                           request_data: Dict) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u521b\u5efa508\u54cd\u5e94&#034;&#034;&#034;<br \/>\n        record &#061; self.active_requests.get(request_id, {})<\/p>\n<p>        return {<br \/>\n            &#039;status&#039;: 508,<br \/>\n            &#039;headers&#039;: {<br \/>\n                &#039;Content-Type&#039;: &#039;application\/json&#039;,<br \/>\n                &#039;X-Loop-Detected&#039;: &#039;true&#039;,<br \/>\n                &#039;X-Max-Iterations&#039;: str(self.max_iterations)<br \/>\n            },<br \/>\n            &#039;body&#039;: {<br \/>\n                &#039;error&#039;: {<br \/>\n                    &#039;code&#039;: &#039;loop_detected&#039;,<br \/>\n                    &#039;message&#039;: &#039;Infinite loop detected while processing the request&#039;,<br \/>\n                    &#039;details&#039;: {<br \/>\n                        &#039;request_id&#039;: request_id,<br \/>\n                        &#039;iterations&#039;: record.get(&#039;count&#039;, 0),<br \/>\n                        &#039;time_window&#039;: record.get(&#039;last_seen&#039;, 0) &#8211; record.get(&#039;first_seen&#039;, 0),<br \/>\n                        &#039;variants_detected&#039;: len(record.get(&#039;variants&#039;, [])),<br \/>\n                        &#039;detection_mode&#039;: self.current_mode,<br \/>\n                        &#039;request_signature&#039;: self._create_request_signature(request_data)<br \/>\n                    },<br \/>\n                    &#039;suggestions&#039;: [<br \/>\n                        &#039;Check for recursive function calls&#039;,<br \/>\n                        &#039;Verify loop termination conditions&#039;,<br \/>\n                        &#039;Review request parameters for circular references&#039;,<br \/>\n                        &#039;Implement proper caching to avoid redundant processing&#039;<br \/>\n                    ]<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>    def cleanup_old_requests(self, max_age: int &#061; 3600):<br \/>\n        &#034;&#034;&#034;\u6e05\u7406\u65e7\u7684\u8bf7\u6c42\u8bb0\u5f55&#034;&#034;&#034;<br \/>\n        current_time &#061; time.time()<br \/>\n        to_remove &#061; []<\/p>\n<p>        for request_id, record in self.active_requests.items():<br \/>\n            if current_time &#8211; record[&#039;last_seen&#039;] &gt; max_age:<br \/>\n                to_remove.append(request_id)<\/p>\n<p>        for request_id in to_remove:<br \/>\n            del self.active_requests[request_id]<\/p>\n<h4>29.5 510 Not Extended<\/h4>\n<p>510 Not Extended\u00a0\u8868\u793a\u8bf7\u6c42\u9700\u8981\u8fdb\u4e00\u6b65\u6269\u5c55\u624d\u80fd\u88ab\u670d\u52a1\u5668\u5904\u7406\u3002<\/p>\n<h5>29.5.1 \u6269\u5c55\u9700\u6c42\u534f\u5546<\/h5>\n<p>python<\/p>\n<p># \u6269\u5c55\u9700\u6c42\u534f\u5546\u7ba1\u7406\u5668<br \/>\nclass ExtensionNegotiator:<br \/>\n    &#034;&#034;&#034;\u5904\u7406510 Not Extended\u54cd\u5e94&#034;&#034;&#034;<\/p>\n<p>    def __init__(self):<br \/>\n        self.required_extensions &#061; {<br \/>\n            &#039;security&#039;: {<br \/>\n                &#039;require_2fa&#039;: {<br \/>\n                    &#039;description&#039;: &#039;Two-factor authentication required&#039;,<br \/>\n                    &#039;priority&#039;: &#039;high&#039;,<br \/>\n                    &#039;implementation&#039;: &#039;https:\/\/docs.example.com\/2fa&#039;<br \/>\n                },<br \/>\n                &#039;require_ssl&#039;: {<br \/>\n                    &#039;description&#039;: &#039;SSL\/TLS encryption required&#039;,<br \/>\n                    &#039;priority&#039;: &#039;critical&#039;,<br \/>\n                    &#039;implementation&#039;: &#039;https:\/\/docs.example.com\/ssl-setup&#039;<br \/>\n                }<br \/>\n            },<br \/>\n            &#039;compliance&#039;: {<br \/>\n                &#039;require_gdpr_consent&#039;: {<br \/>\n                    &#039;description&#039;: &#039;GDPR consent required for EU users&#039;,<br \/>\n                    &#039;priority&#039;: &#039;medium&#039;,<br \/>\n                    &#039;implementation&#039;: &#039;https:\/\/docs.example.com\/gdpr-compliance&#039;<br \/>\n                }<br \/>\n            },<br \/>\n            &#039;features&#039;: {<br \/>\n                &#039;require_api_key&#039;: {<br \/>\n                    &#039;description&#039;: &#039;API key authentication required&#039;,<br \/>\n                    &#039;priority&#039;: &#039;high&#039;,<br \/>\n                    &#039;implementation&#039;: &#039;https:\/\/docs.example.com\/api-authentication&#039;<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>    def check_requirements(self, request: Dict,<br \/>\n                          user_context: Dict) -&gt; List[Dict]:<br \/>\n        &#034;&#034;&#034;\u68c0\u67e5\u8bf7\u6c42\u662f\u5426\u6ee1\u8db3\u6240\u6709\u8981\u6c42&#034;&#034;&#034;<br \/>\n        missing_extensions &#061; []<\/p>\n<p>        # \u68c0\u67e5\u5b89\u5168\u6269\u5c55<br \/>\n        if not self._check_security_extensions(request, user_context):<br \/>\n            missing_extensions.extend(<br \/>\n                self._get_missing_security_extensions(user_context)<br \/>\n            )<\/p>\n<p>        # \u68c0\u67e5\u5408\u89c4\u6269\u5c55<br \/>\n        if not self._check_compliance_extensions(request, user_context):<br \/>\n            missing_extensions.extend(<br \/>\n                self._get_missing_compliance_extensions(user_context)<br \/>\n            )<\/p>\n<p>        # \u68c0\u67e5\u529f\u80fd\u6269\u5c55<br \/>\n        if not self._check_feature_extensions(request, user_context):<br \/>\n            missing_extensions.extend(<br \/>\n                self._get_missing_feature_extensions(user_context)<br \/>\n            )<\/p>\n<p>        return missing_extensions<\/p>\n<p>    def create_510_response(self, missing_extensions: List[Dict],<br \/>\n                           request: Dict) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u521b\u5efa510\u54cd\u5e94&#034;&#034;&#034;<br \/>\n        return {<br \/>\n            &#039;status&#039;: 510,<br \/>\n            &#039;headers&#039;: {<br \/>\n                &#039;Content-Type&#039;: &#039;application\/json&#039;,<br \/>\n                &#039;X-Required-Extensions&#039;: &#039;,&#039;.join(<br \/>\n                    [ext[&#039;code&#039;] for ext in missing_extensions]<br \/>\n                )<br \/>\n            },<br \/>\n            &#039;body&#039;: {<br \/>\n                &#039;error&#039;: {<br \/>\n                    &#039;code&#039;: &#039;not_extended&#039;,<br \/>\n                    &#039;message&#039;: &#039;Further extensions are required to process this request&#039;,<br \/>\n                    &#039;details&#039;: {<br \/>\n                        &#039;missing_extensions&#039;: missing_extensions,<br \/>\n                        &#039;request_summary&#039;: {<br \/>\n                            &#039;method&#039;: request.get(&#039;method&#039;),<br \/>\n                            &#039;path&#039;: request.get(&#039;path&#039;),<br \/>\n                            &#039;user&#039;: request.get(&#039;user&#039;, {}).get(&#039;id&#039;)<br \/>\n                        },<br \/>\n                        &#039;next_steps&#039;: [<br \/>\n                            &#039;Implement the required extensions listed below&#039;,<br \/>\n                            &#039;Review the implementation documentation&#039;,<br \/>\n                            &#039;Test with the extension verification endpoint&#039;<br \/>\n                        ],<br \/>\n                        &#039;verification_endpoint&#039;: &#039;\/api\/v1\/extensions\/verify&#039;,<br \/>\n                        &#039;documentation&#039;: &#039;https:\/\/docs.example.com\/extensions&#039;<br \/>\n                    }<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>    def _check_security_extensions(self, request: Dict,<br \/>\n                                  user_context: Dict) -&gt; bool:<br \/>\n        &#034;&#034;&#034;\u68c0\u67e5\u5b89\u5168\u6269\u5c55&#034;&#034;&#034;<br \/>\n        # \u68c0\u67e5SSL<br \/>\n        if request.get(&#039;protocol&#039;) !&#061; &#039;https&#039;:<br \/>\n            return False<\/p>\n<p>        # \u68c0\u67e52FA&#xff08;\u5bf9\u4e8e\u654f\u611f\u64cd\u4f5c&#xff09;<br \/>\n        if self._is_sensitive_operation(request):<br \/>\n            if not user_context.get(&#039;two_factor_enabled&#039;, False):<br \/>\n                return False<\/p>\n<p>        return True<\/p>\n<p>    def _get_missing_security_extensions(self, user_context: Dict) -&gt; List[Dict]:<br \/>\n        &#034;&#034;&#034;\u83b7\u53d6\u7f3a\u5c11\u7684\u5b89\u5168\u6269\u5c55&#034;&#034;&#034;<br \/>\n        missing &#061; []<\/p>\n<p>        # \u68c0\u67e52FA<br \/>\n        if not user_context.get(&#039;two_factor_enabled&#039;, False):<br \/>\n            missing.append({<br \/>\n                &#039;category&#039;: &#039;security&#039;,<br \/>\n                &#039;code&#039;: &#039;require_2fa&#039;,<br \/>\n                **self.required_extensions[&#039;security&#039;][&#039;require_2fa&#039;]<br \/>\n            })<\/p>\n<p>        return missing<\/p>\n<h4>29.6 511 Network Authentication Required<\/h4>\n<p>511 Network Authentication Required\u00a0\u8868\u793a\u5ba2\u6237\u7aef\u9700\u8981\u8fdb\u884c\u7f51\u7edc\u8ba4\u8bc1\u624d\u80fd\u8bbf\u95ee\u8d44\u6e90\u3002<\/p>\n<h5>29.6.1 \u7f51\u7edc\u8ba4\u8bc1\u95e8\u6237\u5b9e\u73b0<\/h5>\n<p>python<\/p>\n<p># \u7f51\u7edc\u8ba4\u8bc1\u95e8\u6237\u7ba1\u7406\u5668<br \/>\nclass NetworkAuthPortal:<br \/>\n    &#034;&#034;&#034;\u7ba1\u7406511\u7f51\u7edc\u8ba4\u8bc1&#034;&#034;&#034;<\/p>\n<p>    def __init__(self):<br \/>\n        self.captive_portal_url &#061; &#034;https:\/\/portal.example.com\/auth&#034;<br \/>\n        self.auth_sessions &#061; {}<br \/>\n        self.session_timeout &#061; 3600  # 1\u5c0f\u65f6<\/p>\n<p>        # \u8ba4\u8bc1\u65b9\u6cd5<br \/>\n        self.auth_methods &#061; {<br \/>\n            &#039;social&#039;: {<br \/>\n                &#039;google&#039;: {<br \/>\n                    &#039;name&#039;: &#039;Google&#039;,<br \/>\n                    &#039;url&#039;: &#039;\/auth\/google&#039;,<br \/>\n                    &#039;icon&#039;: &#039;google.svg&#039;<br \/>\n                },<br \/>\n                &#039;facebook&#039;: {<br \/>\n                    &#039;name&#039;: &#039;Facebook&#039;,<br \/>\n                    &#039;url&#039;: &#039;\/auth\/facebook&#039;,<br \/>\n                    &#039;icon&#039;: &#039;facebook.svg&#039;<br \/>\n                }<br \/>\n            },<br \/>\n            &#039;enterprise&#039;: {<br \/>\n                &#039;sso&#039;: {<br \/>\n                    &#039;name&#039;: &#039;Single Sign-On&#039;,<br \/>\n                    &#039;url&#039;: &#039;\/auth\/sso&#039;,<br \/>\n                    &#039;icon&#039;: &#039;sso.svg&#039;<br \/>\n                },<br \/>\n                &#039;ldap&#039;: {<br \/>\n                    &#039;name&#039;: &#039;LDAP\/Active Directory&#039;,<br \/>\n                    &#039;url&#039;: &#039;\/auth\/ldap&#039;,<br \/>\n                    &#039;icon&#039;: &#039;ldap.svg&#039;<br \/>\n                }<br \/>\n            },<br \/>\n            &#039;simple&#039;: {<br \/>\n                &#039;email&#039;: {<br \/>\n                    &#039;name&#039;: &#039;Email&#039;,<br \/>\n                    &#039;url&#039;: &#039;\/auth\/email&#039;,<br \/>\n                    &#039;icon&#039;: &#039;email.svg&#039;<br \/>\n                },<br \/>\n                &#039;sms&#039;: {<br \/>\n                    &#039;name&#039;: &#039;SMS&#039;,<br \/>\n                    &#039;url&#039;: &#039;\/auth\/sms&#039;,<br \/>\n                    &#039;icon&#039;: &#039;sms.svg&#039;<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>    def create_511_response(self, request: Dict,<br \/>\n                           network_info: Dict) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u521b\u5efa511\u54cd\u5e94&#034;&#034;&#034;<br \/>\n        session_id &#061; self._create_auth_session(request, network_info)<\/p>\n<p>        # \u6839\u636e\u8bbe\u5907\u7c7b\u578b\u9009\u62e9\u8ba4\u8bc1\u65b9\u6cd5<br \/>\n        user_agent &#061; request.headers.get(&#039;User-Agent&#039;, &#039;&#039;)<br \/>\n        auth_methods &#061; self._select_auth_methods(user_agent)<\/p>\n<p>        return {<br \/>\n            &#039;status&#039;: 511,<br \/>\n            &#039;headers&#039;: {<br \/>\n                &#039;Content-Type&#039;: &#039;text\/html&#039;,  # \u901a\u5e38\u8fd4\u56deHTML\u95e8\u6237\u9875\u9762<br \/>\n                &#039;X-Network-Auth-Required&#039;: &#039;true&#039;,<br \/>\n                &#039;X-Auth-Session&#039;: session_id,<br \/>\n                &#039;X-Captive-Portal&#039;: self.captive_portal_url<br \/>\n            },<br \/>\n            &#039;body&#039;: self._generate_portal_html(<br \/>\n                session_id,<br \/>\n                network_info,<br \/>\n                auth_methods<br \/>\n            )<br \/>\n        }<\/p>\n<p>    def _generate_portal_html(self, session_id: str,<br \/>\n                             network_info: Dict,<br \/>\n                             auth_methods: List[Dict]) -&gt; str:<br \/>\n        &#034;&#034;&#034;\u751f\u6210\u8ba4\u8bc1\u95e8\u6237HTML&#034;&#034;&#034;<br \/>\n        return f&#034;&#034;&#034;<br \/>\n&lt;!DOCTYPE html&gt;<br \/>\n&lt;html lang&#061;&#034;en&#034;&gt;<br \/>\n&lt;head&gt;<br \/>\n    &lt;meta charset&#061;&#034;UTF-8&#034;&gt;<br \/>\n    &lt;meta name&#061;&#034;viewport&#034; content&#061;&#034;width&#061;device-width, initial-scale&#061;1.0&#034;&gt;<br \/>\n    &lt;title&gt;Network Authentication Required&lt;\/title&gt;<br \/>\n    &lt;style&gt;<br \/>\n        body {{<br \/>\n            font-family: -apple-system, BlinkMacSystemFont, &#039;Segoe UI&#039;, Roboto, sans-serif;<br \/>\n            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);<br \/>\n            min-height: 100vh;<br \/>\n            display: flex;<br \/>\n            align-items: center;<br \/>\n            justify-content: center;<br \/>\n            padding: 20px;<br \/>\n        }}<br \/>\n        .portal-container {{<br \/>\n            background: white;<br \/>\n            border-radius: 12px;<br \/>\n            padding: 40px;<br \/>\n            box-shadow: 0 20px 60px rgba(0,0,0,0.3);<br \/>\n            max-width: 480px;<br \/>\n            width: 100%;<br \/>\n        }}<br \/>\n        .network-info {{<br \/>\n            background: #f7fafc;<br \/>\n            padding: 15px;<br \/>\n            border-radius: 8px;<br \/>\n            margin-bottom: 30px;<br \/>\n        }}<br \/>\n        .auth-methods {{<br \/>\n            display: grid;<br \/>\n            gap: 15px;<br \/>\n            margin-top: 20px;<br \/>\n        }}<br \/>\n        .auth-method {{<br \/>\n            display: flex;<br \/>\n            align-items: center;<br \/>\n            padding: 15px;<br \/>\n            border: 2px solid #e2e8f0;<br \/>\n            border-radius: 8px;<br \/>\n            text-decoration: none;<br \/>\n            color: #2d3748;<br \/>\n            transition: all 0.2s;<br \/>\n        }}<br \/>\n        .auth-method:hover {{<br \/>\n            border-color: #667eea;<br \/>\n            transform: translateY(-2px);<br \/>\n        }}<br \/>\n        .auth-method-icon {{<br \/>\n            width: 24px;<br \/>\n            height: 24px;<br \/>\n            margin-right: 15px;<br \/>\n        }}<br \/>\n    &lt;\/style&gt;<br \/>\n&lt;\/head&gt;<br \/>\n&lt;body&gt;<br \/>\n    &lt;div class&#061;&#034;portal-container&#034;&gt;<br \/>\n        &lt;h1&gt;Network Authentication Required&lt;\/h1&gt;<br \/>\n        &lt;p&gt;You need to authenticate to access this network.&lt;\/p&gt;<\/p>\n<p>        &lt;div class&#061;&#034;network-info&#034;&gt;<br \/>\n            &lt;h3&gt;Network Information&lt;\/h3&gt;<br \/>\n            &lt;p&gt;&lt;strong&gt;SSID:&lt;\/strong&gt; {network_info.get(&#039;ssid&#039;, &#039;Unknown&#039;)}&lt;\/p&gt;<br \/>\n            &lt;p&gt;&lt;strong&gt;IP Address:&lt;\/strong&gt; {network_info.get(&#039;ip&#039;, &#039;Unknown&#039;)}&lt;\/p&gt;<br \/>\n            &lt;p&gt;&lt;strong&gt;Location:&lt;\/strong&gt; {network_info.get(&#039;location&#039;, &#039;Unknown&#039;)}&lt;\/p&gt;<br \/>\n        &lt;\/div&gt;<\/p>\n<p>        &lt;h2&gt;Choose Authentication Method&lt;\/h2&gt;<br \/>\n        &lt;div class&#061;&#034;auth-methods&#034;&gt;<br \/>\n            {&#039; &#039;.join([self._generate_auth_method_html(method) for method in auth_methods])}<br \/>\n        &lt;\/div&gt;<\/p>\n<p>        &lt;div style&#061;&#034;margin-top: 30px; font-size: 0.9em; color: #718096;&#034;&gt;<br \/>\n            &lt;p&gt;By authenticating, you agree to our<br \/>\n            &lt;a href&#061;&#034;\/terms&#034;&gt;Terms of Service&lt;\/a&gt; and<br \/>\n            &lt;a href&#061;&#034;\/privacy&#034;&gt;Privacy Policy&lt;\/a&gt;.&lt;\/p&gt;<br \/>\n        &lt;\/div&gt;<br \/>\n    &lt;\/div&gt;<br \/>\n&lt;\/body&gt;<br \/>\n&lt;\/html&gt;<br \/>\n        &#034;&#034;&#034;<\/p>\n<p>    def _generate_auth_method_html(self, method: Dict) -&gt; str:<br \/>\n        &#034;&#034;&#034;\u751f\u6210\u8ba4\u8bc1\u65b9\u6cd5HTML&#034;&#034;&#034;<br \/>\n        return f&#034;&#034;&#034;<br \/>\n        &lt;a href&#061;&#034;{method[&#039;url&#039;]}&#034; class&#061;&#034;auth-method&#034;&gt;<br \/>\n            &lt;img src&#061;&#034;\/icons\/{method[&#039;icon&#039;]}&#034; class&#061;&#034;auth-method-icon&#034;<br \/>\n                 alt&#061;&#034;{method[&#039;name&#039;]}&#034;&gt;<br \/>\n            &lt;span&gt;Sign in with {method[&#039;name&#039;]}&lt;\/span&gt;<br \/>\n        &lt;\/a&gt;<br \/>\n        &#034;&#034;&#034;<\/p>\n<p>    def _select_auth_methods(self, user_agent: str) -&gt; List[Dict]:<br \/>\n        &#034;&#034;&#034;\u6839\u636e\u7528\u6237\u4ee3\u7406\u9009\u62e9\u8ba4\u8bc1\u65b9\u6cd5&#034;&#034;&#034;<br \/>\n        methods &#061; []<\/p>\n<p>        # \u79fb\u52a8\u8bbe\u5907<br \/>\n        if &#039;Mobile&#039; in user_agent or &#039;Android&#039; in user_agent or &#039;iPhone&#039; in user_agent:<br \/>\n            methods.append(self.auth_methods[&#039;simple&#039;][&#039;sms&#039;])<br \/>\n            methods.append(self.auth_methods[&#039;social&#039;][&#039;google&#039;])<\/p>\n<p>        # \u684c\u9762\u8bbe\u5907<br \/>\n        else:<br \/>\n            methods.append(self.auth_methods[&#039;social&#039;][&#039;google&#039;])<br \/>\n            methods.append(self.auth_methods[&#039;social&#039;][&#039;facebook&#039;])<br \/>\n            methods.append(self.auth_methods[&#039;enterprise&#039;][&#039;sso&#039;])<\/p>\n<p>        # \u603b\u662f\u5305\u542b\u90ae\u7bb1\u8ba4\u8bc1<br \/>\n        methods.append(self.auth_methods[&#039;simple&#039;][&#039;email&#039;])<\/p>\n<p>        return methods<\/p>\n<p>    def _create_auth_session(self, request: Dict,<br \/>\n                            network_info: Dict) -&gt; str:<br \/>\n        &#034;&#034;&#034;\u521b\u5efa\u8ba4\u8bc1\u4f1a\u8bdd&#034;&#034;&#034;<br \/>\n        session_id &#061; self._generate_session_id()<\/p>\n<p>        self.auth_sessions[session_id] &#061; {<br \/>\n            &#039;created_at&#039;: time.time(),<br \/>\n            &#039;ip_address&#039;: request.get(&#039;remote_addr&#039;),<br \/>\n            &#039;user_agent&#039;: request.headers.get(&#039;User-Agent&#039;),<br \/>\n            &#039;original_url&#039;: request.get(&#039;original_url&#039;),<br \/>\n            &#039;network_info&#039;: network_info,<br \/>\n            &#039;status&#039;: &#039;pending&#039;<br \/>\n        }<\/p>\n<p>        return session_id<\/p>\n<h4>29.7 \u6700\u4f73\u5b9e\u8df5\u603b\u7ed3<\/h4>\n<h5>29.7.1 \u72b6\u6001\u7801\u4f7f\u7528\u6307\u5357<\/h5>\n<table>\n<tr>\u72b6\u6001\u7801\u540d\u79f0\u4f7f\u7528\u573a\u666f\u6700\u4f73\u5b9e\u8df5<\/tr>\n<tbody>\n<tr>\n<td>505<\/td>\n<td>HTTP Version Not Supported<\/td>\n<td>\u4e0d\u652f\u6301\u7684HTTP\u534f\u8bae\u7248\u672c<\/td>\n<td>\u63d0\u4f9b\u652f\u6301\u7684\u7248\u672c\u5217\u8868\u548c\u5347\u7ea7\u6307\u5357<\/td>\n<\/tr>\n<tr>\n<td>506<\/td>\n<td>Variant Also Negotiates<\/td>\n<td>\u5185\u5bb9\u534f\u5546\u5faa\u73af<\/td>\n<td>\u5b9e\u73b0\u5faa\u73af\u68c0\u6d4b\u548c\u9650\u5236\u6700\u5927\u6df1\u5ea6<\/td>\n<\/tr>\n<tr>\n<td>507<\/td>\n<td>Insufficient Storage<\/td>\n<td>\u5b58\u50a8\u7a7a\u95f4\u4e0d\u8db3<\/td>\n<td>\u5b9e\u73b0\u914d\u989d\u7ba1\u7406\u548c\u53cb\u597d\u7684\u9519\u8bef\u4fe1\u606f<\/td>\n<\/tr>\n<tr>\n<td>508<\/td>\n<td>Loop Detected<\/td>\n<td>\u68c0\u6d4b\u5230\u65e0\u9650\u5faa\u73af<\/td>\n<td>\u6dfb\u52a0\u5faa\u73af\u68c0\u6d4b\u548c\u9002\u5f53\u7684\u8d85\u65f6<\/td>\n<\/tr>\n<tr>\n<td>510<\/td>\n<td>Not Extended<\/td>\n<td>\u9700\u8981\u989d\u5916\u6269\u5c55<\/td>\n<td>\u660e\u786e\u5217\u51fa\u6240\u9700\u6269\u5c55\u548c\u5b9e\u73b0\u6307\u5357<\/td>\n<\/tr>\n<tr>\n<td>511<\/td>\n<td>Network Authentication Required<\/td>\n<td>\u9700\u8981\u7f51\u7edc\u8ba4\u8bc1<\/td>\n<td>\u63d0\u4f9b\u7528\u6237\u53cb\u597d\u7684\u8ba4\u8bc1\u95e8\u6237<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h5>29.7.2 \u76d1\u63a7\u548c\u544a\u8b66\u914d\u7f6e<\/h5>\n<p>yaml<\/p>\n<p># Prometheus\u76d1\u63a7\u914d\u7f6e<br \/>\nscrape_configs:<br \/>\n  &#8211; job_name: &#039;extended_5xx&#039;<br \/>\n    static_configs:<br \/>\n      &#8211; targets: [&#039;app:9090&#039;]<\/p>\n<p>    # \u76d1\u63a7\u4e0d\u5e38\u89c1\u76845xx\u9519\u8bef<br \/>\n    relabel_configs:<br \/>\n    &#8211; source_labels: [__meta_kubernetes_pod_label_app]<br \/>\n      regex: .*<br \/>\n      action: keep<\/p>\n<p># \u544a\u8b66\u89c4\u5219<br \/>\ngroups:<br \/>\n  &#8211; name: extended_5xx_alerts<br \/>\n    rules:<br \/>\n      &#8211; alert: Unusual5xxError<br \/>\n        expr: |<br \/>\n          sum by (status) (<br \/>\n            rate(http_requests_total{status&#061;~&#034;5[0-9]{2}&#034;}[5m])<br \/>\n          ) &gt; 0<br \/>\n        for: 1m<br \/>\n        labels:<br \/>\n          severity: info<br \/>\n        annotations:<br \/>\n          summary: &#034;Unusual 5xx status code detected&#034;<br \/>\n          description: |<br \/>\n            \u68c0\u6d4b\u5230\u4e0d\u5e38\u89c1\u76845xx\u72b6\u6001\u7801: {{ $labels.status }}<br \/>\n            \u8bf7\u6c42\u8def\u5f84: {{ $labels.path }}<\/p>\n<p>      &#8211; alert: HTTPVersionNotSupported<br \/>\n        expr: |<br \/>\n          rate(http_requests_total{status&#061;&#034;505&#034;}[5m]) &gt; 0.001<br \/>\n        for: 2m<br \/>\n        labels:<br \/>\n          severity: warning<br \/>\n        annotations:<br \/>\n          summary: &#034;HTTP version not supported errors&#034;<br \/>\n          description: |<br \/>\n            505\u9519\u8bef\u7387\u8d85\u8fc70.1%<br \/>\n            \u53ef\u80fd\u9700\u8981\u66f4\u65b0\u5ba2\u6237\u7aef\u6216\u8c03\u6574\u670d\u52a1\u5668\u914d\u7f6e<\/p>\n<p>\u901a\u8fc7\u6b63\u786e\u5904\u7406\u8fd9\u4e9b\u4e0d\u5e38\u89c1\u76845xx\u72b6\u6001\u7801&#xff0c;\u53ef\u4ee5\u63d0\u4f9b\u66f4\u597d\u7684\u7528\u6237\u4f53\u9a8c&#xff0c;\u540c\u65f6\u5e2e\u52a9\u5f00\u53d1\u8005\u548c\u8fd0\u7ef4\u4eba\u5458\u5feb\u901f\u8bca\u65ad\u548c\u89e3\u51b3\u95ee\u9898\u3002<\/p>\n<hr \/>\n<h3>\u603b\u7ed3&#xff1a;5xx\u72b6\u6001\u7801\u7cfb\u7edf\u5316\u5e94\u5bf9\u7b56\u7565<\/h3>\n<h4>\u7efc\u5408\u76d1\u63a7\u4e0e\u544a\u8b66\u4f53\u7cfb<\/h4>\n<p>yaml<\/p>\n<p># \u5b8c\u6574\u76845xx\u9519\u8bef\u76d1\u63a7\u4eea\u8868\u677f\u914d\u7f6e<br \/>\ngrafana_dashboard:<br \/>\n  title: &#034;5xx Server Errors &#8211; Comprehensive Monitoring&#034;<br \/>\n  panels:<br \/>\n    &#8211; title: &#034;5xx Error Rate Trend&#034;<br \/>\n      type: &#034;graph&#034;<br \/>\n      targets:<br \/>\n        &#8211; expr: |<br \/>\n            sum by (status) (<br \/>\n              rate(http_requests_total{status&#061;~&#034;5..&#034;}[5m])<br \/>\n            ) \/<br \/>\n            sum(rate(http_requests_total[5m]))<\/p>\n<p>    &#8211; title: &#034;Top 5xx Error Sources&#034;<br \/>\n      type: &#034;table&#034;<br \/>\n      targets:<br \/>\n        &#8211; expr: |<br \/>\n            topk(10,<br \/>\n              sum by (service, endpoint, status) (<br \/>\n                rate(http_requests_total{status&#061;~&#034;5..&#034;}[5m])<br \/>\n              )<br \/>\n            )<\/p>\n<p>    &#8211; title: &#034;Response Time vs 5xx Errors&#034;<br \/>\n      type: &#034;graph&#034;<br \/>\n      targets:<br \/>\n        &#8211; expr: |<br \/>\n            histogram_quantile(0.95,<br \/>\n              rate(http_response_time_seconds_bucket[5m])<br \/>\n            )<br \/>\n        &#8211; expr: |<br \/>\n            rate(http_requests_total{status&#061;~&#034;5..&#034;}[5m])<\/p>\n<p>    &#8211; title: &#034;Error Recovery Time&#034;<br \/>\n      type: &#034;stat&#034;<br \/>\n      targets:<br \/>\n        &#8211; expr: |<br \/>\n            time() &#8211;<br \/>\n            timestamp(<br \/>\n              max_over_time(<br \/>\n                http_requests_total{status&#061;~&#034;5..&#034;}[1h]<br \/>\n              )<br \/>\n            )<\/p>\n<p>  alerts:<br \/>\n    &#8211; name: &#034;5xx Error SLO Violation&#034;<br \/>\n      condition: |<br \/>\n        (<br \/>\n          sum(rate(http_requests_total{status&#061;~&#034;5..&#034;}[5m]))<br \/>\n          \/<br \/>\n          sum(rate(http_requests_total[5m]))<br \/>\n        ) &gt; 0.01  # 1%\u9519\u8bef\u7387<br \/>\n      for: &#034;5m&#034;<br \/>\n      severity: &#034;critical&#034;<\/p>\n<p>    &#8211; name: &#034;Error Burst Detection&#034;<br \/>\n      condition: |<br \/>\n        rate(http_requests_total{status&#061;~&#034;5..&#034;}[1m])<br \/>\n        &gt;<br \/>\n        10 * rate(http_requests_total{status&#061;~&#034;5..&#034;}[5m])<br \/>\n      for: &#034;1m&#034;<br \/>\n      severity: &#034;warning&#034;<\/p>\n<h4>\u6839\u56e0\u5206\u6790\u51b3\u7b56\u6811<img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1756\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/07\/20260726181702-6a664f1e7da13.png\" width=\"2094\" \/><\/h4>\n<h4>\u6301\u7eed\u6539\u8fdb\u4e0e\u77e5\u8bc6\u7ba1\u7406<\/h4>\n<p>python<\/p>\n<p># \u6545\u969c\u77e5\u8bc6\u5e93\u7ba1\u7406\u7cfb\u7edf<br \/>\nclass IncidentKnowledgeBase:<br \/>\n    &#034;&#034;&#034;5xx\u9519\u8bef\u6545\u969c\u77e5\u8bc6\u5e93&#034;&#034;&#034;<\/p>\n<p>    def __init__(self):<br \/>\n        self.incidents &#061; []<br \/>\n        self.solutions &#061; {}<br \/>\n        self.patterns &#061; {}<\/p>\n<p>    def record_incident(self, error_code: int, context: Dict,<br \/>\n                       resolution: Dict):<br \/>\n        &#034;&#034;&#034;\u8bb0\u5f55\u6545\u969c\u4e8b\u4ef6&#034;&#034;&#034;<br \/>\n        incident &#061; {<br \/>\n            &#039;id&#039;: self._generate_id(),<br \/>\n            &#039;timestamp&#039;: time.time(),<br \/>\n            &#039;error_code&#039;: error_code,<br \/>\n            &#039;context&#039;: context,<br \/>\n            &#039;resolution&#039;: resolution,<br \/>\n            &#039;root_cause&#039;: self._analyze_root_cause(context),<br \/>\n            &#039;prevention_measures&#039;: [],<br \/>\n            &#039;related_incidents&#039;: self._find_related_incidents(error_code, context)<br \/>\n        }<\/p>\n<p>        self.incidents.append(incident)<\/p>\n<p>        # \u66f4\u65b0\u89e3\u51b3\u65b9\u6848\u5e93<br \/>\n        self._update_solutions(error_code, resolution)<\/p>\n<p>        # \u66f4\u65b0\u6a21\u5f0f\u5e93<br \/>\n        self._update_patterns(incident)<\/p>\n<p>        return incident<\/p>\n<p>    def suggest_solutions(self, error_code: int, context: Dict) -&gt; List[Dict]:<br \/>\n        &#034;&#034;&#034;\u6839\u636e\u9519\u8bef\u4ee3\u7801\u548c\u4e0a\u4e0b\u6587\u5efa\u8bae\u89e3\u51b3\u65b9\u6848&#034;&#034;&#034;<br \/>\n        suggestions &#061; []<\/p>\n<p>        # \u57fa\u4e8e\u9519\u8bef\u4ee3\u7801\u7684\u901a\u7528\u89e3\u51b3\u65b9\u6848<br \/>\n        generic_solutions &#061; self.solutions.get(error_code, [])<br \/>\n        suggestions.extend(generic_solutions)<\/p>\n<p>        # \u57fa\u4e8e\u6a21\u5f0f\u7684\u89e3\u51b3\u65b9\u6848<br \/>\n        matched_patterns &#061; self._match_patterns(context)<br \/>\n        for pattern in matched_patterns:<br \/>\n            suggestions.extend(pattern.get(&#039;solutions&#039;, []))<\/p>\n<p>        # \u57fa\u4e8e\u76f8\u4f3c\u5386\u53f2\u4e8b\u4ef6\u7684\u89e3\u51b3\u65b9\u6848<br \/>\n        similar_incidents &#061; self._find_similar_incidents(context)<br \/>\n        for incident in similar_incidents:<br \/>\n            suggestions.append({<br \/>\n                &#039;type&#039;: &#039;historical&#039;,<br \/>\n                &#039;confidence&#039;: incident.get(&#039;similarity_score&#039;, 0),<br \/>\n                &#039;solution&#039;: incident[&#039;resolution&#039;],<br \/>\n                &#039;reference&#039;: incident[&#039;id&#039;]<br \/>\n            })<\/p>\n<p>        # \u53bb\u91cd\u548c\u6392\u5e8f<br \/>\n        unique_suggestions &#061; self._deduplicate_suggestions(suggestions)<br \/>\n        sorted_suggestions &#061; sorted(unique_suggestions,<br \/>\n                                   key&#061;lambda x: x.get(&#039;confidence&#039;, 0),<br \/>\n                                   reverse&#061;True)<\/p>\n<p>        return sorted_suggestions[:5]  # \u8fd4\u56de\u524d5\u4e2a\u5efa\u8bae<\/p>\n<p>    def generate_postmortem(self, incident_id: str) -&gt; Dict:<br \/>\n        &#034;&#034;&#034;\u751f\u6210\u6545\u969c\u590d\u76d8\u62a5\u544a&#034;&#034;&#034;<br \/>\n        incident &#061; self._get_incident(incident_id)<\/p>\n<p>        if not incident:<br \/>\n            return {}<\/p>\n<p>        report &#061; {<br \/>\n            &#039;title&#039;: f&#034;Postmortem: {incident[&#039;error_code&#039;]} Error&#034;,<br \/>\n            &#039;incident_id&#039;: incident_id,<br \/>\n            &#039;executive_summary&#039;: self._generate_summary(incident),<br \/>\n            &#039;timeline&#039;: self._build_timeline(incident),<br \/>\n            &#039;root_cause_analysis&#039;: incident[&#039;root_cause&#039;],<br \/>\n            &#039;impact_assessment&#039;: self._assess_impact(incident),<br \/>\n            &#039;action_items&#039;: self._generate_action_items(incident),<br \/>\n            &#039;lessons_learned&#039;: self._extract_lessons(incident),<br \/>\n            &#039;preventive_measures&#039;: self._suggest_preventions(incident)<br \/>\n        }<\/p>\n<p>        return report<\/p>\n<p>\u901a\u8fc7\u7cfb\u7edf\u5316\u7684\u65b9\u6cd5\u5904\u74065xx\u9519\u8bef&#xff0c;\u4ece\u9884\u9632\u3001\u68c0\u6d4b\u3001\u54cd\u5e94\u5230\u590d\u76d8&#xff0c;\u53ef\u4ee5\u6784\u5efa\u4e00\u4e2a\u5065\u58ee\u7684\u3001\u53ef\u89c2\u6d4b\u7684\u3001\u53ef\u6062\u590d\u7684\u7cfb\u7edf\u67b6\u6784\u3002\u8bb0\u4f4f&#xff0c;\u6bcf\u4e2a5xx\u9519\u8bef\u90fd\u662f\u4e00\u4e2a\u6539\u8fdb\u7cfb\u7edf\u7684\u673a\u4f1a\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u7b2c24\u7ae0&#xff1a;500 Internal Server Error &#8211; \u5185\u90e8\u670d\u52a1\u5668\u9519\u8bef24.1 \u6df1\u5ea6\u6280\u672f\u89e3\u6790&#xff1a;500\u9519\u8bef\u7684\u672c\u8d28500 Internal Server Error\u00a0\u662fHTTP\u534f\u8bae\u4e2d\u6700\u901a\u7528\u3001\u6700\u4ee4\u4eba\u56f0\u60d1\u7684\u670d\u52a1\u5668\u9519\u8bef\u72b6\u6001\u7801\u3002\u4e0e\u5ba2\u6237\u7aef\u9519\u8bef&#xff08;4xx&#xff09;\u4e0d\u540c&#xff0c;500\u9519\u8bef\u660e\u786e\u8868\u793a\u95ee\u9898\u51fa\u5728\u670d\u52a1\u5668\u7aef&#xff0c;\u4f46\u670d\u52a1\u5668\u65e0\u6cd5\u6216\u4e0d\u613f\u63d0\u4f9b\u66f4\u5177\u4f53\u7684\u4fe1\u606f\u300224.1.1 \u6280\u672f\u89c4\u683c\u4e0e\u534f\u8bae\u5b9a\u4e49HTTP\/1.1 RFC 7231\u5b9a\u4e49<\/p>\n","protected":false},"author":2,"featured_media":85156,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[151,43,191],"topic":[],"class_list":["post-85162","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-server","tag-http","tag-43","tag-191"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>HTTP \u72b6\u6001\u7801\uff1a\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u5668\u7684\u901a\u4fe1\u8bed\u8a00\u2014\u2014\u7b2c\u4e94\u90e8\u5206\uff1a\u670d\u52a1\u5668\u9519\u8bef\u72b6\u6001\u7801\uff085xx\uff09\u7cfb\u7edf\u5206\u6790 - \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\/85162.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"HTTP \u72b6\u6001\u7801\uff1a\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u5668\u7684\u901a\u4fe1\u8bed\u8a00\u2014\u2014\u7b2c\u4e94\u90e8\u5206\uff1a\u670d\u52a1\u5668\u9519\u8bef\u72b6\u6001\u7801\uff085xx\uff09\u7cfb\u7edf\u5206\u6790 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"\u7b2c24\u7ae0&#xff1a;500 Internal Server Error - \u5185\u90e8\u670d\u52a1\u5668\u9519\u8bef24.1 \u6df1\u5ea6\u6280\u672f\u89e3\u6790&#xff1a;500\u9519\u8bef\u7684\u672c\u8d28500 Internal Server Error\u00a0\u662fHTTP\u534f\u8bae\u4e2d\u6700\u901a\u7528\u3001\u6700\u4ee4\u4eba\u56f0\u60d1\u7684\u670d\u52a1\u5668\u9519\u8bef\u72b6\u6001\u7801\u3002\u4e0e\u5ba2\u6237\u7aef\u9519\u8bef&#xff08;4xx&#xff09;\u4e0d\u540c&#xff0c;500\u9519\u8bef\u660e\u786e\u8868\u793a\u95ee\u9898\u51fa\u5728\u670d\u52a1\u5668\u7aef&#xff0c;\u4f46\u670d\u52a1\u5668\u65e0\u6cd5\u6216\u4e0d\u613f\u63d0\u4f9b\u66f4\u5177\u4f53\u7684\u4fe1\u606f\u300224.1.1 \u6280\u672f\u89c4\u683c\u4e0e\u534f\u8bae\u5b9a\u4e49HTTP\/1.1 RFC 7231\u5b9a\u4e49\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/85162.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-07-26T18:17:05+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/07\/20260726181654-6a664f16b62ae.png\" \/>\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=\"69 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/85162.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/85162.html\",\"name\":\"HTTP \u72b6\u6001\u7801\uff1a\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u5668\u7684\u901a\u4fe1\u8bed\u8a00\u2014\u2014\u7b2c\u4e94\u90e8\u5206\uff1a\u670d\u52a1\u5668\u9519\u8bef\u72b6\u6001\u7801\uff085xx\uff09\u7cfb\u7edf\u5206\u6790 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-07-26T18:17:05+00:00\",\"dateModified\":\"2026-07-26T18:17:05+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/85162.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/85162.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/85162.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"HTTP \u72b6\u6001\u7801\uff1a\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u5668\u7684\u901a\u4fe1\u8bed\u8a00\u2014\u2014\u7b2c\u4e94\u90e8\u5206\uff1a\u670d\u52a1\u5668\u9519\u8bef\u72b6\u6001\u7801\uff085xx\uff09\u7cfb\u7edf\u5206\u6790\"}]},{\"@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":"HTTP \u72b6\u6001\u7801\uff1a\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u5668\u7684\u901a\u4fe1\u8bed\u8a00\u2014\u2014\u7b2c\u4e94\u90e8\u5206\uff1a\u670d\u52a1\u5668\u9519\u8bef\u72b6\u6001\u7801\uff085xx\uff09\u7cfb\u7edf\u5206\u6790 - \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\/85162.html","og_locale":"zh_CN","og_type":"article","og_title":"HTTP \u72b6\u6001\u7801\uff1a\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u5668\u7684\u901a\u4fe1\u8bed\u8a00\u2014\u2014\u7b2c\u4e94\u90e8\u5206\uff1a\u670d\u52a1\u5668\u9519\u8bef\u72b6\u6001\u7801\uff085xx\uff09\u7cfb\u7edf\u5206\u6790 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"\u7b2c24\u7ae0&#xff1a;500 Internal Server Error - \u5185\u90e8\u670d\u52a1\u5668\u9519\u8bef24.1 \u6df1\u5ea6\u6280\u672f\u89e3\u6790&#xff1a;500\u9519\u8bef\u7684\u672c\u8d28500 Internal Server Error\u00a0\u662fHTTP\u534f\u8bae\u4e2d\u6700\u901a\u7528\u3001\u6700\u4ee4\u4eba\u56f0\u60d1\u7684\u670d\u52a1\u5668\u9519\u8bef\u72b6\u6001\u7801\u3002\u4e0e\u5ba2\u6237\u7aef\u9519\u8bef&#xff08;4xx&#xff09;\u4e0d\u540c&#xff0c;500\u9519\u8bef\u660e\u786e\u8868\u793a\u95ee\u9898\u51fa\u5728\u670d\u52a1\u5668\u7aef&#xff0c;\u4f46\u670d\u52a1\u5668\u65e0\u6cd5\u6216\u4e0d\u613f\u63d0\u4f9b\u66f4\u5177\u4f53\u7684\u4fe1\u606f\u300224.1.1 \u6280\u672f\u89c4\u683c\u4e0e\u534f\u8bae\u5b9a\u4e49HTTP\/1.1 RFC 7231\u5b9a\u4e49","og_url":"https:\/\/www.wsisp.com\/helps\/85162.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-07-26T18:17:05+00:00","og_image":[{"url":"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/07\/20260726181654-6a664f16b62ae.png"}],"author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"69 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/85162.html","url":"https:\/\/www.wsisp.com\/helps\/85162.html","name":"HTTP \u72b6\u6001\u7801\uff1a\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u5668\u7684\u901a\u4fe1\u8bed\u8a00\u2014\u2014\u7b2c\u4e94\u90e8\u5206\uff1a\u670d\u52a1\u5668\u9519\u8bef\u72b6\u6001\u7801\uff085xx\uff09\u7cfb\u7edf\u5206\u6790 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-07-26T18:17:05+00:00","dateModified":"2026-07-26T18:17:05+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/85162.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/85162.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/85162.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"HTTP \u72b6\u6001\u7801\uff1a\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u5668\u7684\u901a\u4fe1\u8bed\u8a00\u2014\u2014\u7b2c\u4e94\u90e8\u5206\uff1a\u670d\u52a1\u5668\u9519\u8bef\u72b6\u6001\u7801\uff085xx\uff09\u7cfb\u7edf\u5206\u6790"}]},{"@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\/85162","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=85162"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/85162\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media\/85156"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=85162"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=85162"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=85162"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=85162"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}