{"id":68956,"date":"2026-01-30T22:57:06","date_gmt":"2026-01-30T14:57:06","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/68956.html"},"modified":"2026-01-30T22:57:06","modified_gmt":"2026-01-30T14:57:06","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%e5%85%ad%e9%83%a8","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/68956.html","title":{"rendered":"HTTP \u72b6\u6001\u7801\uff1a\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u5668\u7684\u901a\u4fe1\u8bed\u8a00\u2014\u2014\u7b2c\u516d\u90e8\u5206\uff1a\u72b6\u6001\u7801\u7684\u5b9e\u8df5\u5e94\u7528\uff08\u4e8c\uff09"},"content":{"rendered":"<h2>\u7b2c33\u7ae0&#xff1a;\u5fae\u670d\u52a1\u67b6\u6784\u4e2d\u7684\u72b6\u6001\u7801\u4f20\u64ad<\/h2>\n<h3>33.1 \u5fae\u670d\u52a1\u67b6\u6784\u4e2d\u7684\u72b6\u6001\u7801\u6311\u6218<\/h3>\n<h4>33.1.1 \u5206\u5e03\u5f0f\u7cfb\u7edf\u7684\u590d\u6742\u6027<\/h4>\n<p>\u5fae\u670d\u52a1\u67b6\u6784\u5e26\u6765\u4e86\u72b6\u6001\u7801\u5904\u7406\u7684\u5168\u65b0\u6311\u6218&#xff1a;<\/p>\n<p>yaml<\/p>\n<p># \u5fae\u670d\u52a1\u8c03\u7528\u94fe\u793a\u4f8b<br \/>\nrequest:<br \/>\n  path: \/api\/order\/123<br \/>\n  flow:<br \/>\n    &#8211; API Gateway (nginx\/ingress)<br \/>\n    &#8211; Authentication Service<br \/>\n    &#8211; Order Service<br \/>\n      &#8211; calls: User Service<br \/>\n      &#8211; calls: Inventory Service<br \/>\n      &#8211; calls: Payment Service<br \/>\n      &#8211; calls: Notification Service<br \/>\n    &#8211; Load Balancer<br \/>\n    &#8211; Service Mesh (Istio\/Linkerd)<\/p>\n<p># \u6bcf\u4e2a\u670d\u52a1\u90fd\u53ef\u80fd\u8fd4\u56de\u4e0d\u540c\u7684\u72b6\u6001\u7801<br \/>\nstatus_codes_chain:<br \/>\n  &#8211; API Gateway: 200<br \/>\n  &#8211; Authentication Service: 401 (token expired)<br \/>\n  &#8211; Order Service: 500 (dependency failed)<br \/>\n  &#8211; User Service: 404 (user not found)<br \/>\n  &#8211; Inventory Service: 409 (insufficient stock)<br \/>\n  &#8211; Payment Service: 422 (payment failed)<br \/>\n  &#8211; Notification Service: 503 (service unavailable)<\/p>\n<h4>33.1.2 \u72b6\u6001\u7801\u4f20\u64ad\u539f\u5219<\/h4>\n<p>java<\/p>\n<p>\/\/ \u5fae\u670d\u52a1\u72b6\u6001\u7801\u4f20\u64ad\u7684\u6838\u5fc3\u539f\u5219<br \/>\npublic class StatusCodePropagationPrinciples {<\/p>\n<p>    \/\/ \u539f\u52191: \u900f\u660e\u7684\u9519\u8bef\u4f20\u64ad<br \/>\n    public static class TransparentPropagation {<br \/>\n        \/\/ \u9519\u8bef\u5e94\u8be5\u5c3d\u53ef\u80fd\u900f\u660e\u5730\u4f20\u64ad\u5230\u8c03\u7528\u94fe\u7684\u4e0a\u6e38<br \/>\n        \/\/ \u4f46\u540c\u65f6\u9700\u8981\u907f\u514d\u654f\u611f\u4fe1\u606f\u6cc4\u9732<br \/>\n    }<\/p>\n<p>    \/\/ \u539f\u52192: \u4e0a\u4e0b\u6587\u5b8c\u6574\u6027<br \/>\n    public static class ContextIntegrity {<br \/>\n        \/\/ \u6bcf\u4e2a\u9519\u8bef\u90fd\u5e94\u8be5\u643a\u5e26\u5b8c\u6574\u7684\u8c03\u7528\u94fe\u4e0a\u4e0b\u6587<br \/>\n        \/\/ \u5305\u62ec\u670d\u52a1\u540d\u79f0\u3001\u8c03\u7528\u8def\u5f84\u3001\u65f6\u95f4\u6233\u7b49<br \/>\n    }<\/p>\n<p>    \/\/ \u539f\u52193: \u964d\u7ea7\u7b56\u7565<br \/>\n    public static class GracefulDegradation {<br \/>\n        \/\/ \u90e8\u5206\u670d\u52a1\u7684\u5931\u8d25\u4e0d\u5e94\u8be5\u5bfc\u81f4\u6574\u4e2a\u7cfb\u7edf\u5d29\u6e83<br \/>\n        \/\/ \u9700\u8981\u5b9e\u73b0\u4f18\u96c5\u7684\u964d\u7ea7\u7b56\u7565<br \/>\n    }<\/p>\n<p>    \/\/ \u539f\u52194: \u53ef\u8ffd\u6eaf\u6027<br \/>\n    public static class Traceability {<br \/>\n        \/\/ \u6bcf\u4e2a\u72b6\u6001\u7801\u90fd\u5e94\u8be5\u80fd\u591f\u8ffd\u6eaf\u5230\u5177\u4f53\u7684\u670d\u52a1\u548c\u64cd\u4f5c<br \/>\n    }<br \/>\n}<\/p>\n<h3>33.2 \u670d\u52a1\u95f4\u72b6\u6001\u7801\u4f20\u64ad\u6a21\u5f0f<\/h3>\n<h4>33.2.1 \u76f4\u63a5\u4f20\u64ad\u6a21\u5f0f<\/h4>\n<p>go<\/p>\n<p>\/\/ Go\u8bed\u8a00\u5b9e\u73b0\u7684\u72b6\u6001\u7801\u76f4\u63a5\u4f20\u64ad<br \/>\npackage main<\/p>\n<p>import (<br \/>\n    &#034;context&#034;<br \/>\n    &#034;encoding\/json&#034;<br \/>\n    &#034;fmt&#034;<br \/>\n    &#034;net\/http&#034;<br \/>\n    &#034;time&#034;<\/p>\n<p>    &#034;github.com\/opentracing\/opentracing-go&#034;<br \/>\n    &#034;go.uber.org\/zap&#034;<br \/>\n)<\/p>\n<p>\/\/ \u76f4\u63a5\u4f20\u64ad\u4e2d\u95f4\u4ef6<br \/>\nfunc DirectPropagationMiddleware(next http.Handler) http.Handler {<br \/>\n    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {<br \/>\n        \/\/ 1. \u4ece\u4e0a\u6e38\u670d\u52a1\u63a5\u6536\u8bf7\u6c42\u4e0a\u4e0b\u6587<br \/>\n        ctx :&#061; r.Context()<\/p>\n<p>        \/\/ 2. \u63d0\u53d6\u4e0a\u6e38\u7684\u72b6\u6001\u7801\u4fe1\u606f<br \/>\n        upstreamStatusCode :&#061; r.Header.Get(&#034;X-Upstream-Status-Code&#034;)<br \/>\n        upstreamService :&#061; r.Header.Get(&#034;X-Upstream-Service&#034;)<\/p>\n<p>        \/\/ 3. \u521b\u5efa\u54cd\u5e94\u5305\u88c5\u5668\u4ee5\u6355\u83b7\u72b6\u6001\u7801<br \/>\n        rw :&#061; &amp;responseWriter{ResponseWriter: w}<\/p>\n<p>        \/\/ 4. \u5904\u7406\u8bf7\u6c42<br \/>\n        next.ServeHTTP(rw, r)<\/p>\n<p>        \/\/ 5. \u5411\u4e0b\u6e38\u4f20\u64ad\u72b6\u6001\u7801<br \/>\n        if rw.statusCode &gt;&#061; 400 {<br \/>\n            \/\/ \u8bb0\u5f55\u9519\u8bef\u4e0a\u4e0b\u6587<br \/>\n            logErrorContext(r, upstreamStatusCode, upstreamService, rw.statusCode)<\/p>\n<p>            \/\/ \u8bbe\u7f6e\u54cd\u5e94\u5934&#xff0c;\u4e3a\u53ef\u80fd\u7684\u4e0b\u6e38\u670d\u52a1\u63d0\u4f9b\u4e0a\u4e0b\u6587<br \/>\n            w.Header().Set(&#034;X-Error-Propagated&#034;, &#034;true&#034;)<br \/>\n            w.Header().Set(&#034;X-Failed-Service&#034;, getServiceName())<\/p>\n<p>            \/\/ \u5982\u679c\u6709\u4e0a\u6e38\u670d\u52a1&#xff0c;\u8bb0\u5f55\u8c03\u7528\u94fe<br \/>\n            if upstreamService !&#061; &#034;&#034; {<br \/>\n                w.Header().Set(&#034;X-Error-Chain&#034;,<br \/>\n                    fmt.Sprintf(&#034;%s-&gt;%s:%d&#034;,<br \/>\n                        upstreamService, getServiceName(), rw.statusCode))<br \/>\n            }<br \/>\n        }<br \/>\n    })<br \/>\n}<\/p>\n<p>\/\/ \u54cd\u5e94\u5305\u88c5\u5668<br \/>\ntype responseWriter struct {<br \/>\n    http.ResponseWriter<br \/>\n    statusCode int<br \/>\n    wroteHeader bool<br \/>\n}<\/p>\n<p>func (rw *responseWriter) WriteHeader(code int) {<br \/>\n    if !rw.wroteHeader {<br \/>\n        rw.statusCode &#061; code<br \/>\n        rw.ResponseWriter.WriteHeader(code)<br \/>\n        rw.wroteHeader &#061; true<br \/>\n    }<br \/>\n}<\/p>\n<p>func (rw *responseWriter) Write(b []byte) (int, error) {<br \/>\n    if !rw.wroteHeader {<br \/>\n        rw.WriteHeader(http.StatusOK)<br \/>\n    }<br \/>\n    return rw.ResponseWriter.Write(b)<br \/>\n}<\/p>\n<p>\/\/ \u65e5\u5fd7\u8bb0\u5f55\u9519\u8bef\u4e0a\u4e0b\u6587<br \/>\nfunc logErrorContext(r *http.Request, upstreamCode, upstreamService string, currentCode int) {<br \/>\n    logger :&#061; zap.L()<\/p>\n<p>    errorContext :&#061; map[string]interface{}{<br \/>\n        &#034;timestamp&#034;:         time.Now().UTC(),<br \/>\n        &#034;request_id&#034;:        r.Header.Get(&#034;X-Request-ID&#034;),<br \/>\n        &#034;trace_id&#034;:          r.Header.Get(&#034;X-Trace-ID&#034;),<br \/>\n        &#034;current_service&#034;:   getServiceName(),<br \/>\n        &#034;current_status&#034;:    currentCode,<br \/>\n        &#034;upstream_service&#034;:  upstreamService,<br \/>\n        &#034;upstream_status&#034;:   upstreamCode,<br \/>\n        &#034;endpoint&#034;:          r.URL.Path,<br \/>\n        &#034;method&#034;:            r.Method,<br \/>\n        &#034;user_agent&#034;:        r.UserAgent(),<br \/>\n        &#034;client_ip&#034;:         getClientIP(r),<br \/>\n    }<\/p>\n<p>    \/\/ \u6dfb\u52a0\u5206\u5e03\u5f0f\u8ffd\u8e2a\u4fe1\u606f<br \/>\n    if span :&#061; opentracing.SpanFromContext(r.Context()); span !&#061; nil {<br \/>\n        errorContext[&#034;span_id&#034;] &#061; fmt.Sprintf(&#034;%v&#034;, span)<br \/>\n    }<\/p>\n<p>    logger.Error(&#034;Service error with propagation context&#034;,<br \/>\n        zap.Any(&#034;context&#034;, errorContext))<br \/>\n}<\/p>\n<p>\/\/ HTTP\u5ba2\u6237\u7aef\u652f\u6301\u72b6\u6001\u7801\u4f20\u64ad<br \/>\ntype PropagatingHTTPClient struct {<br \/>\n    client *http.Client<br \/>\n    serviceName string<br \/>\n}<\/p>\n<p>func NewPropagatingHTTPClient(serviceName string) *PropagatingHTTPClient {<br \/>\n    return &amp;PropagatingHTTPClient{<br \/>\n        client: &amp;http.Client{<br \/>\n            Timeout: 30 * time.Second,<br \/>\n            Transport: &amp;http.Transport{<br \/>\n                MaxIdleConns:        100,<br \/>\n                MaxIdleConnsPerHost: 10,<br \/>\n                IdleConnTimeout:     90 * time.Second,<br \/>\n            },<br \/>\n        },<br \/>\n        serviceName: serviceName,<br \/>\n    }<br \/>\n}<\/p>\n<p>func (c *PropagatingHTTPClient) Do(req *http.Request) (*http.Response, error) {<br \/>\n    \/\/ \u6dfb\u52a0\u4f20\u64ad\u5934<br \/>\n    req.Header.Set(&#034;X-Caller-Service&#034;, c.serviceName)<br \/>\n    req.Header.Set(&#034;X-Caller-Request-ID&#034;, req.Header.Get(&#034;X-Request-ID&#034;))<\/p>\n<p>    \/\/ \u6267\u884c\u8bf7\u6c42<br \/>\n    resp, err :&#061; c.client.Do(req)<\/p>\n<p>    if err !&#061; nil {<br \/>\n        return nil, fmt.Errorf(&#034;HTTP request failed: %w&#034;, err)<br \/>\n    }<\/p>\n<p>    \/\/ \u5982\u679c\u54cd\u5e94\u662f\u9519\u8bef&#xff0c;\u8bb0\u5f55\u4f20\u64ad\u4fe1\u606f<br \/>\n    if resp.StatusCode &gt;&#061; 400 {<br \/>\n        errorChain :&#061; resp.Header.Get(&#034;X-Error-Chain&#034;)<br \/>\n        if errorChain &#061;&#061; &#034;&#034; {<br \/>\n            resp.Header.Set(&#034;X-Error-Chain&#034;,<br \/>\n                fmt.Sprintf(&#034;%s:%d&#034;, c.serviceName, resp.StatusCode))<br \/>\n        } else {<br \/>\n            resp.Header.Set(&#034;X-Error-Chain&#034;,<br \/>\n                fmt.Sprintf(&#034;%s-&gt;%s:%d&#034;, errorChain, c.serviceName, resp.StatusCode))<br \/>\n        }<br \/>\n    }<\/p>\n<p>    return resp, nil<br \/>\n}<\/p>\n<h4>33.2.2 \u805a\u5408\u4f20\u64ad\u6a21\u5f0f<\/h4>\n<p>python<\/p>\n<p># Python\u805a\u5408\u4f20\u64ad\u5b9e\u73b0<br \/>\nfrom typing import Dict, List, Optional, Any, Tuple<br \/>\nfrom dataclasses import dataclass, asdict<br \/>\nimport json<br \/>\nimport time<br \/>\nfrom enum import Enum<br \/>\nimport logging<br \/>\nfrom concurrent.futures import ThreadPoolExecutor, as_completed<\/p>\n<p>logger &#061; logging.getLogger(__name__)<\/p>\n<p>class ErrorSeverity(Enum):<br \/>\n    CRITICAL &#061; 100    # 5xx errors<br \/>\n    ERROR &#061; 200       # 4xx errors that affect user<br \/>\n    WARNING &#061; 300     # 4xx errors that don&#039;t affect user<br \/>\n    INFO &#061; 400        # 2xx with warnings<\/p>\n<p>&#064;dataclass<br \/>\nclass ServiceError:<br \/>\n    service: str<br \/>\n    status_code: int<br \/>\n    message: str<br \/>\n    endpoint: str<br \/>\n    timestamp: float<br \/>\n    severity: ErrorSeverity<br \/>\n    retryable: bool<br \/>\n    dependencies: List[str] &#061; None<\/p>\n<p>    def to_dict(self) -&gt; Dict:<br \/>\n        return {<br \/>\n            **asdict(self),<br \/>\n            &#039;severity&#039;: self.severity.value,<br \/>\n            &#039;timestamp&#039;: time.strftime(&#039;%Y-%m-%d %H:%M:%S&#039;,<br \/>\n                                     time.localtime(self.timestamp))<br \/>\n        }<\/p>\n<p>class StatusCodeAggregator:<br \/>\n    def __init__(self, service_name: str):<br \/>\n        self.service_name &#061; service_name<br \/>\n        self.errors: List[ServiceError] &#061; []<br \/>\n        self.successes: List[Dict] &#061; []<\/p>\n<p>    def add_service_result(self, service: str, status_code: int,<br \/>\n                          message: str, endpoint: str,<br \/>\n                          retryable: bool &#061; False):<br \/>\n        &#034;&#034;&#034;\u6dfb\u52a0\u670d\u52a1\u8c03\u7528\u7ed3\u679c&#034;&#034;&#034;<br \/>\n        # \u786e\u5b9a\u9519\u8bef\u4e25\u91cd\u6027<br \/>\n        if 500 &lt;&#061; status_code &lt; 600:<br \/>\n            severity &#061; ErrorSeverity.CRITICAL<br \/>\n        elif status_code &#061;&#061; 401 or status_code &#061;&#061; 403:<br \/>\n            severity &#061; ErrorSeverity.ERROR<br \/>\n        elif 400 &lt;&#061; status_code &lt; 500:<br \/>\n            severity &#061; ErrorSeverity.WARNING<br \/>\n        elif 200 &lt;&#061; status_code &lt; 300:<br \/>\n            severity &#061; ErrorSeverity.INFO<br \/>\n        else:<br \/>\n            severity &#061; ErrorSeverity.WARNING<\/p>\n<p>        error &#061; ServiceError(<br \/>\n            service&#061;service,<br \/>\n            status_code&#061;status_code,<br \/>\n            message&#061;message,<br \/>\n            endpoint&#061;endpoint,<br \/>\n            timestamp&#061;time.time(),<br \/>\n            severity&#061;severity,<br \/>\n            retryable&#061;retryable<br \/>\n        )<\/p>\n<p>        if status_code &gt;&#061; 400:<br \/>\n            self.errors.append(error)<br \/>\n        else:<br \/>\n            self.successes.append(error.to_dict())<\/p>\n<p>        return error<\/p>\n<p>    def aggregate_status_code(self) -&gt; Tuple[int, Dict[str, Any]]:<br \/>\n        &#034;&#034;&#034;\u805a\u5408\u591a\u4e2a\u670d\u52a1\u7684\u72b6\u6001\u7801&#034;&#034;&#034;<br \/>\n        if not self.errors:<br \/>\n            return 200, {<br \/>\n                &#039;status&#039;: &#039;success&#039;,<br \/>\n                &#039;data&#039;: self.successes,<br \/>\n                &#039;timestamp&#039;: time.time()<br \/>\n            }<\/p>\n<p>        # \u6309\u4e25\u91cd\u6027\u6392\u5e8f\u9519\u8bef<br \/>\n        self.errors.sort(key&#061;lambda x: x.severity.value)<\/p>\n<p>        # \u83b7\u53d6\u6700\u9ad8\u4e25\u91cd\u6027\u7684\u9519\u8bef<br \/>\n        primary_error &#061; self.errors[0]<\/p>\n<p>        # \u786e\u5b9a\u6700\u7ec8\u72b6\u6001\u7801<br \/>\n        final_status_code &#061; self._determine_final_status_code()<\/p>\n<p>        # \u6784\u5efa\u54cd\u5e94<br \/>\n        response &#061; {<br \/>\n            &#039;status&#039;: &#039;partial_failure&#039; if len(self.errors) &lt; len(self.errors) &#043; len(self.successes) else &#039;failure&#039;,<br \/>\n            &#039;error&#039;: {<br \/>\n                &#039;code&#039;: f&#034;AGGREGATED_ERROR_{final_status_code}&#034;,<br \/>\n                &#039;message&#039;: self._generate_aggregated_message(),<br \/>\n                &#039;timestamp&#039;: time.time(),<br \/>\n                &#039;details&#039;: {<br \/>\n                    &#039;primary_error&#039;: primary_error.to_dict(),<br \/>\n                    &#039;all_errors&#039;: [e.to_dict() for e in self.errors],<br \/>\n                    &#039;successful_calls&#039;: self.successes,<br \/>\n                    &#039;aggregation_strategy&#039;: &#039;highest_severity&#039;<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>        return final_status_code, response<\/p>\n<p>    def _determine_final_status_code(self) -&gt; int:<br \/>\n        &#034;&#034;&#034;\u6839\u636e\u805a\u5408\u7b56\u7565\u786e\u5b9a\u6700\u7ec8\u72b6\u6001\u7801&#034;&#034;&#034;<br \/>\n        # \u7b56\u75651: \u5982\u679c\u67095xx\u9519\u8bef&#xff0c;\u8fd4\u56de500<br \/>\n        if any(e.severity &#061;&#061; ErrorSeverity.CRITICAL for e in self.errors):<br \/>\n            return 500<\/p>\n<p>        # \u7b56\u75652: \u5982\u679c\u6709\u7528\u6237\u76f8\u5173\u76844xx\u9519\u8bef&#xff0c;\u8fd4\u56de\u6700\u76f8\u5173\u7684\u90a3\u4e2a<br \/>\n        user_errors &#061; [e for e in self.errors<br \/>\n                      if e.severity &#061;&#061; ErrorSeverity.ERROR]<br \/>\n        if user_errors:<br \/>\n            # \u4f18\u5148\u8fd4\u56de\u8ba4\u8bc1\/\u6388\u6743\u9519\u8bef<br \/>\n            for error in user_errors:<br \/>\n                if error.status_code in [401, 403]:<br \/>\n                    return error.status_code<br \/>\n            # \u5426\u5219\u8fd4\u56de\u7b2c\u4e00\u4e2a\u7528\u6237\u9519\u8bef<br \/>\n            return user_errors[0].status_code<\/p>\n<p>        # \u7b56\u75653: \u8fd4\u56de\u7b2c\u4e00\u4e2a\u8b66\u544a\u7ea7\u522b\u7684\u9519\u8bef<br \/>\n        return self.errors[0].status_code<\/p>\n<p>    def _generate_aggregated_message(self) -&gt; str:<br \/>\n        &#034;&#034;&#034;\u751f\u6210\u805a\u5408\u9519\u8bef\u6d88\u606f&#034;&#034;&#034;<br \/>\n        if len(self.errors) &#061;&#061; 1:<br \/>\n            return f&#034;Service {self.errors[0].service} failed: {self.errors[0].message}&#034;<\/p>\n<p>        error_count &#061; len(self.errors)<br \/>\n        critical_count &#061; sum(1 for e in self.errors<br \/>\n                           if e.severity &#061;&#061; ErrorSeverity.CRITICAL)<\/p>\n<p>        if critical_count &gt; 0:<br \/>\n            return f&#034;{critical_count} critical service(s) failed out of {error_count} errors&#034;<\/p>\n<p>        return f&#034;{error_count} service(s) reported errors&#034;<\/p>\n<p># \u4f7f\u7528\u793a\u4f8b&#xff1a;\u8ba2\u5355\u5904\u7406\u670d\u52a1<br \/>\nclass OrderProcessingService:<br \/>\n    def __init__(self):<br \/>\n        self.aggregator &#061; StatusCodeAggregator(&#034;order-service&#034;)<\/p>\n<p>    def process_order(self, order_data: Dict) -&gt; Tuple[int, Dict]:<br \/>\n        &#034;&#034;&#034;\u5904\u7406\u8ba2\u5355&#xff0c;\u8c03\u7528\u591a\u4e2a\u5fae\u670d\u52a1&#034;&#034;&#034;<br \/>\n        # \u5e76\u884c\u8c03\u7528\u591a\u4e2a\u670d\u52a1<br \/>\n        with ThreadPoolExecutor(max_workers&#061;4) as executor:<br \/>\n            futures &#061; {<br \/>\n                executor.submit(self._validate_user, order_data[&#039;user_id&#039;]): &#039;user-service&#039;,<br \/>\n                executor.submit(self._check_inventory, order_data[&#039;items&#039;]): &#039;inventory-service&#039;,<br \/>\n                executor.submit(self._calculate_shipping, order_data[&#039;address&#039;]): &#039;shipping-service&#039;,<br \/>\n                executor.submit(self._validate_payment, order_data[&#039;payment&#039;]): &#039;payment-service&#039;<br \/>\n            }<\/p>\n<p>            for future in as_completed(futures):<br \/>\n                service_name &#061; futures[future]<br \/>\n                try:<br \/>\n                    status_code, message &#061; future.result(timeout&#061;10)<br \/>\n                    self.aggregator.add_service_result(<br \/>\n                        service_name, status_code, message,<br \/>\n                        f&#034;\/api\/{service_name.replace(&#039;-&#039;, &#039;\/&#039;)}&#034;<br \/>\n                    )<br \/>\n                except TimeoutError:<br \/>\n                    self.aggregator.add_service_result(<br \/>\n                        service_name, 504, &#034;Service timeout&#034;,<br \/>\n                        f&#034;\/api\/{service_name.replace(&#039;-&#039;, &#039;\/&#039;)}&#034;,<br \/>\n                        retryable&#061;True<br \/>\n                    )<br \/>\n                except Exception as e:<br \/>\n                    self.aggregator.add_service_result(<br \/>\n                        service_name, 500, str(e),<br \/>\n                        f&#034;\/api\/{service_name.replace(&#039;-&#039;, &#039;\/&#039;)}&#034;,<br \/>\n                        retryable&#061;True<br \/>\n                    )<\/p>\n<p>        # \u805a\u5408\u7ed3\u679c<br \/>\n        final_status, response &#061; self.aggregator.aggregate_status_code()<\/p>\n<p>        # \u5982\u679c\u6240\u6709\u5fc5\u9700\u670d\u52a1\u90fd\u6210\u529f&#xff0c;\u521b\u5efa\u8ba2\u5355<br \/>\n        if final_status &#061;&#061; 200:<br \/>\n            order_result &#061; self._create_order(order_data)<br \/>\n            response[&#039;data&#039;][&#039;order&#039;] &#061; order_result<\/p>\n<p>        return final_status, response<\/p>\n<p>    def _validate_user(self, user_id: str) -&gt; Tuple[int, str]:<br \/>\n        # \u8c03\u7528\u7528\u6237\u670d\u52a1<br \/>\n        # \u8fd4\u56de (status_code, message)<br \/>\n        pass<\/p>\n<p>    def _check_inventory(self, items: List) -&gt; Tuple[int, str]:<br \/>\n        # \u8c03\u7528\u5e93\u5b58\u670d\u52a1<br \/>\n        pass<\/p>\n<p>    def _calculate_shipping(self, address: Dict) -&gt; Tuple[int, str]:<br \/>\n        # \u8c03\u7528\u7269\u6d41\u670d\u52a1<br \/>\n        pass<\/p>\n<p>    def _validate_payment(self, payment: Dict) -&gt; Tuple[int, str]:<br \/>\n        # \u8c03\u7528\u652f\u4ed8\u670d\u52a1<br \/>\n        pass<\/p>\n<p>    def _create_order(self, order_data: Dict) -&gt; Dict:<br \/>\n        # \u521b\u5efa\u8ba2\u5355<br \/>\n        pass<\/p>\n<h3>33.3 \u5206\u5e03\u5f0f\u8ffd\u8e2a\u4e0e\u72b6\u6001\u7801<\/h3>\n<h4>33.3.1 OpenTelemetry\u96c6\u6210<\/h4>\n<p>typescript<\/p>\n<p>\/\/ TypeScript OpenTelemetry\u96c6\u6210<br \/>\nimport { NodeTracerProvider } from &#039;&#064;opentelemetry\/node&#039;;<br \/>\nimport { SimpleSpanProcessor } from &#039;&#064;opentelemetry\/tracing&#039;;<br \/>\nimport { JaegerExporter } from &#039;&#064;opentelemetry\/exporter-jaeger&#039;;<br \/>\nimport { ZipkinExporter } from &#039;&#064;opentelemetry\/exporter-zipkin&#039;;<br \/>\nimport { context, Span, SpanStatusCode } from &#039;&#064;opentelemetry\/api&#039;;<br \/>\nimport { HttpInstrumentation } from &#039;&#064;opentelemetry\/instrumentation-http&#039;;<br \/>\nimport { ExpressInstrumentation } from &#039;&#064;opentelemetry\/instrumentation-express&#039;;<br \/>\nimport { Resource } from &#039;&#064;opentelemetry\/resources&#039;;<br \/>\nimport { SemanticResourceAttributes } from &#039;&#064;opentelemetry\/semantic-conventions&#039;;<\/p>\n<p>\/\/ \u914d\u7f6e\u8ffd\u8e2a\u63d0\u4f9b\u5546<br \/>\nconst provider &#061; new NodeTracerProvider({<br \/>\n  resource: new Resource({<br \/>\n    [SemanticResourceAttributes.SERVICE_NAME]: process.env.SERVICE_NAME || &#039;unknown-service&#039;,<br \/>\n    [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: process.env.NODE_ENV || &#039;development&#039;,<br \/>\n  }),<br \/>\n});<\/p>\n<p>\/\/ \u6dfb\u52a0\u5bfc\u51fa\u5668<br \/>\nconst jaegerExporter &#061; new JaegerExporter({<br \/>\n  endpoint: process.env.JAEGER_ENDPOINT || &#039;http:\/\/localhost:14268\/api\/traces&#039;,<br \/>\n});<\/p>\n<p>const zipkinExporter &#061; new ZipkinExporter({<br \/>\n  url: process.env.ZIPKIN_ENDPOINT || &#039;http:\/\/localhost:9411\/api\/v2\/spans&#039;,<br \/>\n});<\/p>\n<p>provider.addSpanProcessor(new SimpleSpanProcessor(jaegerExporter));<br \/>\nprovider.addSpanProcessor(new SimpleSpanProcessor(zipkinExporter));<\/p>\n<p>\/\/ \u6ce8\u518c\u63d0\u4f9b\u5546<br \/>\nprovider.register();<\/p>\n<p>\/\/ \u4eea\u8868\u5316HTTP\u548cExpress<br \/>\nconst httpInstrumentation &#061; new HttpInstrumentation();<br \/>\nconst expressInstrumentation &#061; new ExpressInstrumentation();<\/p>\n<p>\/\/ \u72b6\u6001\u7801\u8ffd\u8e2a\u4e2d\u95f4\u4ef6<br \/>\nexport function statusCodeTracingMiddleware(req: any, res: any, next: Function) {<br \/>\n  const tracer &#061; provider.getTracer(&#039;http-server&#039;);<br \/>\n  const span &#061; tracer.startSpan(&#096;${req.method} ${req.path}&#096;, {<br \/>\n    attributes: {<br \/>\n      &#039;http.method&#039;: req.method,<br \/>\n      &#039;http.url&#039;: req.url,<br \/>\n      &#039;http.route&#039;: req.path,<br \/>\n      &#039;http.user_agent&#039;: req.get(&#039;user-agent&#039;),<br \/>\n      &#039;http.client_ip&#039;: req.ip,<br \/>\n    },<br \/>\n  });<\/p>\n<p>  \/\/ \u5c06span\u5b58\u50a8\u5728\u4e0a\u4e0b\u6587\u4e2d<br \/>\n  const ctx &#061; context.active();<br \/>\n  context.bind(ctx, span);<\/p>\n<p>  \/\/ \u5b58\u50a8span\u5728\u8bf7\u6c42\u5bf9\u8c61\u4e0a\u4ee5\u4fbf\u540e\u7eed\u8bbf\u95ee<br \/>\n  req.span &#061; span;<\/p>\n<p>  \/\/ \u76d1\u542c\u54cd\u5e94\u5b8c\u6210<br \/>\n  const originalEnd &#061; res.end;<br \/>\n  res.end &#061; function(&#8230;args: any[]) {<br \/>\n    \/\/ \u8bb0\u5f55\u72b6\u6001\u7801<br \/>\n    span.setAttribute(&#039;http.status_code&#039;, res.statusCode);<br \/>\n    span.setAttribute(&#039;http.status_text&#039;, res.statusMessage);<\/p>\n<p>    \/\/ \u6839\u636e\u72b6\u6001\u7801\u8bbe\u7f6espan\u72b6\u6001<br \/>\n    if (res.statusCode &gt;&#061; 400) {<br \/>\n      span.setStatus({<br \/>\n        code: SpanStatusCode.ERROR,<br \/>\n        message: &#096;HTTP ${res.statusCode}&#096;,<br \/>\n      });<\/p>\n<p>      \/\/ \u6dfb\u52a0\u9519\u8bef\u5c5e\u6027<br \/>\n      span.setAttribute(&#039;error&#039;, true);<br \/>\n      span.setAttribute(&#039;error.type&#039;, &#096;HTTP_${res.statusCode}&#096;);<\/p>\n<p>      \/\/ \u5982\u679c\u6709\u9519\u8bef\u4fe1\u606f&#xff0c;\u8bb0\u5f55\u5b83<br \/>\n      if (res.locals.error) {<br \/>\n        span.setAttribute(&#039;error.message&#039;, res.locals.error.message);<br \/>\n        span.recordException(res.locals.error);<br \/>\n      }<br \/>\n    } else {<br \/>\n      span.setStatus({ code: SpanStatusCode.OK });<br \/>\n    }<\/p>\n<p>    \/\/ \u8bb0\u5f55\u54cd\u5e94\u5927\u5c0f<br \/>\n    const contentLength &#061; res.get(&#039;content-length&#039;);<br \/>\n    if (contentLength) {<br \/>\n      span.setAttribute(&#039;http.response_size&#039;, parseInt(contentLength));<br \/>\n    }<\/p>\n<p>    \/\/ \u8bb0\u5f55\u6301\u7eed\u65f6\u95f4<br \/>\n    const startTime &#061; req._startTime || Date.now();<br \/>\n    const duration &#061; Date.now() &#8211; startTime;<br \/>\n    span.setAttribute(&#039;http.duration_ms&#039;, duration);<\/p>\n<p>    \/\/ \u7ed3\u675fspan<br \/>\n    span.end();<\/p>\n<p>    \/\/ \u8c03\u7528\u539f\u59cb\u7684end\u65b9\u6cd5<br \/>\n    return originalEnd.apply(this, args);<br \/>\n  };<\/p>\n<p>  \/\/ \u8bb0\u5f55\u8bf7\u6c42\u5f00\u59cb\u65f6\u95f4<br \/>\n  req._startTime &#061; Date.now();<\/p>\n<p>  next();<br \/>\n}<\/p>\n<p>\/\/ HTTP\u5ba2\u6237\u7aef\u4eea\u8868\u5316<br \/>\nexport class TracedHttpClient {<br \/>\n  private tracer: any;<\/p>\n<p>  constructor(private baseURL: string, serviceName: string) {<br \/>\n    this.tracer &#061; provider.getTracer(serviceName);<br \/>\n  }<\/p>\n<p>  async request&lt;T&gt;(<br \/>\n    method: string,<br \/>\n    path: string,<br \/>\n    data?: any,<br \/>\n    options: any &#061; {}<br \/>\n  ): Promise&lt;{ status: number; data: T; headers: any }&gt; {<br \/>\n    const span &#061; this.tracer.startSpan(&#096;${method} ${path}&#096;, {<br \/>\n      attributes: {<br \/>\n        &#039;http.method&#039;: method,<br \/>\n        &#039;http.url&#039;: &#096;${this.baseURL}${path}&#096;,<br \/>\n        &#039;peer.service&#039;: this.baseURL.replace(\/https?:\\\\\/\\\\\/\/, &#039;&#039;),<br \/>\n      },<br \/>\n    });<\/p>\n<p>    try {<br \/>\n      const url &#061; &#096;${this.baseURL}${path}&#096;;<br \/>\n      const headers &#061; {<br \/>\n        &#039;Content-Type&#039;: &#039;application\/json&#039;,<br \/>\n        &#8230;options.headers,<br \/>\n      };<\/p>\n<p>      \/\/ \u4f20\u64ad\u8ffd\u8e2a\u4e0a\u4e0b\u6587<br \/>\n      const carrier: any &#061; {};<br \/>\n      const ctx &#061; context.active();<br \/>\n      const activeSpan &#061; context.getActiveSpan();<br \/>\n      if (activeSpan) {<br \/>\n        const traceparent &#061; activeSpan.spanContext().traceId;<br \/>\n        headers[&#039;traceparent&#039;] &#061; &#096;00-${traceparent}-${span.spanContext().spanId}-01&#096;;<br \/>\n        headers[&#039;tracestate&#039;] &#061; activeSpan.spanContext().traceState?.serialize();<br \/>\n      }<\/p>\n<p>      const response &#061; await fetch(url, {<br \/>\n        method,<br \/>\n        headers,<br \/>\n        body: data ? JSON.stringify(data) : undefined,<br \/>\n        &#8230;options,<br \/>\n      });<\/p>\n<p>      \/\/ \u8bb0\u5f55\u54cd\u5e94\u4fe1\u606f<br \/>\n      span.setAttribute(&#039;http.status_code&#039;, response.status);<br \/>\n      span.setAttribute(&#039;http.status_text&#039;, response.statusText);<\/p>\n<p>      const responseData &#061; await response.json().catch(() &#061;&gt; null);<\/p>\n<p>      \/\/ \u6839\u636e\u72b6\u6001\u7801\u8bbe\u7f6espan\u72b6\u6001<br \/>\n      if (response.status &gt;&#061; 400) {<br \/>\n        span.setStatus({<br \/>\n          code: SpanStatusCode.ERROR,<br \/>\n          message: &#096;HTTP ${response.status}&#096;,<br \/>\n        });<\/p>\n<p>        \/\/ \u8bb0\u5f55\u9519\u8bef\u8be6\u60c5<br \/>\n        span.setAttribute(&#039;error&#039;, true);<br \/>\n        span.setAttribute(&#039;error.type&#039;, &#096;HTTP_${response.status}&#096;);<\/p>\n<p>        if (responseData?.error) {<br \/>\n          span.setAttribute(&#039;error.message&#039;, responseData.error.message);<br \/>\n        }<br \/>\n      } else {<br \/>\n        span.setStatus({ code: SpanStatusCode.OK });<br \/>\n      }<\/p>\n<p>      \/\/ \u8bb0\u5f55\u54cd\u5e94\u5934\u4e2d\u7684\u8ffd\u8e2a\u4fe1\u606f<br \/>\n      const serverTraceId &#061; response.headers.get(&#039;x-trace-id&#039;);<br \/>\n      if (serverTraceId) {<br \/>\n        span.setAttribute(&#039;peer.trace_id&#039;, serverTraceId);<br \/>\n      }<\/p>\n<p>      return {<br \/>\n        status: response.status,<br \/>\n        data: responseData,<br \/>\n        headers: Object.fromEntries(response.headers.entries()),<br \/>\n      };<\/p>\n<p>    } catch (error: any) {<br \/>\n      \/\/ \u8bb0\u5f55\u5f02\u5e38<br \/>\n      span.setStatus({<br \/>\n        code: SpanStatusCode.ERROR,<br \/>\n        message: error.message,<br \/>\n      });<br \/>\n      span.recordException(error);<br \/>\n      span.setAttribute(&#039;error&#039;, true);<br \/>\n      span.setAttribute(&#039;error.type&#039;, &#039;NETWORK_ERROR&#039;);<\/p>\n<p>      throw error;<br \/>\n    } finally {<br \/>\n      span.end();<br \/>\n    }<br \/>\n  }<\/p>\n<p>  \/\/ \u6279\u91cf\u8bf7\u6c42\u8ffd\u8e2a<br \/>\n  async batchRequest&lt;T&gt;(<br \/>\n    requests: Array&lt;{ method: string; path: string; data?: any }&gt;<br \/>\n  ): Promise&lt;Array&lt;{ status: number; data: T; error?: any }&gt;&gt; {<br \/>\n    const batchSpan &#061; this.tracer.startSpan(&#039;batch_request&#039;, {<br \/>\n      attributes: {<br \/>\n        &#039;batch.request_count&#039;: requests.length,<br \/>\n        &#039;batch.service&#039;: this.baseURL,<br \/>\n      },<br \/>\n    });<\/p>\n<p>    try {<br \/>\n      const results &#061; await Promise.all(<br \/>\n        requests.map(async (req) &#061;&gt; {<br \/>\n          const span &#061; this.tracer.startSpan(&#096;${req.method} ${req.path}&#096;, {<br \/>\n            attributes: {<br \/>\n              &#039;http.method&#039;: req.method,<br \/>\n              &#039;http.url&#039;: &#096;${this.baseURL}${req.path}&#096;,<br \/>\n            },<br \/>\n          });<\/p>\n<p>          try {<br \/>\n            const result &#061; await this.request&lt;T&gt;(req.method, req.path, req.data);<\/p>\n<p>            span.setAttribute(&#039;http.status_code&#039;, result.status);<\/p>\n<p>            if (result.status &gt;&#061; 400) {<br \/>\n              span.setStatus({ code: SpanStatusCode.ERROR });<br \/>\n            } else {<br \/>\n              span.setStatus({ code: SpanStatusCode.OK });<br \/>\n            }<\/p>\n<p>            return result;<br \/>\n          } catch (error: any) {<br \/>\n            span.setStatus({<br \/>\n              code: SpanStatusCode.ERROR,<br \/>\n              message: error.message,<br \/>\n            });<br \/>\n            span.recordException(error);<\/p>\n<p>            return {<br \/>\n              status: 500,<br \/>\n              data: null as any,<br \/>\n              error: error.message,<br \/>\n            };<br \/>\n          } finally {<br \/>\n            span.end();<br \/>\n          }<br \/>\n        })<br \/>\n      );<\/p>\n<p>      \/\/ \u7edf\u8ba1\u6279\u91cf\u7ed3\u679c<br \/>\n      const successCount &#061; results.filter(r &#061;&gt; r.status &lt; 400).length;<br \/>\n      const errorCount &#061; results.length &#8211; successCount;<\/p>\n<p>      batchSpan.setAttribute(&#039;batch.success_count&#039;, successCount);<br \/>\n      batchSpan.setAttribute(&#039;batch.error_count&#039;, errorCount);<\/p>\n<p>      if (errorCount &gt; 0) {<br \/>\n        batchSpan.setStatus({<br \/>\n          code: SpanStatusCode.ERROR,<br \/>\n          message: &#096;${errorCount} requests failed in batch&#096;,<br \/>\n        });<br \/>\n      } else {<br \/>\n        batchSpan.setStatus({ code: SpanStatusCode.OK });<br \/>\n      }<\/p>\n<p>      return results;<br \/>\n    } finally {<br \/>\n      batchSpan.end();<br \/>\n    }<br \/>\n  }<br \/>\n}<\/p>\n<p>\/\/ \u72b6\u6001\u7801\u5206\u6790\u4e2d\u95f4\u4ef6<br \/>\nexport function statusCodeAnalyticsMiddleware(req: any, res: any, next: Function) {<br \/>\n  const tracer &#061; provider.getTracer(&#039;analytics&#039;);<br \/>\n  const span &#061; tracer.startSpan(&#039;status_code_analysis&#039;, {<br \/>\n    attributes: {<br \/>\n      &#039;analysis.type&#039;: &#039;status_code_distribution&#039;,<br \/>\n      &#039;service.name&#039;: process.env.SERVICE_NAME,<br \/>\n    },<br \/>\n  });<\/p>\n<p>  \/\/ \u6536\u96c6\u6307\u6807<br \/>\n  const metrics &#061; {<br \/>\n    request_count: 0,<br \/>\n    status_2xx: 0,<br \/>\n    status_3xx: 0,<br \/>\n    status_4xx: 0,<br \/>\n    status_5xx: 0,<br \/>\n    errors_by_code: {} as Record&lt;string, number&gt;,<br \/>\n    avg_response_time: 0,<br \/>\n  };<\/p>\n<p>  \/\/ \u76d1\u542c\u54cd\u5e94\u5b8c\u6210<br \/>\n  const originalEnd &#061; res.end;<br \/>\n  res.end &#061; function(&#8230;args: any[]) {<br \/>\n    metrics.request_count&#043;&#043;;<\/p>\n<p>    \/\/ \u5206\u7c7b\u72b6\u6001\u7801<br \/>\n    if (res.statusCode &gt;&#061; 200 &amp;&amp; res.statusCode &lt; 300) {<br \/>\n      metrics.status_2xx&#043;&#043;;<br \/>\n    } else if (res.statusCode &gt;&#061; 300 &amp;&amp; res.statusCode &lt; 400) {<br \/>\n      metrics.status_3xx&#043;&#043;;<br \/>\n    } else if (res.statusCode &gt;&#061; 400 &amp;&amp; res.statusCode &lt; 500) {<br \/>\n      metrics.status_4xx&#043;&#043;;<br \/>\n      metrics.errors_by_code[res.statusCode] &#061;<br \/>\n        (metrics.errors_by_code[res.statusCode] || 0) &#043; 1;<br \/>\n    } else if (res.statusCode &gt;&#061; 500) {<br \/>\n      metrics.status_5xx&#043;&#043;;<br \/>\n      metrics.errors_by_code[res.statusCode] &#061;<br \/>\n        (metrics.errors_by_code[res.statusCode] || 0) &#043; 1;<br \/>\n    }<\/p>\n<p>    \/\/ \u8bb0\u5f55\u54cd\u5e94\u65f6\u95f4<br \/>\n    const startTime &#061; req._startTime || Date.now();<br \/>\n    const duration &#061; Date.now() &#8211; startTime;<\/p>\n<p>    \/\/ \u66f4\u65b0\u5e73\u5747\u54cd\u5e94\u65f6\u95f4<br \/>\n    metrics.avg_response_time &#061;<br \/>\n      (metrics.avg_response_time * (metrics.request_count &#8211; 1) &#043; duration) \/<br \/>\n      metrics.request_count;<\/p>\n<p>    \/\/ \u66f4\u65b0span\u5c5e\u6027<br \/>\n    span.setAttributes({<br \/>\n      &#039;analysis.request_count&#039;: metrics.request_count,<br \/>\n      &#039;analysis.status_2xx&#039;: metrics.status_2xx,<br \/>\n      &#039;analysis.status_3xx&#039;: metrics.status_3xx,<br \/>\n      &#039;analysis.status_4xx&#039;: metrics.status_4xx,<br \/>\n      &#039;analysis.status_5xx&#039;: metrics.status_5xx,<br \/>\n      &#039;analysis.avg_response_time_ms&#039;: metrics.avg_response_time,<br \/>\n      &#8230;Object.entries(metrics.errors_by_code).reduce((acc, [code, count]) &#061;&gt; ({<br \/>\n        &#8230;acc,<br \/>\n        [&#096;analysis.errors.${code}&#096;]: count,<br \/>\n      }), {}),<br \/>\n    });<\/p>\n<p>    \/\/ \u5982\u679c\u9519\u8bef\u7387\u8fc7\u9ad8&#xff0c;\u8bb0\u5f55\u8b66\u544a<br \/>\n    const errorRate &#061; (metrics.status_4xx &#043; metrics.status_5xx) \/ metrics.request_count;<br \/>\n    if (errorRate &gt; 0.1 &amp;&amp; metrics.request_count &gt; 10) {<br \/>\n      span.setStatus({<br \/>\n        code: SpanStatusCode.ERROR,<br \/>\n        message: &#096;High error rate: ${(errorRate * 100).toFixed(1)}%&#096;,<br \/>\n      });<br \/>\n      span.setAttribute(&#039;analysis.high_error_rate&#039;, true);<br \/>\n      span.setAttribute(&#039;analysis.error_rate&#039;, errorRate);<br \/>\n    }<\/p>\n<p>    return originalEnd.apply(this, args);<br \/>\n  };<\/p>\n<p>  \/\/ \u5b9a\u671f\u63d0\u4ea4\u6307\u6807<br \/>\n  const interval &#061; setInterval(() &#061;&gt; {<br \/>\n    if (metrics.request_count &gt; 0) {<br \/>\n      span.addEvent(&#039;metrics_snapshot&#039;, metrics);<\/p>\n<p>      \/\/ \u91cd\u7f6e\u8ba1\u6570\u5668&#xff08;\u4fdd\u7559\u9519\u8bef\u5206\u5e03&#xff09;<br \/>\n      metrics.request_count &#061; 0;<br \/>\n      metrics.status_2xx &#061; 0;<br \/>\n      metrics.status_3xx &#061; 0;<br \/>\n      metrics.status_4xx &#061; 0;<br \/>\n      metrics.status_5xx &#061; 0;<br \/>\n      metrics.avg_response_time &#061; 0;<br \/>\n    }<br \/>\n  }, 60000); \/\/ \u6bcf\u5206\u949f\u63d0\u4ea4\u4e00\u6b21<\/p>\n<p>  \/\/ \u6e05\u7406\u5b9a\u65f6\u5668<br \/>\n  req.on(&#039;close&#039;, () &#061;&gt; {<br \/>\n    clearInterval(interval);<br \/>\n    span.end();<br \/>\n  });<\/p>\n<p>  next();<br \/>\n}<\/p>\n<h4>33.3.2 Jaeger\u8ffd\u8e2a\u53ef\u89c6\u5316<\/h4>\n<p>yaml<\/p>\n<p># jaeger-service-map.yaml<br \/>\n# Jaeger\u670d\u52a1\u4f9d\u8d56\u56fe\u914d\u7f6e<br \/>\nservice_dependencies:<br \/>\n  enabled: true<br \/>\n  storage: elasticsearch<\/p>\n<p>  # \u72b6\u6001\u7801\u76f8\u5173\u7684\u6807\u7b7e<br \/>\n  tags:<br \/>\n    &#8211; &#034;http.status_code&#034;<br \/>\n    &#8211; &#034;error&#034;<br \/>\n    &#8211; &#034;span.kind&#034;<\/p>\n<p>  # \u670d\u52a1\u7ea7\u522b\u6307\u6807<br \/>\n  metrics:<br \/>\n    &#8211; name: &#034;error_rate&#034;<br \/>\n      query: &#034;sum(rate(http_server_requests_seconds_count{status&#061;~\\\\&#034;4..|5..\\\\&#034;}[5m])) \/ sum(rate(http_server_requests_seconds_count[5m]))&#034;<br \/>\n      threshold: 0.05<br \/>\n      severity: &#034;warning&#034;<\/p>\n<p>    &#8211; name: &#034;p95_latency&#034;<br \/>\n      query: &#034;histogram_quantile(0.95, rate(http_server_requests_seconds_bucket[5m]))&#034;<br \/>\n      threshold: 1.0<br \/>\n      severity: &#034;warning&#034;<\/p>\n<p># \u72b6\u6001\u7801\u5206\u5e03\u4eea\u8868\u677f<br \/>\ndashboard:<br \/>\n  panels:<br \/>\n    &#8211; title: &#034;Status Code Distribution&#034;<br \/>\n      type: &#034;heatmap&#034;<br \/>\n      query: &#034;sum(rate(http_server_requests_seconds_count[5m])) by (status, service)&#034;<\/p>\n<p>    &#8211; title: &#034;Error Propagation Chain&#034;<br \/>\n      type: &#034;graph&#034;<br \/>\n      query: |<br \/>\n        trace_id, span_id, parent_id,<br \/>\n        operationName, serviceName,<br \/>\n        tags.http.status_code as status_code,<br \/>\n        tags.error as error<br \/>\n      filter: &#034;tags.http.status_code &gt;&#061; 400&#034;<\/p>\n<p>    &#8211; title: &#034;Service Dependency Health&#034;<br \/>\n      type: &#034;dependency_graph&#034;<br \/>\n      nodes:<br \/>\n        &#8211; service: &#034;api-gateway&#034;<br \/>\n          health: &#034;sum(rate(http_server_requests_seconds_count{service&#061;\\\\&#034;api-gateway\\\\&#034;, status&#061;~\\\\&#034;2..\\\\&#034;}[5m])) \/ sum(rate(http_server_requests_seconds_count{service&#061;\\\\&#034;api-gateway\\\\&#034;}[5m]))&#034;<\/p>\n<p>        &#8211; service: &#034;order-service&#034;<br \/>\n          health: &#034;sum(rate(http_server_requests_seconds_count{service&#061;\\\\&#034;order-service\\\\&#034;, status&#061;~\\\\&#034;2..\\\\&#034;}[5m])) \/ sum(rate(http_server_requests_seconds_count{service&#061;\\\\&#034;order-service\\\\&#034;}[5m]))&#034;<\/p>\n<p>        &#8211; service: &#034;payment-service&#034;<br \/>\n          health: &#034;sum(rate(http_server_requests_seconds_count{service&#061;\\\\&#034;payment-service\\\\&#034;, status&#061;~\\\\&#034;2..\\\\&#034;}[5m])) \/ sum(rate(http_server_requests_seconds_count{service&#061;\\\\&#034;payment-service\\\\&#034;}[5m]))&#034;<\/p>\n<h3>33.4 \u65ad\u8def\u5668\u4e0e\u72b6\u6001\u7801\u5904\u7406<\/h3>\n<h4>33.4.1 Resilience4j\u65ad\u8def\u5668<\/h4>\n<p>java<\/p>\n<p>\/\/ Java Resilience4j\u65ad\u8def\u5668\u914d\u7f6e<br \/>\n&#064;Configuration<br \/>\npublic class CircuitBreakerConfiguration {<\/p>\n<p>    private final MeterRegistry meterRegistry;<br \/>\n    private final Tracer tracer;<\/p>\n<p>    public CircuitBreakerConfiguration(MeterRegistry meterRegistry,<br \/>\n                                      Tracer tracer) {<br \/>\n        this.meterRegistry &#061; meterRegistry;<br \/>\n        this.tracer &#061; tracer;<br \/>\n    }<\/p>\n<p>    &#064;Bean<br \/>\n    public CircuitBreakerRegistry circuitBreakerRegistry() {<br \/>\n        CircuitBreakerConfig config &#061; CircuitBreakerConfig.custom()<br \/>\n            \/\/ \u57fa\u4e8e\u72b6\u6001\u7801\u7684\u5931\u8d25\u5224\u65ad<br \/>\n            .recordExceptions(<br \/>\n                HttpClientErrorException.class,   \/\/ 4xx<br \/>\n                HttpServerErrorException.class,   \/\/ 5xx<br \/>\n                TimeoutException.class,<br \/>\n                IOException.class<br \/>\n            )<br \/>\n            .ignoreExceptions(<br \/>\n                \/\/ \u5ffd\u7565\u67d0\u4e9b\u7279\u5b9a\u76844xx\u9519\u8bef&#xff0c;\u5982404&#xff08;\u8d44\u6e90\u4e0d\u5b58\u5728&#xff09;<br \/>\n                NotFoundException.class<br \/>\n            )<br \/>\n            \/\/ \u6ed1\u52a8\u7a97\u53e3\u914d\u7f6e<br \/>\n            .slidingWindowType(SlidingWindowType.COUNT_BASED)<br \/>\n            .slidingWindowSize(100)<br \/>\n            \/\/ \u5931\u8d25\u7387\u9608\u503c<br \/>\n            .failureRateThreshold(50)<br \/>\n            \/\/ \u6162\u8c03\u7528\u9608\u503c<br \/>\n            .slowCallRateThreshold(30)<br \/>\n            .slowCallDurationThreshold(Duration.ofSeconds(2))<br \/>\n            \/\/ \u534a\u5f00\u72b6\u6001\u914d\u7f6e<br \/>\n            .permittedNumberOfCallsInHalfOpenState(10)<br \/>\n            .maxWaitDurationInHalfOpenState(Duration.ofSeconds(10))<br \/>\n            \/\/ \u81ea\u52a8\u4ece\u5f00\u542f\u72b6\u6001\u8f6c\u6362<br \/>\n            .automaticTransitionFromOpenToHalfOpenEnabled(true)<br \/>\n            .waitDurationInOpenState(Duration.ofSeconds(30))<br \/>\n            .build();<\/p>\n<p>        CircuitBreakerRegistry registry &#061; CircuitBreakerRegistry.of(config);<\/p>\n<p>        \/\/ \u6dfb\u52a0\u6307\u6807<br \/>\n        TaggedCircuitBreakerMetrics.ofCircuitBreakerRegistry(registry)<br \/>\n            .bindTo(meterRegistry);<\/p>\n<p>        return registry;<br \/>\n    }<\/p>\n<p>    &#064;Bean<br \/>\n    public RetryRegistry retryRegistry() {<br \/>\n        RetryConfig config &#061; RetryConfig.custom()<br \/>\n            .maxAttempts(3)<br \/>\n            .waitDuration(Duration.ofMillis(500))<br \/>\n            .intervalFunction(IntervalFunction.ofExponentialBackoff())<br \/>\n            .retryOnException(e -&gt; {<br \/>\n                \/\/ \u53ea\u5728\u7279\u5b9a\u72b6\u6001\u7801\u4e0b\u91cd\u8bd5<br \/>\n                if (e instanceof HttpClientErrorException) {<br \/>\n                    HttpClientErrorException ex &#061; (HttpClientErrorException) e;<br \/>\n                    return ex.getStatusCode().is5xxServerError() ||<br \/>\n                           ex.getStatusCode() &#061;&#061; HttpStatus.REQUEST_TIMEOUT ||<br \/>\n                           ex.getStatusCode() &#061;&#061; HttpStatus.TOO_MANY_REQUESTS;<br \/>\n                }<br \/>\n                return e instanceof IOException ||<br \/>\n                       e instanceof TimeoutException;<br \/>\n            })<br \/>\n            .failAfterMaxAttempts(true)<br \/>\n            .build();<\/p>\n<p>        return RetryRegistry.of(config);<br \/>\n    }<\/p>\n<p>    &#064;Bean<br \/>\n    public BulkheadRegistry bulkheadRegistry() {<br \/>\n        BulkheadConfig config &#061; BulkheadConfig.custom()<br \/>\n            .maxConcurrentCalls(100)<br \/>\n            .maxWaitDuration(Duration.ofMillis(500))<br \/>\n            .build();<\/p>\n<p>        return BulkheadRegistry.of(config);<br \/>\n    }<\/p>\n<p>    \/\/ \u72b6\u6001\u7801\u611f\u77e5\u7684\u65ad\u8def\u5668\u88c5\u9970\u5668<br \/>\n    &#064;Bean<br \/>\n    public RestTemplate statusCodeAwareRestTemplate(<br \/>\n            CircuitBreakerRegistry circuitBreakerRegistry,<br \/>\n            RetryRegistry retryRegistry,<br \/>\n            BulkheadRegistry bulkheadRegistry) {<\/p>\n<p>        RestTemplate restTemplate &#061; new RestTemplate();<\/p>\n<p>        \/\/ \u6dfb\u52a0\u62e6\u622a\u5668<br \/>\n        restTemplate.getInterceptors().add((request, body, execution) -&gt; {<br \/>\n            String serviceName &#061; extractServiceName(request.getURI());<\/p>\n<p>            \/\/ \u83b7\u53d6\u6216\u521b\u5efa\u65ad\u8def\u5668<br \/>\n            CircuitBreaker circuitBreaker &#061; circuitBreakerRegistry<br \/>\n                .circuitBreaker(serviceName, serviceName);<\/p>\n<p>            Retry retry &#061; retryRegistry.retry(serviceName, serviceName);<\/p>\n<p>            Bulkhead bulkhead &#061; bulkheadRegistry.bulkhead(serviceName, serviceName);<\/p>\n<p>            \/\/ \u521b\u5efa\u8ffd\u8e2aspan<br \/>\n            Span span &#061; tracer.buildSpan(&#034;http_request&#034;)<br \/>\n                .withTag(&#034;http.method&#034;, request.getMethod().name())<br \/>\n                .withTag(&#034;http.url&#034;, request.getURI().toString())<br \/>\n                .withTag(&#034;peer.service&#034;, serviceName)<br \/>\n                .start();<\/p>\n<p>            try (Scope scope &#061; tracer.activateSpan(span)) {<br \/>\n                \/\/ \u4f7f\u7528Resilience4j\u88c5\u9970\u8c03\u7528<br \/>\n                Supplier&lt;ClientHttpResponse&gt; supplier &#061; () -&gt; {<br \/>\n                    try {<br \/>\n                        return execution.execute(request, body);<br \/>\n                    } catch (IOException e) {<br \/>\n                        throw new RuntimeException(e);<br \/>\n                    }<br \/>\n                };<\/p>\n<p>                \/\/ \u7ec4\u5408 Resilience4j \u88c5\u9970\u5668<br \/>\n                Supplier&lt;ClientHttpResponse&gt; decoratedSupplier &#061; Decorators.ofSupplier(supplier)<br \/>\n                    .withCircuitBreaker(circuitBreaker)<br \/>\n                    .withRetry(retry)<br \/>\n                    .withBulkhead(bulkhead)<br \/>\n                    .decorate();<\/p>\n<p>                ClientHttpResponse response &#061; decoratedSupplier.get();<\/p>\n<p>                \/\/ \u8bb0\u5f55\u72b6\u6001\u7801<br \/>\n                span.setTag(&#034;http.status_code&#034;, response.getRawStatusCode());<\/p>\n<p>                if (response.getRawStatusCode() &gt;&#061; 400) {<br \/>\n                    span.setTag(&#034;error&#034;, true);<br \/>\n                    span.log(Map.of(<br \/>\n                        &#034;event&#034;, &#034;error&#034;,<br \/>\n                        &#034;message&#034;, &#034;HTTP error response&#034;,<br \/>\n                        &#034;status_code&#034;, response.getRawStatusCode(),<br \/>\n                        &#034;status_text&#034;, response.getStatusText()<br \/>\n                    ));<\/p>\n<p>                    \/\/ \u6839\u636e\u72b6\u6001\u7801\u51b3\u5b9a\u662f\u5426\u5e94\u8be5\u89e6\u53d1\u65ad\u8def\u5668<br \/>\n                    if (response.getRawStatusCode() &gt;&#061; 500) {<br \/>\n                        \/\/ 5xx\u9519\u8bef\u5e94\u8be5\u88ab\u8bb0\u5f55\u4e3a\u5931\u8d25<br \/>\n                        circuitBreaker.onError(<br \/>\n                            response.getRawStatusCode(),<br \/>\n                            new HttpServerErrorException(<br \/>\n                                response.getStatusCode(),<br \/>\n                                response.getStatusText()<br \/>\n                            )<br \/>\n                        );<br \/>\n                    } else if (response.getRawStatusCode() &#061;&#061; 429) {<br \/>\n                        \/\/ 429 Too Many Requests&#xff0c;\u53ef\u80fd\u5e94\u8be5\u7b49\u5f85<br \/>\n                        circuitBreaker.onError(<br \/>\n                            response.getRawStatusCode(),<br \/>\n                            new HttpClientErrorException(<br \/>\n                                response.getStatusCode(),<br \/>\n                                response.getStatusText()<br \/>\n                            )<br \/>\n                        );<br \/>\n                    }<br \/>\n                } else {<br \/>\n                    circuitBreaker.onSuccess(<br \/>\n                        response.getRawStatusCode(),<br \/>\n                        response.getStatusCode()<br \/>\n                    );<br \/>\n                }<\/p>\n<p>                return response;<\/p>\n<p>            } catch (Exception e) {<br \/>\n                span.setTag(&#034;error&#034;, true);<br \/>\n                span.log(Map.of(<br \/>\n                    &#034;event&#034;, &#034;error&#034;,<br \/>\n                    &#034;message&#034;, e.getMessage(),<br \/>\n                    &#034;error.object&#034;, e.getClass().getName()<br \/>\n                ));<\/p>\n<p>                \/\/ \u8bb0\u5f55\u5230\u65ad\u8def\u5668<br \/>\n                circuitBreaker.onError(<br \/>\n                    -1, \/\/ \u672a\u77e5\u72b6\u6001\u7801<br \/>\n                    e<br \/>\n                );<\/p>\n<p>                throw e;<br \/>\n            } finally {<br \/>\n                span.finish();<br \/>\n            }<br \/>\n        });<\/p>\n<p>        return restTemplate;<br \/>\n    }<\/p>\n<p>    private String extractServiceName(URI uri) {<br \/>\n        return uri.getHost();<br \/>\n    }<br \/>\n}<\/p>\n<p>\/\/ \u72b6\u6001\u7801\u611f\u77e5\u7684\u65ad\u8def\u5668\u76d1\u63a7<br \/>\n&#064;Component<br \/>\npublic class CircuitBreakerMonitor {<\/p>\n<p>    private final CircuitBreakerRegistry circuitBreakerRegistry;<br \/>\n    private final MeterRegistry meterRegistry;<br \/>\n    private final Map&lt;String, CircuitBreaker.State&gt; previousStates &#061; new ConcurrentHashMap&lt;&gt;();<\/p>\n<p>    public CircuitBreakerMonitor(CircuitBreakerRegistry circuitBreakerRegistry,<br \/>\n                                MeterRegistry meterRegistry) {<br \/>\n        this.circuitBreakerRegistry &#061; circuitBreakerRegistry;<br \/>\n        this.meterRegistry &#061; meterRegistry;<\/p>\n<p>        \/\/ \u5b9a\u671f\u76d1\u63a7\u65ad\u8def\u5668\u72b6\u6001<br \/>\n        ScheduledExecutorService scheduler &#061; Executors.newSingleThreadScheduledExecutor();<br \/>\n        scheduler.scheduleAtFixedRate(this::monitorCircuitBreakers,<br \/>\n                                     0, 10, TimeUnit.SECONDS);<br \/>\n    }<\/p>\n<p>    private void monitorCircuitBreakers() {<br \/>\n        circuitBreakerRegistry.getAllCircuitBreakers().forEach((name, cb) -&gt; {<br \/>\n            CircuitBreaker.Metrics metrics &#061; cb.getMetrics();<br \/>\n            CircuitBreaker.State currentState &#061; cb.getState();<\/p>\n<p>            \/\/ \u8bb0\u5f55\u6307\u6807<br \/>\n            Gauge.builder(&#034;circuitbreaker.state&#034;, cb,<br \/>\n                    circuitBreaker -&gt; circuitBreaker.getState().getOrder())<br \/>\n                .tag(&#034;name&#034;, name)<br \/>\n                .register(meterRegistry);<\/p>\n<p>            Counter.builder(&#034;circuitbreaker.transitions&#034;)<br \/>\n                .tag(&#034;name&#034;, name)<br \/>\n                .tag(&#034;from&#034;, previousStates.getOrDefault(name, CircuitBreaker.State.CLOSED).name())<br \/>\n                .tag(&#034;to&#034;, currentState.name())<br \/>\n                .register(meterRegistry)<br \/>\n                .increment();<\/p>\n<p>            \/\/ \u8bb0\u5f55\u57fa\u4e8e\u72b6\u6001\u7801\u7684\u5931\u8d25\u7edf\u8ba1<br \/>\n            Map&lt;Integer, Long&gt; statusCodeFailures &#061; getStatusCodeFailures(name);<br \/>\n            statusCodeFailures.forEach((statusCode, count) -&gt; {<br \/>\n                Counter.builder(&#034;circuitbreaker.failures_by_status&#034;)<br \/>\n                    .tag(&#034;name&#034;, name)<br \/>\n                    .tag(&#034;status_code&#034;, String.valueOf(statusCode))<br \/>\n                    .register(meterRegistry)<br \/>\n                    .increment(count);<br \/>\n            });<\/p>\n<p>            \/\/ \u72b6\u6001\u53d8\u66f4\u901a\u77e5<br \/>\n            if (previousStates.containsKey(name) &amp;&amp;<br \/>\n                previousStates.get(name) !&#061; currentState) {<\/p>\n<p>                logStateChange(name, previousStates.get(name), currentState, metrics);<\/p>\n<p>                \/\/ \u53d1\u9001\u544a\u8b66<br \/>\n                if (currentState &#061;&#061; CircuitBreaker.State.OPEN) {<br \/>\n                    sendAlert(name, &#034;Circuit breaker OPENED&#034;, metrics);<br \/>\n                } else if (currentState &#061;&#061; CircuitBreaker.State.HALF_OPEN) {<br \/>\n                    sendAlert(name, &#034;Circuit breaker HALF_OPEN&#034;, metrics);<br \/>\n                } else if (currentState &#061;&#061; CircuitBreaker.State.CLOSED &amp;&amp;<br \/>\n                           previousStates.get(name) &#061;&#061; CircuitBreaker.State.OPEN) {<br \/>\n                    sendAlert(name, &#034;Circuit breaker CLOSED&#034;, metrics);<br \/>\n                }<br \/>\n            }<\/p>\n<p>            previousStates.put(name, currentState);<br \/>\n        });<br \/>\n    }<\/p>\n<p>    private Map&lt;Integer, Long&gt; getStatusCodeFailures(String circuitBreakerName) {<br \/>\n        \/\/ \u8fd9\u91cc\u5e94\u8be5\u4ece\u65ad\u8def\u5668\u7684\u4e8b\u4ef6\u6d41\u4e2d\u63d0\u53d6\u57fa\u4e8e\u72b6\u6001\u7801\u7684\u5931\u8d25\u7edf\u8ba1<br \/>\n        \/\/ \u5b9e\u9645\u5b9e\u73b0\u53ef\u80fd\u9700\u8981\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u5904\u7406\u5668<br \/>\n        return new HashMap&lt;&gt;();<br \/>\n    }<\/p>\n<p>    private void logStateChange(String name, CircuitBreaker.State from,<br \/>\n                               CircuitBreaker.State to, CircuitBreaker.Metrics metrics) {<br \/>\n        logger.info(&#034;Circuit breaker state changed: {} {} -&gt; {} (failureRate: {}%)&#034;,<br \/>\n                   name, from, to,<br \/>\n                   metrics.getFailureRate());<br \/>\n    }<\/p>\n<p>    private void sendAlert(String circuitBreakerName, String message,<br \/>\n                          CircuitBreaker.Metrics metrics) {<br \/>\n        \/\/ \u53d1\u9001\u544a\u8b66\u5230\u76d1\u63a7\u7cfb\u7edf<br \/>\n        Map&lt;String, Object&gt; alert &#061; Map.of(<br \/>\n            &#034;circuit_breaker&#034;, circuitBreakerName,<br \/>\n            &#034;message&#034;, message,<br \/>\n            &#034;failure_rate&#034;, metrics.getFailureRate(),<br \/>\n            &#034;slow_call_rate&#034;, metrics.getSlowCallRate(),<br \/>\n            &#034;timestamp&#034;, Instant.now().toString()<br \/>\n        );<\/p>\n<p>        \/\/ \u53d1\u9001\u5230\u76d1\u63a7\u7cfb\u7edf<br \/>\n        \/\/ monitoringService.sendAlert(alert);<br \/>\n    }<br \/>\n}<\/p>\n<h3>33.5 API\u7f51\u5173\u4e2d\u7684\u72b6\u6001\u7801\u5904\u7406<\/h3>\n<h4>33.5.1 Kong\u7f51\u5173\u914d\u7f6e<\/h4>\n<p>yaml<\/p>\n<p># kong-status-code-handling.yaml<br \/>\n_format_version: &#034;2.1&#034;<br \/>\n_transform: true<\/p>\n<p># \u670d\u52a1\u5b9a\u4e49<br \/>\nservices:<br \/>\n  &#8211; name: order-service<br \/>\n    url: http:\/\/order-service:8080<br \/>\n    routes:<br \/>\n      &#8211; name: order-routes<br \/>\n        paths:<br \/>\n          &#8211; \/orders<br \/>\n          &#8211; \/orders\/<br \/>\n        strip_path: true<\/p>\n<p>    # \u63d2\u4ef6\u914d\u7f6e<br \/>\n    plugins:<br \/>\n      # 1. \u8bf7\u6c42\u8f6c\u6362\u63d2\u4ef6<br \/>\n      &#8211; name: request-transformer<br \/>\n        config:<br \/>\n          add:<br \/>\n            headers:<br \/>\n              &#8211; &#034;X-Request-ID:$ {request_id}&#034;<br \/>\n              &#8211; &#034;X-Client-IP:$ {real_ip_remote_addr}&#034;<br \/>\n              &#8211; &#034;X-Forwarded-For:$ {proxy_add_x_forwarded_for}&#034;<\/p>\n<p>      # 2. \u54cd\u5e94\u8f6c\u6362\u63d2\u4ef6<br \/>\n      &#8211; name: response-transformer<br \/>\n        config:<br \/>\n          add:<br \/>\n            headers:<br \/>\n              &#8211; &#034;X-Service-Name:order-service&#034;<br \/>\n              &#8211; &#034;X-Response-Time:$ {latency}&#034;<br \/>\n          remove:<br \/>\n            headers:<br \/>\n              &#8211; &#034;Server&#034;<br \/>\n              &#8211; &#034;X-Powered-By&#034;<\/p>\n<p>      # 3. \u72b6\u6001\u7801\u91cd\u5199\u63d2\u4ef6<br \/>\n      &#8211; name: status-code-rewrite<br \/>\n        enabled: true<br \/>\n        config:<br \/>\n          rules:<br \/>\n            # \u5c06\u7279\u5b9a\u7684\u540e\u7aef\u9519\u8bef\u8f6c\u6362\u4e3a\u6807\u51c6\u9519\u8bef<br \/>\n            &#8211; backend_status: 502<br \/>\n              gateway_status: 503<br \/>\n              message: &#034;Service temporarily unavailable&#034;<br \/>\n              body: &#039;{&#034;error&#034;:{&#034;code&#034;:&#034;SERVICE_UNAVAILABLE&#034;,&#034;message&#034;:&#034;The service is temporarily unavailable&#034;}}&#039;<\/p>\n<p>            &#8211; backend_status: 504<br \/>\n              gateway_status: 503<br \/>\n              message: &#034;Service timeout&#034;<br \/>\n              body: &#039;{&#034;error&#034;:{&#034;code&#034;:&#034;TIMEOUT&#034;,&#034;message&#034;:&#034;The service did not respond in time&#034;}}&#039;<\/p>\n<p>            # \u9690\u85cf\u5185\u90e8\u9519\u8bef\u8be6\u60c5<br \/>\n            &#8211; backend_status: 500<br \/>\n              gateway_status: 500<br \/>\n              message: &#034;Internal server error&#034;<br \/>\n              body: &#039;{&#034;error&#034;:{&#034;code&#034;:&#034;INTERNAL_ERROR&#034;,&#034;message&#034;:&#034;An internal server error occurred&#034;}}&#039;<br \/>\n              hide_details: true<\/p>\n<p>      # 4. \u65ad\u8def\u5668\u63d2\u4ef6<br \/>\n      &#8211; name: circuit-breaker<br \/>\n        config:<br \/>\n          window_size: 60<br \/>\n          window_type: sliding<br \/>\n          failure_threshold: 5<br \/>\n          unhealthy:<br \/>\n            http_statuses:<br \/>\n              &#8211; 500<br \/>\n              &#8211; 502<br \/>\n              &#8211; 503<br \/>\n              &#8211; 504<br \/>\n            tcp_failures: 2<br \/>\n            timeouts: 3<br \/>\n          healthy:<br \/>\n            http_statuses:<br \/>\n              &#8211; 200<br \/>\n              &#8211; 201<br \/>\n              &#8211; 202<br \/>\n            successes: 1<br \/>\n          healthcheck:<br \/>\n            active:<br \/>\n              type: http<br \/>\n              http_path: \/health<br \/>\n              timeout: 5<br \/>\n              concurrency: 10<br \/>\n              healthy:<br \/>\n                interval: 30<br \/>\n                http_statuses:<br \/>\n                  &#8211; 200<br \/>\n                  &#8211; 302<br \/>\n                successes: 2<br \/>\n              unhealthy:<br \/>\n                interval: 30<br \/>\n                http_statuses:<br \/>\n                  &#8211; 429<br \/>\n                  &#8211; 500<br \/>\n                  &#8211; 503<br \/>\n                tcp_failures: 2<br \/>\n                timeouts: 3<br \/>\n                http_failures: 2<br \/>\n            passive:<br \/>\n              type: http<br \/>\n              healthy:<br \/>\n                http_statuses:<br \/>\n                  &#8211; 200<br \/>\n                  &#8211; 201<br \/>\n                  &#8211; 202<br \/>\n                  &#8211; 203<br \/>\n                  &#8211; 204<br \/>\n                  &#8211; 205<br \/>\n                  &#8211; 206<br \/>\n                  &#8211; 207<br \/>\n                  &#8211; 208<br \/>\n                  &#8211; 226<br \/>\n                successes: 5<br \/>\n              unhealthy:<br \/>\n                http_statuses:<br \/>\n                  &#8211; 500<br \/>\n                  &#8211; 502<br \/>\n                  &#8211; 503<br \/>\n                  &#8211; 504<br \/>\n                tcp_failures: 2<br \/>\n                timeouts: 7<br \/>\n                http_failures: 5<\/p>\n<p># \u5168\u5c40\u63d2\u4ef6<br \/>\nplugins:<br \/>\n  &#8211; name: correlation-id<br \/>\n    config:<br \/>\n      header_name: X-Request-ID<br \/>\n      generator: uuid<br \/>\n      echo_downstream: true<\/p>\n<p>  &#8211; name: prometheus<br \/>\n    config:<br \/>\n      status_code_metrics: true<br \/>\n      latency_metrics: true<br \/>\n      bandwidth_metrics: true<br \/>\n      upstream_health_metrics: true<\/p>\n<p>  &#8211; name: zipkin<br \/>\n    config:<br \/>\n      http_endpoint: http:\/\/zipkin:9411\/api\/v2\/spans<br \/>\n      sample_ratio: 1<br \/>\n      include_credential: true<br \/>\n      traceid_byte_count: 16<br \/>\n      header_type: preserve<\/p>\n<p>  # \u5168\u5c40\u9519\u8bef\u5904\u7406\u5668<br \/>\n  &#8211; name: error-handler<br \/>\n    config:<br \/>\n      default_response:<br \/>\n        status_code: 500<br \/>\n        content_type: application\/json<br \/>\n        body: &#039;{&#034;error&#034;:{&#034;code&#034;:&#034;INTERNAL_ERROR&#034;,&#034;message&#034;:&#034;An unexpected error occurred&#034;}}&#039;<\/p>\n<p>      custom_responses:<br \/>\n        &#8211; status_code: 404<br \/>\n          content_type: application\/json<br \/>\n          body: &#039;{&#034;error&#034;:{&#034;code&#034;:&#034;NOT_FOUND&#034;,&#034;message&#034;:&#034;The requested resource was not found&#034;}}&#039;<\/p>\n<p>        &#8211; status_code: 429<br \/>\n          content_type: application\/json<br \/>\n          headers:<br \/>\n            Retry-After: &#034;60&#034;<br \/>\n          body: &#039;{&#034;error&#034;:{&#034;code&#034;:&#034;RATE_LIMITED&#034;,&#034;message&#034;:&#034;Too many requests, please try again later&#034;}}&#039;<\/p>\n<p>        &#8211; status_code: 503<br \/>\n          content_type: application\/json<br \/>\n          headers:<br \/>\n            Retry-After: &#034;30&#034;<br \/>\n          body: &#039;{&#034;error&#034;:{&#034;code&#034;:&#034;SERVICE_UNAVAILABLE&#034;,&#034;message&#034;:&#034;Service is temporarily unavailable&#034;}}&#039;<\/p>\n<p># \u4e0a\u6e38\u5065\u5eb7\u68c0\u67e5<br \/>\nupstreams:<br \/>\n  &#8211; name: order-service-upstream<br \/>\n    algorithm: round-robin<br \/>\n    healthchecks:<br \/>\n      active:<br \/>\n        type: http<br \/>\n        http_path: \/health<br \/>\n        timeout: 5<br \/>\n        healthy:<br \/>\n          interval: 30<br \/>\n          http_statuses:<br \/>\n            &#8211; 200<br \/>\n            &#8211; 302<br \/>\n          successes: 2<br \/>\n        unhealthy:<br \/>\n          interval: 30<br \/>\n          http_statuses:<br \/>\n            &#8211; 429<br \/>\n            &#8211; 500<br \/>\n            &#8211; 503<br \/>\n          tcp_failures: 2<br \/>\n          timeouts: 3<br \/>\n          http_failures: 2<br \/>\n      passive:<br \/>\n        healthy:<br \/>\n          http_statuses:<br \/>\n            &#8211; 200<br \/>\n            &#8211; 201<br \/>\n            &#8211; 202<br \/>\n            &#8211; 203<br \/>\n            &#8211; 204<br \/>\n            &#8211; 205<br \/>\n            &#8211; 206<br \/>\n            &#8211; 207<br \/>\n            &#8211; 208<br \/>\n            &#8211; 226<br \/>\n          successes: 5<br \/>\n        unhealthy:<br \/>\n          http_statuses:<br \/>\n            &#8211; 500<br \/>\n            &#8211; 502<br \/>\n            &#8211; 503<br \/>\n            &#8211; 504<br \/>\n          tcp_failures: 2<br \/>\n          timeouts: 7<br \/>\n          http_failures: 5<\/p>\n<p>    targets:<br \/>\n      &#8211; target: order-service-1:8080<br \/>\n        weight: 100<br \/>\n      &#8211; target: order-service-2:8080<br \/>\n        weight: 100<\/p>\n<h4>33.5.2 Envoy\u4ee3\u7406\u914d\u7f6e<\/h4>\n<p>yaml<\/p>\n<p># envoy-status-code-config.yaml<br \/>\nstatic_resources:<br \/>\n  listeners:<br \/>\n    &#8211; name: api_listener<br \/>\n      address:<br \/>\n        socket_address:<br \/>\n          address: 0.0.0.0<br \/>\n          port_value: 8080<\/p>\n<p>      filter_chains:<br \/>\n        &#8211; filters:<br \/>\n            &#8211; name: envoy.filters.network.http_connection_manager<br \/>\n              typed_config:<br \/>\n                &#034;&#064;type&#034;: type.googleapis.com\/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager<\/p>\n<p>                stat_prefix: ingress_http<br \/>\n                route_config:<br \/>\n                  name: local_route<br \/>\n                  virtual_hosts:<br \/>\n                    &#8211; name: api<br \/>\n                      domains: [&#034;*&#034;]<br \/>\n                      routes:<br \/>\n                        &#8211; match:<br \/>\n                            prefix: &#034;\/orders&#034;<br \/>\n                          route:<br \/>\n                            cluster: order_service<br \/>\n                            timeout: 30s<br \/>\n                            retry_policy:<br \/>\n                              retry_on: &#034;5xx,gateway-error,connect-failure,retriable-4xx&#034;<br \/>\n                              num_retries: 3<br \/>\n                              per_try_timeout: 10s<br \/>\n                              retry_back_off:<br \/>\n                                base_interval: 0.1s<br \/>\n                                max_interval: 10s<\/p>\n<p>                            # \u72b6\u6001\u7801\u91cd\u5199<br \/>\n                            upgrade_configs:<br \/>\n                              &#8211; upgrade_type: &#034;websocket&#034;<\/p>\n<p>                # HTTP\u8fc7\u6ee4\u5668<br \/>\n                http_filters:<br \/>\n                  # 1. \u72b6\u6001\u7801\u91cd\u5199\u8fc7\u6ee4\u5668<br \/>\n                  &#8211; name: envoy.filters.http.status_code_rewrite<br \/>\n                    typed_config:<br \/>\n                      &#034;&#064;type&#034;: type.googleapis.com\/envoy.extensions.filters.http.status_code_rewrite.v3.StatusCodeRewrite<br \/>\n                      rules:<br \/>\n                        &#8211; upstream_status: &#034;502&#034;<br \/>\n                          gateway_status: &#034;503&#034;<br \/>\n                          headers_to_add:<br \/>\n                            &#8211; header:<br \/>\n                                key: &#034;X-Status-Reason&#034;<br \/>\n                                value: &#034;Bad Gateway converted to Service Unavailable&#034;<\/p>\n<p>                        &#8211; upstream_status: &#034;504&#034;<br \/>\n                          gateway_status: &#034;503&#034;<br \/>\n                          headers_to_add:<br \/>\n                            &#8211; header:<br \/>\n                                key: &#034;X-Status-Reason&#034;<br \/>\n                                value: &#034;Gateway Timeout converted to Service Unavailable&#034;<\/p>\n<p>                  # 2. \u65ad\u8def\u5668\u8fc7\u6ee4\u5668<br \/>\n                  &#8211; name: envoy.filters.http.circuit_breaker<br \/>\n                    typed_config:<br \/>\n                      &#034;&#064;type&#034;: type.googleapis.com\/envoy.extensions.filters.http.circuit_breaker.v3.CircuitBreaker<br \/>\n                      max_connections: 1024<br \/>\n                      max_pending_requests: 1024<br \/>\n                      max_requests: 1024<br \/>\n                      max_retries: 3<br \/>\n                      track_remaining: true<\/p>\n<p>                  # 3. \u6545\u969c\u6ce8\u5165\u8fc7\u6ee4\u5668<br \/>\n                  &#8211; name: envoy.filters.http.fault<br \/>\n                    typed_config:<br \/>\n                      &#034;&#064;type&#034;: type.googleapis.com\/envoy.extensions.filters.http.fault.v3.HTTPFault<br \/>\n                      abort:<br \/>\n                        http_status: 503<br \/>\n                        percentage:<br \/>\n                          numerator: 5  # 5%\u7684\u8bf7\u6c42\u4f1a\u6536\u5230503\u9519\u8bef<br \/>\n                          denominator: HUNDRED<\/p>\n<p>                      delay:<br \/>\n                        fixed_delay: 1s<br \/>\n                        percentage:<br \/>\n                          numerator: 10  # 10%\u7684\u8bf7\u6c42\u4f1a\u67091\u79d2\u5ef6\u8fdf<br \/>\n                          denominator: HUNDRED<\/p>\n<p>                  # 4. \u5916\u90e8\u6388\u6743\u8fc7\u6ee4\u5668<br \/>\n                  &#8211; name: envoy.filters.http.ext_authz<br \/>\n                    typed_config:<br \/>\n                      &#034;&#064;type&#034;: type.googleapis.com\/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz<br \/>\n                      http_service:<br \/>\n                        server_uri:<br \/>\n                          uri: auth-service:9000<br \/>\n                          cluster: auth_service<br \/>\n                          timeout: 0.25s<\/p>\n<p>                        authorization_request:<br \/>\n                          allowed_headers:<br \/>\n                            patterns:<br \/>\n                              &#8211; exact: &#034;content-type&#034;<br \/>\n                              &#8211; exact: &#034;authorization&#034;<br \/>\n                              &#8211; exact: &#034;x-request-id&#034;<\/p>\n<p>                        authorization_response:<br \/>\n                          allowed_upstream_headers:<br \/>\n                            patterns:<br \/>\n                              &#8211; exact: &#034;x-user-id&#034;<br \/>\n                              &#8211; exact: &#034;x-user-role&#034;<\/p>\n<p>                          allowed_client_headers:<br \/>\n                            patterns:<br \/>\n                              &#8211; exact: &#034;x-auth-status&#034;<\/p>\n<p>                  # 5. \u901f\u7387\u9650\u5236\u8fc7\u6ee4\u5668<br \/>\n                  &#8211; name: envoy.filters.http.ratelimit<br \/>\n                    typed_config:<br \/>\n                      &#034;&#064;type&#034;: type.googleapis.com\/envoy.extensions.filters.http.ratelimit.v3.RateLimit<br \/>\n                      domain: api-gateway<br \/>\n                      failure_mode_deny: false<br \/>\n                      timeout: 0.05s<br \/>\n                      rate_limit_service:<br \/>\n                        grpc_service:<br \/>\n                          envoy_grpc:<br \/>\n                            cluster_name: rate_limit_service<\/p>\n<p>                  # 6. \u8def\u7531\u5668\u8fc7\u6ee4\u5668&#xff08;\u5fc5\u987b\u6700\u540e\u4e00\u4e2a&#xff09;<br \/>\n                  &#8211; name: envoy.filters.http.router<br \/>\n                    typed_config:<br \/>\n                      &#034;&#064;type&#034;: type.googleapis.com\/envoy.extensions.filters.http.router.v3.Router<br \/>\n                      suppress_envoy_headers: true<br \/>\n                      start_child_span: true<\/p>\n<p>                # \u8bbf\u95ee\u65e5\u5fd7<br \/>\n                access_log:<br \/>\n                  &#8211; name: envoy.access_loggers.file<br \/>\n                    typed_config:<br \/>\n                      &#034;&#064;type&#034;: type.googleapis.com\/envoy.extensions.access_loggers.file.v3.FileAccessLog<br \/>\n                      path: \/dev\/stdout<\/p>\n<p>                      log_format:<br \/>\n                        json_format:<br \/>\n                          timestamp: &#034;%START_TIME%&#034;<br \/>\n                          request_id: &#034;%REQ(X-REQUEST-ID)%&#034;<br \/>\n                          client_ip: &#034;%DOWNSTREAM_REMOTE_ADDRESS%&#034;<br \/>\n                          method: &#034;%REQ(:METHOD)%&#034;<br \/>\n                          path: &#034;%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%&#034;<br \/>\n                          protocol: &#034;%PROTOCOL%&#034;<br \/>\n                          response_code: &#034;%RESPONSE_CODE%&#034;<br \/>\n                          response_flags: &#034;%RESPONSE_FLAGS%&#034;<br \/>\n                          bytes_received: &#034;%BYTES_RECEIVED%&#034;<br \/>\n                          bytes_sent: &#034;%BYTES_SENT%&#034;<br \/>\n                          duration: &#034;%DURATION%&#034;<br \/>\n                          upstream_service_time: &#034;%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%&#034;<br \/>\n                          upstream_host: &#034;%UPSTREAM_HOST%&#034;<br \/>\n                          upstream_cluster: &#034;%UPSTREAM_CLUSTER%&#034;<br \/>\n                          upstream_local_address: &#034;%UPSTREAM_LOCAL_ADDRESS%&#034;<br \/>\n                          downstream_local_address: &#034;%DOWNSTREAM_LOCAL_ADDRESS%&#034;<br \/>\n                          downstream_remote_address: &#034;%DOWNSTREAM_REMOTE_ADDRESS%&#034;<br \/>\n                          requested_server_name: &#034;%REQUESTED_SERVER_NAME%&#034;<br \/>\n                          route_name: &#034;%ROUTE_NAME%&#034;<\/p>\n<p>                # \u8ffd\u8e2a\u914d\u7f6e<br \/>\n                tracing:<br \/>\n                  provider:<br \/>\n                    name: envoy.tracers.zipkin<br \/>\n                    typed_config:<br \/>\n                      &#034;&#064;type&#034;: type.googleapis.com\/envoy.config.trace.v3.ZipkinConfig<br \/>\n                      collector_cluster: zipkin<br \/>\n                      collector_endpoint: &#034;\/api\/v2\/spans&#034;<br \/>\n                      collector_endpoint_version: HTTP_JSON<br \/>\n                      shared_span_context: false<br \/>\n                      trace_id_128bit: true<\/p>\n<p>  # \u96c6\u7fa4\u5b9a\u4e49<br \/>\n  clusters:<br \/>\n    &#8211; name: order_service<br \/>\n      type: STRICT_DNS<br \/>\n      lb_policy: ROUND_ROBIN<br \/>\n      load_assignment:<br \/>\n        cluster_name: order_service<br \/>\n        endpoints:<br \/>\n          &#8211; lb_endpoints:<br \/>\n              &#8211; endpoint:<br \/>\n                  address:<br \/>\n                    socket_address:<br \/>\n                      address: order-service<br \/>\n                      port_value: 8080<\/p>\n<p>      circuit_breakers:<br \/>\n        thresholds:<br \/>\n          &#8211; priority: DEFAULT<br \/>\n            max_connections: 1024<br \/>\n            max_pending_requests: 1024<br \/>\n            max_requests: 1024<br \/>\n            max_retries: 3<br \/>\n          &#8211; priority: HIGH<br \/>\n            max_connections: 2048<br \/>\n            max_pending_requests: 2048<br \/>\n            max_requests: 2048<br \/>\n            max_retries: 3<\/p>\n<p>      outlier_detection:<br \/>\n        consecutive_5xx: 10<br \/>\n        interval: 30s<br \/>\n        base_ejection_time: 30s<br \/>\n        max_ejection_percent: 50<\/p>\n<p>      health_checks:<br \/>\n        &#8211; timeout: 5s<br \/>\n          interval: 30s<br \/>\n          unhealthy_threshold: 3<br \/>\n          healthy_threshold: 2<br \/>\n          http_health_check:<br \/>\n            path: \/health<br \/>\n            expected_statuses:<br \/>\n              start: 200<br \/>\n              end: 299<\/p>\n<p>    &#8211; name: auth_service<br \/>\n      type: STRICT_DNS<br \/>\n      connect_timeout: 0.25s<br \/>\n      lb_policy: ROUND_ROBIN<br \/>\n      load_assignment:<br \/>\n        cluster_name: auth_service<br \/>\n        endpoints:<br \/>\n          &#8211; lb_endpoints:<br \/>\n              &#8211; endpoint:<br \/>\n                  address:<br \/>\n                    socket_address:<br \/>\n                      address: auth-service<br \/>\n                      port_value: 9000<\/p>\n<p>    &#8211; name: rate_limit_service<br \/>\n      type: STRICT_DNS<br \/>\n      connect_timeout: 0.05s<br \/>\n      lb_policy: ROUND_ROBIN<br \/>\n      http2_protocol_options: {}<br \/>\n      load_assignment:<br \/>\n        cluster_name: rate_limit_service<br \/>\n        endpoints:<br \/>\n          &#8211; lb_endpoints:<br \/>\n              &#8211; endpoint:<br \/>\n                  address:<br \/>\n                    socket_address:<br \/>\n                      address: rate-limit-service<br \/>\n                      port_value: 8081<\/p>\n<p>    &#8211; name: zipkin<br \/>\n      type: STRICT_DNS<br \/>\n      lb_policy: ROUND_ROBIN<br \/>\n      load_assignment:<br \/>\n        cluster_name: zipkin<br \/>\n        endpoints:<br \/>\n          &#8211; lb_endpoints:<br \/>\n              &#8211; endpoint:<br \/>\n                  address:<br \/>\n                    socket_address:<br \/>\n                      address: zipkin<br \/>\n                      port_value: 9411<\/p>\n<p># \u7ba1\u7406\u63a5\u53e3<br \/>\nadmin:<br \/>\n  address:<br \/>\n    socket_address:<br \/>\n      address: 0.0.0.0<br \/>\n      port_value: 9901<\/p>\n<h3>33.6 \u670d\u52a1\u7f51\u683c\u4e2d\u7684\u72b6\u6001\u7801\u4f20\u64ad<\/h3>\n<h4>33.6.1 Istio\u670d\u52a1\u7f51\u683c\u914d\u7f6e<\/h4>\n<p>yaml<\/p>\n<p># istio-status-code-policies.yaml<br \/>\napiVersion: networking.istio.io\/v1beta1<br \/>\nkind: VirtualService<br \/>\nmetadata:<br \/>\n  name: order-service<br \/>\nspec:<br \/>\n  hosts:<br \/>\n    &#8211; order-service<br \/>\n  http:<br \/>\n    &#8211; match:<br \/>\n        &#8211; uri:<br \/>\n            prefix: \/orders<br \/>\n      route:<br \/>\n        &#8211; destination:<br \/>\n            host: order-service<br \/>\n            port:<br \/>\n              number: 8080<br \/>\n          weight: 100<\/p>\n<p>      # \u91cd\u8bd5\u7b56\u7565<br \/>\n      retries:<br \/>\n        attempts: 3<br \/>\n        retryOn: &#034;5xx,gateway-error,connect-failure,retriable-4xx&#034;<br \/>\n        perTryTimeout: 10s<\/p>\n<p>      # \u8d85\u65f6\u914d\u7f6e<br \/>\n      timeout: 30s<\/p>\n<p>      # \u6545\u969c\u6ce8\u5165<br \/>\n      fault:<br \/>\n        abort:<br \/>\n          percentage:<br \/>\n            value: 0.1  # 0.1%\u7684\u8bf7\u6c42\u4f1a\u6536\u5230503\u9519\u8bef<br \/>\n          httpStatus: 503<br \/>\n        delay:<br \/>\n          percentage:<br \/>\n            value: 1  # 1%\u7684\u8bf7\u6c42\u4f1a\u6709100ms\u5ef6\u8fdf<br \/>\n          fixedDelay: 100ms<\/p>\n<p>      # \u72b6\u6001\u7801\u91cd\u5199<br \/>\n      headers:<br \/>\n        request:<br \/>\n          set:<br \/>\n            X-Request-ID: &#034;%REQ(X-REQUEST-ID)%&#034;<br \/>\n            X-Client-IP: &#034;%DOWNSTREAM_REMOTE_ADDRESS%&#034;<br \/>\n        response:<br \/>\n          set:<br \/>\n            X-Service-Version: &#034;v1.0.0&#034;<br \/>\n            X-Response-Time: &#034;%RESPONSE_DURATION%&#034;<br \/>\n          remove:<br \/>\n            &#8211; &#034;Server&#034;<\/p>\n<p>      # CORS\u7b56\u7565<br \/>\n      corsPolicy:<br \/>\n        allowOrigin:<br \/>\n          &#8211; &#034;*&#034;<br \/>\n        allowMethods:<br \/>\n          &#8211; POST<br \/>\n          &#8211; GET<br \/>\n          &#8211; OPTIONS<br \/>\n          &#8211; PUT<br \/>\n          &#8211; DELETE<br \/>\n        allowHeaders:<br \/>\n          &#8211; content-type<br \/>\n          &#8211; authorization<br \/>\n          &#8211; x-request-id<br \/>\n        maxAge: &#034;24h&#034;<\/p>\n<p>&#8212;<br \/>\napiVersion: networking.istio.io\/v1beta1<br \/>\nkind: DestinationRule<br \/>\nmetadata:<br \/>\n  name: order-service<br \/>\nspec:<br \/>\n  host: order-service<br \/>\n  trafficPolicy:<br \/>\n    # \u8fde\u63a5\u6c60\u8bbe\u7f6e<br \/>\n    connectionPool:<br \/>\n      tcp:<br \/>\n        maxConnections: 100<br \/>\n        connectTimeout: 30ms<br \/>\n      http:<br \/>\n        http1MaxPendingRequests: 1024<br \/>\n        http2MaxRequests: 1024<br \/>\n        maxRequestsPerConnection: 1024<br \/>\n        maxRetries: 3<br \/>\n        idleTimeout: 3600s<\/p>\n<p>    # \u8d1f\u8f7d\u5747\u8861<br \/>\n    loadBalancer:<br \/>\n      simple: ROUND_ROBIN<\/p>\n<p>    # \u5f02\u5e38\u68c0\u6d4b<br \/>\n    outlierDetection:<br \/>\n      consecutive5xxErrors: 10<br \/>\n      interval: 30s<br \/>\n      baseEjectionTime: 30s<br \/>\n      maxEjectionPercent: 50<\/p>\n<p>    # TLS\u8bbe\u7f6e<br \/>\n    tls:<br \/>\n      mode: ISTIO_MUTUAL<br \/>\n&#8212;<br \/>\n# \u72b6\u6001\u7801\u76d1\u63a7\u914d\u7f6e<br \/>\napiVersion: telemetry.istio.io\/v1alpha1<br \/>\nkind: Telemetry<br \/>\nmetadata:<br \/>\n  name: status-code-metrics<br \/>\nspec:<br \/>\n  metrics:<br \/>\n    &#8211; providers:<br \/>\n        &#8211; name: prometheus<br \/>\n      overrides:<br \/>\n        # \u8bf7\u6c42\u8ba1\u6570&#xff0c;\u6309\u72b6\u6001\u7801\u5206\u7c7b<br \/>\n        &#8211; match:<br \/>\n            metric: REQUEST_COUNT<br \/>\n          mode: CLIENT_AND_SERVER<br \/>\n          tagOverrides:<br \/>\n            response_code:<br \/>\n              value: &#034;%RESPONSE_CODE%&#034;<\/p>\n<p>        # \u8bf7\u6c42\u6301\u7eed\u65f6\u95f4&#xff0c;\u6309\u72b6\u6001\u7801\u5206\u7c7b<br \/>\n        &#8211; match:<br \/>\n            metric: REQUEST_DURATION<br \/>\n          mode: CLIENT_AND_SERVER<br \/>\n          tagOverrides:<br \/>\n            response_code:<br \/>\n              value: &#034;%RESPONSE_CODE%&#034;<\/p>\n<p>        # \u8bf7\u6c42\u5927\u5c0f&#xff0c;\u6309\u72b6\u6001\u7801\u5206\u7c7b<br \/>\n        &#8211; match:<br \/>\n            metric: REQUEST_SIZE<br \/>\n          mode: CLIENT_AND_SERVER<br \/>\n          tagOverrides:<br \/>\n            response_code:<br \/>\n              value: &#034;%RESPONSE_CODE%&#034;<\/p>\n<p>        # \u54cd\u5e94\u5927\u5c0f&#xff0c;\u6309\u72b6\u6001\u7801\u5206\u7c7b<br \/>\n        &#8211; match:<br \/>\n            metric: RESPONSE_SIZE<br \/>\n          mode: CLIENT_AND_SERVER<br \/>\n          tagOverrides:<br \/>\n            response_code:<br \/>\n              value: &#034;%RESPONSE_CODE%&#034;<\/p>\n<p>      # \u81ea\u5b9a\u4e49\u6307\u6807<br \/>\n      customMetrics:<br \/>\n        &#8211; name: error_rate_by_service<br \/>\n          dimensions:<br \/>\n            destination_service: &#034;string(destination.service)&#034;<br \/>\n            response_code: &#034;string(response.code)&#034;<br \/>\n            source_service: &#034;string(source.service)&#034;<br \/>\n          value: &#034;double(1)&#034;<\/p>\n<p>        &#8211; name: latency_by_status_code<br \/>\n          dimensions:<br \/>\n            destination_service: &#034;string(destination.service)&#034;<br \/>\n            response_code: &#034;string(response.code)&#034;<br \/>\n            percentile: &#034;string(percentile)&#034;<br \/>\n          value: &#034;double(response.duration)&#034;<br \/>\n&#8212;<br \/>\n# \u72b6\u6001\u7801\u544a\u8b66\u89c4\u5219<br \/>\napiVersion: monitoring.coreos.com\/v1<br \/>\nkind: PrometheusRule<br \/>\nmetadata:<br \/>\n  name: status-code-alerts<br \/>\nspec:<br \/>\n  groups:<br \/>\n    &#8211; name: status-code-monitoring<br \/>\n      rules:<br \/>\n        # \u9ad8\u9519\u8bef\u7387\u544a\u8b66<br \/>\n        &#8211; alert: High5xxErrorRate<br \/>\n          expr: |<br \/>\n            sum(rate(istio_requests_total{<br \/>\n              response_code&#061;~&#034;5..&#034;,<br \/>\n              reporter&#061;&#034;destination&#034;<br \/>\n            }[5m])) by (destination_service)<br \/>\n            \/<br \/>\n            sum(rate(istio_requests_total{<br \/>\n              reporter&#061;&#034;destination&#034;<br \/>\n            }[5m])) by (destination_service)<br \/>\n            &gt; 0.05<br \/>\n          for: 5m<br \/>\n          labels:<br \/>\n            severity: critical<br \/>\n          annotations:<br \/>\n            summary: &#034;High 5xx error rate for {{ $labels.destination_service }}&#034;<br \/>\n            description: &#034;5xx error rate is {{ $value | humanizePercentage }} for service {{ $labels.destination_service }}&#034;<\/p>\n<p>        # 4xx\u9519\u8bef\u7387\u589e\u52a0<br \/>\n        &#8211; alert: High4xxErrorRate<br \/>\n          expr: |<br \/>\n            sum(rate(istio_requests_total{<br \/>\n              response_code&#061;~&#034;4..&#034;,<br \/>\n              reporter&#061;&#034;destination&#034;<br \/>\n            }[5m])) by (destination_service)<br \/>\n            \/<br \/>\n            sum(rate(istio_requests_total{<br \/>\n              reporter&#061;&#034;destination&#034;<br \/>\n            }[5m])) by (destination_service)<br \/>\n            &gt; 0.10<br \/>\n          for: 10m<br \/>\n          labels:<br \/>\n            severity: warning<br \/>\n          annotations:<br \/>\n            summary: &#034;High 4xx error rate for {{ $labels.destination_service }}&#034;<br \/>\n            description: &#034;4xx error rate is {{ $value | humanizePercentage }} for service {{ $labels.destination_service }}&#034;<\/p>\n<p>        # \u670d\u52a1\u4e0d\u53ef\u7528<br \/>\n        &#8211; alert: ServiceUnavailable<br \/>\n          expr: |<br \/>\n            sum(rate(istio_requests_total{<br \/>\n              response_code&#061;~&#034;5..&#034;,<br \/>\n              reporter&#061;&#034;destination&#034;<br \/>\n            }[5m])) by (destination_service) &#061;&#061; 0<br \/>\n            and<br \/>\n            sum(rate(istio_requests_total{<br \/>\n              reporter&#061;&#034;destination&#034;<br \/>\n            }[5m])) by (destination_service) &#061;&#061; 0<br \/>\n          for: 2m<br \/>\n          labels:<br \/>\n            severity: critical<br \/>\n          annotations:<br \/>\n            summary: &#034;Service {{ $labels.destination_service }} is unavailable&#034;<br \/>\n            description: &#034;Service {{ $labels.destination_service }} has not received any requests in the last 2 minutes&#034;<\/p>\n<p>        # \u6162\u54cd\u5e94\u544a\u8b66<br \/>\n        &#8211; alert: SlowResponses<br \/>\n          expr: |<br \/>\n            histogram_quantile(0.95,<br \/>\n              sum(rate(istio_request_duration_milliseconds_bucket{<br \/>\n                reporter&#061;&#034;destination&#034;<br \/>\n              }[5m])) by (le, destination_service)<br \/>\n            ) &gt; 1000<br \/>\n          for: 5m<br \/>\n          labels:<br \/>\n            severity: warning<br \/>\n          annotations:<br \/>\n            summary: &#034;Slow responses for {{ $labels.destination_service }}&#034;<br \/>\n            description: &#034;95th percentile response time is {{ $value }}ms for service {{ $labels.destination_service }}&#034;<\/p>\n<h3>33.7 \u9519\u8bef\u6062\u590d\u4e0e\u964d\u7ea7\u7b56\u7565<\/h3>\n<h4>33.7.1 \u591a\u7ea7\u964d\u7ea7\u7b56\u7565<\/h4>\n<p>python<\/p>\n<p># \u591a\u7ea7\u964d\u7ea7\u7b56\u7565\u5b9e\u73b0<br \/>\nfrom enum import Enum<br \/>\nfrom typing import Dict, Any, Optional, Callable<br \/>\nimport time<br \/>\nimport logging<br \/>\nfrom dataclasses import dataclass<br \/>\nfrom functools import wraps<\/p>\n<p>logger &#061; logging.getLogger(__name__)<\/p>\n<p>class DegradationLevel(Enum):<br \/>\n    NORMAL &#061; 1          # \u6b63\u5e38\u6a21\u5f0f<br \/>\n    DEGRADED &#061; 2        # \u964d\u7ea7\u6a21\u5f0f<br \/>\n    LIMITED &#061; 3         # \u9650\u5236\u6a21\u5f0f<br \/>\n    MAINTENANCE &#061; 4     # \u7ef4\u62a4\u6a21\u5f0f<br \/>\n    FAILSAFE &#061; 5        # \u5b89\u5168\u6a21\u5f0f<\/p>\n<p>&#064;dataclass<br \/>\nclass ServiceHealth:<br \/>\n    name: str<br \/>\n    status_code: int<br \/>\n    response_time: float<br \/>\n    error_rate: float<br \/>\n    last_check: float<br \/>\n    degradation_level: DegradationLevel &#061; DegradationLevel.NORMAL<\/p>\n<p>class MultiLevelDegradation:<br \/>\n    def __init__(self):<br \/>\n        self.service_health: Dict[str, ServiceHealth] &#061; {}<br \/>\n        self.degradation_strategies: Dict[DegradationLevel, Callable] &#061; {}<br \/>\n        self._setup_strategies()<\/p>\n<p>    def _setup_strategies(self):<br \/>\n        &#034;&#034;&#034;\u8bbe\u7f6e\u5404\u7ea7\u964d\u7ea7\u7b56\u7565&#034;&#034;&#034;<br \/>\n        self.degradation_strategies &#061; {<br \/>\n            DegradationLevel.NORMAL: self._normal_strategy,<br \/>\n            DegradationLevel.DEGRADED: self._degraded_strategy,<br \/>\n            DegradationLevel.LIMITED: self._limited_strategy,<br \/>\n            DegradationLevel.MAINTENANCE: self._maintenance_strategy,<br \/>\n            DegradationLevel.FAILSAFE: self._failsafe_strategy,<br \/>\n        }<\/p>\n<p>    def assess_health(self, service_name: str,<br \/>\n                     status_code: int,<br \/>\n                     response_time: float) -&gt; DegradationLevel:<br \/>\n        &#034;&#034;&#034;\u8bc4\u4f30\u670d\u52a1\u5065\u5eb7\u72b6\u51b5\u5e76\u786e\u5b9a\u964d\u7ea7\u7ea7\u522b&#034;&#034;&#034;<br \/>\n        if service_name not in self.service_health:<br \/>\n            self.service_health[service_name] &#061; ServiceHealth(<br \/>\n                name&#061;service_name,<br \/>\n                status_code&#061;status_code,<br \/>\n                response_time&#061;response_time,<br \/>\n                error_rate&#061;0.0,<br \/>\n                last_check&#061;time.time()<br \/>\n            )<\/p>\n<p>        health &#061; self.service_health[service_name]<\/p>\n<p>        # \u66f4\u65b0\u5065\u5eb7\u6307\u6807<br \/>\n        is_error &#061; status_code &gt;&#061; 400<br \/>\n        error_count &#061; 1 if is_error else 0<br \/>\n        total_count &#061; 1<\/p>\n<p>        # \u8ba1\u7b97\u6ed1\u52a8\u7a97\u53e3\u9519\u8bef\u7387&#xff08;\u7b80\u5316\u5b9e\u73b0&#xff09;<br \/>\n        window_size &#061; 100<br \/>\n        health.error_rate &#061; (<br \/>\n            health.error_rate * (window_size &#8211; 1) &#043; error_count<br \/>\n        ) \/ window_size<\/p>\n<p>        health.status_code &#061; status_code<br \/>\n        health.response_time &#061; response_time<br \/>\n        health.last_check &#061; time.time()<\/p>\n<p>        # \u786e\u5b9a\u964d\u7ea7\u7ea7\u522b<br \/>\n        if status_code &#061;&#061; 503:<br \/>\n            return DegradationLevel.MAINTENANCE<\/p>\n<p>        elif status_code &gt;&#061; 500:<br \/>\n            if health.error_rate &gt; 0.5:<br \/>\n                return DegradationLevel.FAILSAFE<br \/>\n            elif health.error_rate &gt; 0.2:<br \/>\n                return DegradationLevel.LIMITED<br \/>\n            else:<br \/>\n                return DegradationLevel.DEGRADED<\/p>\n<p>        elif status_code &#061;&#061; 429:  # Rate limited<br \/>\n            return DegradationLevel.LIMITED<\/p>\n<p>        elif status_code &gt;&#061; 400:<br \/>\n            if health.error_rate &gt; 0.3:<br \/>\n                return DegradationLevel.DEGRADED<br \/>\n            else:<br \/>\n                return DegradationLevel.NORMAL<\/p>\n<p>        elif response_time &gt; 5.0:  # 5\u79d2\u8d85\u65f6<br \/>\n            return DegradationLevel.DEGRADED<\/p>\n<p>        elif response_time &gt; 2.0:  # 2\u79d2\u5ef6\u8fdf<br \/>\n            if health.error_rate &gt; 0.1:<br \/>\n                return DegradationLevel.DEGRADED<br \/>\n            else:<br \/>\n                return DegradationLevel.NORMAL<\/p>\n<p>        else:<br \/>\n            return DegradationLevel.NORMAL<\/p>\n<p>    def apply_strategy(self, service_name: str,<br \/>\n                      original_call: Callable,<br \/>\n                      *args, **kwargs) -&gt; Any:<br \/>\n        &#034;&#034;&#034;\u5e94\u7528\u964d\u7ea7\u7b56\u7565\u6267\u884c\u8c03\u7528&#034;&#034;&#034;<br \/>\n        health &#061; self.service_health.get(service_name)<\/p>\n<p>        if not health:<br \/>\n            # \u9996\u6b21\u8c03\u7528&#xff0c;\u6b63\u5e38\u6267\u884c<br \/>\n            return self._execute_with_monitoring(service_name, original_call, *args, **kwargs)<\/p>\n<p>        # \u83b7\u53d6\u964d\u7ea7\u7b56\u7565<br \/>\n        strategy &#061; self.degradation_strategies.get(<br \/>\n            health.degradation_level,<br \/>\n            self._normal_strategy<br \/>\n        )<\/p>\n<p>        return strategy(service_name, original_call, *args, **kwargs)<\/p>\n<p>    def _execute_with_monitoring(self, service_name: str,<br \/>\n                                original_call: Callable,<br \/>\n                                *args, **kwargs) -&gt; Any:<br \/>\n        &#034;&#034;&#034;\u6267\u884c\u8c03\u7528\u5e76\u76d1\u63a7\u7ed3\u679c&#034;&#034;&#034;<br \/>\n        start_time &#061; time.time()<\/p>\n<p>        try:<br \/>\n            result &#061; original_call(*args, **kwargs)<br \/>\n            response_time &#061; time.time() &#8211; start_time<\/p>\n<p>            # \u5047\u8bberesult\u6709status_code\u5c5e\u6027<br \/>\n            status_code &#061; getattr(result, &#039;status_code&#039;, 200)<\/p>\n<p>            # \u8bc4\u4f30\u5065\u5eb7\u72b6\u51b5<br \/>\n            degradation_level &#061; self.assess_health(<br \/>\n                service_name, status_code, response_time<br \/>\n            )<\/p>\n<p>            # \u66f4\u65b0\u964d\u7ea7\u7ea7\u522b<br \/>\n            if service_name in self.service_health:<br \/>\n                self.service_health[service_name].degradation_level &#061; degradation_level<\/p>\n<p>            return result<\/p>\n<p>        except Exception as e:<br \/>\n            response_time &#061; time.time() &#8211; start_time<\/p>\n<p>            # \u6839\u636e\u5f02\u5e38\u7c7b\u578b\u786e\u5b9a\u72b6\u6001\u7801<br \/>\n            status_code &#061; self._exception_to_status_code(e)<\/p>\n<p>            # \u8bc4\u4f30\u5065\u5eb7\u72b6\u51b5<br \/>\n            degradation_level &#061; self.assess_health(<br \/>\n                service_name, status_code, response_time<br \/>\n            )<\/p>\n<p>            # \u66f4\u65b0\u964d\u7ea7\u7ea7\u522b<br \/>\n            if service_name in self.service_health:<br \/>\n                self.service_health[service_name].degradation_level &#061; degradation_level<\/p>\n<p>            raise<\/p>\n<p>    def _exception_to_status_code(self, e: Exception) -&gt; int:<br \/>\n        &#034;&#034;&#034;\u5c06\u5f02\u5e38\u8f6c\u6362\u4e3a\u72b6\u6001\u7801&#034;&#034;&#034;<br \/>\n        if hasattr(e, &#039;status_code&#039;):<br \/>\n            return e.status_code<br \/>\n        elif isinstance(e, TimeoutError):<br \/>\n            return 504<br \/>\n        elif isinstance(e, ConnectionError):<br \/>\n            return 503<br \/>\n        else:<br \/>\n            return 500<\/p>\n<p>    # \u5404\u7ea7\u7b56\u7565\u5b9e\u73b0<br \/>\n    def _normal_strategy(self, service_name: str,<br \/>\n                        original_call: Callable,<br \/>\n                        *args, **kwargs) -&gt; Any:<br \/>\n        &#034;&#034;&#034;\u6b63\u5e38\u7b56\u7565&#xff1a;\u5b8c\u6574\u529f\u80fd&#034;&#034;&#034;<br \/>\n        logger.debug(f&#034;Normal strategy for {service_name}&#034;)<br \/>\n        return original_call(*args, **kwargs)<\/p>\n<p>    def _degraded_strategy(self, service_name: str,<br \/>\n                          original_call: Callable,<br \/>\n                          *args, **kwargs) -&gt; Any:<br \/>\n        &#034;&#034;&#034;\u964d\u7ea7\u7b56\u7565&#xff1a;\u57fa\u672c\u529f\u80fd&#xff0c;\u91cd\u8bd5\u673a\u5236&#034;&#034;&#034;<br \/>\n        logger.warning(f&#034;Degraded strategy for {service_name}&#034;)<\/p>\n<p>        # \u5b9e\u73b0\u91cd\u8bd5\u673a\u5236<br \/>\n        max_retries &#061; 2<br \/>\n        for attempt in range(max_retries &#043; 1):<br \/>\n            try:<br \/>\n                return original_call(*args, **kwargs)<br \/>\n            except Exception as e:<br \/>\n                if attempt &#061;&#061; max_retries:<br \/>\n                    raise<\/p>\n<p>                # \u6307\u6570\u9000\u907f<br \/>\n                delay &#061; 2 ** attempt<br \/>\n                time.sleep(delay)<\/p>\n<p>                logger.info(f&#034;Retry {attempt &#043; 1} for {service_name} after {delay}s&#034;)<\/p>\n<p>    def _limited_strategy(self, service_name: str,<br \/>\n                         original_call: Callable,<br \/>\n                         *args, **kwargs) -&gt; Any:<br \/>\n        &#034;&#034;&#034;\u9650\u5236\u7b56\u7565&#xff1a;\u7b80\u5316\u529f\u80fd&#xff0c;\u4f7f\u7528\u7f13\u5b58&#034;&#034;&#034;<br \/>\n        logger.warning(f&#034;Limited strategy for {service_name}&#034;)<\/p>\n<p>        # \u5c1d\u8bd5\u4f7f\u7528\u7f13\u5b58<br \/>\n        cache_key &#061; f&#034;{service_name}:{str(args)}:{str(kwargs)}&#034;<br \/>\n        cached_result &#061; self._get_from_cache(cache_key)<\/p>\n<p>        if cached_result:<br \/>\n            logger.info(f&#034;Using cached result for {service_name}&#034;)<br \/>\n            return cached_result<\/p>\n<p>        # \u6709\u9650\u91cd\u8bd5<br \/>\n        try:<br \/>\n            result &#061; original_call(*args, **kwargs)<br \/>\n            self._save_to_cache(cache_key, result)<br \/>\n            return result<br \/>\n        except Exception as e:<br \/>\n            # \u8fd4\u56de\u964d\u7ea7\u7ed3\u679c<br \/>\n            return self._get_fallback_result(service_name, *args, **kwargs)<\/p>\n<p>    def _maintenance_strategy(self, service_name: str,<br \/>\n                             original_call: Callable,<br \/>\n                             *args, **kwargs) -&gt; Any:<br \/>\n        &#034;&#034;&#034;\u7ef4\u62a4\u7b56\u7565&#xff1a;\u8fd4\u56de\u7ef4\u62a4\u4fe1\u606f&#xff0c;\u4e0d\u5c1d\u8bd5\u8c03\u7528&#034;&#034;&#034;<br \/>\n        logger.error(f&#034;Maintenance strategy for {service_name}&#034;)<\/p>\n<p>        # \u76f4\u63a5\u8fd4\u56de\u7ef4\u62a4\u4fe1\u606f<br \/>\n        return {<br \/>\n            &#034;status&#034;: &#034;maintenance&#034;,<br \/>\n            &#034;service&#034;: service_name,<br \/>\n            &#034;message&#034;: &#034;Service is under maintenance&#034;,<br \/>\n            &#034;timestamp&#034;: time.time()<br \/>\n        }<\/p>\n<p>    def _failsafe_strategy(self, service_name: str,<br \/>\n                          original_call: Callable,<br \/>\n                          *args, **kwargs) -&gt; Any:<br \/>\n        &#034;&#034;&#034;\u5b89\u5168\u6a21\u5f0f&#xff1a;\u8fd4\u56de\u9ed8\u8ba4\u503c&#xff0c;\u4fdd\u62a4\u7cfb\u7edf&#034;&#034;&#034;<br \/>\n        logger.critical(f&#034;Failsafe strategy for {service_name}&#034;)<\/p>\n<p>        # \u8fd4\u56de\u5b89\u5168\u9ed8\u8ba4\u503c<br \/>\n        return self._get_failsafe_result(service_name, *args, **kwargs)<\/p>\n<p>    def _get_from_cache(self, key: str) -&gt; Optional[Any]:<br \/>\n        &#034;&#034;&#034;\u4ece\u7f13\u5b58\u83b7\u53d6\u7ed3\u679c&#xff08;\u7b80\u5316\u5b9e\u73b0&#xff09;&#034;&#034;&#034;<br \/>\n        # \u5b9e\u9645\u5b9e\u73b0\u5e94\u8be5\u4f7f\u7528Redis\u3001Memcached\u7b49<br \/>\n        return None<\/p>\n<p>    def _save_to_cache(self, key: str, value: Any) -&gt; None:<br \/>\n        &#034;&#034;&#034;\u4fdd\u5b58\u7ed3\u679c\u5230\u7f13\u5b58&#xff08;\u7b80\u5316\u5b9e\u73b0&#xff09;&#034;&#034;&#034;<br \/>\n        pass<\/p>\n<p>    def _get_fallback_result(self, service_name: str,<br \/>\n                            *args, **kwargs) -&gt; Any:<br \/>\n        &#034;&#034;&#034;\u83b7\u53d6\u964d\u7ea7\u7ed3\u679c&#034;&#034;&#034;<br \/>\n        # \u6839\u636e\u670d\u52a1\u7c7b\u578b\u8fd4\u56de\u4e0d\u540c\u7684\u964d\u7ea7\u7ed3\u679c<br \/>\n        if &#034;user&#034; in service_name:<br \/>\n            return {<br \/>\n                &#034;status&#034;: &#034;degraded&#034;,<br \/>\n                &#034;user&#034;: {&#034;id&#034;: &#034;unknown&#034;, &#034;name&#034;: &#034;Guest&#034;},<br \/>\n                &#034;message&#034;: &#034;User service is degraded&#034;<br \/>\n            }<br \/>\n        elif &#034;order&#034; in service_name:<br \/>\n            return {<br \/>\n                &#034;status&#034;: &#034;degraded&#034;,<br \/>\n                &#034;order&#034;: {&#034;status&#034;: &#034;processing&#034;},<br \/>\n                &#034;message&#034;: &#034;Order service is degraded&#034;<br \/>\n            }<br \/>\n        else:<br \/>\n            return {<br \/>\n                &#034;status&#034;: &#034;degraded&#034;,<br \/>\n                &#034;message&#034;: f&#034;Service {service_name} is degraded&#034;<br \/>\n            }<\/p>\n<p>    def _get_failsafe_result(self, service_name: str,<br \/>\n                            *args, **kwargs) -&gt; Any:<br \/>\n        &#034;&#034;&#034;\u83b7\u53d6\u5b89\u5168\u6a21\u5f0f\u7ed3\u679c&#034;&#034;&#034;<br \/>\n        return {<br \/>\n            &#034;status&#034;: &#034;failsafe&#034;,<br \/>\n            &#034;service&#034;: service_name,<br \/>\n            &#034;message&#034;: &#034;Service is in failsafe mode&#034;,<br \/>\n            &#034;timestamp&#034;: time.time()<br \/>\n        }<\/p>\n<p># \u4f7f\u7528\u88c5\u9970\u5668\u5b9e\u73b0<br \/>\ndef degradation_aware(service_name: str):<br \/>\n    &#034;&#034;&#034;\u964d\u7ea7\u611f\u77e5\u88c5\u9970\u5668&#034;&#034;&#034;<br \/>\n    degradation_manager &#061; MultiLevelDegradation()<\/p>\n<p>    def decorator(func):<br \/>\n        &#064;wraps(func)<br \/>\n        def wrapper(*args, **kwargs):<br \/>\n            return degradation_manager.apply_strategy(<br \/>\n                service_name, func, *args, **kwargs<br \/>\n            )<br \/>\n        return wrapper<br \/>\n    return decorator<\/p>\n<p># \u4f7f\u7528\u793a\u4f8b<br \/>\nclass UserService:<br \/>\n    &#064;degradation_aware(&#034;user-service&#034;)<br \/>\n    def get_user_profile(self, user_id: str):<br \/>\n        # \u8c03\u7528\u5b9e\u9645\u7684\u7528\u6237\u670d\u52a1<br \/>\n        response &#061; self._call_user_service(f&#034;\/users\/{user_id}&#034;)<br \/>\n        return response<\/p>\n<p>    def _call_user_service(self, endpoint: str):<br \/>\n        # \u6a21\u62dfHTTP\u8c03\u7528<br \/>\n        # \u5b9e\u9645\u5b9e\u73b0\u5e94\u8be5\u4f7f\u7528HTTP\u5ba2\u6237\u7aef<br \/>\n        pass<\/p>\n<p>class OrderService:<br \/>\n    &#064;degradation_aware(&#034;order-service&#034;)<br \/>\n    def create_order(self, order_data: Dict) -&gt; Dict:<br \/>\n        # \u8c03\u7528\u8ba2\u5355\u670d\u52a1<br \/>\n        response &#061; self._call_order_service(&#034;\/orders&#034;, order_data)<br \/>\n        return response<\/p>\n<p>    &#064;degradation_aware(&#034;inventory-service&#034;)<br \/>\n    def check_inventory(self, product_id: str) -&gt; Dict:<br \/>\n        # \u8c03\u7528\u5e93\u5b58\u670d\u52a1<br \/>\n        response &#061; self._call_inventory_service(f&#034;\/inventory\/{product_id}&#034;)<br \/>\n        return response<\/p>\n<p>    def _call_order_service(self, endpoint: str, data: Dict):<br \/>\n        pass<\/p>\n<p>    def _call_inventory_service(self, endpoint: str):<br \/>\n        pass<\/p>\n<h3>33.8 \u76d1\u63a7\u4e0e\u544a\u8b66<\/h3>\n<h4>33.8.1 Prometheus\u72b6\u6001\u7801\u76d1\u63a7<\/h4>\n<p>yaml<\/p>\n<p># prometheus-status-code-rules.yaml<br \/>\nglobal:<br \/>\n  scrape_interval: 15s<br \/>\n  evaluation_interval: 15s<\/p>\n<p>scrape_configs:<br \/>\n  &#8211; job_name: &#039;api-gateway&#039;<br \/>\n    static_configs:<br \/>\n      &#8211; targets: [&#039;api-gateway:9090&#039;]<br \/>\n    metrics_path: &#039;\/metrics&#039;<\/p>\n<p>  &#8211; job_name: &#039;order-service&#039;<br \/>\n    static_configs:<br \/>\n      &#8211; targets: [&#039;order-service:8080&#039;]<br \/>\n    metrics_path: &#039;\/actuator\/prometheus&#039;<\/p>\n<p>  &#8211; job_name: &#039;user-service&#039;<br \/>\n    static_configs:<br \/>\n      &#8211; targets: [&#039;user-service:8080&#039;]<br \/>\n    metrics_path: &#039;\/actuator\/prometheus&#039;<\/p>\n<p>  &#8211; job_name: &#039;payment-service&#039;<br \/>\n    static_configs:<br \/>\n      &#8211; targets: [&#039;payment-service:8080&#039;]<br \/>\n    metrics_path: &#039;\/metrics&#039;<\/p>\n<p># \u8bb0\u5f55\u89c4\u5219<br \/>\nrule_files:<br \/>\n  &#8211; &#034;status-code-rules.yml&#034;<\/p>\n<p># \u544a\u8b66\u89c4\u5219<br \/>\nalerting:<br \/>\n  alertmanagers:<br \/>\n    &#8211; static_configs:<br \/>\n        &#8211; targets: [&#039;alertmanager:9093&#039;]<\/p>\n<p># \u72b6\u6001\u7801\u89c4\u5219\u6587\u4ef6&#xff08;status-code-rules.yml&#xff09;<br \/>\ngroups:<br \/>\n  &#8211; name: status_code_recording_rules<br \/>\n    interval: 30s<br \/>\n    rules:<br \/>\n      # \u6309\u670d\u52a1\u7edf\u8ba1\u72b6\u6001\u7801<br \/>\n      &#8211; record: http_requests_total:rate5m<br \/>\n        expr: |<br \/>\n          sum(rate(http_requests_total[5m])) by (service, status_code)<\/p>\n<p>      # \u9519\u8bef\u7387<br \/>\n      &#8211; record: http_error_rate:rate5m<br \/>\n        expr: |<br \/>\n          sum(rate(http_requests_total{status_code&#061;~&#034;4..|5..&#034;}[5m])) by (service)<br \/>\n          \/<br \/>\n          sum(rate(http_requests_total[5m])) by (service)<\/p>\n<p>      # 5xx\u9519\u8bef\u7387<br \/>\n      &#8211; record: http_5xx_error_rate:rate5m<br \/>\n        expr: |<br \/>\n          sum(rate(http_requests_total{status_code&#061;~&#034;5..&#034;}[5m])) by (service)<br \/>\n          \/<br \/>\n          sum(rate(http_requests_total[5m])) by (service)<\/p>\n<p>      # 4xx\u9519\u8bef\u7387<br \/>\n      &#8211; record: http_4xx_error_rate:rate5m<br \/>\n        expr: |<br \/>\n          sum(rate(http_requests_total{status_code&#061;~&#034;4..&#034;}[5m])) by (service)<br \/>\n          \/<br \/>\n          sum(rate(http_requests_total[5m])) by (service)<\/p>\n<p>      # \u6309\u72b6\u6001\u7801\u5206\u7c7b\u7684\u54cd\u5e94\u65f6\u95f4\u767e\u5206\u4f4d<br \/>\n      &#8211; record: http_response_time_percentile:status<br \/>\n        expr: |<br \/>\n          histogram_quantile(0.95,<br \/>\n            sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service, status_code)<br \/>\n          )<\/p>\n<p>      # \u670d\u52a1\u4f9d\u8d56\u5065\u5eb7\u5ea6<br \/>\n      &#8211; record: service_dependency_health<br \/>\n        expr: |<br \/>\n          (<br \/>\n            sum(rate(http_requests_total{status_code&#061;~&#034;2..&#034;}[5m])) by (caller, target)<br \/>\n            \/<br \/>\n            sum(rate(http_requests_total[5m])) by (caller, target)<br \/>\n          ) * 100<\/p>\n<p>      # \u9519\u8bef\u4f20\u64ad\u94fe<br \/>\n      &#8211; record: error_propagation_chain<br \/>\n        expr: |<br \/>\n          count by (error_chain) (<br \/>\n            http_requests_total{status_code&#061;~&#034;4..|5..&#034;}<br \/>\n          )<\/p>\n<p>  &#8211; name: status_code_alerts<br \/>\n    rules:<br \/>\n      # \u5168\u5c40\u9519\u8bef\u7387\u544a\u8b66<br \/>\n      &#8211; alert: GlobalHighErrorRate<br \/>\n        expr: |<br \/>\n          sum(rate(http_requests_total{status_code&#061;~&#034;4..|5..&#034;}[5m]))<br \/>\n          \/<br \/>\n          sum(rate(http_requests_total[5m]))<br \/>\n          &gt; 0.05<br \/>\n        for: 5m<br \/>\n        labels:<br \/>\n          severity: critical<br \/>\n          team: platform<br \/>\n        annotations:<br \/>\n          summary: &#034;Global error rate is high&#034;<br \/>\n          description: &#034;Global error rate is {{ $value | humanizePercentage }}&#034;<\/p>\n<p>      # \u670d\u52a1\u7ea7\u9519\u8bef\u7387\u544a\u8b66<br \/>\n      &#8211; alert: ServiceHighErrorRate<br \/>\n        expr: |<br \/>\n          http_error_rate:rate5m &gt; 0.10<br \/>\n        for: 5m<br \/>\n        labels:<br \/>\n          severity: warning<br \/>\n        annotations:<br \/>\n          summary: &#034;High error rate for service {{ $labels.service }}&#034;<br \/>\n          description: &#034;Error rate is {{ $value | humanizePercentage }} for service {{ $labels.service }}&#034;<\/p>\n<p>      # 5xx\u9519\u8bef\u7387\u544a\u8b66<br \/>\n      &#8211; alert: ServiceHigh5xxErrorRate<br \/>\n        expr: |<br \/>\n          http_5xx_error_rate:rate5m &gt; 0.05<br \/>\n        for: 3m<br \/>\n        labels:<br \/>\n          severity: critical<br \/>\n        annotations:<br \/>\n          summary: &#034;High 5xx error rate for service {{ $labels.service }}&#034;<br \/>\n          description: &#034;5xx error rate is {{ $value | humanizePercentage }} for service {{ $labels.service }}&#034;<\/p>\n<p>      # \u670d\u52a1\u5b8c\u5168\u4e0d\u53ef\u7528<br \/>\n      &#8211; alert: ServiceCompletelyUnavailable<br \/>\n        expr: |<br \/>\n          up{job&#061;~&#034;.*&#034;} &#061;&#061; 0<br \/>\n        for: 2m<br \/>\n        labels:<br \/>\n          severity: critical<br \/>\n        annotations:<br \/>\n          summary: &#034;Service {{ $labels.job }} is completely unavailable&#034;<br \/>\n          description: &#034;Service {{ $labels.job }} has been down for more than 2 minutes&#034;<\/p>\n<p>      # \u9519\u8bef\u4f20\u64ad\u94fe\u68c0\u6d4b<br \/>\n      &#8211; alert: ErrorPropagationDetected<br \/>\n        expr: |<br \/>\n          increase(error_propagation_chain[5m]) &gt; 10<br \/>\n        for: 2m<br \/>\n        labels:<br \/>\n          severity: warning<br \/>\n        annotations:<br \/>\n          summary: &#034;Error propagation detected in the system&#034;<br \/>\n          description: &#034;Error chain {{ $labels.error_chain }} has propagated {{ $value }} times in the last 5 minutes&#034;<\/p>\n<p>      # \u6162\u54cd\u5e94\u544a\u8b66<br \/>\n      &#8211; alert: SlowServiceResponses<br \/>\n        expr: |<br \/>\n          http_response_time_percentile:status &gt; 2<br \/>\n        for: 5m<br \/>\n        labels:<br \/>\n          severity: warning<br \/>\n        annotations:<br \/>\n          summary: &#034;Slow responses for service {{ $labels.service }}&#034;<br \/>\n          description: &#034;95th percentile response time is {{ $value }}s for status code {{ $labels.status_code }} in service {{ $labels.service }}&#034;<\/p>\n<p>      # \u4f9d\u8d56\u670d\u52a1\u5065\u5eb7\u5ea6\u4e0b\u964d<br \/>\n      &#8211; alert: ServiceDependencyDegraded<br \/>\n        expr: |<br \/>\n          service_dependency_health &lt; 95<br \/>\n        for: 10m<br \/>\n        labels:<br \/>\n          severity: warning<br \/>\n        annotations:<br \/>\n          summary: &#034;Service dependency health is degraded&#034;<br \/>\n          description: &#034;Dependency from {{ $labels.caller }} to {{ $labels.target }} has health of {{ $value }}%&#034;<\/p>\n<h3>33.9 \u603b\u7ed3<\/h3>\n<h4>33.9.1 \u5fae\u670d\u52a1\u72b6\u6001\u7801\u4f20\u64ad\u6700\u4f73\u5b9e\u8df5<\/h4>\n<li>\n<p>\u900f\u660e\u4f20\u64ad\u4e0e\u5c01\u88c5\u5e73\u8861<\/p>\n<ul>\n<li>\n<p>\u5185\u90e8\u9519\u8bef\u7ec6\u8282\u4e0d\u5e94\u8be5\u76f4\u63a5\u66b4\u9732\u7ed9\u5ba2\u6237\u7aef<\/p>\n<\/li>\n<li>\n<p>\u4f46\u9700\u8981\u8db3\u591f\u7684\u4e0a\u4e0b\u6587\u8fdb\u884c\u6545\u969c\u8bca\u65ad<\/p>\n<\/li>\n<li>\n<p>\u4f7f\u7528\u6807\u51c6\u5316\u7684\u9519\u8bef\u683c\u5f0f&#xff08;\u5982RFC 7807&#xff09;<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u5206\u5e03\u5f0f\u8ffd\u8e2a\u96c6\u6210<\/p>\n<ul>\n<li>\n<p>\u6240\u6709\u670d\u52a1\u8c03\u7528\u90fd\u5e94\u8be5\u6709\u552f\u4e00\u7684\u8ffd\u8e2aID<\/p>\n<\/li>\n<li>\n<p>\u72b6\u6001\u7801\u5e94\u8be5\u4f5c\u4e3aspan\u6807\u7b7e\u8bb0\u5f55<\/p>\n<\/li>\n<li>\n<p>\u9519\u8bef\u4f20\u64ad\u94fe\u5e94\u8be5\u5728\u8ffd\u8e2a\u4e2d\u53ef\u89c6\u5316<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u667a\u80fd\u65ad\u8def\u5668\u7b56\u7565<\/p>\n<ul>\n<li>\n<p>\u57fa\u4e8e\u72b6\u6001\u7801\u7684\u5931\u8d25\u68c0\u6d4b<\/p>\n<\/li>\n<li>\n<p>\u4e0d\u540c\u72b6\u6001\u7801\u5e94\u8be5\u6709\u4e0d\u540c\u7684\u91cd\u8bd5\u7b56\u7565<\/p>\n<\/li>\n<li>\n<p>\u65ad\u8def\u5668\u72b6\u6001\u5e94\u8be5\u88ab\u76d1\u63a7\u548c\u544a\u8b66<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u591a\u7ea7\u964d\u7ea7\u7b56\u7565<\/p>\n<ul>\n<li>\n<p>\u6839\u636e\u9519\u8bef\u7c7b\u578b\u548c\u9891\u7387\u5b9e\u65bd\u4e0d\u540c\u7ea7\u522b\u7684\u964d\u7ea7<\/p>\n<\/li>\n<li>\n<p>\u964d\u7ea7\u7b56\u7565\u5e94\u8be5\u662f\u53ef\u914d\u7f6e\u7684<\/p>\n<\/li>\n<li>\n<p>\u964d\u7ea7\u72b6\u6001\u5e94\u8be5\u88ab\u76d1\u63a7\u548c\u62a5\u544a<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u7edf\u4e00\u7684\u76d1\u63a7\u544a\u8b66<\/p>\n<ul>\n<li>\n<p>\u6240\u6709\u670d\u52a1\u5e94\u8be5\u66b4\u9732\u6807\u51c6\u5316\u7684\u6307\u6807<\/p>\n<\/li>\n<li>\n<p>\u72b6\u6001\u7801\u5206\u5e03\u5e94\u8be5\u88ab\u5b9e\u65f6\u76d1\u63a7<\/p>\n<\/li>\n<li>\n<p>\u57fa\u4e8e\u72b6\u6001\u7801\u7684\u544a\u8b66\u5e94\u8be5\u53ca\u65f6\u51c6\u786e<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<h4>33.9.2 \u67b6\u6784\u6a21\u5f0f\u603b\u7ed3<img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1760\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260130145703-697cc6bf0b49d.png\" width=\"670\" \/><\/h4>\n<p>\u901a\u8fc7\u672c\u7ae0\u7684\u5b66\u4e60&#xff0c;\u6211\u4eec\u6df1\u5165\u4e86\u89e3\u4e86\u5fae\u670d\u52a1\u67b6\u6784\u4e2d\u72b6\u6001\u7801\u4f20\u64ad\u7684\u590d\u6742\u6027\u548c\u91cd\u8981\u6027\u3002\u5728\u5206\u5e03\u5f0f\u7cfb\u7edf\u4e2d&#xff0c;\u72b6\u6001\u7801\u4e0d\u4ec5\u4ec5\u662f\u5355\u4e2a\u670d\u52a1\u7684\u54cd\u5e94&#xff0c;\u800c\u662f\u6574\u4e2a\u8c03\u7528\u94fe\u5065\u5eb7\u72b6\u51b5\u7684\u4f53\u73b0\u3002\u5408\u7406\u7684\u72b6\u6001\u7801\u4f20\u64ad\u7b56\u7565\u3001\u667a\u80fd\u7684\u65ad\u8def\u5668\u6a21\u5f0f\u3001\u5b8c\u5584\u7684\u76d1\u63a7\u544a\u8b66\u7cfb\u7edf&#xff0c;\u90fd\u662f\u6784\u5efa\u53ef\u9760\u5fae\u670d\u52a1\u67b6\u6784\u7684\u5173\u952e\u7ec4\u6210\u90e8\u5206\u3002<\/p>\n<hr \/>\n<p>\u7b2c33\u7ae0\u8981\u70b9\u603b\u7ed3&#xff1a;<\/p>\n<li>\n<p>\u5fae\u670d\u52a1\u72b6\u6001\u7801\u4f20\u64ad\u9700\u8981\u8003\u8651\u8c03\u7528\u94fe\u4e0a\u4e0b\u6587<\/p>\n<\/li>\n<li>\n<p>\u5206\u5e03\u5f0f\u8ffd\u8e2a\u662f\u7406\u89e3\u9519\u8bef\u4f20\u64ad\u7684\u5173\u952e\u5de5\u5177<\/p>\n<\/li>\n<li>\n<p>\u65ad\u8def\u5668\u5e94\u8be5\u57fa\u4e8e\u72b6\u6001\u7801\u667a\u80fd\u51b3\u7b56<\/p>\n<\/li>\n<li>\n<p>API\u7f51\u5173\u5728\u72b6\u6001\u7801\u8f6c\u6362\u4e2d\u8d77\u91cd\u8981\u4f5c\u7528<\/p>\n<\/li>\n<li>\n<p>\u591a\u7ea7\u964d\u7ea7\u7b56\u7565\u53ef\u4ee5\u63d0\u9ad8\u7cfb\u7edf\u97e7\u6027<\/p>\n<\/li>\n<li>\n<p>\u7edf\u4e00\u7684\u76d1\u63a7\u544a\u8b66\u4f53\u7cfb\u662f\u8fd0\u7ef4\u7684\u57fa\u7840<\/p>\n<\/li>\n<h2>\u7b2c34\u7ae0&#xff1a;\u72b6\u6001\u7801\u4e0e\u9519\u8bef\u5904\u7406\u7b56\u7565<\/h2>\n<h3>34.1 \u9519\u8bef\u5904\u7406\u54f2\u5b66\u4e0e\u539f\u5219<\/h3>\n<h4>34.1.1 \u9519\u8bef\u5904\u7406\u7684\u4e09\u79cd\u8303\u5f0f<\/h4>\n<p>\u5728\u8f6f\u4ef6\u5de5\u7a0b\u4e2d&#xff0c;\u9519\u8bef\u5904\u7406\u6709\u4e09\u79cd\u4e3b\u8981\u8303\u5f0f&#xff0c;\u6bcf\u79cd\u8303\u5f0f\u5bf9\u72b6\u6001\u7801\u7684\u4f7f\u7528\u6709\u7740\u4e0d\u540c\u7684\u7406\u89e3&#xff1a;<\/p>\n<p>python<\/p>\n<p># \u9519\u8bef\u5904\u7406\u7684\u4e09\u79cd\u8303\u5f0f\u793a\u4f8b<br \/>\nfrom typing import Union, Optional<br \/>\nfrom dataclasses import dataclass<\/p>\n<p># 1. \u8fd4\u56de\u7801\u8303\u5f0f&#xff08;C\u8bed\u8a00\u98ce\u683c&#xff09;<br \/>\nclass ReturnCodeParadigm:<br \/>\n    &#034;&#034;&#034;\u901a\u8fc7\u8fd4\u56de\u503c\u8868\u793a\u6210\u529f\u6216\u5931\u8d25&#034;&#034;&#034;<br \/>\n    def divide(self, a: float, b: float) -&gt; Union[float, int]:<br \/>\n        &#034;&#034;&#034;\u8fd4\u56de\u9519\u8bef\u7801\u800c\u4e0d\u662f\u629b\u51fa\u5f02\u5e38&#034;&#034;&#034;<br \/>\n        if b &#061;&#061; 0:<br \/>\n            return -1  # \u9519\u8bef\u7801<br \/>\n        return a \/ b<\/p>\n<p>    def process(self):<br \/>\n        result &#061; self.divide(10, 0)<br \/>\n        if result &#061;&#061; -1:<br \/>\n            print(&#034;Division by zero error&#034;)<br \/>\n        else:<br \/>\n            print(f&#034;Result: {result}&#034;)<\/p>\n<p># 2. \u5f02\u5e38\u8303\u5f0f&#xff08;Java\/Python\u98ce\u683c&#xff09;<br \/>\nclass ExceptionParadigm:<br \/>\n    &#034;&#034;&#034;\u901a\u8fc7\u629b\u51fa\u5f02\u5e38\u8868\u793a\u9519\u8bef&#034;&#034;&#034;<br \/>\n    class DivisionByZeroError(Exception):<br \/>\n        pass<\/p>\n<p>    def divide(self, a: float, b: float) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u629b\u51fa\u5f02\u5e38\u800c\u4e0d\u662f\u8fd4\u56de\u9519\u8bef\u7801&#034;&#034;&#034;<br \/>\n        if b &#061;&#061; 0:<br \/>\n            raise self.DivisionByZeroError(&#034;Cannot divide by zero&#034;)<br \/>\n        return a \/ b<\/p>\n<p>    def process(self):<br \/>\n        try:<br \/>\n            result &#061; self.divide(10, 0)<br \/>\n            print(f&#034;Result: {result}&#034;)<br \/>\n        except self.DivisionByZeroError as e:<br \/>\n            print(f&#034;Error: {e}&#034;)<\/p>\n<p># 3. \u7ed3\u679c\u7c7b\u578b\u8303\u5f0f&#xff08;\u51fd\u6570\u5f0f\u98ce\u683c&#xff09;<br \/>\n&#064;dataclass<br \/>\nclass Result[T, E]:<br \/>\n    &#034;&#034;&#034;\u5305\u542b\u6210\u529f\u503c\u6216\u9519\u8bef\u503c\u7684\u5bb9\u5668\u7c7b\u578b&#034;&#034;&#034;<br \/>\n    value: Optional[T] &#061; None<br \/>\n    error: Optional[E] &#061; None<br \/>\n    is_success: bool &#061; True<\/p>\n<p>    &#064;classmethod<br \/>\n    def success(cls, value: T) -&gt; &#039;Result[T, E]&#039;:<br \/>\n        return cls(value&#061;value, is_success&#061;True)<\/p>\n<p>    &#064;classmethod<br \/>\n    def failure(cls, error: E) -&gt; &#039;Result[T, E]&#039;:<br \/>\n        return cls(error&#061;error, is_success&#061;False)<\/p>\n<p>    def unwrap(self) -&gt; T:<br \/>\n        if not self.is_success:<br \/>\n            raise ValueError(f&#034;Result contains error: {self.error}&#034;)<br \/>\n        return self.value<\/p>\n<p>class ResultParadigm:<br \/>\n    &#034;&#034;&#034;\u4f7f\u7528Result\u7c7b\u578b\u5305\u88c5\u53ef\u80fd\u5931\u8d25\u7684\u64cd\u4f5c&#034;&#034;&#034;<br \/>\n    def divide(self, a: float, b: float) -&gt; Result[float, str]:<br \/>\n        &#034;&#034;&#034;\u8fd4\u56de\u5305\u542b\u7ed3\u679c\u6216\u9519\u8bef\u7684Result\u5bf9\u8c61&#034;&#034;&#034;<br \/>\n        if b &#061;&#061; 0:<br \/>\n            return Result.failure(&#034;Division by zero&#034;)<br \/>\n        return Result.success(a \/ b)<\/p>\n<p>    def process(self):<br \/>\n        result &#061; self.divide(10, 0)<br \/>\n        if result.is_success:<br \/>\n            print(f&#034;Result: {result.unwrap()}&#034;)<br \/>\n        else:<br \/>\n            print(f&#034;Error: {result.error}&#034;)<\/p>\n<h4>34.1.2 \u9519\u8bef\u5904\u7406\u6838\u5fc3\u539f\u5219<\/h4>\n<p>java<\/p>\n<p>\/\/ \u9519\u8bef\u5904\u7406\u7684\u6838\u5fc3\u539f\u5219\u5b9e\u73b0<br \/>\npublic class ErrorHandlingPrinciples {<\/p>\n<p>    \/\/ \u539f\u52191: \u5feb\u901f\u5931\u8d25&#xff08;Fail Fast&#xff09;<br \/>\n    public static class FailFastPrinciple {<br \/>\n        public User validateAndCreate(String email, String password) {<br \/>\n            \/\/ \u5c3d\u65e9\u9a8c\u8bc1&#xff0c;\u5c3d\u65e9\u5931\u8d25<br \/>\n            if (email &#061;&#061; null || email.isEmpty()) {<br \/>\n                throw new ValidationException(&#034;Email is required&#034;);<br \/>\n            }<\/p>\n<p>            if (!isValidEmail(email)) {<br \/>\n                throw new ValidationException(&#034;Invalid email format&#034;);<br \/>\n            }<\/p>\n<p>            if (password &#061;&#061; null || password.length() &lt; 8) {<br \/>\n                throw new ValidationException(&#034;Password must be at least 8 characters&#034;);<br \/>\n            }<\/p>\n<p>            \/\/ \u6240\u6709\u9a8c\u8bc1\u901a\u8fc7\u540e\u624d\u6267\u884c\u4e1a\u52a1\u903b\u8f91<br \/>\n            return new User(email, password);<br \/>\n        }<br \/>\n    }<\/p>\n<p>    \/\/ \u539f\u52192: \u660e\u786e\u9519\u8bef\u7c7b\u578b&#xff08;Be Specific&#xff09;<br \/>\n    public static class SpecificErrorPrinciple {<br \/>\n        public enum ErrorType {<br \/>\n            USER_NOT_FOUND,<br \/>\n            INSUFFICIENT_PERMISSIONS,<br \/>\n            INVALID_INPUT,<br \/>\n            NETWORK_ERROR,<br \/>\n            DATABASE_ERROR<br \/>\n        }<\/p>\n<p>        &#064;Data<br \/>\n        public static class SpecificError {<br \/>\n            private final ErrorType type;<br \/>\n            private final String message;<br \/>\n            private final Map&lt;String, Object&gt; context;<br \/>\n            private final Instant timestamp;<\/p>\n<p>            public SpecificError(ErrorType type, String message,<br \/>\n                               Map&lt;String, Object&gt; context) {<br \/>\n                this.type &#061; type;<br \/>\n                this.message &#061; message;<br \/>\n                this.context &#061; context;<br \/>\n                this.timestamp &#061; Instant.now();<br \/>\n            }<\/p>\n<p>            public HttpStatus toHttpStatus() {<br \/>\n                switch (type) {<br \/>\n                    case USER_NOT_FOUND:<br \/>\n                        return HttpStatus.NOT_FOUND;<br \/>\n                    case INSUFFICIENT_PERMISSIONS:<br \/>\n                        return HttpStatus.FORBIDDEN;<br \/>\n                    case INVALID_INPUT:<br \/>\n                        return HttpStatus.BAD_REQUEST;<br \/>\n                    case NETWORK_ERROR:<br \/>\n                    case DATABASE_ERROR:<br \/>\n                        return HttpStatus.INTERNAL_SERVER_ERROR;<br \/>\n                    default:<br \/>\n                        return HttpStatus.INTERNAL_SERVER_ERROR;<br \/>\n                }<br \/>\n            }<br \/>\n        }<br \/>\n    }<\/p>\n<p>    \/\/ \u539f\u52193: \u53ef\u6062\u590d\u6027\u8bbe\u8ba1&#xff08;Design for Recovery&#xff09;<br \/>\n    public static class RecoveryDesignPrinciple {<br \/>\n        private final RetryTemplate retryTemplate;<br \/>\n        private final CircuitBreaker circuitBreaker;<\/p>\n<p>        public RecoveryDesignPrinciple() {<br \/>\n            this.retryTemplate &#061; new RetryTemplate();<br \/>\n            this.circuitBreaker &#061; new CircuitBreaker();<br \/>\n        }<\/p>\n<p>        public Result&lt;Order&gt; placeOrderWithRecovery(OrderRequest request) {<br \/>\n            return circuitBreaker.executeSupplier(() -&gt; {<br \/>\n                return retryTemplate.execute(context -&gt; {<br \/>\n                    try {<br \/>\n                        return Result.success(placeOrder(request));<br \/>\n                    } catch (TemporaryFailureException e) {<br \/>\n                        \/\/ \u8bb0\u5f55\u91cd\u8bd5<br \/>\n                        context.setAttribute(&#034;retry_count&#034;,<br \/>\n                            context.getRetryCount() &#043; 1);<br \/>\n                        throw e;<br \/>\n                    }<br \/>\n                });<br \/>\n            });<br \/>\n        }<\/p>\n<p>        private Order placeOrder(OrderRequest request) {<br \/>\n            \/\/ \u6a21\u62df\u53ef\u80fd\u5931\u8d25\u7684\u64cd\u4f5c<br \/>\n            return new Order();<br \/>\n        }<br \/>\n    }<\/p>\n<p>    \/\/ \u539f\u52194: \u9519\u8bef\u9694\u79bb&#xff08;Error Isolation&#xff09;<br \/>\n    public static class ErrorIsolationPrinciple {<br \/>\n        private final ExecutorService isolatedExecutor;<\/p>\n<p>        public ErrorIsolationPrinciple() {<br \/>\n            \/\/ \u521b\u5efa\u72ec\u7acb\u7684\u7ebf\u7a0b\u6c60\u6765\u9694\u79bb\u53ef\u80fd\u5931\u8d25\u7684\u64cd\u4f5c<br \/>\n            this.isolatedExecutor &#061; Executors.newFixedThreadPool(3,<br \/>\n                new ThreadFactoryBuilder()<br \/>\n                    .setNameFormat(&#034;isolated-task-%d&#034;)<br \/>\n                    .setUncaughtExceptionHandler((t, e) -&gt; {<br \/>\n                        \/\/ \u9694\u79bb\u7684\u5f02\u5e38\u5904\u7406&#xff0c;\u4e0d\u4f1a\u5f71\u54cd\u4e3b\u7ebf\u7a0b<br \/>\n                        logIsolatedError(t.getName(), e);<br \/>\n                    })<br \/>\n                    .build());<br \/>\n        }<\/p>\n<p>        public CompletableFuture&lt;Void&gt; executeIsolated(Runnable task) {<br \/>\n            return CompletableFuture.runAsync(task, isolatedExecutor)<br \/>\n                .exceptionally(throwable -&gt; {<br \/>\n                    \/\/ \u5904\u7406\u5f02\u5e38&#xff0c;\u4f46\u4e0d\u4f1a\u4f20\u64ad\u5230\u8c03\u7528\u8005<br \/>\n                    logIsolatedError(&#034;isolated-task&#034;, throwable);<br \/>\n                    return null;<br \/>\n                });<br \/>\n        }<\/p>\n<p>        private void logIsolatedError(String taskName, Throwable throwable) {<br \/>\n            System.err.printf(&#034;Isolated error in %s: %s%n&#034;,<br \/>\n                taskName, throwable.getMessage());<br \/>\n        }<br \/>\n    }<\/p>\n<p>    \/\/ \u539f\u52195: \u4f18\u96c5\u964d\u7ea7&#xff08;Graceful Degradation&#xff09;<br \/>\n    public static class GracefulDegradationPrinciple {<br \/>\n        private final CacheService cacheService;<br \/>\n        private final FallbackService fallbackService;<\/p>\n<p>        public GracefulDegradationPrinciple() {<br \/>\n            this.cacheService &#061; new CacheService();<br \/>\n            this.fallbackService &#061; new FallbackService();<br \/>\n        }<\/p>\n<p>        public Product getProduct(String productId) {<br \/>\n            try {<br \/>\n                \/\/ 1. \u9996\u5148\u5c1d\u8bd5\u4e3b\u670d\u52a1<br \/>\n                return productService.getProduct(productId);<br \/>\n            } catch (ServiceUnavailableException e) {<br \/>\n                \/\/ 2. \u4e3b\u670d\u52a1\u5931\u8d25&#xff0c;\u5c1d\u8bd5\u7f13\u5b58<br \/>\n                Product cached &#061; cacheService.getProduct(productId);<br \/>\n                if (cached !&#061; null) {<br \/>\n                    return cached;<br \/>\n                }<\/p>\n<p>                \/\/ 3. \u7f13\u5b58\u4e5f\u6ca1\u6709&#xff0c;\u4f7f\u7528\u964d\u7ea7\u670d\u52a1<br \/>\n                return fallbackService.getBasicProductInfo(productId);<br \/>\n            }<br \/>\n        }<br \/>\n    }<br \/>\n}<\/p>\n<h3>34.2 \u72b6\u6001\u7801\u9a71\u52a8\u7684\u9519\u8bef\u5206\u7c7b<\/h3>\n<h4>34.2.1 \u9519\u8bef\u5206\u7c7b\u4f53\u7cfb<\/h4>\n<p>typescript<\/p>\n<p>\/\/ \u57fa\u4e8e\u72b6\u6001\u7801\u7684\u9519\u8bef\u5206\u7c7b\u4f53\u7cfb<br \/>\ntype ErrorCategory &#061;<br \/>\n  | &#039;CLIENT_ERROR&#039;      \/\/ 4xx \u9519\u8bef<br \/>\n  | &#039;SERVER_ERROR&#039;      \/\/ 5xx \u9519\u8bef<br \/>\n  | &#039;NETWORK_ERROR&#039;     \/\/ \u7f51\u7edc\u76f8\u5173\u9519\u8bef<br \/>\n  | &#039;VALIDATION_ERROR&#039;  \/\/ \u9a8c\u8bc1\u9519\u8bef<br \/>\n  | &#039;BUSINESS_ERROR&#039;    \/\/ \u4e1a\u52a1\u903b\u8f91\u9519\u8bef<br \/>\n  | &#039;SECURITY_ERROR&#039;    \/\/ \u5b89\u5168\u76f8\u5173\u9519\u8bef<br \/>\n  | &#039;INTEGRATION_ERROR&#039; \/\/ \u96c6\u6210\u9519\u8bef<br \/>\n  | &#039;TIMEOUT_ERROR&#039;;    \/\/ \u8d85\u65f6\u9519\u8bef<\/p>\n<p>interface ErrorClassification {<br \/>\n  category: ErrorCategory;<br \/>\n  severity: &#039;LOW&#039; | &#039;MEDIUM&#039; | &#039;HIGH&#039; | &#039;CRITICAL&#039;;<br \/>\n  retryable: boolean;<br \/>\n  userFacing: boolean;<br \/>\n  logLevel: &#039;DEBUG&#039; | &#039;INFO&#039; | &#039;WARN&#039; | &#039;ERROR&#039; | &#039;FATAL&#039;;<br \/>\n  suggestedAction: string;<br \/>\n}<\/p>\n<p>class StatusCodeClassifier {<br \/>\n  private static readonly CLASSIFICATION_MAP: Map&lt;number, ErrorClassification&gt; &#061; new Map([<br \/>\n    \/\/ 4xx \u9519\u8bef\u5206\u7c7b<br \/>\n    [400, {<br \/>\n      category: &#039;CLIENT_ERROR&#039;,<br \/>\n      severity: &#039;MEDIUM&#039;,<br \/>\n      retryable: false,<br \/>\n      userFacing: true,<br \/>\n      logLevel: &#039;WARN&#039;,<br \/>\n      suggestedAction: &#039;Fix request parameters and retry&#039;<br \/>\n    }],<br \/>\n    [401, {<br \/>\n      category: &#039;SECURITY_ERROR&#039;,<br \/>\n      severity: &#039;MEDIUM&#039;,<br \/>\n      retryable: true,<br \/>\n      userFacing: true,<br \/>\n      logLevel: &#039;WARN&#039;,<br \/>\n      suggestedAction: &#039;Authenticate and retry with valid credentials&#039;<br \/>\n    }],<br \/>\n    [403, {<br \/>\n      category: &#039;SECURITY_ERROR&#039;,<br \/>\n      severity: &#039;MEDIUM&#039;,<br \/>\n      retryable: false,<br \/>\n      userFacing: true,<br \/>\n      logLevel: &#039;WARN&#039;,<br \/>\n      suggestedAction: &#039;Request appropriate permissions&#039;<br \/>\n    }],<br \/>\n    [404, {<br \/>\n      category: &#039;CLIENT_ERROR&#039;,<br \/>\n      severity: &#039;LOW&#039;,<br \/>\n      retryable: false,<br \/>\n      userFacing: true,<br \/>\n      logLevel: &#039;DEBUG&#039;,<br \/>\n      suggestedAction: &#039;Check resource identifier and retry&#039;<br \/>\n    }],<br \/>\n    [409, {<br \/>\n      category: &#039;BUSINESS_ERROR&#039;,<br \/>\n      severity: &#039;MEDIUM&#039;,<br \/>\n      retryable: true,<br \/>\n      userFacing: true,<br \/>\n      logLevel: &#039;WARN&#039;,<br \/>\n      suggestedAction: &#039;Resolve conflict and retry&#039;<br \/>\n    }],<br \/>\n    [422, {<br \/>\n      category: &#039;VALIDATION_ERROR&#039;,<br \/>\n      severity: &#039;MEDIUM&#039;,<br \/>\n      retryable: false,<br \/>\n      userFacing: true,<br \/>\n      logLevel: &#039;WARN&#039;,<br \/>\n      suggestedAction: &#039;Fix validation errors and retry&#039;<br \/>\n    }],<br \/>\n    [429, {<br \/>\n      category: &#039;CLIENT_ERROR&#039;,<br \/>\n      severity: &#039;MEDIUM&#039;,<br \/>\n      retryable: true,<br \/>\n      userFacing: true,<br \/>\n      logLevel: &#039;WARN&#039;,<br \/>\n      suggestedAction: &#039;Wait and retry after rate limit resets&#039;<br \/>\n    }],<\/p>\n<p>    \/\/ 5xx \u9519\u8bef\u5206\u7c7b<br \/>\n    [500, {<br \/>\n      category: &#039;SERVER_ERROR&#039;,<br \/>\n      severity: &#039;HIGH&#039;,<br \/>\n      retryable: true,<br \/>\n      userFacing: false,<br \/>\n      logLevel: &#039;ERROR&#039;,<br \/>\n      suggestedAction: &#039;Retry after some time or contact support&#039;<br \/>\n    }],<br \/>\n    [502, {<br \/>\n      category: &#039;INTEGRATION_ERROR&#039;,<br \/>\n      severity: &#039;HIGH&#039;,<br \/>\n      retryable: true,<br \/>\n      userFacing: false,<br \/>\n      logLevel: &#039;ERROR&#039;,<br \/>\n      suggestedAction: &#039;Retry after upstream service recovers&#039;<br \/>\n    }],<br \/>\n    [503, {<br \/>\n      category: &#039;SERVER_ERROR&#039;,<br \/>\n      severity: &#039;HIGH&#039;,<br \/>\n      retryable: true,<br \/>\n      userFacing: true,<br \/>\n      logLevel: &#039;ERROR&#039;,<br \/>\n      suggestedAction: &#039;Retry after service maintenance completes&#039;<br \/>\n    }],<br \/>\n    [504, {<br \/>\n      category: &#039;TIMEOUT_ERROR&#039;,<br \/>\n      severity: &#039;MEDIUM&#039;,<br \/>\n      retryable: true,<br \/>\n      userFacing: false,<br \/>\n      logLevel: &#039;WARN&#039;,<br \/>\n      suggestedAction: &#039;Retry with longer timeout or check network&#039;<br \/>\n    }]<br \/>\n  ]);<\/p>\n<p>  static classify(statusCode: number): ErrorClassification {<br \/>\n    const classification &#061; this.CLASSIFICATION_MAP.get(statusCode);<\/p>\n<p>    if (!classification) {<br \/>\n      \/\/ \u9ed8\u8ba4\u5206\u7c7b<br \/>\n      if (statusCode &gt;&#061; 400 &amp;&amp; statusCode &lt; 500) {<br \/>\n        return {<br \/>\n          category: &#039;CLIENT_ERROR&#039;,<br \/>\n          severity: &#039;MEDIUM&#039;,<br \/>\n          retryable: false,<br \/>\n          userFacing: true,<br \/>\n          logLevel: &#039;WARN&#039;,<br \/>\n          suggestedAction: &#039;Review request and retry&#039;<br \/>\n        };<br \/>\n      } else if (statusCode &gt;&#061; 500) {<br \/>\n        return {<br \/>\n          category: &#039;SERVER_ERROR&#039;,<br \/>\n          severity: &#039;HIGH&#039;,<br \/>\n          retryable: true,<br \/>\n          userFacing: false,<br \/>\n          logLevel: &#039;ERROR&#039;,<br \/>\n          suggestedAction: &#039;Retry after some time&#039;<br \/>\n        };<br \/>\n      }<\/p>\n<p>      throw new Error(&#096;Unsupported status code: ${statusCode}&#096;);<br \/>\n    }<\/p>\n<p>    return classification;<br \/>\n  }<\/p>\n<p>  static getErrorResponse(statusCode: number, errorDetails?: any): ErrorResponse {<br \/>\n    const classification &#061; this.classify(statusCode);<\/p>\n<p>    return {<br \/>\n      statusCode,<br \/>\n      error: {<br \/>\n        code: &#096;HTTP_${statusCode}&#096;,<br \/>\n        message: this.getDefaultMessage(statusCode),<br \/>\n        category: classification.category,<br \/>\n        severity: classification.severity,<br \/>\n        retryable: classification.retryable,<br \/>\n        timestamp: new Date().toISOString(),<br \/>\n        details: errorDetails,<br \/>\n        suggestedAction: classification.suggestedAction<br \/>\n      }<br \/>\n    };<br \/>\n  }<\/p>\n<p>  private static getDefaultMessage(statusCode: number): string {<br \/>\n    const messages: Record&lt;number, string&gt; &#061; {<br \/>\n      400: &#039;Bad Request&#039;,<br \/>\n      401: &#039;Unauthorized&#039;,<br \/>\n      403: &#039;Forbidden&#039;,<br \/>\n      404: &#039;Not Found&#039;,<br \/>\n      409: &#039;Conflict&#039;,<br \/>\n      422: &#039;Unprocessable Entity&#039;,<br \/>\n      429: &#039;Too Many Requests&#039;,<br \/>\n      500: &#039;Internal Server Error&#039;,<br \/>\n      502: &#039;Bad Gateway&#039;,<br \/>\n      503: &#039;Service Unavailable&#039;,<br \/>\n      504: &#039;Gateway Timeout&#039;<br \/>\n    };<\/p>\n<p>    return messages[statusCode] || &#039;Unknown Error&#039;;<br \/>\n  }<\/p>\n<p>  static shouldRetry(statusCode: number, retryCount: number &#061; 0): boolean {<br \/>\n    const classification &#061; this.classify(statusCode);<\/p>\n<p>    if (!classification.retryable) {<br \/>\n      return false;<br \/>\n    }<\/p>\n<p>    \/\/ \u68c0\u67e5\u91cd\u8bd5\u6b21\u6570\u9650\u5236<br \/>\n    const maxRetries &#061; this.getMaxRetries(statusCode);<br \/>\n    return retryCount &lt; maxRetries;<br \/>\n  }<\/p>\n<p>  private static getMaxRetries(statusCode: number): number {<br \/>\n    const retryConfig: Record&lt;number, number&gt; &#061; {<br \/>\n      401: 1,    \/\/ \u8ba4\u8bc1\u9519\u8bef&#xff0c;\u91cd\u8bd51\u6b21<br \/>\n      429: 3,    \/\/ \u9650\u6d41\u9519\u8bef&#xff0c;\u6700\u591a\u91cd\u8bd53\u6b21<br \/>\n      500: 3,    \/\/ \u670d\u52a1\u5668\u9519\u8bef&#xff0c;\u6700\u591a\u91cd\u8bd53\u6b21<br \/>\n      502: 3,    \/\/ \u7f51\u5173\u9519\u8bef&#xff0c;\u6700\u591a\u91cd\u8bd53\u6b21<br \/>\n      503: 5,    \/\/ \u670d\u52a1\u4e0d\u53ef\u7528&#xff0c;\u6700\u591a\u91cd\u8bd55\u6b21<br \/>\n      504: 2     \/\/ \u8d85\u65f6\u9519\u8bef&#xff0c;\u6700\u591a\u91cd\u8bd52\u6b21<br \/>\n    };<\/p>\n<p>    return retryConfig[statusCode] || 0;<br \/>\n  }<\/p>\n<p>  static getRetryDelay(statusCode: number, retryCount: number): number {<br \/>\n    \/\/ \u6307\u6570\u9000\u907f\u7b97\u6cd5<br \/>\n    const baseDelay &#061; 1000; \/\/ 1\u79d2<br \/>\n    const maxDelay &#061; 30000; \/\/ 30\u79d2<\/p>\n<p>    if (statusCode &#061;&#061;&#061; 429) {<br \/>\n      \/\/ \u5bf9\u4e8e\u9650\u6d41\u9519\u8bef&#xff0c;\u4f7f\u7528\u66f4\u4fdd\u5b88\u7684\u9000\u907f<br \/>\n      return Math.min(baseDelay * Math.pow(1.5, retryCount), maxDelay);<br \/>\n    }<\/p>\n<p>    \/\/ \u5bf9\u4e8e\u5176\u4ed6\u53ef\u91cd\u8bd5\u9519\u8bef&#xff0c;\u4f7f\u7528\u6307\u6570\u9000\u907f<br \/>\n    return Math.min(baseDelay * Math.pow(2, retryCount), maxDelay);<br \/>\n  }<br \/>\n}<\/p>\n<p>\/\/ \u4f7f\u7528\u793a\u4f8b<br \/>\nconst response &#061; await fetch(&#039;https:\/\/api.example.com\/data&#039;);<br \/>\nif (!response.ok) {<br \/>\n  const classification &#061; StatusCodeClassifier.classify(response.status);<\/p>\n<p>  console.log(&#039;Error Classification:&#039;, {<br \/>\n    category: classification.category,<br \/>\n    severity: classification.severity,<br \/>\n    shouldRetry: classification.retryable,<br \/>\n    suggestedAction: classification.suggestedAction<br \/>\n  });<\/p>\n<p>  \/\/ \u6839\u636e\u5206\u7c7b\u51b3\u5b9a\u5982\u4f55\u5904\u7406\u9519\u8bef<br \/>\n  switch (classification.category) {<br \/>\n    case &#039;CLIENT_ERROR&#039;:<br \/>\n      \/\/ \u5ba2\u6237\u7aef\u9519\u8bef&#xff0c;\u901a\u5e38\u4e0d\u9700\u8981\u91cd\u8bd5<br \/>\n      throw new UserFacingError(<br \/>\n        StatusCodeClassifier.getDefaultMessage(response.status)<br \/>\n      );<\/p>\n<p>    case &#039;SERVER_ERROR&#039;:<br \/>\n      \/\/ \u670d\u52a1\u5668\u9519\u8bef&#xff0c;\u53ef\u4ee5\u91cd\u8bd5<br \/>\n      if (classification.retryable) {<br \/>\n        const delay &#061; StatusCodeClassifier.getRetryDelay(<br \/>\n          response.status,<br \/>\n          0 \/\/ \u7b2c\u4e00\u6b21\u91cd\u8bd5<br \/>\n        );<br \/>\n        await new Promise(resolve &#061;&gt; setTimeout(resolve, delay));<br \/>\n        \/\/ \u91cd\u8bd5\u903b\u8f91&#8230;<br \/>\n      }<br \/>\n      break;<\/p>\n<p>    case &#039;SECURITY_ERROR&#039;:<br \/>\n      \/\/ \u5b89\u5168\u9519\u8bef&#xff0c;\u53ef\u80fd\u9700\u8981\u91cd\u65b0\u8ba4\u8bc1<br \/>\n      if (response.status &#061;&#061;&#061; 401) {<br \/>\n        await refreshAuthentication();<br \/>\n        \/\/ \u91cd\u8bd5\u8bf7\u6c42&#8230;<br \/>\n      }<br \/>\n      break;<br \/>\n  }<br \/>\n}<\/p>\n<h4>34.2.2 \u5206\u5c42\u9519\u8bef\u5904\u7406\u67b6\u6784<\/h4>\n<p>java<\/p>\n<p>\/\/ Java\u5206\u5c42\u9519\u8bef\u5904\u7406\u67b6\u6784<br \/>\npublic class LayeredErrorHandlingArchitecture {<\/p>\n<p>    \/\/ \u7b2c\u4e00\u5c42&#xff1a;\u57fa\u7840\u8bbe\u65bd\u5c42\u9519\u8bef<br \/>\n    public static class InfrastructureLayer {<br \/>\n        &#064;Service<br \/>\n        public class DatabaseService {<br \/>\n            private final JdbcTemplate jdbcTemplate;<br \/>\n            private final CircuitBreaker circuitBreaker;<\/p>\n<p>            public DatabaseService(JdbcTemplate jdbcTemplate) {<br \/>\n                this.jdbcTemplate &#061; jdbcTemplate;<br \/>\n                this.circuitBreaker &#061; CircuitBreaker.ofDefaults(&#034;database&#034;);<br \/>\n            }<\/p>\n<p>            public User findUserById(String userId) {<br \/>\n                return circuitBreaker.executeSupplier(() -&gt; {<br \/>\n                    try {<br \/>\n                        return jdbcTemplate.queryForObject(<br \/>\n                            &#034;SELECT * FROM users WHERE id &#061; ?&#034;,<br \/>\n                            new UserRowMapper(),<br \/>\n                            userId<br \/>\n                        );<br \/>\n                    } catch (DataAccessException e) {<br \/>\n                        \/\/ \u57fa\u7840\u8bbe\u65bd\u9519\u8bef\u8f6c\u6362\u4e3a\u9886\u57df\u9519\u8bef<br \/>\n                        throw new DatabaseUnavailableException(<br \/>\n                            &#034;Database temporarily unavailable&#034;,<br \/>\n                            e<br \/>\n                        );<br \/>\n                    }<br \/>\n                });<br \/>\n            }<br \/>\n        }<\/p>\n<p>        &#064;Service<br \/>\n        public class ExternalApiClient {<br \/>\n            private final RestTemplate restTemplate;<br \/>\n            private final RetryTemplate retryTemplate;<\/p>\n<p>            public ExternalApiClient(RestTemplate restTemplate) {<br \/>\n                this.restTemplate &#061; restTemplate;<br \/>\n                this.retryTemplate &#061; new RetryTemplate();<br \/>\n            }<\/p>\n<p>            public ApiResponse callExternalApi(String endpoint) {<br \/>\n                return retryTemplate.execute(context -&gt; {<br \/>\n                    try {<br \/>\n                        ResponseEntity&lt;ApiResponse&gt; response &#061; restTemplate<br \/>\n                            .getForEntity(endpoint, ApiResponse.class);<\/p>\n<p>                        if (!response.getStatusCode().is2xxSuccessful()) {<br \/>\n                            \/\/ \u6839\u636e\u72b6\u6001\u7801\u51b3\u5b9a\u662f\u5426\u91cd\u8bd5<br \/>\n                            if (shouldRetry(response.getStatusCode())) {<br \/>\n                                throw new RetryableApiException(<br \/>\n                                    &#034;API returned error: &#034; &#043; response.getStatusCode()<br \/>\n                                );<br \/>\n                            } else {<br \/>\n                                throw new NonRetryableApiException(<br \/>\n                                    &#034;API returned unrecoverable error&#034;<br \/>\n                                );<br \/>\n                            }<br \/>\n                        }<\/p>\n<p>                        return response.getBody();<br \/>\n                    } catch (RestClientException e) {<br \/>\n                        \/\/ \u7f51\u7edc\u9519\u8bef&#xff0c;\u53ef\u4ee5\u91cd\u8bd5<br \/>\n                        throw new RetryableApiException(<br \/>\n                            &#034;Network error calling external API&#034;,<br \/>\n                            e<br \/>\n                        );<br \/>\n                    }<br \/>\n                });<br \/>\n            }<\/p>\n<p>            private boolean shouldRetry(HttpStatus status) {<br \/>\n                return status.is5xxServerError() ||<br \/>\n                       status &#061;&#061; HttpStatus.REQUEST_TIMEOUT ||<br \/>\n                       status &#061;&#061; HttpStatus.TOO_MANY_REQUESTS;<br \/>\n            }<br \/>\n        }<br \/>\n    }<\/p>\n<p>    \/\/ \u7b2c\u4e8c\u5c42&#xff1a;\u9886\u57df\u5c42\u9519\u8bef<br \/>\n    public static class DomainLayer {<br \/>\n        public static class InsufficientFundsException<br \/>\n                extends BusinessException {<br \/>\n            public InsufficientFundsException(BigDecimal current,<br \/>\n                                            BigDecimal required) {<br \/>\n                super(<br \/>\n                    &#034;Insufficient funds&#034;,<br \/>\n                    ErrorCode.INSUFFICIENT_FUNDS,<br \/>\n                    Map.of(<br \/>\n                        &#034;current_balance&#034;, current,<br \/>\n                        &#034;required_amount&#034;, required<br \/>\n                    )<br \/>\n                );<br \/>\n            }<br \/>\n        }<\/p>\n<p>        public static class ProductOutOfStockException<br \/>\n                extends BusinessException {<br \/>\n            public ProductOutOfStockException(String productId,<br \/>\n                                            int available) {<br \/>\n                super(<br \/>\n                    &#034;Product is out of stock&#034;,<br \/>\n                    ErrorCode.PRODUCT_OUT_OF_STOCK,<br \/>\n                    Map.of(<br \/>\n                        &#034;product_id&#034;, productId,<br \/>\n                        &#034;available_quantity&#034;, available<br \/>\n                    )<br \/>\n                );<br \/>\n            }<br \/>\n        }<\/p>\n<p>        &#064;Service<br \/>\n        public class OrderService {<br \/>\n            private final PaymentService paymentService;<br \/>\n            private final InventoryService inventoryService;<\/p>\n<p>            public OrderService(PaymentService paymentService,<br \/>\n                              InventoryService inventoryService) {<br \/>\n                this.paymentService &#061; paymentService;<br \/>\n                this.inventoryService &#061; inventoryService;<br \/>\n            }<\/p>\n<p>            &#064;Transactional<br \/>\n            public Order placeOrder(OrderRequest request) {<br \/>\n                \/\/ \u9a8c\u8bc1\u5e93\u5b58<br \/>\n                if (!inventoryService.isInStock(request.getProductId(),<br \/>\n                                               request.getQuantity())) {<br \/>\n                    throw new ProductOutOfStockException(<br \/>\n                        request.getProductId(),<br \/>\n                        inventoryService.getAvailableQuantity(<br \/>\n                            request.getProductId()<br \/>\n                        )<br \/>\n                    );<br \/>\n                }<\/p>\n<p>                \/\/ \u5904\u7406\u652f\u4ed8<br \/>\n                try {<br \/>\n                    PaymentResult result &#061; paymentService.processPayment(<br \/>\n                        request.getPaymentDetails(),<br \/>\n                        request.getTotalAmount()<br \/>\n                    );<\/p>\n<p>                    if (!result.isSuccess()) {<br \/>\n                        throw new PaymentFailedException(<br \/>\n                            &#034;Payment processing failed&#034;,<br \/>\n                            result.getErrorCode()<br \/>\n                        );<br \/>\n                    }<\/p>\n<p>                    \/\/ \u6263\u51cf\u5e93\u5b58<br \/>\n                    inventoryService.reduceStock(<br \/>\n                        request.getProductId(),<br \/>\n                        request.getQuantity()<br \/>\n                    );<\/p>\n<p>                    \/\/ \u521b\u5efa\u8ba2\u5355<br \/>\n                    return createOrder(request, result);<\/p>\n<p>                } catch (PaymentProcessingException e) {<br \/>\n                    \/\/ \u652f\u4ed8\u5904\u7406\u5f02\u5e38\u8f6c\u6362\u4e3a\u9886\u57df\u5f02\u5e38<br \/>\n                    throw new PaymentFailedException(<br \/>\n                        &#034;Payment processing error&#034;,<br \/>\n                        e.getErrorCode(),<br \/>\n                        e<br \/>\n                    );<br \/>\n                }<br \/>\n            }<br \/>\n        }<br \/>\n    }<\/p>\n<p>    \/\/ \u7b2c\u4e09\u5c42&#xff1a;\u5e94\u7528\u5c42\u9519\u8bef<br \/>\n    public static class ApplicationLayer {<br \/>\n        &#064;RestControllerAdvice<br \/>\n        public class GlobalExceptionHandler {<\/p>\n<p>            \/\/ \u5904\u7406\u9886\u57df\u5c42\u5f02\u5e38<br \/>\n            &#064;ExceptionHandler(BusinessException.class)<br \/>\n            public ResponseEntity&lt;ErrorResponse&gt; handleBusinessException(<br \/>\n                    BusinessException ex) {<\/p>\n<p>                ErrorResponse error &#061; ErrorResponse.builder()<br \/>\n                    .code(ex.getErrorCode())<br \/>\n                    .message(ex.getMessage())<br \/>\n                    .details(ex.getContext())<br \/>\n                    .timestamp(Instant.now())<br \/>\n                    .build();<\/p>\n<p>                \/\/ \u6839\u636e\u9519\u8bef\u7c7b\u578b\u51b3\u5b9aHTTP\u72b6\u6001\u7801<br \/>\n                HttpStatus status &#061; mapErrorCodeToHttpStatus(ex.getErrorCode());<\/p>\n<p>                return ResponseEntity<br \/>\n                    .status(status)<br \/>\n                    .body(error);<br \/>\n            }<\/p>\n<p>            \/\/ \u5904\u7406\u57fa\u7840\u8bbe\u65bd\u5c42\u5f02\u5e38<br \/>\n            &#064;ExceptionHandler(DatabaseUnavailableException.class)<br \/>\n            public ResponseEntity&lt;ErrorResponse&gt; handleDatabaseException(<br \/>\n                    DatabaseUnavailableException ex) {<\/p>\n<p>                ErrorResponse error &#061; ErrorResponse.builder()<br \/>\n                    .code(ErrorCode.DATABASE_UNAVAILABLE)<br \/>\n                    .message(&#034;Database service is temporarily unavailable&#034;)<br \/>\n                    .timestamp(Instant.now())<br \/>\n                    .build();<\/p>\n<p>                return ResponseEntity<br \/>\n                    .status(HttpStatus.SERVICE_UNAVAILABLE)<br \/>\n                    .header(&#034;Retry-After&#034;, &#034;30&#034;)<br \/>\n                    .body(error);<br \/>\n            }<\/p>\n<p>            \/\/ \u5904\u7406\u5916\u90e8API\u5f02\u5e38<br \/>\n            &#064;ExceptionHandler(ApiException.class)<br \/>\n            public ResponseEntity&lt;ErrorResponse&gt; handleApiException(<br \/>\n                    ApiException ex) {<\/p>\n<p>                ErrorResponse error &#061; ErrorResponse.builder()<br \/>\n                    .code(ErrorCode.EXTERNAL_SERVICE_ERROR)<br \/>\n                    .message(&#034;External service error occurred&#034;)<br \/>\n                    .timestamp(Instant.now())<br \/>\n                    .build();<\/p>\n<p>                return ResponseEntity<br \/>\n                    .status(HttpStatus.BAD_GATEWAY)<br \/>\n                    .body(error);<br \/>\n            }<\/p>\n<p>            \/\/ \u5904\u7406\u9a8c\u8bc1\u5f02\u5e38<br \/>\n            &#064;ExceptionHandler(MethodArgumentNotValidException.class)<br \/>\n            public ResponseEntity&lt;ErrorResponse&gt; handleValidationException(<br \/>\n                    MethodArgumentNotValidException ex) {<\/p>\n<p>                List&lt;ValidationError&gt; validationErrors &#061; ex.getBindingResult()<br \/>\n                    .getFieldErrors()<br \/>\n                    .stream()<br \/>\n                    .map(fieldError -&gt; ValidationError.builder()<br \/>\n                        .field(fieldError.getField())<br \/>\n                        .message(fieldError.getDefaultMessage())<br \/>\n                        .rejectedValue(fieldError.getRejectedValue())<br \/>\n                        .build())<br \/>\n                    .collect(Collectors.toList());<\/p>\n<p>                ErrorResponse error &#061; ErrorResponse.builder()<br \/>\n                    .code(ErrorCode.VALIDATION_ERROR)<br \/>\n                    .message(&#034;Request validation failed&#034;)<br \/>\n                    .details(Map.of(&#034;validation_errors&#034;, validationErrors))<br \/>\n                    .timestamp(Instant.now())<br \/>\n                    .build();<\/p>\n<p>                return ResponseEntity<br \/>\n                    .status(HttpStatus.UNPROCESSABLE_ENTITY)<br \/>\n                    .body(error);<br \/>\n            }<\/p>\n<p>            \/\/ \u515c\u5e95\u5f02\u5e38\u5904\u7406<br \/>\n            &#064;ExceptionHandler(Exception.class)<br \/>\n            public ResponseEntity&lt;ErrorResponse&gt; handleGenericException(<br \/>\n                    Exception ex) {<\/p>\n<p>                \/\/ \u8bb0\u5f55\u672a\u77e5\u5f02\u5e38<br \/>\n                log.error(&#034;Unhandled exception occurred&#034;, ex);<\/p>\n<p>                ErrorResponse error &#061; ErrorResponse.builder()<br \/>\n                    .code(ErrorCode.INTERNAL_ERROR)<br \/>\n                    .message(&#034;An unexpected error occurred&#034;)<br \/>\n                    .timestamp(Instant.now())<br \/>\n                    .build();<\/p>\n<p>                return ResponseEntity<br \/>\n                    .status(HttpStatus.INTERNAL_SERVER_ERROR)<br \/>\n                    .body(error);<br \/>\n            }<\/p>\n<p>            private HttpStatus mapErrorCodeToHttpStatus(ErrorCode errorCode) {<br \/>\n                switch (errorCode) {<br \/>\n                    case INSUFFICIENT_FUNDS:<br \/>\n                    case PRODUCT_OUT_OF_STOCK:<br \/>\n                        return HttpStatus.CONFLICT;<br \/>\n                    case VALIDATION_ERROR:<br \/>\n                        return HttpStatus.UNPROCESSABLE_ENTITY;<br \/>\n                    case AUTHENTICATION_ERROR:<br \/>\n                        return HttpStatus.UNAUTHORIZED;<br \/>\n                    case AUTHORIZATION_ERROR:<br \/>\n                        return HttpStatus.FORBIDDEN;<br \/>\n                    case RESOURCE_NOT_FOUND:<br \/>\n                        return HttpStatus.NOT_FOUND;<br \/>\n                    default:<br \/>\n                        return HttpStatus.BAD_REQUEST;<br \/>\n                }<br \/>\n            }<br \/>\n        }<\/p>\n<p>        &#064;Service<br \/>\n        public class ErrorMonitoringService {<br \/>\n            private final ErrorReportingClient errorReportingClient;<br \/>\n            private final MetricsService metricsService;<\/p>\n<p>            public ErrorMonitoringService(ErrorReportingClient errorReportingClient,<br \/>\n                                         MetricsService metricsService) {<br \/>\n                this.errorReportingClient &#061; errorReportingClient;<br \/>\n                this.metricsService &#061; metricsService;<br \/>\n            }<\/p>\n<p>            public void reportError(Throwable throwable, ErrorContext context) {<br \/>\n                \/\/ 1. \u8bb0\u5f55\u6307\u6807<br \/>\n                metricsService.incrementCounter(&#034;errors_total&#034;,<br \/>\n                    &#034;error_type&#034;, throwable.getClass().getSimpleName());<\/p>\n<p>                \/\/ 2. \u53d1\u9001\u5230\u9519\u8bef\u62a5\u544a\u7cfb\u7edf<br \/>\n                ErrorReport report &#061; ErrorReport.builder()<br \/>\n                    .error(throwable)<br \/>\n                    .context(context)<br \/>\n                    .timestamp(Instant.now())<br \/>\n                    .build();<\/p>\n<p>                errorReportingClient.report(report);<\/p>\n<p>                \/\/ 3. \u6839\u636e\u9519\u8bef\u7c7b\u578b\u51b3\u5b9a\u662f\u5426\u9700\u8981\u544a\u8b66<br \/>\n                if (isCriticalError(throwable)) {<br \/>\n                    sendAlert(report);<br \/>\n                }<br \/>\n            }<\/p>\n<p>            private boolean isCriticalError(Throwable throwable) {<br \/>\n                return throwable instanceof OutOfMemoryError ||<br \/>\n                       throwable instanceof DatabaseUnavailableException ||<br \/>\n                       throwable instanceof CircuitBreakerOpenException;<br \/>\n            }<\/p>\n<p>            private void sendAlert(ErrorReport report) {<br \/>\n                \/\/ \u53d1\u9001\u544a\u8b66\u5230\u76d1\u63a7\u7cfb\u7edf<br \/>\n                Alert alert &#061; Alert.builder()<br \/>\n                    .severity(AlertSeverity.CRITICAL)<br \/>\n                    .message(&#034;Critical error detected&#034;)<br \/>\n                    .details(report)<br \/>\n                    .timestamp(Instant.now())<br \/>\n                    .build();<\/p>\n<p>                \/\/ alertService.send(alert);<br \/>\n            }<br \/>\n        }<br \/>\n    }<\/p>\n<p>    \/\/ \u9519\u8bef\u57fa\u7c7b<br \/>\n    public static abstract class BusinessException extends RuntimeException {<br \/>\n        private final ErrorCode errorCode;<br \/>\n        private final Map&lt;String, Object&gt; context;<\/p>\n<p>        public BusinessException(String message, ErrorCode errorCode,<br \/>\n                               Map&lt;String, Object&gt; context) {<br \/>\n            super(message);<br \/>\n            this.errorCode &#061; errorCode;<br \/>\n            this.context &#061; context;<br \/>\n        }<\/p>\n<p>        public BusinessException(String message, ErrorCode errorCode,<br \/>\n                               Map&lt;String, Object&gt; context, Throwable cause) {<br \/>\n            super(message, cause);<br \/>\n            this.errorCode &#061; errorCode;<br \/>\n            this.context &#061; context;<br \/>\n        }<\/p>\n<p>        public ErrorCode getErrorCode() { return errorCode; }<br \/>\n        public Map&lt;String, Object&gt; getContext() { return context; }<br \/>\n    }<br \/>\n}<\/p>\n<h3>34.3 \u667a\u80fd\u91cd\u8bd5\u7b56\u7565<\/h3>\n<h4>34.3.1 \u81ea\u9002\u5e94\u91cd\u8bd5\u7b97\u6cd5<\/h4>\n<p>python<\/p>\n<p># \u81ea\u9002\u5e94\u91cd\u8bd5\u7b56\u7565\u5b9e\u73b0<br \/>\nimport time<br \/>\nimport math<br \/>\nimport random<br \/>\nfrom dataclasses import dataclass<br \/>\nfrom enum import Enum<br \/>\nfrom typing import Optional, Callable, Any, Dict<br \/>\nfrom datetime import datetime, timedelta<\/p>\n<p>class RetryStrategy(Enum):<br \/>\n    &#034;&#034;&#034;\u91cd\u8bd5\u7b56\u7565\u679a\u4e3e&#034;&#034;&#034;<br \/>\n    EXPONENTIAL_BACKOFF &#061; &#034;exponential_backoff&#034;<br \/>\n    FIBONACCI_BACKOFF &#061; &#034;fibonacci_backoff&#034;<br \/>\n    FIXED_DELAY &#061; &#034;fixed_delay&#034;<br \/>\n    LINEAR_BACKOFF &#061; &#034;linear_backoff&#034;<br \/>\n    RANDOM_JITTER &#061; &#034;random_jitter&#034;<\/p>\n<p>class ErrorPattern(Enum):<br \/>\n    &#034;&#034;&#034;\u9519\u8bef\u6a21\u5f0f\u679a\u4e3e&#034;&#034;&#034;<br \/>\n    TRANSIENT &#061; &#034;transient&#034;      # \u4e34\u65f6\u9519\u8bef&#xff0c;\u53ef\u4ee5\u91cd\u8bd5<br \/>\n    PERMANENT &#061; &#034;permanent&#034;      # \u6c38\u4e45\u9519\u8bef&#xff0c;\u4e0d\u5e94\u91cd\u8bd5<br \/>\n    THROTTLING &#061; &#034;throttling&#034;    # \u9650\u6d41\u9519\u8bef&#xff0c;\u9700\u8981\u7b49\u5f85<br \/>\n    NETWORK &#061; &#034;network&#034;          # \u7f51\u7edc\u9519\u8bef<\/p>\n<p>&#064;dataclass<br \/>\nclass RetryContext:<br \/>\n    &#034;&#034;&#034;\u91cd\u8bd5\u4e0a\u4e0b\u6587&#034;&#034;&#034;<br \/>\n    attempt_number: int<br \/>\n    max_attempts: int<br \/>\n    last_error: Optional[Exception]<br \/>\n    last_status_code: Optional[int]<br \/>\n    start_time: datetime<br \/>\n    total_duration: timedelta<br \/>\n    custom_data: Dict[str, Any]<\/p>\n<p>    def should_continue(self) -&gt; bool:<br \/>\n        &#034;&#034;&#034;\u662f\u5426\u5e94\u8be5\u7ee7\u7eed\u91cd\u8bd5&#034;&#034;&#034;<br \/>\n        if self.attempt_number &gt;&#061; self.max_attempts:<br \/>\n            return False<\/p>\n<p>        # \u68c0\u67e5\u603b\u6301\u7eed\u65f6\u95f4\u9650\u5236<br \/>\n        if self.total_duration.total_seconds() &gt; 300:  # 5\u5206\u949f<br \/>\n            return False<\/p>\n<p>        return True<\/p>\n<p>class AdaptiveRetryStrategy:<br \/>\n    &#034;&#034;&#034;\u81ea\u9002\u5e94\u91cd\u8bd5\u7b56\u7565&#034;&#034;&#034;<\/p>\n<p>    def __init__(<br \/>\n        self,<br \/>\n        max_attempts: int &#061; 5,<br \/>\n        base_delay: float &#061; 1.0,  # \u79d2<br \/>\n        max_delay: float &#061; 60.0,  # \u79d2<br \/>\n        strategy: RetryStrategy &#061; RetryStrategy.EXPONENTIAL_BACKOFF,<br \/>\n        jitter: bool &#061; True,<br \/>\n        jitter_factor: float &#061; 0.1<br \/>\n    ):<br \/>\n        self.max_attempts &#061; max_attempts<br \/>\n        self.base_delay &#061; base_delay<br \/>\n        self.max_delay &#061; max_delay<br \/>\n        self.strategy &#061; strategy<br \/>\n        self.jitter &#061; jitter<br \/>\n        self.jitter_factor &#061; jitter_factor<\/p>\n<p>        # \u9519\u8bef\u6a21\u5f0f\u68c0\u6d4b\u5668<br \/>\n        self.error_patterns &#061; self._initialize_error_patterns()<\/p>\n<p>    def _initialize_error_patterns(self) -&gt; Dict[ErrorPattern, Callable[[Exception], bool]]:<br \/>\n        &#034;&#034;&#034;\u521d\u59cb\u5316\u9519\u8bef\u6a21\u5f0f\u68c0\u6d4b\u5668&#034;&#034;&#034;<br \/>\n        return {<br \/>\n            ErrorPattern.TRANSIENT: self._is_transient_error,<br \/>\n            ErrorPattern.PERMANENT: self._is_permanent_error,<br \/>\n            ErrorPattern.THROTTLING: self._is_throttling_error,<br \/>\n            ErrorPattern.NETWORK: self._is_network_error<br \/>\n        }<\/p>\n<p>    def execute(self, func: Callable[[], Any], context_data: Dict[str, Any] &#061; None) -&gt; Any:<br \/>\n        &#034;&#034;&#034;\u6267\u884c\u5e26\u91cd\u8bd5\u7684\u51fd\u6570&#034;&#034;&#034;<br \/>\n        context &#061; RetryContext(<br \/>\n            attempt_number&#061;0,<br \/>\n            max_attempts&#061;self.max_attempts,<br \/>\n            last_error&#061;None,<br \/>\n            last_status_code&#061;None,<br \/>\n            start_time&#061;datetime.now(),<br \/>\n            total_duration&#061;timedelta(),<br \/>\n            custom_data&#061;context_data or {}<br \/>\n        )<\/p>\n<p>        while context.should_continue():<br \/>\n            try:<br \/>\n                result &#061; func()<\/p>\n<p>                # \u6210\u529f&#xff0c;\u91cd\u7f6e\u91cd\u8bd5\u72b6\u6001&#xff08;\u5982\u679c\u9700\u8981\u7684\u8bdd&#xff09;<br \/>\n                self._on_success(context)<br \/>\n                return result<\/p>\n<p>            except Exception as e:<br \/>\n                context.last_error &#061; e<br \/>\n                context.last_status_code &#061; getattr(e, &#039;status_code&#039;, None)<br \/>\n                context.attempt_number &#043;&#061; 1<\/p>\n<p>                # \u5206\u6790\u9519\u8bef\u6a21\u5f0f<br \/>\n                error_pattern &#061; self._analyze_error(e, context)<\/p>\n<p>                # \u6839\u636e\u9519\u8bef\u6a21\u5f0f\u51b3\u5b9a\u662f\u5426\u91cd\u8bd5<br \/>\n                if not self._should_retry(error_pattern, context):<br \/>\n                    raise e<\/p>\n<p>                # \u8ba1\u7b97\u7b49\u5f85\u65f6\u95f4<br \/>\n                wait_time &#061; self._calculate_wait_time(context, error_pattern)<\/p>\n<p>                # \u66f4\u65b0\u603b\u6301\u7eed\u65f6\u95f4<br \/>\n                context.total_duration &#043;&#061; timedelta(seconds&#061;wait_time)<\/p>\n<p>                # \u7b49\u5f85<br \/>\n                self._wait(wait_time, context)<\/p>\n<p>    def _analyze_error(self, error: Exception, context: RetryContext) -&gt; ErrorPattern:<br \/>\n        &#034;&#034;&#034;\u5206\u6790\u9519\u8bef\u6a21\u5f0f&#034;&#034;&#034;<br \/>\n        # \u68c0\u67e5\u9519\u8bef\u7c7b\u578b<br \/>\n        for pattern, detector in self.error_patterns.items():<br \/>\n            if detector(error):<br \/>\n                return pattern<\/p>\n<p>        # \u68c0\u67e5\u72b6\u6001\u7801<br \/>\n        if context.last_status_code:<br \/>\n            if context.last_status_code &#061;&#061; 429:<br \/>\n                return ErrorPattern.THROTTLING<br \/>\n            elif 500 &lt;&#061; context.last_status_code &lt; 600:<br \/>\n                return ErrorPattern.TRANSIENT<br \/>\n            elif 400 &lt;&#061; context.last_status_code &lt; 500:<br \/>\n                # \u67d0\u4e9b4xx\u9519\u8bef\u53ef\u80fd\u662f\u4e34\u65f6\u6027\u7684<br \/>\n                if context.last_status_code in [408, 423, 425, 429]:<br \/>\n                    return ErrorPattern.TRANSIENT<br \/>\n                else:<br \/>\n                    return ErrorPattern.PERMANENT<\/p>\n<p>        # \u9ed8\u8ba4\u8ba4\u4e3a\u662f\u7f51\u7edc\u9519\u8bef<br \/>\n        return ErrorPattern.NETWORK<\/p>\n<p>    def _should_retry(self, error_pattern: ErrorPattern, context: RetryContext) -&gt; bool:<br \/>\n        &#034;&#034;&#034;\u6839\u636e\u9519\u8bef\u6a21\u5f0f\u51b3\u5b9a\u662f\u5426\u91cd\u8bd5&#034;&#034;&#034;<br \/>\n        if error_pattern &#061;&#061; ErrorPattern.PERMANENT:<br \/>\n            return False<\/p>\n<p>        # \u68c0\u67e5\u91cd\u8bd5\u6b21\u6570<br \/>\n        if context.attempt_number &gt;&#061; self.max_attempts:<br \/>\n            return False<\/p>\n<p>        # \u68c0\u67e5\u603b\u6301\u7eed\u65f6\u95f4<br \/>\n        if context.total_duration.total_seconds() &gt; 300:  # 5\u5206\u949f<br \/>\n            return False<\/p>\n<p>        return True<\/p>\n<p>    def _calculate_wait_time(self, context: RetryContext, error_pattern: ErrorPattern) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u8ba1\u7b97\u7b49\u5f85\u65f6\u95f4&#034;&#034;&#034;<br \/>\n        attempt &#061; context.attempt_number<\/p>\n<p>        # \u57fa\u7840\u5ef6\u8fdf\u8ba1\u7b97<br \/>\n        if error_pattern &#061;&#061; ErrorPattern.THROTTLING:<br \/>\n            # \u9650\u6d41\u9519\u8bef\u4f7f\u7528\u66f4\u957f\u7684\u7b49\u5f85\u65f6\u95f4<br \/>\n            base_wait &#061; self._calculate_throttling_wait(context)<br \/>\n        else:<br \/>\n            # \u6839\u636e\u7b56\u7565\u8ba1\u7b97\u57fa\u7840\u7b49\u5f85\u65f6\u95f4<br \/>\n            base_wait &#061; self._calculate_base_wait(attempt)<\/p>\n<p>        # \u6dfb\u52a0\u6296\u52a8<br \/>\n        if self.jitter:<br \/>\n            jitter_amount &#061; base_wait * self.jitter_factor<br \/>\n            base_wait &#043;&#061; random.uniform(-jitter_amount, jitter_amount)<\/p>\n<p>        # \u786e\u4fdd\u5728\u5408\u7406\u8303\u56f4\u5185<br \/>\n        return max(0, min(base_wait, self.max_delay))<\/p>\n<p>    def _calculate_base_wait(self, attempt: int) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u6839\u636e\u7b56\u7565\u8ba1\u7b97\u57fa\u7840\u7b49\u5f85\u65f6\u95f4&#034;&#034;&#034;<br \/>\n        if self.strategy &#061;&#061; RetryStrategy.EXPONENTIAL_BACKOFF:<br \/>\n            # \u6307\u6570\u9000\u907f&#xff1a;1, 2, 4, 8, 16, &#8230;<br \/>\n            return self.base_delay * (2 ** (attempt &#8211; 1))<\/p>\n<p>        elif self.strategy &#061;&#061; RetryStrategy.FIBONACCI_BACKOFF:<br \/>\n            # \u6590\u6ce2\u90a3\u5951\u9000\u907f&#xff1a;1, 1, 2, 3, 5, 8, &#8230;<br \/>\n            fib &#061; self._fibonacci(attempt)<br \/>\n            return self.base_delay * fib<\/p>\n<p>        elif self.strategy &#061;&#061; RetryStrategy.FIXED_DELAY:<br \/>\n            # \u56fa\u5b9a\u5ef6\u8fdf<br \/>\n            return self.base_delay<\/p>\n<p>        elif self.strategy &#061;&#061; RetryStrategy.LINEAR_BACKOFF:<br \/>\n            # \u7ebf\u6027\u9000\u907f&#xff1a;1, 2, 3, 4, 5, &#8230;<br \/>\n            return self.base_delay * attempt<\/p>\n<p>        else:<br \/>\n            # \u9ed8\u8ba4\u4f7f\u7528\u6307\u6570\u9000\u907f<br \/>\n            return self.base_delay * (2 ** (attempt &#8211; 1))<\/p>\n<p>    def _calculate_throttling_wait(self, context: RetryContext) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u8ba1\u7b97\u9650\u6d41\u7b49\u5f85\u65f6\u95f4&#034;&#034;&#034;<br \/>\n        # \u68c0\u67e5\u9519\u8bef\u4e2d\u662f\u5426\u5305\u542bRetry-After\u5934<br \/>\n        if hasattr(context.last_error, &#039;headers&#039;):<br \/>\n            headers &#061; context.last_error.headers<br \/>\n            if &#039;Retry-After&#039; in headers:<br \/>\n                retry_after &#061; headers[&#039;Retry-After&#039;]<br \/>\n                try:<br \/>\n                    # \u53ef\u80fd\u662f\u79d2\u6570\u6216\u65e5\u671f\u65f6\u95f4<br \/>\n                    if retry_after.isdigit():<br \/>\n                        return float(retry_after)<br \/>\n                    else:<br \/>\n                        # \u89e3\u6790\u65e5\u671f\u65f6\u95f4<br \/>\n                        retry_time &#061; datetime.fromisoformat(retry_after)<br \/>\n                        wait_seconds &#061; (retry_time &#8211; datetime.now()).total_seconds()<br \/>\n                        return max(0, wait_seconds)<br \/>\n                except (ValueError, TypeError):<br \/>\n                    pass<\/p>\n<p>        # \u6ca1\u6709Retry-After\u5934&#xff0c;\u4f7f\u7528\u6307\u6570\u9000\u907f\u52a0\u4e0a\u989d\u5916\u5ef6\u8fdf<br \/>\n        base_wait &#061; self._calculate_base_wait(context.attempt_number)<br \/>\n        return base_wait * 2  # \u9650\u6d41\u9519\u8bef\u7b49\u5f85\u65f6\u95f4\u52a0\u500d<\/p>\n<p>    def _fibonacci(self, n: int) -&gt; int:<br \/>\n        &#034;&#034;&#034;\u8ba1\u7b97\u6590\u6ce2\u90a3\u5951\u6570&#034;&#034;&#034;<br \/>\n        if n &lt;&#061; 0:<br \/>\n            return 0<br \/>\n        elif n &#061;&#061; 1:<br \/>\n            return 1<br \/>\n        else:<br \/>\n            a, b &#061; 0, 1<br \/>\n            for _ in range(n):<br \/>\n                a, b &#061; b, a &#043; b<br \/>\n            return a<\/p>\n<p>    def _is_transient_error(self, error: Exception) -&gt; bool:<br \/>\n        &#034;&#034;&#034;\u5224\u65ad\u662f\u5426\u4e3a\u4e34\u65f6\u9519\u8bef&#034;&#034;&#034;<br \/>\n        transient_error_types &#061; [<br \/>\n            &#039;TimeoutError&#039;,<br \/>\n            &#039;ConnectionError&#039;,<br \/>\n            &#039;TemporaryFailure&#039;,<br \/>\n            &#039;ServiceUnavailable&#039;<br \/>\n        ]<\/p>\n<p>        error_type &#061; error.__class__.__name__<br \/>\n        return error_type in transient_error_types<\/p>\n<p>    def _is_permanent_error(self, error: Exception) -&gt; bool:<br \/>\n        &#034;&#034;&#034;\u5224\u65ad\u662f\u5426\u4e3a\u6c38\u4e45\u9519\u8bef&#034;&#034;&#034;<br \/>\n        permanent_error_types &#061; [<br \/>\n            &#039;ValidationError&#039;,<br \/>\n            &#039;AuthenticationError&#039;,<br \/>\n            &#039;AuthorizationError&#039;,<br \/>\n            &#039;InvalidRequest&#039;<br \/>\n        ]<\/p>\n<p>        error_type &#061; error.__class__.__name__<br \/>\n        return error_type in permanent_error_types<\/p>\n<p>    def _is_throttling_error(self, error: Exception) -&gt; bool:<br \/>\n        &#034;&#034;&#034;\u5224\u65ad\u662f\u5426\u4e3a\u9650\u6d41\u9519\u8bef&#034;&#034;&#034;<br \/>\n        if hasattr(error, &#039;status_code&#039;) and error.status_code &#061;&#061; 429:<br \/>\n            return True<\/p>\n<p>        error_type &#061; error.__class__.__name__<br \/>\n        return error_type in [&#039;RateLimitError&#039;, &#039;ThrottlingError&#039;]<\/p>\n<p>    def _is_network_error(self, error: Exception) -&gt; bool:<br \/>\n        &#034;&#034;&#034;\u5224\u65ad\u662f\u5426\u4e3a\u7f51\u7edc\u9519\u8bef&#034;&#034;&#034;<br \/>\n        network_error_types &#061; [<br \/>\n            &#039;ConnectionError&#039;,<br \/>\n            &#039;NetworkError&#039;,<br \/>\n            &#039;SocketError&#039;,<br \/>\n            &#039;HTTPError&#039;<br \/>\n        ]<\/p>\n<p>        error_type &#061; error.__class__.__name__<br \/>\n        return error_type in network_error_types<\/p>\n<p>    def _wait(self, seconds: float, context: RetryContext):<br \/>\n        &#034;&#034;&#034;\u7b49\u5f85\u6307\u5b9a\u7684\u65f6\u95f4&#034;&#034;&#034;<br \/>\n        # \u8bb0\u5f55\u7b49\u5f85\u5f00\u59cb\u65f6\u95f4<br \/>\n        wait_start &#061; datetime.now()<\/p>\n<p>        # \u5b9e\u9645\u7b49\u5f85<br \/>\n        time.sleep(seconds)<\/p>\n<p>        # \u8bb0\u5f55\u7b49\u5f85\u7ed3\u675f\u65f6\u95f4<br \/>\n        wait_end &#061; datetime.now()<\/p>\n<p>        # \u53ef\u4ee5\u5728\u8fd9\u91cc\u6dfb\u52a0\u7b49\u5f85\u65e5\u5fd7\u6216\u76d1\u63a7<br \/>\n        self._log_wait(context, seconds, wait_start, wait_end)<\/p>\n<p>    def _log_wait(self, context: RetryContext, wait_time: float,<br \/>\n                 start_time: datetime, end_time: datetime):<br \/>\n        &#034;&#034;&#034;\u8bb0\u5f55\u7b49\u5f85\u4fe1\u606f&#034;&#034;&#034;<br \/>\n        log_data &#061; {<br \/>\n            &#039;attempt&#039;: context.attempt_number,<br \/>\n            &#039;wait_time_seconds&#039;: wait_time,<br \/>\n            &#039;start_time&#039;: start_time.isoformat(),<br \/>\n            &#039;end_time&#039;: end_time.isoformat(),<br \/>\n            &#039;error_type&#039;: context.last_error.__class__.__name__ if context.last_error else None,<br \/>\n            &#039;status_code&#039;: context.last_status_code,<br \/>\n            &#039;total_duration_seconds&#039;: context.total_duration.total_seconds()<br \/>\n        }<\/p>\n<p>        print(f&#034;Retry wait: {log_data}&#034;)<\/p>\n<p>    def _on_success(self, context: RetryContext):<br \/>\n        &#034;&#034;&#034;\u6210\u529f\u65f6\u7684\u56de\u8c03&#034;&#034;&#034;<br \/>\n        # \u53ef\u4ee5\u5728\u8fd9\u91cc\u6dfb\u52a0\u6210\u529f\u65e5\u5fd7\u3001\u91cd\u7f6e\u8ba1\u6570\u5668\u7b49<br \/>\n        success_data &#061; {<br \/>\n            &#039;attempts_made&#039;: context.attempt_number,<br \/>\n            &#039;total_duration_seconds&#039;: context.total_duration.total_seconds(),<br \/>\n            &#039;success_time&#039;: datetime.now().isoformat()<br \/>\n        }<\/p>\n<p>        print(f&#034;Operation succeeded: {success_data}&#034;)<\/p>\n<p># \u4f7f\u7528\u793a\u4f8b<br \/>\ndef test_retry_strategy():<br \/>\n    # \u521b\u5efa\u81ea\u9002\u5e94\u91cd\u8bd5\u7b56\u7565<br \/>\n    retry_strategy &#061; AdaptiveRetryStrategy(<br \/>\n        max_attempts&#061;5,<br \/>\n        base_delay&#061;1.0,<br \/>\n        max_delay&#061;30.0,<br \/>\n        strategy&#061;RetryStrategy.EXPONENTIAL_BACKOFF,<br \/>\n        jitter&#061;True,<br \/>\n        jitter_factor&#061;0.1<br \/>\n    )<\/p>\n<p>    # \u6a21\u62df\u4e00\u4e2a\u53ef\u80fd\u5931\u8d25\u7684\u64cd\u4f5c<br \/>\n    call_count &#061; 0<\/p>\n<p>    def unreliable_operation():<br \/>\n        nonlocal call_count<br \/>\n        call_count &#043;&#061; 1<\/p>\n<p>        if call_count &lt; 3:<br \/>\n            # \u6a21\u62df\u4e34\u65f6\u9519\u8bef<br \/>\n            class MockError(Exception):<br \/>\n                status_code &#061; 503<\/p>\n<p>            raise MockError(&#034;Service temporarily unavailable&#034;)<br \/>\n        elif call_count &#061;&#061; 3:<br \/>\n            # \u6a21\u62df\u9650\u6d41\u9519\u8bef<br \/>\n            class ThrottlingError(Exception):<br \/>\n                status_code &#061; 429<br \/>\n                headers &#061; {&#039;Retry-After&#039;: &#039;5&#039;}<\/p>\n<p>            raise ThrottlingError(&#034;Too many requests&#034;)<br \/>\n        else:<br \/>\n            # \u6210\u529f<br \/>\n            return {&#034;data&#034;: &#034;success&#034;}<\/p>\n<p>    try:<br \/>\n        # \u6267\u884c\u5e26\u91cd\u8bd5\u7684\u64cd\u4f5c<br \/>\n        result &#061; retry_strategy.execute(unreliable_operation)<br \/>\n        print(f&#034;\u6700\u7ec8\u7ed3\u679c: {result}&#034;)<br \/>\n    except Exception as e:<br \/>\n        print(f&#034;\u64cd\u4f5c\u6700\u7ec8\u5931\u8d25: {e}&#034;)<\/p>\n<p># \u8fd0\u884c\u6d4b\u8bd5<br \/>\nif __name__ &#061;&#061; &#034;__main__&#034;:<br \/>\n    test_retry_strategy()<\/p>\n<h4>34.3.2 \u57fa\u4e8e\u673a\u5668\u5b66\u4e60\u7684\u667a\u80fd\u91cd\u8bd5<\/h4>\n<p>python<\/p>\n<p># \u57fa\u4e8e\u673a\u5668\u5b66\u4e60\u7684\u667a\u80fd\u91cd\u8bd5\u7cfb\u7edf<br \/>\nimport numpy as np<br \/>\nimport pandas as pd<br \/>\nfrom sklearn.ensemble import RandomForestClassifier, RandomForestRegressor<br \/>\nfrom sklearn.preprocessing import LabelEncoder, StandardScaler<br \/>\nfrom sklearn.model_selection import train_test_split<br \/>\nimport joblib<br \/>\nfrom datetime import datetime<br \/>\nfrom typing import Dict, List, Any, Optional, Tuple<br \/>\nimport hashlib<br \/>\nimport json<\/p>\n<p>class MLRetryOptimizer:<br \/>\n    &#034;&#034;&#034;\u57fa\u4e8e\u673a\u5668\u5b66\u4e60\u7684\u91cd\u8bd5\u4f18\u5316\u5668&#034;&#034;&#034;<\/p>\n<p>    def __init__(self, model_path: str &#061; None):<br \/>\n        # \u7279\u5f81\u5de5\u7a0b<br \/>\n        self.feature_columns &#061; [<br \/>\n            &#039;hour_of_day&#039;, &#039;day_of_week&#039;, &#039;response_time_ms&#039;,<br \/>\n            &#039;status_code&#039;, &#039;error_type&#039;, &#039;retry_count&#039;,<br \/>\n            &#039;service_name&#039;, &#039;endpoint&#039;, &#039;client_ip_prefix&#039;,<br \/>\n            &#039;request_size_kb&#039;, &#039;response_size_kb&#039;, &#039;concurrent_requests&#039;<br \/>\n        ]<\/p>\n<p>        # \u76ee\u6807\u53d8\u91cf<br \/>\n        self.target_column &#061; &#039;retry_success_probability&#039;<\/p>\n<p>        # \u7f16\u7801\u5668<br \/>\n        self.label_encoders &#061; {}<br \/>\n        self.scaler &#061; StandardScaler()<\/p>\n<p>        # \u6a21\u578b<br \/>\n        self.classification_model &#061; RandomForestClassifier(<br \/>\n            n_estimators&#061;100,<br \/>\n            random_state&#061;42<br \/>\n        )<br \/>\n        self.regression_model &#061; RandomForestRegressor(<br \/>\n            n_estimators&#061;100,<br \/>\n            random_state&#061;42<br \/>\n        )<\/p>\n<p>        # \u6570\u636e\u5b58\u50a8<br \/>\n        self.training_data &#061; []<br \/>\n        self.model_path &#061; model_path<\/p>\n<p>        # \u52a0\u8f7d\u73b0\u6709\u6a21\u578b<br \/>\n        if model_path:<br \/>\n            self.load_model(model_path)<\/p>\n<p>    def extract_features(self, request_context: Dict[str, Any],<br \/>\n                        error_context: Dict[str, Any]) -&gt; Dict[str, Any]:<br \/>\n        &#034;&#034;&#034;\u4ece\u8bf7\u6c42\u548c\u9519\u8bef\u4e0a\u4e0b\u6587\u4e2d\u63d0\u53d6\u7279\u5f81&#034;&#034;&#034;<br \/>\n        features &#061; {}<\/p>\n<p>        # \u65f6\u95f4\u7279\u5f81<br \/>\n        timestamp &#061; request_context.get(&#039;timestamp&#039;, datetime.now())<br \/>\n        features[&#039;hour_of_day&#039;] &#061; timestamp.hour<br \/>\n        features[&#039;day_of_week&#039;] &#061; timestamp.weekday()  # 0&#061;Monday, 6&#061;Sunday<\/p>\n<p>        # \u54cd\u5e94\u7279\u5f81<br \/>\n        features[&#039;response_time_ms&#039;] &#061; error_context.get(&#039;response_time_ms&#039;, 0)<br \/>\n        features[&#039;status_code&#039;] &#061; error_context.get(&#039;status_code&#039;, 0)<br \/>\n        features[&#039;error_type&#039;] &#061; error_context.get(&#039;error_type&#039;, &#039;unknown&#039;)<\/p>\n<p>        # \u8bf7\u6c42\u7279\u5f81<br \/>\n        features[&#039;retry_count&#039;] &#061; error_context.get(&#039;retry_count&#039;, 0)<br \/>\n        features[&#039;service_name&#039;] &#061; request_context.get(&#039;service_name&#039;, &#039;unknown&#039;)<br \/>\n        features[&#039;endpoint&#039;] &#061; request_context.get(&#039;endpoint&#039;, &#039;unknown&#039;)<\/p>\n<p>        # \u5ba2\u6237\u7aef\u7279\u5f81<br \/>\n        client_ip &#061; request_context.get(&#039;client_ip&#039;, &#039;0.0.0.0&#039;)<br \/>\n        features[&#039;client_ip_prefix&#039;] &#061; self._extract_ip_prefix(client_ip)<\/p>\n<p>        # \u8bf7\u6c42\u5927\u5c0f<br \/>\n        features[&#039;request_size_kb&#039;] &#061; request_context.get(&#039;request_size_kb&#039;, 0)<br \/>\n        features[&#039;response_size_kb&#039;] &#061; error_context.get(&#039;response_size_kb&#039;, 0)<\/p>\n<p>        # \u7cfb\u7edf\u8d1f\u8f7d\u7279\u5f81<br \/>\n        features[&#039;concurrent_requests&#039;] &#061; request_context.get(<br \/>\n            &#039;concurrent_requests&#039;, 0<br \/>\n        )<\/p>\n<p>        return features<\/p>\n<p>    def predict_retry_success(self, features: Dict[str, Any]) -&gt; Dict[str, Any]:<br \/>\n        &#034;&#034;&#034;\u9884\u6d4b\u91cd\u8bd5\u6210\u529f\u7684\u6982\u7387\u548c\u6700\u4f73\u7b49\u5f85\u65f6\u95f4&#034;&#034;&#034;<br \/>\n        # \u8f6c\u6362\u4e3aDataFrame<br \/>\n        features_df &#061; pd.DataFrame([features])<\/p>\n<p>        # \u7f16\u7801\u5206\u7c7b\u7279\u5f81<br \/>\n        encoded_features &#061; self._encode_features(features_df)<\/p>\n<p>        # \u9884\u6d4b<br \/>\n        if hasattr(self, &#039;classification_model&#039;) and self.classification_model:<br \/>\n            # \u5206\u7c7b&#xff1a;\u9884\u6d4b\u662f\u5426\u4f1a\u6210\u529f<br \/>\n            success_probability &#061; self.classification_model.predict_proba(<br \/>\n                encoded_features<br \/>\n            )[0][1]  # \u83b7\u53d6\u6b63\u7c7b&#xff08;\u6210\u529f&#xff09;\u7684\u6982\u7387<\/p>\n<p>            # \u56de\u5f52&#xff1a;\u9884\u6d4b\u6700\u4f73\u7b49\u5f85\u65f6\u95f4<br \/>\n            if hasattr(self, &#039;regression_model&#039;) and self.regression_model:<br \/>\n                optimal_wait_time &#061; self.regression_model.predict(<br \/>\n                    encoded_features<br \/>\n                )[0]<br \/>\n            else:<br \/>\n                optimal_wait_time &#061; self._calculate_default_wait_time(<br \/>\n                    features[&#039;retry_count&#039;]<br \/>\n                )<br \/>\n        else:<br \/>\n            # \u6ca1\u6709\u8bad\u7ec3\u597d\u7684\u6a21\u578b&#xff0c;\u4f7f\u7528\u542f\u53d1\u5f0f\u65b9\u6cd5<br \/>\n            success_probability &#061; self._heuristic_success_probability(features)<br \/>\n            optimal_wait_time &#061; self._calculate_default_wait_time(<br \/>\n                features[&#039;retry_count&#039;]<br \/>\n            )<\/p>\n<p>        return {<br \/>\n            &#039;success_probability&#039;: float(success_probability),<br \/>\n            &#039;optimal_wait_time_seconds&#039;: float(optimal_wait_time),<br \/>\n            &#039;should_retry&#039;: success_probability &gt; 0.5,  # \u9608\u503c\u53ef\u4ee5\u8c03\u6574<br \/>\n            &#039;confidence&#039;: min(abs(success_probability &#8211; 0.5) * 2, 1.0)<br \/>\n        }<\/p>\n<p>    def record_retry_outcome(self, features: Dict[str, Any],<br \/>\n                            outcome: Dict[str, Any]):<br \/>\n        &#034;&#034;&#034;\u8bb0\u5f55\u91cd\u8bd5\u7ed3\u679c\u7528\u4e8e\u6a21\u578b\u8bad\u7ec3&#034;&#034;&#034;<br \/>\n        # \u51c6\u5907\u8bad\u7ec3\u6570\u636e<br \/>\n        training_example &#061; features.copy()<br \/>\n        training_example[&#039;retry_success&#039;] &#061; outcome.get(&#039;success&#039;, False)<br \/>\n        training_example[&#039;actual_wait_time&#039;] &#061; outcome.get(&#039;wait_time_seconds&#039;, 0)<\/p>\n<p>        # \u6dfb\u52a0\u65f6\u95f4\u6233<br \/>\n        training_example[&#039;recorded_at&#039;] &#061; datetime.now().isoformat()<\/p>\n<p>        # \u5b58\u50a8<br \/>\n        self.training_data.append(training_example)<\/p>\n<p>        # \u5b9a\u671f\u8bad\u7ec3\u6a21\u578b<br \/>\n        if len(self.training_data) % 1000 &#061;&#061; 0:  # \u6bcf1000\u6761\u8bb0\u5f55\u8bad\u7ec3\u4e00\u6b21<br \/>\n            self.train_models()<\/p>\n<p>    def train_models(self):<br \/>\n        &#034;&#034;&#034;\u8bad\u7ec3\u673a\u5668\u5b66\u4e60\u6a21\u578b&#034;&#034;&#034;<br \/>\n        if len(self.training_data) &lt; 100:<br \/>\n            print(&#034;Not enough training data&#034;)<br \/>\n            return<\/p>\n<p>        # \u8f6c\u6362\u4e3aDataFrame<br \/>\n        df &#061; pd.DataFrame(self.training_data)<\/p>\n<p>        # \u51c6\u5907\u7279\u5f81<br \/>\n        X &#061; df[self.feature_columns].copy()<\/p>\n<p>        # \u7f16\u7801\u5206\u7c7b\u7279\u5f81<br \/>\n        X_encoded &#061; self._encode_features(X, fit&#061;True)<\/p>\n<p>        # \u51c6\u5907\u76ee\u6807\u53d8\u91cf<br \/>\n        y_classification &#061; df[&#039;retry_success&#039;].astype(int)<br \/>\n        y_regression &#061; df[&#039;actual_wait_time&#039;]<\/p>\n<p>        # \u5212\u5206\u8bad\u7ec3\u96c6\u548c\u6d4b\u8bd5\u96c6<br \/>\n        X_train, X_test, y_train_cls, y_test_cls, y_train_reg, y_test_reg &#061; \\\\<br \/>\n            train_test_split(<br \/>\n                X_encoded, y_classification, y_regression,<br \/>\n                test_size&#061;0.2, random_state&#061;42<br \/>\n            )<\/p>\n<p>        # \u8bad\u7ec3\u5206\u7c7b\u6a21\u578b<br \/>\n        print(&#034;Training classification model&#8230;&#034;)<br \/>\n        self.classification_model.fit(X_train, y_train_cls)<\/p>\n<p>        # \u8bc4\u4f30\u5206\u7c7b\u6a21\u578b<br \/>\n        train_score &#061; self.classification_model.score(X_train, y_train_cls)<br \/>\n        test_score &#061; self.classification_model.score(X_test, y_test_cls)<br \/>\n        print(f&#034;Classification model &#8211; Train score: {train_score:.3f}, &#034;<br \/>\n              f&#034;Test score: {test_score:.3f}&#034;)<\/p>\n<p>        # \u8bad\u7ec3\u56de\u5f52\u6a21\u578b&#xff08;\u53ea\u5728\u6210\u529f\u7684\u60c5\u51b5\u4e0b&#xff09;<br \/>\n        success_mask &#061; y_classification &#061;&#061; 1<br \/>\n        if success_mask.sum() &gt; 10:  # \u9700\u8981\u6709\u8db3\u591f\u7684\u6210\u529f\u6837\u672c<br \/>\n            X_success &#061; X_encoded[success_mask]<br \/>\n            y_wait_success &#061; y_regression[success_mask]<\/p>\n<p>            print(&#034;Training regression model&#8230;&#034;)<br \/>\n            self.regression_model.fit(X_success, y_wait_success)<\/p>\n<p>            # \u8bc4\u4f30\u56de\u5f52\u6a21\u578b<br \/>\n            y_pred &#061; self.regression_model.predict(X_success)<br \/>\n            mse &#061; np.mean((y_wait_success &#8211; y_pred) ** 2)<br \/>\n            print(f&#034;Regression model &#8211; MSE: {mse:.3f}&#034;)<\/p>\n<p>        # \u4fdd\u5b58\u6a21\u578b<br \/>\n        if self.model_path:<br \/>\n            self.save_model(self.model_path)<\/p>\n<p>    def _encode_features(self, df: pd.DataFrame, fit: bool &#061; False) -&gt; np.ndarray:<br \/>\n        &#034;&#034;&#034;\u7f16\u7801\u7279\u5f81&#034;&#034;&#034;<br \/>\n        df_encoded &#061; df.copy()<\/p>\n<p>        # \u5bf9\u5206\u7c7b\u7279\u5f81\u8fdb\u884c\u6807\u7b7e\u7f16\u7801<br \/>\n        categorical_columns &#061; [&#039;error_type&#039;, &#039;service_name&#039;, &#039;endpoint&#039;,<br \/>\n                             &#039;client_ip_prefix&#039;]<\/p>\n<p>        for col in categorical_columns:<br \/>\n            if col in df_encoded.columns:<br \/>\n                if fit:<br \/>\n                    # \u62df\u5408\u7f16\u7801\u5668<br \/>\n                    le &#061; LabelEncoder()<br \/>\n                    df_encoded[col] &#061; le.fit_transform(df_encoded[col].fillna(&#039;unknown&#039;))<br \/>\n                    self.label_encoders[col] &#061; le<br \/>\n                else:<br \/>\n                    # \u4f7f\u7528\u5df2\u6709\u7684\u7f16\u7801\u5668<br \/>\n                    if col in self.label_encoders:<br \/>\n                        le &#061; self.label_encoders[col]<br \/>\n                        # \u5904\u7406\u672a\u89c1\u8fc7\u7684\u6807\u7b7e<br \/>\n                        unseen_mask &#061; ~df_encoded[col].isin(le.classes_)<br \/>\n                        df_encoded.loc[unseen_mask, col] &#061; &#039;unknown&#039;<br \/>\n                        df_encoded[col] &#061; le.transform(df_encoded[col].fillna(&#039;unknown&#039;))<\/p>\n<p>        # \u6807\u51c6\u5316\u6570\u503c\u7279\u5f81<br \/>\n        numerical_columns &#061; [&#039;hour_of_day&#039;, &#039;day_of_week&#039;, &#039;response_time_ms&#039;,<br \/>\n                           &#039;status_code&#039;, &#039;retry_count&#039;, &#039;request_size_kb&#039;,<br \/>\n                           &#039;response_size_kb&#039;, &#039;concurrent_requests&#039;]<\/p>\n<p>        numerical_features &#061; df_encoded[numerical_columns].values<\/p>\n<p>        if fit:<br \/>\n            numerical_features &#061; self.scaler.fit_transform(numerical_features)<br \/>\n        else:<br \/>\n            numerical_features &#061; self.scaler.transform(numerical_features)<\/p>\n<p>        # \u5408\u5e76\u7279\u5f81<br \/>\n        categorical_features &#061; df_encoded[categorical_columns].values<br \/>\n        features &#061; np.hstack([numerical_features, categorical_features])<\/p>\n<p>        return features<\/p>\n<p>    def _extract_ip_prefix(self, ip: str) -&gt; str:<br \/>\n        &#034;&#034;&#034;\u63d0\u53d6IP\u5730\u5740\u524d\u7f00&#034;&#034;&#034;<br \/>\n        if &#039;.&#039; in ip:  # IPv4<br \/>\n            parts &#061; ip.split(&#039;.&#039;)<br \/>\n            return &#039;.&#039;.join(parts[:2])  # \u53d6\u524d\u4e24\u4e2a\u516b\u4f4d\u7ec4<br \/>\n        elif &#039;:&#039; in ip:  # IPv6<br \/>\n            # \u7b80\u5316\u5904\u7406&#xff0c;\u53d6\u524d4\u4e2a\u5b57\u7b26<br \/>\n            return ip[:4]<br \/>\n        else:<br \/>\n            return &#039;unknown&#039;<\/p>\n<p>    def _calculate_default_wait_time(self, retry_count: int) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u8ba1\u7b97\u9ed8\u8ba4\u7b49\u5f85\u65f6\u95f4&#xff08;\u6307\u6570\u9000\u907f&#xff09;&#034;&#034;&#034;<br \/>\n        base_delay &#061; 1.0<br \/>\n        max_delay &#061; 60.0<br \/>\n        wait_time &#061; min(base_delay * (2 ** retry_count), max_delay)<br \/>\n        return wait_time<\/p>\n<p>    def _heuristic_success_probability(self, features: Dict[str, Any]) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u542f\u53d1\u5f0f\u65b9\u6cd5\u4f30\u8ba1\u6210\u529f\u6982\u7387&#034;&#034;&#034;<br \/>\n        probability &#061; 0.5  # \u57fa\u7840\u6982\u7387<\/p>\n<p>        # \u57fa\u4e8e\u72b6\u6001\u7801\u8c03\u6574<br \/>\n        status_code &#061; features.get(&#039;status_code&#039;, 0)<br \/>\n        if 500 &lt;&#061; status_code &lt; 600:<br \/>\n            probability -&#061; 0.2  # \u670d\u52a1\u5668\u9519\u8bef&#xff0c;\u6210\u529f\u6982\u7387\u964d\u4f4e<br \/>\n        elif status_code &#061;&#061; 429:<br \/>\n            probability -&#061; 0.1  # \u9650\u6d41\u9519\u8bef&#xff0c;\u6210\u529f\u6982\u7387\u964d\u4f4e<br \/>\n        elif 400 &lt;&#061; status_code &lt; 500:<br \/>\n            probability -&#061; 0.3  # \u5ba2\u6237\u7aef\u9519\u8bef&#xff0c;\u6210\u529f\u6982\u7387\u964d\u4f4e<\/p>\n<p>        # \u57fa\u4e8e\u91cd\u8bd5\u6b21\u6570\u8c03\u6574<br \/>\n        retry_count &#061; features.get(&#039;retry_count&#039;, 0)<br \/>\n        probability -&#061; retry_count * 0.1  # \u91cd\u8bd5\u6b21\u6570\u8d8a\u591a&#xff0c;\u6210\u529f\u6982\u7387\u8d8a\u4f4e<\/p>\n<p>        # \u57fa\u4e8e\u54cd\u5e94\u65f6\u95f4\u8c03\u6574<br \/>\n        response_time &#061; features.get(&#039;response_time_ms&#039;, 0)<br \/>\n        if response_time &gt; 5000:  # 5\u79d2\u4ee5\u4e0a<br \/>\n            probability -&#061; 0.15  # \u54cd\u5e94\u6162&#xff0c;\u6210\u529f\u6982\u7387\u964d\u4f4e<\/p>\n<p>        # \u786e\u4fdd\u57280-1\u8303\u56f4\u5185<br \/>\n        return max(0.0, min(1.0, probability))<\/p>\n<p>    def save_model(self, path: str):<br \/>\n        &#034;&#034;&#034;\u4fdd\u5b58\u6a21\u578b\u5230\u6587\u4ef6&#034;&#034;&#034;<br \/>\n        model_data &#061; {<br \/>\n            &#039;classification_model&#039;: self.classification_model,<br \/>\n            &#039;regression_model&#039;: self.regression_model,<br \/>\n            &#039;label_encoders&#039;: self.label_encoders,<br \/>\n            &#039;scaler&#039;: self.scaler,<br \/>\n            &#039;feature_columns&#039;: self.feature_columns<br \/>\n        }<\/p>\n<p>        joblib.dump(model_data, path)<br \/>\n        print(f&#034;Model saved to {path}&#034;)<\/p>\n<p>    def load_model(self, path: str):<br \/>\n        &#034;&#034;&#034;\u4ece\u6587\u4ef6\u52a0\u8f7d\u6a21\u578b&#034;&#034;&#034;<br \/>\n        try:<br \/>\n            model_data &#061; joblib.load(path)<br \/>\n            self.classification_model &#061; model_data[&#039;classification_model&#039;]<br \/>\n            self.regression_model &#061; model_data[&#039;regression_model&#039;]<br \/>\n            self.label_encoders &#061; model_data[&#039;label_encoders&#039;]<br \/>\n            self.scaler &#061; model_data[&#039;scaler&#039;]<br \/>\n            self.feature_columns &#061; model_data[&#039;feature_columns&#039;]<br \/>\n            print(f&#034;Model loaded from {path}&#034;)<br \/>\n        except Exception as e:<br \/>\n            print(f&#034;Failed to load model: {e}&#034;)<\/p>\n<p># \u4f7f\u7528\u793a\u4f8b<br \/>\nclass SmartRetryManager:<br \/>\n    &#034;&#034;&#034;\u667a\u80fd\u91cd\u8bd5\u7ba1\u7406\u5668&#034;&#034;&#034;<\/p>\n<p>    def __init__(self, ml_optimizer: MLRetryOptimizer &#061; None):<br \/>\n        self.ml_optimizer &#061; ml_optimizer or MLRetryOptimizer()<br \/>\n        self.retry_history &#061; {}<\/p>\n<p>    async def execute_with_smart_retry(<br \/>\n        self,<br \/>\n        operation: callable,<br \/>\n        operation_id: str,<br \/>\n        context: Dict[str, Any],<br \/>\n        max_attempts: int &#061; 5<br \/>\n    ) -&gt; Any:<br \/>\n        &#034;&#034;&#034;\u4f7f\u7528\u667a\u80fd\u91cd\u8bd5\u6267\u884c\u64cd\u4f5c&#034;&#034;&#034;<\/p>\n<p>        attempt &#061; 0<br \/>\n        last_error &#061; None<\/p>\n<p>        while attempt &lt; max_attempts:<br \/>\n            try:<br \/>\n                # \u6267\u884c\u64cd\u4f5c<br \/>\n                result &#061; await operation()<\/p>\n<p>                # \u8bb0\u5f55\u6210\u529f<br \/>\n                self._record_success(operation_id, attempt, context)<br \/>\n                return result<\/p>\n<p>            except Exception as e:<br \/>\n                attempt &#043;&#061; 1<br \/>\n                last_error &#061; e<\/p>\n<p>                # \u5206\u6790\u9519\u8bef<br \/>\n                error_analysis &#061; self._analyze_error(e, attempt)<\/p>\n<p>                # \u63d0\u53d6\u7279\u5f81<br \/>\n                features &#061; self.ml_optimizer.extract_features(<br \/>\n                    context, error_analysis<br \/>\n                )<\/p>\n<p>                # \u9884\u6d4b\u91cd\u8bd5\u6210\u529f\u7684\u6982\u7387<br \/>\n                if self.ml_optimizer:<br \/>\n                    prediction &#061; self.ml_optimizer.predict_retry_success(features)<\/p>\n<p>                    # \u6839\u636e\u9884\u6d4b\u51b3\u5b9a\u662f\u5426\u91cd\u8bd5<br \/>\n                    if not prediction[&#039;should_retry&#039;]:<br \/>\n                        print(f&#034;Predicted low success probability: &#034;<br \/>\n                              f&#034;{prediction[&#039;success_probability&#039;]:.2f}&#034;)<br \/>\n                        break<\/p>\n<p>                    # \u4f7f\u7528\u9884\u6d4b\u7684\u6700\u4f73\u7b49\u5f85\u65f6\u95f4<br \/>\n                    wait_time &#061; prediction[&#039;optimal_wait_time_seconds&#039;]<br \/>\n                else:<br \/>\n                    # \u4f7f\u7528\u9ed8\u8ba4\u7684\u9000\u907f\u7b56\u7565<br \/>\n                    wait_time &#061; self._calculate_backoff(attempt)<\/p>\n<p>                # \u7b49\u5f85<br \/>\n                print(f&#034;Attempt {attempt} failed, waiting {wait_time:.1f}s before retry&#8230;&#034;)<br \/>\n                await asyncio.sleep(wait_time)<\/p>\n<p>        # \u6240\u6709\u91cd\u8bd5\u90fd\u5931\u8d25\u4e86<br \/>\n        self._record_failure(operation_id, attempt, context, last_error)<br \/>\n        raise last_error<\/p>\n<p>    def _analyze_error(self, error: Exception, attempt: int) -&gt; Dict[str, Any]:<br \/>\n        &#034;&#034;&#034;\u5206\u6790\u9519\u8bef&#034;&#034;&#034;<br \/>\n        analysis &#061; {<br \/>\n            &#039;error_type&#039;: error.__class__.__name__,<br \/>\n            &#039;error_message&#039;: str(error),<br \/>\n            &#039;retry_count&#039;: attempt,<br \/>\n            &#039;timestamp&#039;: datetime.now().isoformat()<br \/>\n        }<\/p>\n<p>        # \u63d0\u53d6\u72b6\u6001\u7801&#xff08;\u5982\u679c\u53ef\u7528&#xff09;<br \/>\n        if hasattr(error, &#039;status_code&#039;):<br \/>\n            analysis[&#039;status_code&#039;] &#061; error.status_code<\/p>\n<p>        # \u63d0\u53d6\u54cd\u5e94\u65f6\u95f4&#xff08;\u5982\u679c\u53ef\u7528&#xff09;<br \/>\n        if hasattr(error, &#039;response_time_ms&#039;):<br \/>\n            analysis[&#039;response_time_ms&#039;] &#061; error.response_time_ms<\/p>\n<p>        return analysis<\/p>\n<p>    def _calculate_backoff(self, attempt: int) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u8ba1\u7b97\u9000\u907f\u65f6\u95f4&#034;&#034;&#034;<br \/>\n        base_delay &#061; 1.0<br \/>\n        max_delay &#061; 60.0<br \/>\n        return min(base_delay * (2 ** (attempt &#8211; 1)), max_delay)<\/p>\n<p>    def _record_success(self, operation_id: str, attempt: int,<br \/>\n                       context: Dict[str, Any]):<br \/>\n        &#034;&#034;&#034;\u8bb0\u5f55\u6210\u529f&#034;&#034;&#034;<br \/>\n        if self.ml_optimizer:<br \/>\n            # \u4e3a\u673a\u5668\u5b66\u4e60\u51c6\u5907\u6570\u636e<br \/>\n            features &#061; self.ml_optimizer.extract_features(context, {<br \/>\n                &#039;retry_count&#039;: attempt<br \/>\n            })<\/p>\n<p>            # \u8bb0\u5f55\u6210\u529f\u7ed3\u679c<br \/>\n            self.ml_optimizer.record_retry_outcome(features, {<br \/>\n                &#039;success&#039;: True,<br \/>\n                &#039;wait_time_seconds&#039;: 0<br \/>\n            })<\/p>\n<p>        # \u66f4\u65b0\u5386\u53f2\u8bb0\u5f55<br \/>\n        if operation_id not in self.retry_history:<br \/>\n            self.retry_history[operation_id] &#061; []<\/p>\n<p>        self.retry_history[operation_id].append({<br \/>\n            &#039;timestamp&#039;: datetime.now().isoformat(),<br \/>\n            &#039;attempt&#039;: attempt,<br \/>\n            &#039;success&#039;: True<br \/>\n        })<\/p>\n<p>    def _record_failure(self, operation_id: str, attempt: int,<br \/>\n                       context: Dict[str, Any], error: Exception):<br \/>\n        &#034;&#034;&#034;\u8bb0\u5f55\u5931\u8d25&#034;&#034;&#034;<br \/>\n        if self.ml_optimizer:<br \/>\n            # \u4e3a\u673a\u5668\u5b66\u4e60\u51c6\u5907\u6570\u636e<br \/>\n            features &#061; self.ml_optimizer.extract_features(context, {<br \/>\n                &#039;retry_count&#039;: attempt,<br \/>\n                &#039;error_type&#039;: error.__class__.__name__,<br \/>\n                &#039;status_code&#039;: getattr(error, &#039;status_code&#039;, None)<br \/>\n            })<\/p>\n<p>            # \u8bb0\u5f55\u5931\u8d25\u7ed3\u679c<br \/>\n            self.ml_optimizer.record_retry_outcome(features, {<br \/>\n                &#039;success&#039;: False,<br \/>\n                &#039;wait_time_seconds&#039;: 0<br \/>\n            })<\/p>\n<p>        # \u66f4\u65b0\u5386\u53f2\u8bb0\u5f55<br \/>\n        if operation_id not in self.retry_history:<br \/>\n            self.retry_history[operation_id] &#061; []<\/p>\n<p>        self.retry_history[operation_id].append({<br \/>\n            &#039;timestamp&#039;: datetime.now().isoformat(),<br \/>\n            &#039;attempt&#039;: attempt,<br \/>\n            &#039;success&#039;: False,<br \/>\n            &#039;error&#039;: str(error)<br \/>\n        })<\/p>\n<p># \u5f02\u6b65\u4f7f\u7528\u793a\u4f8b<br \/>\nimport asyncio<\/p>\n<p>async def example_usage():<br \/>\n    # \u521b\u5efa\u667a\u80fd\u91cd\u8bd5\u7ba1\u7406\u5668<br \/>\n    retry_manager &#061; SmartRetryManager()<\/p>\n<p>    # \u6a21\u62df\u4e00\u4e2a\u53ef\u80fd\u5931\u8d25\u7684\u64cd\u4f5c<br \/>\n    class ExternalServiceError(Exception):<br \/>\n        def __init__(self, status_code, message):<br \/>\n            self.status_code &#061; status_code<br \/>\n            self.message &#061; message<br \/>\n            super().__init__(f&#034;{status_code}: {message}&#034;)<\/p>\n<p>    async def call_external_service():<br \/>\n        # \u6a21\u62df\u5916\u90e8\u670d\u52a1\u8c03\u7528<br \/>\n        import random<\/p>\n<p>        # \u968f\u673a\u5931\u8d25<br \/>\n        if random.random() &lt; 0.7:  # 70%\u7684\u6982\u7387\u5931\u8d25<br \/>\n            raise ExternalServiceError(<br \/>\n                503,<br \/>\n                &#034;Service temporarily unavailable&#034;<br \/>\n            )<\/p>\n<p>        return {&#034;data&#034;: &#034;success&#034;}<\/p>\n<p>    # \u51c6\u5907\u4e0a\u4e0b\u6587<br \/>\n    context &#061; {<br \/>\n        &#039;service_name&#039;: &#039;external-api&#039;,<br \/>\n        &#039;endpoint&#039;: &#039;\/api\/data&#039;,<br \/>\n        &#039;client_ip&#039;: &#039;192.168.1.100&#039;,<br \/>\n        &#039;timestamp&#039;: datetime.now(),<br \/>\n        &#039;request_size_kb&#039;: 2.5,<br \/>\n        &#039;concurrent_requests&#039;: 10<br \/>\n    }<\/p>\n<p>    try:<br \/>\n        # \u4f7f\u7528\u667a\u80fd\u91cd\u8bd5\u6267\u884c<br \/>\n        result &#061; await retry_manager.execute_with_smart_retry(<br \/>\n            call_external_service,<br \/>\n            operation_id&#061;&#034;external_api_call_001&#034;,<br \/>\n            context&#061;context,<br \/>\n            max_attempts&#061;5<br \/>\n        )<\/p>\n<p>        print(f&#034;\u64cd\u4f5c\u6210\u529f: {result}&#034;)<\/p>\n<p>    except Exception as e:<br \/>\n        print(f&#034;\u64cd\u4f5c\u6700\u7ec8\u5931\u8d25: {e}&#034;)<\/p>\n<p># \u8fd0\u884c\u793a\u4f8b<br \/>\nif __name__ &#061;&#061; &#034;__main__&#034;:<br \/>\n    asyncio.run(example_usage())<\/p>\n<h3>34.4 \u9519\u8bef\u76d1\u63a7\u4e0e\u544a\u8b66<\/h3>\n<h4>34.4.1 \u5b9e\u65f6\u9519\u8bef\u76d1\u63a7\u7cfb\u7edf<\/h4>\n<p>typescript<\/p>\n<p>\/\/ TypeScript\u5b9e\u65f6\u9519\u8bef\u76d1\u63a7\u7cfb\u7edf<br \/>\nimport { EventEmitter } from &#039;events&#039;;<br \/>\nimport { createHash } from &#039;crypto&#039;;<br \/>\nimport WebSocket from &#039;ws&#039;;<\/p>\n<p>interface ErrorEvent {<br \/>\n  id: string;<br \/>\n  timestamp: Date;<br \/>\n  service: string;<br \/>\n  endpoint: string;<br \/>\n  statusCode: number;<br \/>\n  errorType: string;<br \/>\n  errorMessage: string;<br \/>\n  stackTrace?: string;<br \/>\n  context: Record&lt;string, any&gt;;<br \/>\n  severity: &#039;LOW&#039; | &#039;MEDIUM&#039; | &#039;HIGH&#039; | &#039;CRITICAL&#039;;<br \/>\n  environment: &#039;development&#039; | &#039;staging&#039; | &#039;production&#039;;<br \/>\n}<\/p>\n<p>interface ErrorAggregate {<br \/>\n  errorHash: string;<br \/>\n  firstOccurrence: Date;<br \/>\n  lastOccurrence: Date;<br \/>\n  count: number;<br \/>\n  affectedServices: Set&lt;string&gt;;<br \/>\n  affectedEndpoints: Set&lt;string&gt;;<br \/>\n  statusCodes: Set&lt;number&gt;;<br \/>\n  sampleError: ErrorEvent;<br \/>\n}<\/p>\n<p>interface AlertRule {<br \/>\n  id: string;<br \/>\n  name: string;<br \/>\n  description: string;<br \/>\n  condition: (aggregate: ErrorAggregate) &#061;&gt; boolean;<br \/>\n  severity: &#039;LOW&#039; | &#039;MEDIUM&#039; | &#039;HIGH&#039; | &#039;CRITICAL&#039;;<br \/>\n  actions: string[];<br \/>\n}<\/p>\n<p>class RealTimeErrorMonitor extends EventEmitter {<br \/>\n  private errors: Map&lt;string, ErrorEvent[]&gt; &#061; new Map();<br \/>\n  private aggregates: Map&lt;string, ErrorAggregate&gt; &#061; new Map();<br \/>\n  private alertRules: AlertRule[] &#061; [];<br \/>\n  private webSocketServer: WebSocket.Server;<br \/>\n  private aggregationWindow: number &#061; 60000; \/\/ 1\u5206\u949f<\/p>\n<p>  constructor(port: number &#061; 8080) {<br \/>\n    super();<\/p>\n<p>    \/\/ \u521d\u59cb\u5316WebSocket\u670d\u52a1\u5668<br \/>\n    this.webSocketServer &#061; new WebSocket.Server({ port });<br \/>\n    this.setupWebSocket();<\/p>\n<p>    \/\/ \u521d\u59cb\u5316\u9ed8\u8ba4\u544a\u8b66\u89c4\u5219<br \/>\n    this.initializeDefaultRules();<\/p>\n<p>    \/\/ \u5b9a\u671f\u6e05\u7406\u65e7\u6570\u636e<br \/>\n    setInterval(() &#061;&gt; this.cleanupOldData(), 3600000); \/\/ \u6bcf\u5c0f\u65f6\u6e05\u7406\u4e00\u6b21<br \/>\n  }<\/p>\n<p>  recordError(error: Omit&lt;ErrorEvent, &#039;id&#039; | &#039;timestamp&#039;&gt;): string {<br \/>\n    const errorEvent: ErrorEvent &#061; {<br \/>\n      id: this.generateErrorId(),<br \/>\n      timestamp: new Date(),<br \/>\n      &#8230;error<br \/>\n    };<\/p>\n<p>    \/\/ \u5b58\u50a8\u539f\u59cb\u9519\u8bef<br \/>\n    const key &#061; this.getStorageKey(errorEvent);<br \/>\n    if (!this.errors.has(key)) {<br \/>\n      this.errors.set(key, []);<br \/>\n    }<br \/>\n    this.errors.get(key)!.push(errorEvent);<\/p>\n<p>    \/\/ \u805a\u5408\u9519\u8bef<br \/>\n    this.aggregateError(errorEvent);<\/p>\n<p>    \/\/ \u89e6\u53d1\u4e8b\u4ef6<br \/>\n    this.emit(&#039;errorRecorded&#039;, errorEvent);<\/p>\n<p>    \/\/ \u68c0\u67e5\u544a\u8b66\u89c4\u5219<br \/>\n    this.checkAlertRules(errorEvent);<\/p>\n<p>    \/\/ \u5e7f\u64ad\u5230WebSocket\u5ba2\u6237\u7aef<br \/>\n    this.broadcastError(errorEvent);<\/p>\n<p>    return errorEvent.id;<br \/>\n  }<\/p>\n<p>  private generateErrorId(): string {<br \/>\n    return createHash(&#039;sha256&#039;)<br \/>\n      .update(Date.now().toString() &#043; Math.random().toString())<br \/>\n      .digest(&#039;hex&#039;)<br \/>\n      .substring(0, 16);<br \/>\n  }<\/p>\n<p>  private getStorageKey(error: ErrorEvent): string {<br \/>\n    \/\/ \u6309\u670d\u52a1\u3001\u9519\u8bef\u7c7b\u578b\u548c\u65e5\u671f\u5206\u7ec4\u5b58\u50a8<br \/>\n    const date &#061; error.timestamp.toISOString().split(&#039;T&#039;)[0];<br \/>\n    return &#096;${error.service}:${error.errorType}:${date}&#096;;<br \/>\n  }<\/p>\n<p>  private aggregateError(error: ErrorEvent): void {<br \/>\n    const errorHash &#061; this.calculateErrorHash(error);<\/p>\n<p>    if (!this.aggregates.has(errorHash)) {<br \/>\n      this.aggregates.set(errorHash, {<br \/>\n        errorHash,<br \/>\n        firstOccurrence: error.timestamp,<br \/>\n        lastOccurrence: error.timestamp,<br \/>\n        count: 1,<br \/>\n        affectedServices: new Set([error.service]),<br \/>\n        affectedEndpoints: new Set([error.endpoint]),<br \/>\n        statusCodes: new Set([error.statusCode]),<br \/>\n        sampleError: error<br \/>\n      });<br \/>\n    } else {<br \/>\n      const aggregate &#061; this.aggregates.get(errorHash)!;<br \/>\n      aggregate.count&#043;&#043;;<br \/>\n      aggregate.lastOccurrence &#061; error.timestamp;<br \/>\n      aggregate.affectedServices.add(error.service);<br \/>\n      aggregate.affectedEndpoints.add(error.endpoint);<br \/>\n      aggregate.statusCodes.add(error.statusCode);<br \/>\n    }<\/p>\n<p>    \/\/ \u89e6\u53d1\u805a\u5408\u66f4\u65b0\u4e8b\u4ef6<br \/>\n    this.emit(&#039;aggregateUpdated&#039;, this.aggregates.get(errorHash));<br \/>\n  }<\/p>\n<p>  private calculateErrorHash(error: ErrorEvent): string {<br \/>\n    \/\/ \u57fa\u4e8e\u9519\u8bef\u7279\u5f81\u8ba1\u7b97\u54c8\u5e0c<br \/>\n    const errorFingerprint &#061; {<br \/>\n      service: error.service,<br \/>\n      errorType: error.errorType,<br \/>\n      statusCode: error.statusCode,<br \/>\n      \/\/ \u53ef\u4ee5\u6dfb\u52a0\u66f4\u591a\u7279\u5f81<br \/>\n    };<\/p>\n<p>    return createHash(&#039;sha256&#039;)<br \/>\n      .update(JSON.stringify(errorFingerprint))<br \/>\n      .digest(&#039;hex&#039;)<br \/>\n      .substring(0, 16);<br \/>\n  }<\/p>\n<p>  private initializeDefaultRules(): void {<br \/>\n    this.alertRules &#061; [<br \/>\n      {<br \/>\n        id: &#039;high-error-rate&#039;,<br \/>\n        name: &#039;\u9ad8\u9519\u8bef\u7387\u544a\u8b66&#039;,<br \/>\n        description: &#039;\u77ed\u65f6\u95f4\u5185\u76f8\u540c\u9519\u8bef\u53d1\u751f\u591a\u6b21&#039;,<br \/>\n        condition: (aggregate) &#061;&gt; {<br \/>\n          const timeWindow &#061; 5 * 60 * 1000; \/\/ 5\u5206\u949f<br \/>\n          const timeDiff &#061; aggregate.lastOccurrence.getTime() &#8211;<br \/>\n                          aggregate.firstOccurrence.getTime();<\/p>\n<p>          if (timeDiff &lt; timeWindow &amp;&amp; aggregate.count &gt;&#061; 10) {<br \/>\n            const rate &#061; aggregate.count \/ (timeDiff \/ 60000); \/\/ \u6bcf\u5206\u949f\u9519\u8bef\u6570<br \/>\n            return rate &gt;&#061; 2; \/\/ \u6bcf\u5206\u949f2\u4e2a\u4ee5\u4e0a\u76f8\u540c\u9519\u8bef<br \/>\n          }<br \/>\n          return false;<br \/>\n        },<br \/>\n        severity: &#039;HIGH&#039;,<br \/>\n        actions: [&#039;email&#039;, &#039;slack&#039;, &#039;pagerduty&#039;]<br \/>\n      },<br \/>\n      {<br \/>\n        id: &#039;critical-errors&#039;,<br \/>\n        name: &#039;\u5173\u952e\u9519\u8bef\u544a\u8b66&#039;,<br \/>\n        description: &#039;\u51fa\u73b0\u4e25\u91cd\u7ea7\u522b\u7684\u9519\u8bef&#039;,<br \/>\n        condition: (aggregate) &#061;&gt; {<br \/>\n          return aggregate.sampleError.severity &#061;&#061;&#061; &#039;CRITICAL&#039;;<br \/>\n        },<br \/>\n        severity: &#039;CRITICAL&#039;,<br \/>\n        actions: [&#039;pagerduty&#039;, &#039;sms&#039;, &#039;phone&#039;]<br \/>\n      },<br \/>\n      {<br \/>\n        id: &#039;service-outage&#039;,<br \/>\n        name: &#039;\u670d\u52a1\u4e2d\u65ad\u544a\u8b66&#039;,<br \/>\n        description: &#039;\u540c\u4e00\u670d\u52a1\u51fa\u73b0\u5927\u91cf\u4e0d\u540c\u9519\u8bef&#039;,<br \/>\n        condition: (aggregate) &#061;&gt; {<br \/>\n          \/\/ \u68c0\u67e5\u8fc7\u53bb10\u5206\u949f\u5185\u540c\u4e00\u670d\u52a1\u7684\u9519\u8bef\u6570\u91cf<br \/>\n          const tenMinutesAgo &#061; new Date(Date.now() &#8211; 10 * 60 * 1000);<br \/>\n          const serviceErrors &#061; Array.from(this.aggregates.values())<br \/>\n            .filter(agg &#061;&gt; agg.affectedServices.has(aggregate.sampleError.service))<br \/>\n            .filter(agg &#061;&gt; agg.lastOccurrence &gt; tenMinutesAgo);<\/p>\n<p>          const totalErrors &#061; serviceErrors.reduce((sum, agg) &#061;&gt; sum &#043; agg.count, 0);<br \/>\n          return totalErrors &gt;&#061; 50;<br \/>\n        },<br \/>\n        severity: &#039;CRITICAL&#039;,<br \/>\n        actions: [&#039;pagerduty&#039;, &#039;sms&#039;, &#039;phone&#039;]<br \/>\n      },<br \/>\n      {<br \/>\n        id: &#039;status-code-5xx&#039;,<br \/>\n        name: &#039;5xx\u9519\u8bef\u544a\u8b66&#039;,<br \/>\n        description: &#039;\u51fa\u73b0\u670d\u52a1\u5668\u9519\u8bef&#039;,<br \/>\n        condition: (aggregate) &#061;&gt; {<br \/>\n          return Array.from(aggregate.statusCodes)<br \/>\n            .some(code &#061;&gt; code &gt;&#061; 500 &amp;&amp; code &lt; 600);<br \/>\n        },<br \/>\n        severity: &#039;HIGH&#039;,<br \/>\n        actions: [&#039;email&#039;, &#039;slack&#039;]<br \/>\n      }<br \/>\n    ];<br \/>\n  }<\/p>\n<p>  private checkAlertRules(error: ErrorEvent): void {<br \/>\n    const errorHash &#061; this.calculateErrorHash(error);<br \/>\n    const aggregate &#061; this.aggregates.get(errorHash);<\/p>\n<p>    if (!aggregate) return;<\/p>\n<p>    for (const rule of this.alertRules) {<br \/>\n      if (rule.condition(aggregate)) {<br \/>\n        this.triggerAlert(rule, aggregate);<br \/>\n      }<br \/>\n    }<br \/>\n  }<\/p>\n<p>  private triggerAlert(rule: AlertRule, aggregate: ErrorAggregate): void {<br \/>\n    const alert &#061; {<br \/>\n      id: createHash(&#039;sha256&#039;)<br \/>\n        .update(rule.id &#043; aggregate.errorHash &#043; Date.now().toString())<br \/>\n        .digest(&#039;hex&#039;)<br \/>\n        .substring(0, 16),<br \/>\n      rule,<br \/>\n      aggregate,<br \/>\n      timestamp: new Date(),<br \/>\n      acknowledged: false,<br \/>\n      resolved: false<br \/>\n    };<\/p>\n<p>    \/\/ \u89e6\u53d1\u544a\u8b66\u4e8b\u4ef6<br \/>\n    this.emit(&#039;alertTriggered&#039;, alert);<\/p>\n<p>    \/\/ \u6267\u884c\u544a\u8b66\u52a8\u4f5c<br \/>\n    this.executeAlertActions(alert);<\/p>\n<p>    \/\/ \u5e7f\u64ad\u5230WebSocket\u5ba2\u6237\u7aef<br \/>\n    this.broadcastAlert(alert);<br \/>\n  }<\/p>\n<p>  private executeAlertActions(alert: any): void {<br \/>\n    for (const action of alert.rule.actions) {<br \/>\n      switch (action) {<br \/>\n        case &#039;email&#039;:<br \/>\n          this.sendEmailAlert(alert);<br \/>\n          break;<br \/>\n        case &#039;slack&#039;:<br \/>\n          this.sendSlackAlert(alert);<br \/>\n          break;<br \/>\n        case &#039;pagerduty&#039;:<br \/>\n          this.sendPagerDutyAlert(alert);<br \/>\n          break;<br \/>\n        case &#039;sms&#039;:<br \/>\n          this.sendSmsAlert(alert);<br \/>\n          break;<br \/>\n        case &#039;phone&#039;:<br \/>\n          this.makePhoneCall(alert);<br \/>\n          break;<br \/>\n      }<br \/>\n    }<br \/>\n  }<\/p>\n<p>  private sendEmailAlert(alert: any): void {<br \/>\n    const emailContent &#061; this.formatEmailAlert(alert);<br \/>\n    console.log(&#039;Sending email alert:&#039;, emailContent.subject);<br \/>\n    \/\/ \u5b9e\u9645\u5b9e\u73b0\u5e94\u8be5\u8c03\u7528\u90ae\u4ef6\u670d\u52a1<br \/>\n  }<\/p>\n<p>  private sendSlackAlert(alert: any): void {<br \/>\n    const slackMessage &#061; this.formatSlackAlert(alert);<br \/>\n    console.log(&#039;Sending Slack alert:&#039;, slackMessage);<br \/>\n    \/\/ \u5b9e\u9645\u5b9e\u73b0\u5e94\u8be5\u8c03\u7528Slack Webhook<br \/>\n  }<\/p>\n<p>  private formatEmailAlert(alert: any): { subject: string; body: string } {<br \/>\n    return {<br \/>\n      subject: &#096;[${alert.rule.severity}] ${alert.rule.name} &#8211; ${alert.aggregate.sampleError.service}&#096;,<br \/>\n      body: &#096;<br \/>\n        Alert: ${alert.rule.name}<br \/>\n        Description: ${alert.rule.description}<\/p>\n<p>        Error Details:<br \/>\n        &#8211; Service: ${alert.aggregate.sampleError.service}<br \/>\n        &#8211; Endpoint: ${alert.aggregate.sampleError.endpoint}<br \/>\n        &#8211; Error Type: ${alert.aggregate.sampleError.errorType}<br \/>\n        &#8211; Status Code: ${alert.aggregate.sampleError.statusCode}<br \/>\n        &#8211; Occurrences: ${alert.aggregate.count}<br \/>\n        &#8211; First Occurrence: ${alert.aggregate.firstOccurrence.toISOString()}<br \/>\n        &#8211; Last Occurrence: ${alert.aggregate.lastOccurrence.toISOString()}<\/p>\n<p>        Sample Error Message: ${alert.aggregate.sampleError.errorMessage}<\/p>\n<p>        Please investigate immediately.<br \/>\n      &#096;<br \/>\n    };<br \/>\n  }<\/p>\n<p>  private formatSlackAlert(alert: any): any {<br \/>\n    const severityColors &#061; {<br \/>\n      &#039;LOW&#039;: &#039;#36a64f&#039;,    \/\/ \u7eff\u8272<br \/>\n      &#039;MEDIUM&#039;: &#039;#ffcc00&#039;, \/\/ \u9ec4\u8272<br \/>\n      &#039;HIGH&#039;: &#039;#ff9900&#039;,   \/\/ \u6a59\u8272<br \/>\n      &#039;CRITICAL&#039;: &#039;#ff0000&#039; \/\/ \u7ea2\u8272<br \/>\n    };<\/p>\n<p>    return {<br \/>\n      attachments: [{<br \/>\n        color: severityColors[alert.rule.severity],<br \/>\n        title: &#096;&#x1f6a8; ${alert.rule.name}&#096;,<br \/>\n        text: alert.rule.description,<br \/>\n        fields: [<br \/>\n          {<br \/>\n            title: &#039;Service&#039;,<br \/>\n            value: alert.aggregate.sampleError.service,<br \/>\n            short: true<br \/>\n          },<br \/>\n          {<br \/>\n            title: &#039;Error Count&#039;,<br \/>\n            value: alert.aggregate.count.toString(),<br \/>\n            short: true<br \/>\n          },<br \/>\n          {<br \/>\n            title: &#039;Status Code&#039;,<br \/>\n            value: alert.aggregate.sampleError.statusCode.toString(),<br \/>\n            short: true<br \/>\n          },<br \/>\n          {<br \/>\n            title: &#039;Environment&#039;,<br \/>\n            value: alert.aggregate.sampleError.environment,<br \/>\n            short: true<br \/>\n          }<br \/>\n        ],<br \/>\n        footer: &#096;Alert ID: ${alert.id}&#096;,<br \/>\n        ts: Math.floor(alert.timestamp.getTime() \/ 1000)<br \/>\n      }]<br \/>\n    };<br \/>\n  }<\/p>\n<p>  private setupWebSocket(): void {<br \/>\n    this.webSocketServer.on(&#039;connection&#039;, (ws) &#061;&gt; {<br \/>\n      console.log(&#039;New WebSocket connection&#039;);<\/p>\n<p>      \/\/ \u53d1\u9001\u5f53\u524d\u72b6\u6001<br \/>\n      ws.send(JSON.stringify({<br \/>\n        type: &#039;INITIAL_STATE&#039;,<br \/>\n        data: {<br \/>\n          activeAlerts: Array.from(this.aggregates.values())<br \/>\n            .filter(agg &#061;&gt; this.shouldShowAggregate(agg)),<br \/>\n          recentErrors: this.getRecentErrors(50)<br \/>\n        }<br \/>\n      }));<\/p>\n<p>      ws.on(&#039;message&#039;, (message) &#061;&gt; {<br \/>\n        this.handleWebSocketMessage(ws, message.toString());<br \/>\n      });<\/p>\n<p>      ws.on(&#039;close&#039;, () &#061;&gt; {<br \/>\n        console.log(&#039;WebSocket connection closed&#039;);<br \/>\n      });<br \/>\n    });<br \/>\n  }<\/p>\n<p>  private handleWebSocketMessage(ws: WebSocket, message: string): void {<br \/>\n    try {<br \/>\n      const data &#061; JSON.parse(message);<\/p>\n<p>      switch (data.type) {<br \/>\n        case &#039;SUBSCRIBE&#039;:<br \/>\n          this.handleSubscribe(ws, data.channel);<br \/>\n          break;<br \/>\n        case &#039;UNSUBSCRIBE&#039;:<br \/>\n          this.handleUnsubscribe(ws, data.channel);<br \/>\n          break;<br \/>\n        case &#039;ACKNOWLEDGE_ALERT&#039;:<br \/>\n          this.handleAcknowledgeAlert(data.alertId);<br \/>\n          break;<br \/>\n      }<br \/>\n    } catch (error) {<br \/>\n      console.error(&#039;Error handling WebSocket message:&#039;, error);<br \/>\n    }<br \/>\n  }<\/p>\n<p>  private handleSubscribe(ws: WebSocket, channel: string): void {<br \/>\n    \/\/ \u5b9e\u9645\u5b9e\u73b0\u5e94\u8be5\u7ba1\u7406\u8ba2\u9605\u5173\u7cfb<br \/>\n    console.log(&#096;Client subscribed to ${channel}&#096;);<br \/>\n  }<\/p>\n<p>  private broadcastError(error: ErrorEvent): void {<br \/>\n    const message &#061; JSON.stringify({<br \/>\n      type: &#039;NEW_ERROR&#039;,<br \/>\n      data: error<br \/>\n    });<\/p>\n<p>    this.webSocketServer.clients.forEach((client) &#061;&gt; {<br \/>\n      if (client.readyState &#061;&#061;&#061; WebSocket.OPEN) {<br \/>\n        client.send(message);<br \/>\n      }<br \/>\n    });<br \/>\n  }<\/p>\n<p>  private broadcastAlert(alert: any): void {<br \/>\n    const message &#061; JSON.stringify({<br \/>\n      type: &#039;NEW_ALERT&#039;,<br \/>\n      data: alert<br \/>\n    });<\/p>\n<p>    this.webSocketServer.clients.forEach((client) &#061;&gt; {<br \/>\n      if (client.readyState &#061;&#061;&#061; WebSocket.OPEN) {<br \/>\n        client.send(message);<br \/>\n      }<br \/>\n    });<br \/>\n  }<\/p>\n<p>  private getRecentErrors(count: number): ErrorEvent[] {<br \/>\n    const allErrors: ErrorEvent[] &#061; [];<\/p>\n<p>    for (const errors of this.errors.values()) {<br \/>\n      allErrors.push(&#8230;errors);<br \/>\n    }<\/p>\n<p>    return allErrors<br \/>\n      .sort((a, b) &#061;&gt; b.timestamp.getTime() &#8211; a.timestamp.getTime())<br \/>\n      .slice(0, count);<br \/>\n  }<\/p>\n<p>  private shouldShowAggregate(aggregate: ErrorAggregate): boolean {<br \/>\n    \/\/ \u53ea\u663e\u793a\u6700\u8fd1\u6d3b\u8dc3\u7684\u805a\u5408<br \/>\n    const fiveMinutesAgo &#061; new Date(Date.now() &#8211; 5 * 60 * 1000);<br \/>\n    return aggregate.lastOccurrence &gt; fiveMinutesAgo &amp;&amp; aggregate.count &gt;&#061; 5;<br \/>\n  }<\/p>\n<p>  private cleanupOldData(): void {<br \/>\n    const twentyFourHoursAgo &#061; new Date(Date.now() &#8211; 24 * 60 * 60 * 1000);<\/p>\n<p>    \/\/ \u6e05\u7406\u65e7\u9519\u8bef<br \/>\n    for (const [key, errors] of this.errors) {<br \/>\n      const recentErrors &#061; errors.filter(error &#061;&gt;<br \/>\n        error.timestamp &gt; twentyFourHoursAgo<br \/>\n      );<\/p>\n<p>      if (recentErrors.length &#061;&#061;&#061; 0) {<br \/>\n        this.errors.delete(key);<br \/>\n      } else {<br \/>\n        this.errors.set(key, recentErrors);<br \/>\n      }<br \/>\n    }<\/p>\n<p>    \/\/ \u6e05\u7406\u65e7\u805a\u5408<br \/>\n    for (const [hash, aggregate] of this.aggregates) {<br \/>\n      if (aggregate.lastOccurrence &lt; twentyFourHoursAgo) {<br \/>\n        this.aggregates.delete(hash);<br \/>\n      }<br \/>\n    }<\/p>\n<p>    console.log(&#039;Cleanup completed&#039;);<br \/>\n  }<\/p>\n<p>  \/\/ \u516c\u5171API\u65b9\u6cd5<br \/>\n  getErrorStatistics(): any {<br \/>\n    const now &#061; new Date();<br \/>\n    const oneHourAgo &#061; new Date(now.getTime() &#8211; 60 * 60 * 1000);<br \/>\n    const twentyFourHoursAgo &#061; new Date(now.getTime() &#8211; 24 * 60 * 60 * 1000);<\/p>\n<p>    const recentErrors &#061; this.getRecentErrors(1000);<br \/>\n    const hourErrors &#061; recentErrors.filter(e &#061;&gt; e.timestamp &gt; oneHourAgo);<br \/>\n    const dayErrors &#061; recentErrors.filter(e &#061;&gt; e.timestamp &gt; twentyFourHoursAgo);<\/p>\n<p>    const stats &#061; {<br \/>\n      current: {<br \/>\n        total: hourErrors.length,<br \/>\n        byService: this.groupBy(hourErrors, &#039;service&#039;),<br \/>\n        byStatusCode: this.groupBy(hourErrors, &#039;statusCode&#039;),<br \/>\n        bySeverity: this.groupBy(hourErrors, &#039;severity&#039;)<br \/>\n      },<br \/>\n      daily: {<br \/>\n        total: dayErrors.length,<br \/>\n        byService: this.groupBy(dayErrors, &#039;service&#039;),<br \/>\n        byStatusCode: this.groupBy(dayErrors, &#039;statusCode&#039;),<br \/>\n        bySeverity: this.groupBy(dayErrors, &#039;severity&#039;)<br \/>\n      },<br \/>\n      aggregates: Array.from(this.aggregates.values())<br \/>\n        .filter(agg &#061;&gt; this.shouldShowAggregate(agg))<br \/>\n        .map(agg &#061;&gt; ({<br \/>\n          errorHash: agg.errorHash,<br \/>\n          count: agg.count,<br \/>\n          services: Array.from(agg.affectedServices),<br \/>\n          statusCodes: Array.from(agg.statusCodes),<br \/>\n          lastOccurrence: agg.lastOccurrence<br \/>\n        }))<br \/>\n    };<\/p>\n<p>    return stats;<br \/>\n  }<\/p>\n<p>  private groupBy(errors: ErrorEvent[], key: keyof ErrorEvent): Record&lt;string, number&gt; {<br \/>\n    const result: Record&lt;string, number&gt; &#061; {};<\/p>\n<p>    for (const error of errors) {<br \/>\n      const value &#061; String(error[key]);<br \/>\n      result[value] &#061; (result[value] || 0) &#043; 1;<br \/>\n    }<\/p>\n<p>    return result;<br \/>\n  }<\/p>\n<p>  acknowledgeAlert(alertId: string): void {<br \/>\n    this.emit(&#039;alertAcknowledged&#039;, alertId);<br \/>\n  }<\/p>\n<p>  addAlertRule(rule: AlertRule): void {<br \/>\n    this.alertRules.push(rule);<br \/>\n  }<\/p>\n<p>  removeAlertRule(ruleId: string): void {<br \/>\n    this.alertRules &#061; this.alertRules.filter(rule &#061;&gt; rule.id !&#061;&#061; ruleId);<br \/>\n  }<br \/>\n}<\/p>\n<p>\/\/ \u4f7f\u7528\u793a\u4f8b<br \/>\nconst errorMonitor &#061; new RealTimeErrorMonitor(8080);<\/p>\n<p>\/\/ \u76d1\u542c\u4e8b\u4ef6<br \/>\nerrorMonitor.on(&#039;errorRecorded&#039;, (error: ErrorEvent) &#061;&gt; {<br \/>\n  console.log(&#039;Error recorded:&#039;, error.id, error.errorType);<br \/>\n});<\/p>\n<p>errorMonitor.on(&#039;alertTriggered&#039;, (alert) &#061;&gt; {<br \/>\n  console.log(&#039;Alert triggered:&#039;, alert.rule.name);<br \/>\n});<\/p>\n<p>\/\/ \u8bb0\u5f55\u9519\u8bef<br \/>\nerrorMonitor.recordError({<br \/>\n  service: &#039;order-service&#039;,<br \/>\n  endpoint: &#039;\/api\/orders&#039;,<br \/>\n  statusCode: 503,<br \/>\n  errorType: &#039;ServiceUnavailableError&#039;,<br \/>\n  errorMessage: &#039;Database connection failed&#039;,<br \/>\n  context: {<br \/>\n    userId: &#039;user123&#039;,<br \/>\n    orderId: &#039;order456&#039;,<br \/>\n    retryCount: 2<br \/>\n  },<br \/>\n  severity: &#039;HIGH&#039;,<br \/>\n  environment: &#039;production&#039;<br \/>\n});<\/p>\n<p>\/\/ \u83b7\u53d6\u7edf\u8ba1\u4fe1\u606f<br \/>\nconst stats &#061; errorMonitor.getErrorStatistics();<br \/>\nconsole.log(&#039;Error statistics:&#039;, stats);<\/p>\n<h3>34.5 \u9519\u8bef\u5904\u7406\u6700\u4f73\u5b9e\u8df5\u603b\u7ed3<\/h3>\n<h4>34.5.1 \u72b6\u6001\u7801\u4e0e\u9519\u8bef\u5904\u7406\u68c0\u67e5\u6e05\u5355<\/h4>\n<p>yaml<\/p>\n<p># \u72b6\u6001\u7801\u4e0e\u9519\u8bef\u5904\u7406\u6700\u4f73\u5b9e\u8df5\u68c0\u67e5\u6e05\u5355<br \/>\nerror_handling_checklist:<\/p>\n<p>  # \u8bbe\u8ba1\u9636\u6bb5<br \/>\n  design_phase:<br \/>\n    &#8211; \u5b9a\u4e49\u4e86\u6e05\u6670\u7684\u9519\u8bef\u5206\u7c7b\u4f53\u7cfb<br \/>\n    &#8211; \u5efa\u7acb\u4e86\u9519\u8bef\u4e25\u91cd\u6027\u7b49\u7ea7<br \/>\n    &#8211; \u8bbe\u8ba1\u4e86\u5206\u5c42\u9519\u8bef\u5904\u7406\u67b6\u6784<br \/>\n    &#8211; \u786e\u5b9a\u4e86\u9519\u8bef\u4f20\u64ad\u7b56\u7565<br \/>\n    &#8211; \u89c4\u5212\u4e86\u964d\u7ea7\u548c\u6062\u590d\u673a\u5236<\/p>\n<p>  # \u5f00\u53d1\u9636\u6bb5<br \/>\n  development_phase:<br \/>\n    http_status_codes:<br \/>\n      &#8211; \u6b63\u786e\u4f7f\u7528\u8bed\u4e49\u5316\u7684\u72b6\u6001\u7801<br \/>\n      &#8211; 4xx\u9519\u8bef\u7528\u4e8e\u5ba2\u6237\u7aef\u95ee\u9898<br \/>\n      &#8211; 5xx\u9519\u8bef\u7528\u4e8e\u670d\u52a1\u5668\u95ee\u9898<br \/>\n      &#8211; \u4e3a\u7279\u6b8a\u60c5\u51b5\u4f7f\u7528\u6b63\u786e\u7684\u72b6\u6001\u7801&#xff08;\u5982422\u3001429&#xff09;<\/p>\n<p>    error_responses:<br \/>\n      &#8211; \u9519\u8bef\u54cd\u5e94\u683c\u5f0f\u6807\u51c6\u5316&#xff08;RFC 7807&#xff09;<br \/>\n      &#8211; \u5305\u542b\u552f\u4e00\u7684\u9519\u8bef\u6807\u8bc6\u7b26<br \/>\n      &#8211; \u63d0\u4f9b\u4eba\u7c7b\u53ef\u8bfb\u7684\u9519\u8bef\u4fe1\u606f<br \/>\n      &#8211; \u5305\u542b\u673a\u5668\u53ef\u8bfb\u7684\u9519\u8bef\u4ee3\u7801<br \/>\n      &#8211; \u63d0\u4f9b\u76f8\u5173\u7684\u4e0a\u4e0b\u6587\u4fe1\u606f<br \/>\n      &#8211; \u5305\u542b\u6709\u5e2e\u52a9\u7684\u5efa\u8bae\u64cd\u4f5c<\/p>\n<p>    client_handling:<br \/>\n      &#8211; \u5ba2\u6237\u7aef\u6709\u9002\u5f53\u7684\u91cd\u8bd5\u903b\u8f91<br \/>\n      &#8211; \u5b9e\u73b0\u4e86\u6307\u6570\u9000\u907f\u7b97\u6cd5<br \/>\n      &#8211; \u8003\u8651\u4e86\u7f51\u7edc\u4e0d\u7a33\u5b9a\u6027<br \/>\n      &#8211; \u63d0\u4f9b\u4e86\u7528\u6237\u53cb\u597d\u7684\u9519\u8bef\u63d0\u793a<br \/>\n      &#8211; \u5b9e\u73b0\u4e86\u4f18\u96c5\u7684\u964d\u7ea7\u5904\u7406<\/p>\n<p>    server_handling:<br \/>\n      &#8211; \u5b9e\u73b0\u4e86\u5168\u5c40\u5f02\u5e38\u5904\u7406<br \/>\n      &#8211; \u9519\u8bef\u88ab\u6b63\u786e\u8bb0\u5f55\u548c\u76d1\u63a7<br \/>\n      &#8211; \u654f\u611f\u4fe1\u606f\u4e0d\u88ab\u6cc4\u9732<br \/>\n      &#8211; \u5b9e\u73b0\u4e86\u65ad\u8def\u5668\u6a21\u5f0f<br \/>\n      &#8211; \u6709\u8d85\u65f6\u548c\u91cd\u8bd5\u63a7\u5236<\/p>\n<p>  # \u8fd0\u7ef4\u9636\u6bb5<br \/>\n  operations_phase:<br \/>\n    monitoring:<br \/>\n      &#8211; \u8bbe\u7f6e\u4e86\u9519\u8bef\u7387\u76d1\u63a7<br \/>\n      &#8211; \u914d\u7f6e\u4e86\u9002\u5f53\u7684\u544a\u8b66\u89c4\u5219<br \/>\n      &#8211; \u5b9e\u73b0\u4e86\u5206\u5e03\u5f0f\u8ffd\u8e2a<br \/>\n      &#8211; \u6709\u5b9e\u65f6\u9519\u8bef\u4eea\u8868\u677f<br \/>\n      &#8211; \u9519\u8bef\u65e5\u5fd7\u7ed3\u6784\u5316<\/p>\n<p>    alerting:<br \/>\n      &#8211; \u544a\u8b66\u7ea7\u522b\u5b9a\u4e49\u6e05\u6670<br \/>\n      &#8211; \u544a\u8b66\u63a5\u6536\u4eba\u914d\u7f6e\u6b63\u786e<br \/>\n      &#8211; \u544a\u8b66\u9608\u503c\u8bbe\u7f6e\u5408\u7406<br \/>\n      &#8211; \u6709\u544a\u8b66\u5347\u7ea7\u673a\u5236<br \/>\n      &#8211; \u544a\u8b66\u5305\u542b\u8db3\u591f\u7684\u4e0a\u4e0b\u6587<\/p>\n<p>    incident_response:<br \/>\n      &#8211; \u6709\u660e\u786e\u7684\u6545\u969c\u6392\u67e5\u6d41\u7a0b<br \/>\n      &#8211; \u9519\u8befID\u53ef\u4ee5\u8ffd\u8e2a\u5230\u5177\u4f53\u8bf7\u6c42<br \/>\n      &#8211; \u6709\u56de\u6eda\u548c\u6062\u590d\u8ba1\u5212<br \/>\n      &#8211; \u5b9a\u671f\u8fdb\u884c\u6545\u969c\u6f14\u7ec3<br \/>\n      &#8211; \u6709\u4e8b\u540e\u5206\u6790&#xff08;Post-mortem&#xff09;\u6d41\u7a0b<\/p>\n<p>  # \u6301\u7eed\u6539\u8fdb<br \/>\n  continuous_improvement:<br \/>\n    &#8211; \u5b9a\u671f\u5206\u6790\u9519\u8bef\u6a21\u5f0f<br \/>\n    &#8211; \u6839\u636e\u9519\u8bef\u6570\u636e\u4f18\u5316\u7cfb\u7edf<br \/>\n    &#8211; \u66f4\u65b0\u9519\u8bef\u5904\u7406\u7b56\u7565<br \/>\n    &#8211; \u6539\u8fdb\u76d1\u63a7\u548c\u544a\u8b66<br \/>\n    &#8211; \u5206\u4eab\u9519\u8bef\u5904\u7406\u7ecf\u9a8c<\/p>\n<h4>34.5.2 \u9519\u8bef\u5904\u7406\u7b56\u7565\u51b3\u7b56\u6811<img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1614\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260130145703-697cc6bf6f23b.png\" width=\"3276\" \/><\/h4>\n<h4>34.5.3 \u9519\u8bef\u5904\u7406\u6210\u719f\u5ea6\u6a21\u578b<\/h4>\n<p>markdown<\/p>\n<p># \u9519\u8bef\u5904\u7406\u6210\u719f\u5ea6\u6a21\u578b<\/p>\n<p>## Level 0: \u6df7\u6c8c\u9636\u6bb5<br \/>\n&#8211; \u9519\u8bef\u88ab\u5ffd\u7565\u6216\u7b80\u5355\u6253\u5370<br \/>\n&#8211; \u6ca1\u6709\u7edf\u4e00\u7684\u9519\u8bef\u5904\u7406<br \/>\n&#8211; \u72b6\u6001\u7801\u4f7f\u7528\u968f\u610f<br \/>\n&#8211; \u9519\u8bef\u4fe1\u606f\u6cc4\u9732\u654f\u611f\u6570\u636e<br \/>\n&#8211; \u6ca1\u6709\u76d1\u63a7\u548c\u544a\u8b66<\/p>\n<p>## Level 1: \u57fa\u7840\u9636\u6bb5<br \/>\n&#8211; \u57fa\u672c\u7684\u5f02\u5e38\u5904\u7406<br \/>\n&#8211; \u7edf\u4e00\u7684\u9519\u8bef\u54cd\u5e94\u683c\u5f0f<br \/>\n&#8211; \u6b63\u786e\u7684HTTP\u72b6\u6001\u7801\u4f7f\u7528<br \/>\n&#8211; \u7b80\u5355\u7684\u65e5\u5fd7\u8bb0\u5f55<br \/>\n&#8211; \u57fa\u7840\u7684\u9519\u8bef\u5206\u7c7b<\/p>\n<p>## Level 2: \u6807\u51c6\u9636\u6bb5<br \/>\n&#8211; \u5206\u5c42\u7684\u9519\u8bef\u5904\u7406\u67b6\u6784<br \/>\n&#8211; \u667a\u80fd\u91cd\u8bd5\u673a\u5236<br \/>\n&#8211; \u65ad\u8def\u5668\u6a21\u5f0f\u5b9e\u73b0<br \/>\n&#8211; \u7ed3\u6784\u5316\u65e5\u5fd7\u8bb0\u5f55<br \/>\n&#8211; \u57fa\u672c\u7684\u76d1\u63a7\u548c\u544a\u8b66<\/p>\n<p>## Level 3: \u5148\u8fdb\u9636\u6bb5<br \/>\n&#8211; \u81ea\u9002\u5e94\u7684\u9519\u8bef\u5904\u7406\u7b56\u7565<br \/>\n&#8211; \u9884\u6d4b\u6027\u9519\u8bef\u9884\u9632<br \/>\n&#8211; \u673a\u5668\u5b66\u4e60\u4f18\u5316<br \/>\n&#8211; \u5b9e\u65f6\u9519\u8bef\u76d1\u63a7<br \/>\n&#8211; \u81ea\u52a8\u5316\u6545\u969c\u6062\u590d<\/p>\n<p>## Level 4: \u5353\u8d8a\u9636\u6bb5<br \/>\n&#8211; \u4e3b\u52a8\u9519\u8bef\u9884\u9632<br \/>\n&#8211; \u81ea\u6211\u4fee\u590d\u7cfb\u7edf<br \/>\n&#8211; \u9884\u6d4b\u6027\u7ef4\u62a4<br \/>\n&#8211; \u5168\u94fe\u8def\u9519\u8bef\u8ffd\u8e2a<br \/>\n&#8211; \u6301\u7eed\u4f18\u5316\u548c\u6539\u8fdb<\/p>\n<p>## \u8bc4\u4f30\u6307\u6807<br \/>\n1. \u9519\u8bef\u5904\u7406\u8986\u76d6\u7387&#xff1a;\u5904\u7406\u4e86\u591a\u5927\u6bd4\u4f8b\u7684\u9519\u8bef\u573a\u666f<br \/>\n2. \u9519\u8bef\u6062\u590d\u65f6\u95f4&#xff1a;\u4ece\u9519\u8bef\u4e2d\u6062\u590d\u7684\u5e73\u5747\u65f6\u95f4<br \/>\n3. \u9519\u8bef\u9884\u9632\u80fd\u529b&#xff1a;\u9884\u9632\u4e86\u591a\u5c11\u6f5c\u5728\u9519\u8bef<br \/>\n4. \u7528\u6237\u4f53\u9a8c\u5f71\u54cd&#xff1a;\u9519\u8bef\u5bf9\u7528\u6237\u7684\u5f71\u54cd\u7a0b\u5ea6<br \/>\n5. \u8fd0\u7ef4\u6548\u7387&#xff1a;\u9519\u8bef\u6392\u67e5\u548c\u89e3\u51b3\u7684\u6548\u7387<\/p>\n<h3>34.6 \u672a\u6765\u8d8b\u52bf<\/h3>\n<h4>34.6.1 AI\u9a71\u52a8\u7684\u9519\u8bef\u5904\u7406<\/h4>\n<p>python<\/p>\n<p># AI\u9a71\u52a8\u7684\u667a\u80fd\u9519\u8bef\u5904\u7406\u7cfb\u7edf<br \/>\nimport openai<br \/>\nfrom typing import Dict, Any, List, Optional<br \/>\nimport json<br \/>\nfrom datetime import datetime<\/p>\n<p>class AIErrorHandler:<br \/>\n    &#034;&#034;&#034;AI\u9a71\u52a8\u7684\u9519\u8bef\u5904\u7406\u5668&#034;&#034;&#034;<\/p>\n<p>    def __init__(self, api_key: str):<br \/>\n        openai.api_key &#061; api_key<br \/>\n        self.error_history: List[Dict[str, Any]] &#061; []<br \/>\n        self.solution_cache: Dict[str, str] &#061; {}<\/p>\n<p>    async def analyze_error(self, error: Exception, context: Dict[str, Any]) -&gt; Dict[str, Any]:<br \/>\n        &#034;&#034;&#034;\u4f7f\u7528AI\u5206\u6790\u9519\u8bef&#034;&#034;&#034;<\/p>\n<p>        # \u51c6\u5907\u5206\u6790\u63d0\u793a<br \/>\n        prompt &#061; self._create_analysis_prompt(error, context)<\/p>\n<p>        try:<br \/>\n            # \u8c03\u7528AI\u5206\u6790<br \/>\n            response &#061; await openai.ChatCompletion.acreate(<br \/>\n                model&#061;&#034;gpt-4&#034;,<br \/>\n                messages&#061;[<br \/>\n                    {&#034;role&#034;: &#034;system&#034;, &#034;content&#034;: &#034;\u4f60\u662f\u4e00\u4e2a\u7ecf\u9a8c\u4e30\u5bcc\u7684\u8f6f\u4ef6\u5de5\u7a0b\u5e08&#xff0c;\u64c5\u957f\u9519\u8bef\u5206\u6790\u548c\u8c03\u8bd5\u3002&#034;},<br \/>\n                    {&#034;role&#034;: &#034;user&#034;, &#034;content&#034;: prompt}<br \/>\n                ],<br \/>\n                temperature&#061;0.7,<br \/>\n                max_tokens&#061;500<br \/>\n            )<\/p>\n<p>            analysis_text &#061; response.choices[0].message.content<\/p>\n<p>            # \u89e3\u6790AI\u54cd\u5e94<br \/>\n            analysis &#061; self._parse_ai_response(analysis_text)<\/p>\n<p>            # \u8bb0\u5f55\u5206\u6790\u7ed3\u679c<br \/>\n            analysis_record &#061; {<br \/>\n                &#034;error&#034;: str(error),<br \/>\n                &#034;error_type&#034;: error.__class__.__name__,<br \/>\n                &#034;context&#034;: context,<br \/>\n                &#034;analysis&#034;: analysis,<br \/>\n                &#034;timestamp&#034;: datetime.now().isoformat()<br \/>\n            }<\/p>\n<p>            self.error_history.append(analysis_record)<\/p>\n<p>            return analysis<\/p>\n<p>        except Exception as e:<br \/>\n            # AI\u5206\u6790\u5931\u8d25&#xff0c;\u8fd4\u56de\u57fa\u672c\u5206\u6790<br \/>\n            return self._basic_error_analysis(error, context)<\/p>\n<p>    def _create_analysis_prompt(self, error: Exception, context: Dict[str, Any]) -&gt; str:<br \/>\n        &#034;&#034;&#034;\u521b\u5efaAI\u5206\u6790\u63d0\u793a&#034;&#034;&#034;<\/p>\n<p>        prompt &#061; f&#034;&#034;&#034;<br \/>\n        \u8bf7\u5206\u6790\u4ee5\u4e0b\u9519\u8bef\u5e76\u63d0\u4f9b\u89e3\u51b3\u65b9\u6848\u5efa\u8bae&#xff1a;<\/p>\n<p>        \u9519\u8bef\u7c7b\u578b&#xff1a;{error.__class__.__name__}<br \/>\n        \u9519\u8bef\u4fe1\u606f&#xff1a;{str(error)}<\/p>\n<p>        \u4e0a\u4e0b\u6587\u4fe1\u606f&#xff1a;<br \/>\n        {json.dumps(context, indent&#061;2, default&#061;str)}<\/p>\n<p>        \u8bf7\u6309\u4ee5\u4e0b\u683c\u5f0f\u63d0\u4f9b\u5206\u6790&#xff1a;<br \/>\n        1. \u9519\u8bef\u539f\u56e0\u5206\u6790<br \/>\n        2. \u5f71\u54cd\u8bc4\u4f30<br \/>\n        3. \u7acb\u5373\u89e3\u51b3\u65b9\u6848<br \/>\n        4. \u957f\u671f\u9884\u9632\u63aa\u65bd<br \/>\n        5. \u76f8\u5173\u6587\u6863\u94fe\u63a5&#xff08;\u5982\u679c\u6709&#xff09;<\/p>\n<p>        \u8bf7\u7528\u4e2d\u6587\u56de\u7b54\u3002<br \/>\n        &#034;&#034;&#034;<\/p>\n<p>        return prompt<\/p>\n<p>    def _parse_ai_response(self, response_text: str) -&gt; Dict[str, Any]:<br \/>\n        &#034;&#034;&#034;\u89e3\u6790AI\u54cd\u5e94&#034;&#034;&#034;<\/p>\n<p>        # \u8fd9\u91cc\u53ef\u4ee5\u6dfb\u52a0\u66f4\u590d\u6742\u7684\u89e3\u6790\u903b\u8f91<br \/>\n        # \u7b80\u5355\u5b9e\u73b0&#xff1a;\u6309\u884c\u5206\u5272\u5e76\u5206\u7c7b<\/p>\n<p>        lines &#061; response_text.strip().split(&#039;\\\\n&#039;)<\/p>\n<p>        analysis &#061; {<br \/>\n            &#034;cause&#034;: &#034;&#034;,<br \/>\n            &#034;impact&#034;: &#034;&#034;,<br \/>\n            &#034;immediate_solution&#034;: &#034;&#034;,<br \/>\n            &#034;long_term_prevention&#034;: &#034;&#034;,<br \/>\n            &#034;documentation&#034;: []<br \/>\n        }<\/p>\n<p>        current_section &#061; None<\/p>\n<p>        for line in lines:<br \/>\n            line &#061; line.strip()<\/p>\n<p>            if line.startswith(&#039;1.&#039;) or &#039;\u9519\u8bef\u539f\u56e0&#039; in line:<br \/>\n                current_section &#061; &#039;cause&#039;<br \/>\n            elif line.startswith(&#039;2.&#039;) or &#039;\u5f71\u54cd\u8bc4\u4f30&#039; in line:<br \/>\n                current_section &#061; &#039;impact&#039;<br \/>\n            elif line.startswith(&#039;3.&#039;) or &#039;\u7acb\u5373\u89e3\u51b3\u65b9\u6848&#039; in line:<br \/>\n                current_section &#061; &#039;immediate_solution&#039;<br \/>\n            elif line.startswith(&#039;4.&#039;) or &#039;\u957f\u671f\u9884\u9632\u63aa\u65bd&#039; in line:<br \/>\n                current_section &#061; &#039;long_term_prevention&#039;<br \/>\n            elif line.startswith(&#039;5.&#039;) or &#039;\u76f8\u5173\u6587\u6863\u94fe\u63a5&#039; in line:<br \/>\n                current_section &#061; &#039;documentation&#039;<br \/>\n            elif current_section and line:<br \/>\n                if current_section &#061;&#061; &#039;documentation&#039;:<br \/>\n                    analysis[&#039;documentation&#039;].append(line)<br \/>\n                else:<br \/>\n                    analysis[current_section] &#043;&#061; line &#043; &#039;\\\\n&#039;<\/p>\n<p>        return analysis<\/p>\n<p>    def _basic_error_analysis(self, error: Exception, context: Dict[str, Any]) -&gt; Dict[str, Any]:<br \/>\n        &#034;&#034;&#034;\u57fa\u672c\u9519\u8bef\u5206\u6790&#xff08;\u5907\u7528&#xff09;&#034;&#034;&#034;<\/p>\n<p>        error_type &#061; error.__class__.__name__<\/p>\n<p>        # \u57fa\u4e8e\u9519\u8bef\u7c7b\u578b\u7684\u7b80\u5355\u5206\u6790<br \/>\n        analysis_templates &#061; {<br \/>\n            &#034;ConnectionError&#034;: {<br \/>\n                &#034;cause&#034;: &#034;\u7f51\u7edc\u8fde\u63a5\u5931\u8d25&#xff0c;\u53ef\u80fd\u662f\u7f51\u7edc\u4e0d\u7a33\u5b9a\u6216\u670d\u52a1\u4e0d\u53ef\u7528&#034;,<br \/>\n                &#034;impact&#034;: &#034;\u7528\u6237\u65e0\u6cd5\u8bbf\u95ee\u76f8\u5173\u529f\u80fd&#034;,<br \/>\n                &#034;immediate_solution&#034;: &#034;\u68c0\u67e5\u7f51\u7edc\u8fde\u63a5&#xff0c;\u91cd\u8bd5\u64cd\u4f5c&#034;,<br \/>\n                &#034;long_term_prevention&#034;: &#034;\u5b9e\u73b0\u91cd\u8bd5\u673a\u5236&#xff0c;\u589e\u52a0\u8fde\u63a5\u8d85\u65f6\u8bbe\u7f6e&#034;<br \/>\n            },<br \/>\n            &#034;TimeoutError&#034;: {<br \/>\n                &#034;cause&#034;: &#034;\u64cd\u4f5c\u8d85\u65f6&#xff0c;\u53ef\u80fd\u662f\u670d\u52a1\u54cd\u5e94\u6162\u6216\u7f51\u7edc\u5ef6\u8fdf&#034;,<br \/>\n                &#034;impact&#034;: &#034;\u7528\u6237\u4f53\u9a8c\u4e0b\u964d&#xff0c;\u64cd\u4f5c\u53ef\u80fd\u5931\u8d25&#034;,<br \/>\n                &#034;immediate_solution&#034;: &#034;\u589e\u52a0\u8d85\u65f6\u65f6\u95f4&#xff0c;\u4f18\u5316\u67e5\u8be2&#034;,<br \/>\n                &#034;long_term_prevention&#034;: &#034;\u4f18\u5316\u670d\u52a1\u6027\u80fd&#xff0c;\u5b9e\u73b0\u5f02\u6b65\u5904\u7406&#034;<br \/>\n            },<br \/>\n            &#034;ValueError&#034;: {<br \/>\n                &#034;cause&#034;: &#034;\u53c2\u6570\u503c\u65e0\u6548&#xff0c;\u53ef\u80fd\u662f\u8f93\u5165\u9a8c\u8bc1\u4e0d\u5145\u5206&#034;,<br \/>\n                &#034;impact&#034;: &#034;\u64cd\u4f5c\u65e0\u6cd5\u5b8c\u6210&#xff0c;\u53ef\u80fd\u5f71\u54cd\u6570\u636e\u4e00\u81f4\u6027&#034;,<br \/>\n                &#034;immediate_solution&#034;: &#034;\u68c0\u67e5\u8f93\u5165\u53c2\u6570&#xff0c;\u63d0\u4f9b\u66f4\u8be6\u7ec6\u7684\u9519\u8bef\u4fe1\u606f&#034;,<br \/>\n                &#034;long_term_prevention&#034;: &#034;\u52a0\u5f3a\u8f93\u5165\u9a8c\u8bc1&#xff0c;\u63d0\u4f9b\u66f4\u597d\u7684\u7528\u6237\u6307\u5bfc&#034;<br \/>\n            }<br \/>\n        }<\/p>\n<p>        if error_type in analysis_templates:<br \/>\n            return analysis_templates[error_type]<br \/>\n        else:<br \/>\n            return {<br \/>\n                &#034;cause&#034;: f&#034;\u672a\u77e5\u9519\u8bef\u7c7b\u578b: {error_type}&#034;,<br \/>\n                &#034;impact&#034;: &#034;\u9700\u8981\u8fdb\u4e00\u6b65\u5206\u6790&#034;,<br \/>\n                &#034;immediate_solution&#034;: &#034;\u67e5\u770b\u8be6\u7ec6\u65e5\u5fd7&#xff0c;\u8054\u7cfb\u5f00\u53d1\u4eba\u5458&#034;,<br \/>\n                &#034;long_term_prevention&#034;: &#034;\u589e\u52a0\u9519\u8bef\u76d1\u63a7\u548c\u65e5\u5fd7\u8bb0\u5f55&#034;<br \/>\n            }<\/p>\n<p>    async def suggest_solution(self, error_signature: str) -&gt; Optional[str]:<br \/>\n        &#034;&#034;&#034;\u57fa\u4e8e\u5386\u53f2\u8bb0\u5f55\u5efa\u8bae\u89e3\u51b3\u65b9\u6848&#034;&#034;&#034;<\/p>\n<p>        # \u68c0\u67e5\u7f13\u5b58<br \/>\n        if error_signature in self.solution_cache:<br \/>\n            return self.solution_cache[error_signature]<\/p>\n<p>        # \u67e5\u627e\u7c7b\u4f3c\u7684\u5386\u53f2\u9519\u8bef<br \/>\n        similar_errors &#061; self._find_similar_errors(error_signature)<\/p>\n<p>        if similar_errors:<br \/>\n            # \u4f7f\u7528AI\u603b\u7ed3\u89e3\u51b3\u65b9\u6848<br \/>\n            prompt &#061; self._create_solution_prompt(similar_errors)<\/p>\n<p>            try:<br \/>\n                response &#061; await openai.ChatCompletion.acreate(<br \/>\n                    model&#061;&#034;gpt-4&#034;,<br \/>\n                    messages&#061;[<br \/>\n                        {&#034;role&#034;: &#034;system&#034;, &#034;content&#034;: &#034;\u4f60\u662f\u4e00\u4e2a\u7ecf\u9a8c\u4e30\u5bcc\u7684\u8f6f\u4ef6\u5de5\u7a0b\u5e08\u3002&#034;},<br \/>\n                        {&#034;role&#034;: &#034;user&#034;, &#034;content&#034;: prompt}<br \/>\n                    ],<br \/>\n                    temperature&#061;0.7,<br \/>\n                    max_tokens&#061;300<br \/>\n                )<\/p>\n<p>                solution &#061; response.choices[0].message.content<\/p>\n<p>                # \u7f13\u5b58\u89e3\u51b3\u65b9\u6848<br \/>\n                self.solution_cache[error_signature] &#061; solution<\/p>\n<p>                return solution<\/p>\n<p>            except Exception:<br \/>\n                return None<\/p>\n<p>        return None<\/p>\n<p>    def _find_similar_errors(self, error_signature: str) -&gt; List[Dict[str, Any]]:<br \/>\n        &#034;&#034;&#034;\u67e5\u627e\u7c7b\u4f3c\u7684\u9519\u8bef&#034;&#034;&#034;<\/p>\n<p>        # \u7b80\u5355\u7684\u76f8\u4f3c\u5ea6\u5339\u914d<br \/>\n        # \u5b9e\u9645\u5b9e\u73b0\u53ef\u4ee5\u4f7f\u7528\u66f4\u590d\u6742\u7684\u7b97\u6cd5<\/p>\n<p>        similar &#061; []<\/p>\n<p>        for error_record in self.error_history[-100:]:  # \u6700\u8fd1100\u4e2a\u9519\u8bef<br \/>\n            error_text &#061; error_record[&#034;error&#034;]<\/p>\n<p>            # \u8ba1\u7b97\u7b80\u5355\u7684\u76f8\u4f3c\u5ea6<br \/>\n            similarity &#061; self._calculate_similarity(error_signature, error_text)<\/p>\n<p>            if similarity &gt; 0.7:  # \u76f8\u4f3c\u5ea6\u9608\u503c<br \/>\n                similar.append(error_record)<\/p>\n<p>        return similar<\/p>\n<p>    def _calculate_similarity(self, text1: str, text2: str) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u8ba1\u7b97\u6587\u672c\u76f8\u4f3c\u5ea6&#xff08;\u7b80\u5316\u5b9e\u73b0&#xff09;&#034;&#034;&#034;<\/p>\n<p>        # \u5b9e\u9645\u5b9e\u73b0\u53ef\u4ee5\u4f7f\u7528\u66f4\u590d\u6742\u7684\u76f8\u4f3c\u5ea6\u7b97\u6cd5<br \/>\n        # \u8fd9\u91cc\u4f7f\u7528\u7b80\u5355\u7684\u8bcd\u91cd\u53e0\u7387<\/p>\n<p>        words1 &#061; set(text1.lower().split())<br \/>\n        words2 &#061; set(text2.lower().split())<\/p>\n<p>        if not words1 or not words2:<br \/>\n            return 0.0<\/p>\n<p>        intersection &#061; words1.intersection(words2)<br \/>\n        union &#061; words1.union(words2)<\/p>\n<p>        return len(intersection) \/ len(union)<\/p>\n<p>    def _create_solution_prompt(self, similar_errors: List[Dict[str, Any]]) -&gt; str:<br \/>\n        &#034;&#034;&#034;\u521b\u5efa\u89e3\u51b3\u65b9\u6848\u63d0\u793a&#034;&#034;&#034;<\/p>\n<p>        prompt &#061; &#034;\u57fa\u4e8e\u4ee5\u4e0b\u7c7b\u4f3c\u9519\u8bef\u7684\u5206\u6790\u548c\u89e3\u51b3\u65b9\u6848&#xff0c;\u8bf7\u603b\u7ed3\u4e00\u4e2a\u901a\u7528\u7684\u89e3\u51b3\u65b9\u6848&#xff1a;\\\\n\\\\n&#034;<\/p>\n<p>        for i, error_record in enumerate(similar_errors[:3], 1):  # \u6700\u591a3\u4e2a\u4f8b\u5b50<br \/>\n            prompt &#043;&#061; f&#034;\u9519\u8bef\u793a\u4f8b {i}:\\\\n&#034;<br \/>\n            prompt &#043;&#061; f&#034;\u9519\u8bef\u4fe1\u606f: {error_record[&#039;error&#039;]}\\\\n&#034;<br \/>\n            if &#039;analysis&#039; in error_record:<br \/>\n                prompt &#043;&#061; f&#034;\u5206\u6790\u7ed3\u679c: {json.dumps(error_record[&#039;analysis&#039;], ensure_ascii&#061;False)}\\\\n&#034;<br \/>\n            prompt &#043;&#061; &#034;\\\\n&#034;<\/p>\n<p>        prompt &#043;&#061; &#034;\u8bf7\u63d0\u4f9b\u4e00\u4e2a\u7b80\u6d01\u6709\u6548\u7684\u89e3\u51b3\u65b9\u6848&#xff0c;\u7528\u4e2d\u6587\u56de\u7b54\u3002&#034;<\/p>\n<p>        return prompt<\/p>\n<p>    def generate_error_report(self, time_period: str &#061; &#034;daily&#034;) -&gt; Dict[str, Any]:<br \/>\n        &#034;&#034;&#034;\u751f\u6210\u9519\u8bef\u62a5\u544a&#034;&#034;&#034;<\/p>\n<p>        now &#061; datetime.now()<\/p>\n<p>        if time_period &#061;&#061; &#034;daily&#034;:<br \/>\n            start_time &#061; datetime(now.year, now.month, now.day)<br \/>\n        elif time_period &#061;&#061; &#034;weekly&#034;:<br \/>\n            start_time &#061; datetime(now.year, now.month, now.day &#8211; 7)<br \/>\n        elif time_period &#061;&#061; &#034;monthly&#034;:<br \/>\n            start_time &#061; datetime(now.year, now.month &#8211; 1, now.day)<br \/>\n        else:<br \/>\n            start_time &#061; datetime(1970, 1, 1)  # \u6240\u6709\u65f6\u95f4<\/p>\n<p>        # \u8fc7\u6ee4\u6307\u5b9a\u65f6\u95f4\u6bb5\u7684\u9519\u8bef<br \/>\n        recent_errors &#061; [<br \/>\n            error for error in self.error_history<br \/>\n            if datetime.fromisoformat(error[&#034;timestamp&#034;]) &gt; start_time<br \/>\n        ]<\/p>\n<p>        # \u751f\u6210\u62a5\u544a<br \/>\n        report &#061; {<br \/>\n            &#034;period&#034;: time_period,<br \/>\n            &#034;total_errors&#034;: len(recent_errors),<br \/>\n            &#034;unique_error_types&#034;: len(set(e[&#034;error_type&#034;] for e in recent_errors)),<br \/>\n            &#034;most_common_errors&#034;: self._get_most_common(recent_errors, &#034;error_type&#034;),<br \/>\n            &#034;error_trend&#034;: self._calculate_error_trend(recent_errors),<br \/>\n            &#034;resolution_rate&#034;: self._calculate_resolution_rate(recent_errors),<br \/>\n            &#034;recommendations&#034;: self._generate_recommendations(recent_errors)<br \/>\n        }<\/p>\n<p>        return report<\/p>\n<p>    def _get_most_common(self, errors: List[Dict[str, Any]], key: str) -&gt; List[Dict[str, Any]]:<br \/>\n        &#034;&#034;&#034;\u83b7\u53d6\u6700\u5e38\u89c1\u7684\u9519\u8bef&#034;&#034;&#034;<\/p>\n<p>        from collections import Counter<\/p>\n<p>        counter &#061; Counter(e[key] for e in errors)<\/p>\n<p>        return [<br \/>\n            {&#034;type&#034;: error_type, &#034;count&#034;: count}<br \/>\n            for error_type, count in counter.most_common(5)<br \/>\n        ]<\/p>\n<p>    def _calculate_error_trend(self, errors: List[Dict[str, Any]]) -&gt; str:<br \/>\n        &#034;&#034;&#034;\u8ba1\u7b97\u9519\u8bef\u8d8b\u52bf&#034;&#034;&#034;<\/p>\n<p>        if len(errors) &lt; 2:<br \/>\n            return &#034;\u6570\u636e\u4e0d\u8db3&#034;<\/p>\n<p>        # \u6309\u65f6\u95f4\u5206\u7ec4<br \/>\n        hourly_counts &#061; {}<\/p>\n<p>        for error in errors:<br \/>\n            timestamp &#061; datetime.fromisoformat(error[&#034;timestamp&#034;])<br \/>\n            hour_key &#061; timestamp.strftime(&#034;%Y-%m-%d %H:00&#034;)<br \/>\n            hourly_counts[hour_key] &#061; hourly_counts.get(hour_key, 0) &#043; 1<\/p>\n<p>        # \u7b80\u5355\u8d8b\u52bf\u5224\u65ad<br \/>\n        sorted_hours &#061; sorted(hourly_counts.keys())<\/p>\n<p>        if len(sorted_hours) &lt; 2:<br \/>\n            return &#034;\u7a33\u5b9a&#034;<\/p>\n<p>        recent_count &#061; hourly_counts[sorted_hours[-1]]<br \/>\n        previous_count &#061; hourly_counts[sorted_hours[-2]]<\/p>\n<p>        if recent_count &gt; previous_count * 1.5:<br \/>\n            return &#034;\u4e0a\u5347&#034;<br \/>\n        elif recent_count &lt; previous_count * 0.5:<br \/>\n            return &#034;\u4e0b\u964d&#034;<br \/>\n        else:<br \/>\n            return &#034;\u7a33\u5b9a&#034;<\/p>\n<p>    def _calculate_resolution_rate(self, errors: List[Dict[str, Any]]) -&gt; float:<br \/>\n        &#034;&#034;&#034;\u8ba1\u7b97\u89e3\u51b3\u7387&#xff08;\u7b80\u5316\u5b9e\u73b0&#xff09;&#034;&#034;&#034;<\/p>\n<p>        # \u5b9e\u9645\u5b9e\u73b0\u5e94\u8be5\u57fa\u4e8e\u5b9e\u9645\u7684\u89e3\u51b3\u72b6\u6001<br \/>\n        # \u8fd9\u91cc\u4f7f\u7528\u4e00\u4e2a\u7b80\u5316\u7684\u5047\u8bbe<\/p>\n<p>        total &#061; len(errors)<br \/>\n        if total &#061;&#061; 0:<br \/>\n            return 1.0<\/p>\n<p>        # \u5047\u8bbe80%\u7684\u9519\u8bef\u5df2\u7ecf\u89e3\u51b3<br \/>\n        return 0.8<\/p>\n<p>    def _generate_recommendations(self, errors: List[Dict[str, Any]]) -&gt; List[str]:<br \/>\n        &#034;&#034;&#034;\u751f\u6210\u6539\u8fdb\u5efa\u8bae&#034;&#034;&#034;<\/p>\n<p>        recommendations &#061; []<\/p>\n<p>        # \u5206\u6790\u9519\u8bef\u6a21\u5f0f<br \/>\n        error_types &#061; [e[&#034;error_type&#034;] for e in errors]<br \/>\n        type_counter &#061; Counter(error_types)<\/p>\n<p>        for error_type, count in type_counter.most_common(3):<br \/>\n            if count &gt; 10:  # \u9891\u7e41\u51fa\u73b0\u7684\u9519\u8bef<br \/>\n                recommendations.append(<br \/>\n                    f&#034;\u9891\u7e41\u51fa\u73b0 {error_type} \u9519\u8bef&#xff08;{count}\u6b21&#xff09;&#xff0c;\u5efa\u8bae\u91cd\u70b9\u6392\u67e5&#034;<br \/>\n                )<\/p>\n<p>        # \u68c0\u67e5\u662f\u5426\u6709\u65b0\u7684\u9519\u8bef\u7c7b\u578b<br \/>\n        recent_errors &#061; errors[-20:]  # \u6700\u8fd120\u4e2a\u9519\u8bef<br \/>\n        new_types &#061; set(e[&#034;error_type&#034;] for e in recent_errors)<br \/>\n        all_types &#061; set(e[&#034;error_type&#034;] for e in errors)<\/p>\n<p>        if len(new_types) &gt; len(all_types) * 0.3:  # 30%\u4ee5\u4e0a\u662f\u65b0\u7c7b\u578b<br \/>\n            recommendations.append(<br \/>\n                &#034;\u53d1\u73b0\u5927\u91cf\u65b0\u7684\u9519\u8bef\u7c7b\u578b&#xff0c;\u5efa\u8bae\u68c0\u67e5\u6700\u8fd1\u7684\u4ee3\u7801\u53d8\u66f4&#034;<br \/>\n            )<\/p>\n<p>        return recommendations<\/p>\n<p># \u4f7f\u7528\u793a\u4f8b<br \/>\nasync def example_ai_error_handling():<br \/>\n    # \u521d\u59cb\u5316AI\u9519\u8bef\u5904\u7406\u5668<br \/>\n    ai_handler &#061; AIErrorHandler(api_key&#061;&#034;your-openai-api-key&#034;)<\/p>\n<p>    # \u6a21\u62df\u4e00\u4e2a\u9519\u8bef<br \/>\n    try:<br \/>\n        # \u6a21\u62df\u4e00\u4e2a\u53ef\u80fd\u5931\u8d25\u7684\u64cd\u4f5c<br \/>\n        raise ConnectionError(&#034;Failed to connect to database: Connection refused&#034;)<\/p>\n<p>    except Exception as e:<br \/>\n        # \u51c6\u5907\u9519\u8bef\u4e0a\u4e0b\u6587<br \/>\n        context &#061; {<br \/>\n            &#034;service&#034;: &#034;order-service&#034;,<br \/>\n            &#034;endpoint&#034;: &#034;\/api\/orders&#034;,<br \/>\n            &#034;user_id&#034;: &#034;user123&#034;,<br \/>\n            &#034;request_id&#034;: &#034;req-abc-123&#034;,<br \/>\n            &#034;timestamp&#034;: datetime.now().isoformat(),<br \/>\n            &#034;environment&#034;: &#034;production&#034;<br \/>\n        }<\/p>\n<p>        # \u4f7f\u7528AI\u5206\u6790\u9519\u8bef<br \/>\n        analysis &#061; await ai_handler.analyze_error(e, context)<\/p>\n<p>        print(&#034;AI\u9519\u8bef\u5206\u6790\u7ed3\u679c:&#034;)<br \/>\n        print(f&#034;\u539f\u56e0: {analysis.get(&#039;cause&#039;, &#039;N\/A&#039;)}&#034;)<br \/>\n        print(f&#034;\u5f71\u54cd: {analysis.get(&#039;impact&#039;, &#039;N\/A&#039;)}&#034;)<br \/>\n        print(f&#034;\u7acb\u5373\u89e3\u51b3\u65b9\u6848: {analysis.get(&#039;immediate_solution&#039;, &#039;N\/A&#039;)}&#034;)<br \/>\n        print(f&#034;\u957f\u671f\u9884\u9632\u63aa\u65bd: {analysis.get(&#039;long_term_prevention&#039;, &#039;N\/A&#039;)}&#034;)<\/p>\n<p>        # \u751f\u6210\u9519\u8bef\u62a5\u544a<br \/>\n        report &#061; ai_handler.generate_error_report(&#034;daily&#034;)<br \/>\n        print(&#034;\\\\n\u6bcf\u65e5\u9519\u8bef\u62a5\u544a:&#034;)<br \/>\n        print(json.dumps(report, indent&#061;2, ensure_ascii&#061;False))<\/p>\n<p># \u8fd0\u884c\u793a\u4f8b<br \/>\nif __name__ &#061;&#061; &#034;__main__&#034;:<br \/>\n    import asyncio<br \/>\n    asyncio.run(example_ai_error_handling())<\/p>\n<h3>34.7 \u603b\u7ed3<\/h3>\n<h4>34.7.1 \u5173\u952e\u6536\u83b7<\/h4>\n<li>\n<p>\u9519\u8bef\u5904\u7406\u662f\u7cfb\u7edf\u5de5\u7a0b<\/p>\n<ul>\n<li>\n<p>\u4e0d\u4ec5\u4ec5\u662f\u6280\u672f\u5b9e\u73b0&#xff0c;\u66f4\u662f\u67b6\u6784\u8bbe\u8ba1<\/p>\n<\/li>\n<li>\n<p>\u9700\u8981\u8003\u8651\u7528\u6237\u4f53\u9a8c\u3001\u8fd0\u7ef4\u6548\u7387\u3001\u7cfb\u7edf\u7a33\u5b9a\u6027\u7b49\u591a\u4e2a\u7ef4\u5ea6<\/p>\n<\/li>\n<li>\n<p>\u5e94\u8be5\u4f5c\u4e3a\u7cfb\u7edf\u8bbe\u8ba1\u7684\u91cd\u8981\u7ec4\u6210\u90e8\u5206<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u72b6\u6001\u7801\u662f\u6307\u5357\u9488<\/p>\n<ul>\n<li>\n<p>\u6b63\u786e\u7684\u72b6\u6001\u7801\u4f7f\u7528\u662f\u826f\u597dAPI\u8bbe\u8ba1\u7684\u57fa\u7840<\/p>\n<\/li>\n<li>\n<p>\u72b6\u6001\u7801\u5e94\u8be5\u4e0e\u9519\u8bef\u7c7b\u578b\u548c\u4e25\u91cd\u6027\u76f8\u5339\u914d<\/p>\n<\/li>\n<li>\n<p>\u72b6\u6001\u7801\u5e94\u8be5\u80fd\u591f\u6307\u5bfc\u5ba2\u6237\u7aef\u7684\u884c\u4e3a<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u667a\u80fd\u5316\u7684\u9519\u8bef\u5904\u7406<\/p>\n<ul>\n<li>\n<p>\u91cd\u8bd5\u7b56\u7565\u5e94\u8be5\u57fa\u4e8e\u9519\u8bef\u7c7b\u578b\u548c\u4e0a\u4e0b\u6587<\/p>\n<\/li>\n<li>\n<p>\u673a\u5668\u5b66\u4e60\u53ef\u4ee5\u5e2e\u52a9\u4f18\u5316\u9519\u8bef\u5904\u7406\u51b3\u7b56<\/p>\n<\/li>\n<li>\n<p>AI\u53ef\u4ee5\u8f85\u52a9\u9519\u8bef\u5206\u6790\u548c\u89e3\u51b3\u65b9\u6848\u751f\u6210<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u76d1\u63a7\u4e0e\u6301\u7eed\u6539\u8fdb<\/p>\n<ul>\n<li>\n<p>\u6ca1\u6709\u76d1\u63a7\u7684\u9519\u8bef\u5904\u7406\u662f\u4e0d\u5b8c\u6574\u7684<\/p>\n<\/li>\n<li>\n<p>\u9519\u8bef\u6570\u636e\u5e94\u8be5\u7528\u4e8e\u6301\u7eed\u6539\u8fdb\u7cfb\u7edf<\/p>\n<\/li>\n<li>\n<p>\u5e94\u8be5\u5efa\u7acb\u9519\u8bef\u5904\u7406\u7684\u53cd\u9988\u5faa\u73af<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<h4>34.7.2 \u5b9e\u9645\u5e94\u7528\u5efa\u8bae<\/h4>\n<li>\n<p>\u4ece\u5c0f\u5904\u5f00\u59cb<\/p>\n<ul>\n<li>\n<p>\u4ece\u6700\u57fa\u672c\u7684\u9519\u8bef\u5206\u7c7b\u548c\u72b6\u6001\u7801\u5f00\u59cb<\/p>\n<\/li>\n<li>\n<p>\u9010\u6b65\u5f15\u5165\u66f4\u9ad8\u7ea7\u7684\u9519\u8bef\u5904\u7406\u7b56\u7565<\/p>\n<\/li>\n<li>\n<p>\u6839\u636e\u5b9e\u9645\u9700\u6c42\u9009\u62e9\u5408\u9002\u7684\u5de5\u5177\u548c\u6280\u672f<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u5173\u6ce8\u7528\u6237\u4f53\u9a8c<\/p>\n<ul>\n<li>\n<p>\u9519\u8bef\u4fe1\u606f\u5e94\u8be5\u5bf9\u7528\u6237\u6709\u5e2e\u52a9<\/p>\n<\/li>\n<li>\n<p>\u63d0\u4f9b\u660e\u786e\u7684\u89e3\u51b3\u65b9\u6848\u6216\u4e0b\u4e00\u6b65\u884c\u52a8<\/p>\n<\/li>\n<li>\n<p>\u907f\u514d\u6280\u672f\u672f\u8bed\u548c\u654f\u611f\u4fe1\u606f<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u5efa\u7acb\u6587\u5316<\/p>\n<ul>\n<li>\n<p>\u9519\u8bef\u5904\u7406\u5e94\u8be5\u662f\u56e2\u961f\u5171\u8bc6<\/p>\n<\/li>\n<li>\n<p>\u9f13\u52b1\u5206\u4eab\u9519\u8bef\u5904\u7406\u7ecf\u9a8c<\/p>\n<\/li>\n<li>\n<p>\u5b9a\u671f\u56de\u987e\u548c\u6539\u8fdb\u9519\u8bef\u5904\u7406\u7b56\u7565<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u4fdd\u6301\u7b80\u5355<\/p>\n<ul>\n<li>\n<p>\u590d\u6742\u4e0d\u7b49\u4e8e\u66f4\u597d<\/p>\n<\/li>\n<li>\n<p>\u9009\u62e9\u7b80\u5355\u6709\u6548\u7684\u89e3\u51b3\u65b9\u6848<\/p>\n<\/li>\n<li>\n<p>\u907f\u514d\u8fc7\u5ea6\u5de5\u7a0b\u5316<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<h4>34.7.3 \u672a\u6765\u5c55\u671b<\/h4>\n<p>\u968f\u7740\u6280\u672f\u7684\u53d1\u5c55&#xff0c;\u9519\u8bef\u5904\u7406\u5c06\u53d8\u5f97\u66f4\u52a0\u667a\u80fd\u548c\u81ea\u52a8\u5316&#xff1a;<\/p>\n<li>\n<p>\u9884\u6d4b\u6027\u9519\u8bef\u9884\u9632<\/p>\n<ul>\n<li>\n<p>\u5728\u9519\u8bef\u53d1\u751f\u524d\u9884\u6d4b\u548c\u9884\u9632<\/p>\n<\/li>\n<li>\n<p>\u57fa\u4e8e\u5386\u53f2\u6570\u636e\u7684\u6a21\u5f0f\u8bc6\u522b<\/p>\n<\/li>\n<li>\n<p>\u81ea\u52a8\u5316\u7684\u7cfb\u7edf\u4f18\u5316<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u81ea\u6108\u7cfb\u7edf<\/p>\n<ul>\n<li>\n<p>\u7cfb\u7edf\u80fd\u591f\u81ea\u52a8\u68c0\u6d4b\u548c\u4fee\u590d\u9519\u8bef<\/p>\n<\/li>\n<li>\n<p>\u57fa\u4e8e\u89c4\u5219\u7684\u81ea\u52a8\u6062\u590d<\/p>\n<\/li>\n<li>\n<p>\u65e0\u9700\u4eba\u5de5\u5e72\u9884\u7684\u9519\u8bef\u5904\u7406<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u5168\u94fe\u8def\u53ef\u89c2\u6d4b\u6027<\/p>\n<ul>\n<li>\n<p>\u7aef\u5230\u7aef\u7684\u9519\u8bef\u8ffd\u8e2a<\/p>\n<\/li>\n<li>\n<p>\u8de8\u670d\u52a1\u7684\u9519\u8bef\u4f20\u64ad\u5206\u6790<\/p>\n<\/li>\n<li>\n<p>\u57fa\u4e8eAI\u7684\u6839\u672c\u539f\u56e0\u5206\u6790<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u4eba\u6027\u5316\u4ea4\u4e92<\/p>\n<ul>\n<li>\n<p>\u66f4\u81ea\u7136\u7684\u9519\u8bef\u6c9f\u901a\u65b9\u5f0f<\/p>\n<\/li>\n<li>\n<p>\u57fa\u4e8e\u4e0a\u4e0b\u6587\u7684\u4e2a\u6027\u5316\u89e3\u51b3\u65b9\u6848<\/p>\n<\/li>\n<li>\n<p>\u589e\u5f3a\u73b0\u5b9e\u8f85\u52a9\u7684\u9519\u8bef\u6392\u67e5<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<p>\u901a\u8fc7\u672c\u7ae0\u7684\u5b66\u4e60&#xff0c;\u60a8\u5e94\u8be5\u5bf9\u72b6\u6001\u7801\u4e0e\u9519\u8bef\u5904\u7406\u7b56\u7565\u6709\u4e86\u5168\u9762\u7684\u7406\u89e3\u3002\u8bb0\u4f4f&#xff0c;\u597d\u7684\u9519\u8bef\u5904\u7406\u4e0d\u4ec5\u80fd\u8ba9\u7cfb\u7edf\u66f4\u52a0\u7a33\u5b9a&#xff0c;\u8fd8\u80fd\u63d0\u5347\u7528\u6237\u4f53\u9a8c&#xff0c;\u51cf\u5c11\u8fd0\u7ef4\u8d1f\u62c5\u3002\u5728\u4e0d\u65ad\u53d8\u5316\u7684\u6570\u5b57\u4e16\u754c\u4e2d&#xff0c;\u5f3a\u5927\u7684\u9519\u8bef\u5904\u7406\u80fd\u529b\u662f\u7cfb\u7edf\u53ef\u9760\u6027\u7684\u57fa\u77f3\u3002<\/p>\n<h2><\/h2>\n","protected":false},"excerpt":{"rendered":"<p>\u7b2c33\u7ae0&#xff1a;\u5fae\u670d\u52a1\u67b6\u6784\u4e2d\u7684\u72b6\u6001\u7801\u4f20\u64ad33.1 \u5fae\u670d\u52a1\u67b6\u6784\u4e2d\u7684\u72b6\u6001\u7801\u6311\u621833.1.1 \u5206\u5e03\u5f0f\u7cfb\u7edf\u7684\u590d\u6742\u6027\u5fae\u670d\u52a1\u67b6\u6784\u5e26\u6765\u4e86\u72b6\u6001\u7801\u5904\u7406\u7684\u5168\u65b0\u6311\u6218&#xff1a;yaml# \u5fae\u670d\u52a1\u8c03\u7528\u94fe\u793a\u4f8b<br \/>\nrequest:path: \/api\/order\/123flow:- API Gateway (nginx\/ingress)- Authentication Service- Order Service- calls: User Service- calls: Inventory S<\/p>\n","protected":false},"author":2,"featured_media":68954,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[151,43,191],"topic":[],"class_list":["post-68956","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\u516d\u90e8\u5206\uff1a\u72b6\u6001\u7801\u7684\u5b9e\u8df5\u5e94\u7528\uff08\u4e8c\uff09 - \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\/68956.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\u516d\u90e8\u5206\uff1a\u72b6\u6001\u7801\u7684\u5b9e\u8df5\u5e94\u7528\uff08\u4e8c\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"\u7b2c33\u7ae0&#xff1a;\u5fae\u670d\u52a1\u67b6\u6784\u4e2d\u7684\u72b6\u6001\u7801\u4f20\u64ad33.1 \u5fae\u670d\u52a1\u67b6\u6784\u4e2d\u7684\u72b6\u6001\u7801\u6311\u621833.1.1 \u5206\u5e03\u5f0f\u7cfb\u7edf\u7684\u590d\u6742\u6027\u5fae\u670d\u52a1\u67b6\u6784\u5e26\u6765\u4e86\u72b6\u6001\u7801\u5904\u7406\u7684\u5168\u65b0\u6311\u6218&#xff1a;yaml# \u5fae\u670d\u52a1\u8c03\u7528\u94fe\u793a\u4f8b request:path: \/api\/order\/123flow:- API Gateway (nginx\/ingress)- Authentication Service- Order Service- calls: User Service- calls: Inventory S\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/68956.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-01-30T14:57:06+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260130145703-697cc6bf0b49d.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=\"67 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/68956.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/68956.html\",\"name\":\"HTTP \u72b6\u6001\u7801\uff1a\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u5668\u7684\u901a\u4fe1\u8bed\u8a00\u2014\u2014\u7b2c\u516d\u90e8\u5206\uff1a\u72b6\u6001\u7801\u7684\u5b9e\u8df5\u5e94\u7528\uff08\u4e8c\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-01-30T14:57:06+00:00\",\"dateModified\":\"2026-01-30T14:57:06+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/68956.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/68956.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/68956.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\u516d\u90e8\u5206\uff1a\u72b6\u6001\u7801\u7684\u5b9e\u8df5\u5e94\u7528\uff08\u4e8c\uff09\"}]},{\"@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\u516d\u90e8\u5206\uff1a\u72b6\u6001\u7801\u7684\u5b9e\u8df5\u5e94\u7528\uff08\u4e8c\uff09 - \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\/68956.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\u516d\u90e8\u5206\uff1a\u72b6\u6001\u7801\u7684\u5b9e\u8df5\u5e94\u7528\uff08\u4e8c\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"\u7b2c33\u7ae0&#xff1a;\u5fae\u670d\u52a1\u67b6\u6784\u4e2d\u7684\u72b6\u6001\u7801\u4f20\u64ad33.1 \u5fae\u670d\u52a1\u67b6\u6784\u4e2d\u7684\u72b6\u6001\u7801\u6311\u621833.1.1 \u5206\u5e03\u5f0f\u7cfb\u7edf\u7684\u590d\u6742\u6027\u5fae\u670d\u52a1\u67b6\u6784\u5e26\u6765\u4e86\u72b6\u6001\u7801\u5904\u7406\u7684\u5168\u65b0\u6311\u6218&#xff1a;yaml# \u5fae\u670d\u52a1\u8c03\u7528\u94fe\u793a\u4f8b request:path: \/api\/order\/123flow:- API Gateway (nginx\/ingress)- Authentication Service- Order Service- calls: User Service- calls: Inventory S","og_url":"https:\/\/www.wsisp.com\/helps\/68956.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-01-30T14:57:06+00:00","og_image":[{"url":"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260130145703-697cc6bf0b49d.png"}],"author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"67 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/68956.html","url":"https:\/\/www.wsisp.com\/helps\/68956.html","name":"HTTP \u72b6\u6001\u7801\uff1a\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u5668\u7684\u901a\u4fe1\u8bed\u8a00\u2014\u2014\u7b2c\u516d\u90e8\u5206\uff1a\u72b6\u6001\u7801\u7684\u5b9e\u8df5\u5e94\u7528\uff08\u4e8c\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-01-30T14:57:06+00:00","dateModified":"2026-01-30T14:57:06+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/68956.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/68956.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/68956.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\u516d\u90e8\u5206\uff1a\u72b6\u6001\u7801\u7684\u5b9e\u8df5\u5e94\u7528\uff08\u4e8c\uff09"}]},{"@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\/68956","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=68956"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/68956\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media\/68954"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=68956"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=68956"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=68956"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=68956"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}