首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

微服務架構實戰第四章:服務容錯與 Hystrix 熔斷器整合完整代碼

     編輯:Java 綜合教學

微服務架構實戰第四章:服務容錯與 Hystrix 熔斷器整合

為什麼需要服務容錯?

微服務架構中,服務間透過網路調用。若下游服務 (如 Service4) 響應緩慢或失效,上游服務 (Service1) 的執行緒會大量阻塞等待,導致執行緒池耗盡,進而拖垮同機器上的其他服務 (Service2、Service3) —— **級聯故障**。

Hystrix 熔斷器雙重保護機制

  1. 隔離與超時熔斷: 調用包裝在 HystrixCommand 中,設定超時時間。超時即刻斷開,執行 getFallback() 降級邏輯,釋放執行緒,保護上游服務穩定。
  2. 熔斷器開啟/半開/關閉狀態機: 統計時間窗內 (預設 10 秒) 錯誤率超過閾值 (預設 50%),熔斷器**開啟**,後續請求直接走降級不再嘗試調用;經過睡眠窗 (預設 5 秒) 進入**半開**狀態允許少量請求探測,成功則**關閉**恢復正常。

技術棧與專案結構

  • 框架模組 (framework):封裝 Consul 註冊/發現、Ribbon 負載均衡、Retrofit 通訊、Hystrix 容錯。
  • 服務 A (myserviceA):被調用方,提供省份資料 API (故意 sleep 5 秒模擬慢服務)。
  • 服務 B (myserviceB):調用方,透過 Feign/Retrofit Client 調用 A。

核心代碼實現 (framework 模組)

1. Maven 依賴 (pom.xml 關鍵片段)

<dependency><groupId>com.netflix.hystrix</groupId><artifactId>hystrix-core</artifactId><version>1.5.3</version></dependency>
<dependency><groupId>com.netflix.hystrix</groupId><artifactId>hystrix-metrics-event-stream</artifactId><version>1.5.3</version></dependency>
<!-- Retrofit + OkHttp + Jackson -->
<dependency><groupId>com.squareup.retrofit</groupId><artifactId>retrofit</artifactId><version>1.9.0</version></dependency>
<dependency><groupId>com.squareup.okhttp</groupId><artifactId>okhttp</artifactId><version>2.4.0</version></dependency>

2. RestAdapterConfig:整合負載均衡與 Hystrix

@Component
public class RestAdapterConfig {
    @Autowired private MyLoadBalancer lb;

    public <T> T create(Class<T> apiType, String serviceName) {
        ServerAddress server = lb.chooseServer(serviceName); // 負載均衡選址
        String groupKey = apiType.getSimpleName(); // Hystrix CommandGroupKey

        RestAdapter adapter = new RestAdapter.Builder()
            .setConverter(new JacksonConverter())
            .setErrorHandler(new MyErrorHandler())
            .setClient(new MyHttpClient(server, groupKey)) // 自定義 Client 注入 Hystrix
            .setEndpoint("/").build();
        return adapter.create(apiType);
    }
}

3. MyHttpClient:Retrofit Client 介面實現,委派給 HystrixCommand

public class MyHttpClient implements Client {
    private final ServerAddress server;
    private final String commandGroupKey;
    private final int timeoutMs = 3000; // 硬編碼超時,後續可配置化

    public MyHttpClient(ServerAddress server, String commandGroupKey) { ... }

    @Override public Response execute(Request request) throws IOException {
        Setter setter = Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(commandGroupKey))
            .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                .withExecutionTimeoutInMilliseconds(timeoutMs));
        return new HttpHystrixCommand(setter, server, request).execute(); // 同步執行
    }
}

4. HttpHystrixCommand:核心 HystrixCommand 實現

public class HttpHystrixCommand extends HystrixCommand<Response> {
    private final ServerAddress server;
    private final Request request;
    private String requestUrl;

    public HttpHystrixCommand(Setter setter, ServerAddress server, Request request) {
        super(setter); this.server = server; this.request = request;
    }

    @Override protected Response run() throws Exception {
        // 1. Retrofit Request -> OkHttp Request (含負載均衡地址)
        Request okReq = buildOkHttpRequest(request, server);
        // 2. OkHttp 同步調用
        com.squareup.okhttp.Response okRes = new OkHttpClient().newCall(okReq).execute();
        // 3. OkHttp Response -> Retrofit Response
        return convertToRetrofitResponse(okRes);
    }

    @Override protected Response getFallback() {
        log.error("Hystrix 超時/失敗,請求URL: {}", requestUrl);
        // 返回特定狀態碼 404 + 錯誤訊息,供 ErrorHandler 識別
        return new Response(requestUrl, 404, "execute getFallback because execution timeout",
                new ArrayList<>(), null);
    }
    // 輔助轉換方法省略...
}

5. MyErrorHandler:識別 Hystrix 降級響應並拋出業務異常

public class MyErrorHandler implements ErrorHandler {
    @Override public Throwable handleError(RetrofitError cause) {
        Response resp = cause.getResponse();
        if (resp != null && resp.getStatus() == 404) {
            return new HystrixRuntimeException(cause); // 自定義運行時異常
        }
        return cause;
    }
}

6. 服務 A 控制器 (模擬慢服務)

@RestController @RequestMapping("/myserviceA")
public class MyserviceAController {
    @PostMapping("/provinces/{provincename}")
    public Province getProvinceByCityName(@PathVariable String provincename,
                                          @RequestParam long personNum) throws InterruptedException {
        Thread.sleep(5000); // 故意延遲 5 秒 > Hystrix 3 秒超時
        return new Province(1, provincename, personNum);
    }
}

7. 服務 B Client 與 Controller

// Client
@Component
public class MyserviceAClient {
    @Autowired RestAdapterConfig adapterConfig;
    public Province getProvinceByCityName(String name, long num) {
        MyserviceAAPI api = adapterConfig.create(MyserviceAAPI.class, "myserviceA");
        return api.getProvinceByCityName(name, num);
    }
}

// Controller
@RestController @RequestMapping("/myserviceB")
public class MyserviceBController {
    @Autowired MyserviceAClient client;
    @PostMapping("/provinces/{provincename}")
    public Province callA(@PathVariable String provincename, @RequestParam long personNum) {
        return client.getProvinceByCityName(provincename, personNum); // 3 秒後返回 Fallback
    }
}

執行驗證

  1. 啟動 Consul、Service A (8080)、Service B (8081)。
  2. 透過 Swagger UI 呼叫 POST /myserviceB/provinces/浙江?personNum=1000。
  3. Service A 需 5 秒,Hystrix 3 秒超時觸發 getFallback(),Service B 於 3 秒內收到 404 降級響應,拋出 HystrixRuntimeException,不會阻塞 5 秒。
  4. 觀察 Hystrix Dashboard (需啟用 hystrix-metrics-event-stream) 監控熔斷指標。

後續優化方向

  • 超時時間、熔斷閾值外部化配置 (Spring Cloud Config / Apollo)。
  • 引入 Ribbon 替換自製負載均衡,Feign 替換 Retrofit 簡化 Client 定義。
  • 整合 Hystrix Dashboard + Turbine 聚合監控。
  • 區分業務異常與系統異常,Fallback 返回具體業務預設值而非拋異常。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved