1. 程式人生 > >註冊中心 Eureka 源碼解析 —— 調試環境搭建(含源碼)

註冊中心 Eureka 源碼解析 —— 調試環境搭建(含源碼)

Java 架構

  • 依賴工具
    Gradle
    JDK
    IntelliJ IDEA
  • 源碼拉取
    https://github.com/Netflix/eureka.git
    使用 IntelliJ IDEA 從 Fork 出來的倉庫拉取代碼。拉取完成後,Gradle 會下載依賴包,可能會花費一些時間,耐心等待下。
  • 本文基於 master 分支。

    1. Eureka-Server 啟動
      Eureka-Server 啟動調試方式,有三種方式,我們來嘗試每一種。

    3.1 MockRemoteEurekaServer
    com.netflix.eureka.AbstractTester,測試抽象類,有如下實現子類:
    技術分享圖片

    使用任意一個子類的單元測試執行即可執行 Eureka-Server 邏輯的調試,這裏以 com.netflix.eureka.resources.ApplicationsResourceTest 作為例子。

    具有1-5工作經驗的,面對目前流行的技術不知從何下手,需要突破技術瓶頸的可以加群。在公司待久了,過得很安逸,但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的可以加群。如果沒有工作經驗,但基礎非常紮實,對java工作機制,常用設計思想,常用java開發框架掌握熟練的可以加群。java架構群:582505643一起交流。
    Debug 運行 ApplicationsResourceTest#testFullAppsGetJson() 單元測試。在方法執行前,ApplicationsResourceTest#setUp() 會運行,初始化 Eureka-Server 模擬環境,例如:
    com.netflix.eureka.mock.MockRemoteEurekaServer ( 模擬 Eureka-Server )。

    因為是模擬環境,對 Eureka-Server 的操作不是 Eureka-Client 請求 Eureka-Server 的方式,而是直接調用單元測試對應的方法。例如:

    // ApplicationsResourceTest.java@Test
    br/>@Test
    Response response = applicationsResource.getContainers(
    Version.V2.name(),
    MediaType.APPLICATION_JSON,
    null, // encoding
    EurekaAccept.full.name(),
    null, // uriInfo
    null // remote regions

    );

    String json = String.valueOf(response.getEntity());
    DecoderWrapper decoder = CodecWrappers.getDecoder(CodecWrappers.LegacyJacksonJson.class);

    Applications decoded = decoder.decode(json, Applications.class);
    // test per app as the full apps list include the mock server that is not part of the test apps
    for (Application application : testApplications.getRegisteredApplications()) {
    Application decodedApp = decoded.getRegisteredApplications(application.getName());
    assertThat(EurekaEntityComparators.equal(application, decodedApp), is(true));
    }
    }
    直接調用 ApplicationsResource#getContainers(...) 方法。
    總結:這種方式,簡單粗暴,容易上手。當然,它的缺點是模擬。剛開始調試 Eureka-Server 可以嘗試這種方式。

    3.2 Eureka-Server war 包
    第一步,編譯 Eureka-Server war 包。該步驟可能消耗漫長的時間,如果執行失敗,請不斷重試。命令如下:

    cd eureka
    ./gradlew clean build
    第二步,Debug 運行com.netflix.eureka.resources.EurekaClientServerRestIntegrationTest 任意單元測試方法。

    總結:這種方式,編譯的過程比較痛苦,不排除失敗的可能性。每次增加對代碼的註冊後,都需要重新編譯打包。因此不建議采用。那咋辦呢?見第三種。良心如博主,趕緊關註博主的×××公眾號:【芋道源碼】。

    3.3 Eureka-Server 直接啟動
    第一步,修改 EurekaClientServerRestIntegrationTest#startServer() 方法,解決第二種方式使用 war 包運行每次修改代碼都需要重新編譯的問題,實現代碼如下:

    // EurekaClientServerRestIntegrationTest.java
    private static void startServer() throws Exception {
    server = new Server(8080);

    // TODO Thread.currentThread().getContextClassLoader() 獲取不到路徑,先暫時這樣;
    WebAppContext webAppCtx = new WebAppContext(new File("./eureka-server/src/main/webapp").getAbsolutePath(), "/");
    webAppCtx.setDescriptor(new File("./eureka-server/src/main/webapp/WEB-INF/web.xml").getAbsolutePath());
    webAppCtx.setResourceBase(new File("./eureka-server/src/main/resources").getAbsolutePath());
    webAppCtx.setClassLoader(Thread.currentThread().getContextClassLoader());
    server.setHandler(webAppCtx);
    server.start();

    eurekaServiceUrl = "http://localhost:8080/v2";
    }
    筆者不太熟悉 Gradle 的打包方式,使用 Thread.currentThread().getContextClassLoader().getResource() 方法,一直無法拿到路徑,有知道的同學麻煩告知下。
    第二步,Debug 運行com.netflix.eureka.resources.EurekaClientServerRestIntegrationTest 任意單元測試方法。TODO[0003]:Thread.currentThread().getContextClassLoader() 獲取不到路徑,先暫時這樣;

    總結:這種方式,完美。建議使用該方式調試。

    1. Eureka-Client 啟動
      我們以 com.netflix.eureka.ExampleEurekaClient 為例子。

    第一步,在 EurekaClientServerRestIntegrationTest#setUp() 方法末尾添加 Thread.sleep(Long.MAX_VALUE) 代碼。

    第二步,按照「 3.3 Eureka-Server 直接啟動」方法啟動 Eureka-Server。

    第三步,將 EurekaClientServerRestIntegrationTest#injectEurekaConfiguration 復制到 ExampleEurekaClient 類裏。

    第四步,在 ExampleEurekaClient#main() 方法的第一行,添加 injectEurekaConfiguration() 代碼。

    第五步,Debug 運行 ExampleEurekaClient#main() 方法。

    技術分享圖片

    eureka-examples 模塊還提供別的例子,可以逐個調試

    註冊中心 Eureka 源碼解析 —— 調試環境搭建(含源碼)