歡迎光臨
每天分享高質量文章

註冊中心 Eureka 原始碼解析 —— 除錯環境搭建

本文主要基於 Eureka 1.8.X 版本

  • 1. 依賴工具

  • 2. 原始碼拉取

  • 3. Eureka-Server 啟動

    • 3.1 MockRemoteEurekaServer

    • 3.2 Eureka-Server war 包

    • 3.3 Eureka-Server 直接啟動

  • 4. Eureka-Client 啟動

  • 666. 彩蛋


友情提示:歡迎關註公眾號【芋道原始碼】。?關註後,拉你進【原始碼圈】微信群和【芋艿】搞基嗨皮。

友情提示:歡迎關註公眾號【芋道原始碼】。?關註後,拉你進【原始碼圈】微信群和【芋艿】】搞基嗨皮。

友情提示:歡迎關註公眾號【芋道原始碼】。?關註後,拉你進【原始碼圈】微信群和【芋艿】】搞基嗨皮。


1. 依賴工具

  • Gradle

  • JDK

  • IntelliJ IDEA

推薦 Spring Cloud 書籍

  • 請支援正版。下載盜版,等於主動編寫低階 BUG 。

  • 程式猿DD —— 《Spring Cloud微服務實戰》

  • 周立 —— 《Spring Cloud與Docker微服務架構實戰》

  • 兩書齊買,京東包郵。

2. 原始碼拉取

從官方倉庫 https://github.com/Netflix/eureka.git Fork 出屬於自己的倉庫。為什麼要 Fork ?既然開始閱讀、除錯原始碼,我們可能會寫一些註釋,有了自己的倉庫,可以進行自由的提交。?

使用 IntelliJ IDEA 從 Fork 出來的倉庫拉取程式碼。拉取完成後,Gradle 會下載依賴包,可能會花費一些時間,耐心等待下。

本文基於 master 分支。

3. Eureka-Server 啟動

Eureka-Server 啟動除錯方式,有三種方式,我們來嘗試每一種。

3.1 MockRemoteEurekaServer

com.netflix.eureka.AbstractTester,測試抽象類,有如下實現子類:

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

Debug 執行 ApplicationsResourceTest#testFullAppsGetJson() 單元測試。在方法執行前,ApplicationsResourceTest#setUp() 會執行,初始化 Eureka-Server 模擬環境,例如:
com.netflix.eureka.mock.MockRemoteEurekaServer ( 模擬 Eureka-Server )。

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

// ApplicationsResourceTest.java
@Test
public void testFullAppsGetJson() throws Exception {
  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() 獲取不到路徑,先暫時這樣;

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

4. 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 模組還提供別的例子,可以逐個除錯。

666. 彩蛋

本文寫的,相對比較簡潔,如果有任何疑問,可以給我公眾號留言。

下一篇更新?恩,我還沒想好,整理《Eureka 原始碼解析》整個系列的目錄ing。

胖友,分享一波朋友圈可好!

贊(0)

分享創造快樂