1. 程式人生 > >Spring Cloud 微服務框架之服務註冊與發現

Spring Cloud 微服務框架之服務註冊與發現

Spring Cloud介紹

Spring Cloud是一個相對比較新的微服務框架,2016才推出1.0的release版本. 雖然Spring Cloud時間最短, 但是相比Dubbo等RPC框架, Spring Cloud提供的全套的分散式系統解決方案。

Spring Cloud 為開發者提供了在分散式系統(配置管理,服務發現,熔斷,路由,微代理,控制匯流排,一次性token,全居瑣,leader選舉,分散式session,叢集狀態)中快速構建的工具,使用Spring Cloud的開發者可以快速的啟動服務或構建應用、同時能夠快速和雲平臺資源進行對接。

微服務架構

微服務可以在“自己的程式”中執行,並通過“輕量級裝置與HTTP型API進行溝通”。關鍵在於該服務可以在自己的程式中執行。通過這一點我們就可以將服務公開與微服務架構(在現有系統中分佈一個API)區分開來。在服務公開中,許多服務都可以被內部獨立程序所限制。如果其中任何一個服務需要增加某種功能,那麼就必須縮小程序範圍。在微服務架構中,只需要在特定的某種服務中增加所需功能,而不影響整體程序。 微服務不需要像普通服務那樣成為一種獨立的功能或者獨立的資源。定義中稱,微服務是需要與業務能力相匹配,這種說法完全正確。不幸的是,仍然意味著,如果能力模型粒度的設計是錯誤的,那麼,我們就必須付出很多代價。如果你閱讀了Fowler的整篇文章,你會發現,其中的指導建議是非常實用的。在決定將所有元件組合到一起時,開發人員需要非常確信這些元件都會有所改變,並且規模也會發生變化。服務粒度越粗,就越難以符合規定原則。服務粒度越細,就越能夠靈活地降低變化和負載所帶來的影響。然而,利弊之間的權衡過程是非常複雜的,我們要在配置和資金模型的基礎上考慮到基礎設施的成本問題。

服務註冊與發現

接下來我們通過實際案例來看看如何使用Spring Cloud搭建服務註冊與發現模組,案例中核心內容就是服務發現模組:Eureka

1、首先建立“服務註冊中心”

(1)建立一個Maven工程,並在pom.xml中引入需要的依賴內容:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.3.5.RELEASE</version>
	<relativePath/>
</parent>
<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<java.version>1.7</java.version>
</properties>
<dependencies>
	
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Brixton.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
(2)通過 @EnableEurekaServer 註解啟動一個服務註冊中心提供給其他應用進行對話。這一步非常的簡單,只需要在一個普通的Spring Boot應用中新增這個註解就能開啟此功能,建立一個Application.java,如下所示:

package com.wys;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class Application {
	public static void main(String[] args) {
		new SpringApplicationBuilder(Application.class).web(true).run(args);
	}
}
(3)在預設設定下,該服務註冊中心也會將自己作為客戶端來嘗試註冊它自己,所以我們需要禁用它的客戶端註冊行為,只需要在 application.properties 中問增加如下配置:
server.port=1111
#eureka.instance.hostname=localhost
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/
至此,簡單的服務註冊就搭建好了,專案整體結構如下:


現在啟動工程(Application.java),訪問:http://localhost:1111/     (注意這裡的1111是自己在application.properties檔案中設定的埠號)

此時,可以看到下面的頁面,其中還沒有發現任何服務


該工程可參考:eureka-server

(4)建立“服務提供方”

接下來我們建立提供服務的客戶端,並向服務註冊中心註冊自己。

假設我們有一個提供計算功能的微服務模組,我們實現一個RESTful API,通過傳入兩個引數a和b,最後返回a + b的結果。

首先,建立一個Maven工程,在pom.xml檔案中加入依賴,如下所示。

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.3.5.RELEASE</version>
	<relativePath/>
</parent>
<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<java.version>1.7</java.version>
</properties>
<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-eureka</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>
<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-dependencies</artifactId>
			<version>Brixton.RELEASE</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>
<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>
(5)實現/add請求處理介面,通過DiscoveryClient物件,在日誌中打印出服務例項的相關內容

package com.wys.web;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ComputeController {
	private final Logger logger=Logger.getLogger(getClass());
	@Autowired
	private DiscoveryClient client;
	@RequestMapping(value="/add",method=RequestMethod.GET)
	public Integer add(@RequestParam Integer a,@RequestParam Integer b){
		ServiceInstance instance=client.getLocalServiceInstance();
		Integer r=a+b;
		logger.info("/add, host:" + instance.getHost() + ", service_id:" + instance.getServiceId() + ", result:" + r);
		return r;
	}
}
(6) 在主類中通過加上 @EnableDiscoveryClient 註解,該註解能啟用Eureka中的 DiscoveryClient 實現,才能實現Controller中對服務資訊的輸出。
package com.wys;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class ComputeServiceApplication {

	public static void main(String[] args) {
		new SpringApplicationBuilder(ComputeServiceApplication.class).web(true).run(args);
	}

}
(7) 完成了服務內容的實現之後,再繼續對 application.properties 做一些配置工作,具體如下:

spring.application.name=compute-service
server.port=2222
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
通過spring.application.name屬性,我們可以指定微服務的名稱後續在呼叫的時候只需要使用該名稱就可以進行服務的訪問。
eureka.client.serviceUrl.defaultZone屬性對應服務註冊中心的配置內容,指定服務註冊中心的位置。
為了在本機上測試區分服務提供方和服務註冊中心,使用server.port屬性可以設定不同的埠。

至此,“服務提供方”已經建立好了,整體專案結構如下:

啟動該工程之前,先啟動剛剛建立的服務註冊中心(eureka-server中的Application.java)

訪問:http://localhost:1111/    可以看到,我們定義的服務被註冊了。


該工程可參考:compute-service