測試開發進階——Spring cloud——理解——微服務中的服務註冊與發現理解(轉載)
什麼是服務註冊與發現
在微服務架構中,整個系統會按職責能力劃分為多個服務,通過服務之間協作來實現業務目標。
這樣在我們的程式碼中免不了要進行服務間的遠端呼叫,服務的消費方要呼叫服務的生產方,為了完成一次請求,消費方需要知道服務生產方的網路位置(IP地址和埠號)。
我們的程式碼可以通過讀取配置檔案的方式讀取服務生產方網路位置,如下:
我們通過Spring boot技術很容易實現:
Service B(服務生產者)
Service B是服務的生產方,暴露/service服務地址,實現程式碼如下:
@SpringBootApplication
@RestController
public class SpringRestProviderBootstrap {
public static void main(String[] args) {
SpringApplication.run(SpringRestProviderBootstrap.class, args);
}
@GetMapping(value = "/service") //暴露服務
public String service(){
return "provider invoke";
}
}
配置檔案:
server.port = 56010
Service A(服務消費者)
實現程式碼:
@SpringBootApplication @RestController public class SpringRestConsumerBootstrap { public static void main(String[] args) { SpringApplication.run(SpringRestConsumerBootstrap.class, args); } @Value("${provider.address}") private String providerAddress; @GetMapping(value = "/service") public String service(){ RestTemplate restTemplate = new RestTemplate(); //呼叫服務 String providerResult = restTemplate.getForObject("http://" + providerAddress + "/service",String.class); return "consumer invoke | " + providerResult; } }
配置檔案:
server.port = 56020
# 服務生產方地址
provider.address = 127.0.0.1:56010
訪問http://127.0.0.1:56020/service,輸出以下內容:
consumer invoke | provider invoke
看上去很完美,但是,仔細考慮以下,此方案對於微服務應用而言行不通。
首先,微服務可能是部署在雲環境的,服務例項的網路位置或許是動態分配的。
另外,每一個服務一般會有多個例項來做負載均衡,由於宕機或升級,服務例項網路地址會經常動態改變。
再者,每一個服務也可能應對臨時訪問壓力增加新的服務節點。正如下圖所示:
基於以上的問題,服務之間如何相互感知?服務如何管理?這就是服務發現的問題了。如下圖:
上圖中服務例項本身並不記錄服務生產方的網路地址,所有服務例項內部都會包含服務發現客戶端。
(1)在每個服務啟動時會向服務發現中心上報自己的網路位置。這樣,在服務發現中心內部會形成一個服務登錄檔,服務登錄檔是服務發現的核心部分,是包含所有服務例項的網路地址的資料庫。
(2)服務發現客戶端會定期從服務發現中心同步服務登錄檔,並快取在客戶端。
(3)當需要對某服務進行請求時,服務例項通過該登錄檔,定位目標服務網路地址。若目標服務存在多個網路地址,則使用負載均衡演算法從多個服務例項中選擇出一個,然後發出請求。
總結一下,在微服務環境中,由於服務執行例項的網路地址是不斷動態變化的,服務例項數量的動態變化 ,
因此無法使用固定的配置檔案來記錄服務提供方的網路地址,必須使用動態的服務發現機制用於實現微服務間的相互感知。
各服務例項會上報自己的網路地址,這樣服務中心就形成了一個完整的服務登錄檔,各服務例項會通過服務發現中心來獲取訪問目標服務的網路地址,從而實現服務發現的機制。