1.Spring Cloud簡介
Spring Cloud是一系列框架的有序集合坪稽。它利用Spring Boot的開發(fā)便利性巧妙地簡化了分布式系統(tǒng)基礎(chǔ)設(shè)施的開發(fā),如服務(wù)發(fā)現(xiàn)注冊鳞骤、配置中心窒百、消息總線、負(fù)載均衡豫尽、斷路器篙梢、數(shù)據(jù)監(jiān)控等,都可以用Spring Boot的開發(fā)風(fēng)格做到一鍵啟動(dòng)和部署美旧。
Spring Cloud并沒有重復(fù)制造輪子渤滞,它只是將目前各家公司開發(fā)的比較成熟贬墩、經(jīng)得起實(shí)際考驗(yàn)的服務(wù)框架組合起來,通過Spring Boot風(fēng)格進(jìn)行再封裝妄呕,屏蔽掉了復(fù)雜的配置和實(shí)現(xiàn)原理陶舞,最終給開發(fā)者留出了一套簡單易懂、易部署和易維護(hù)的分布式系統(tǒng)開發(fā)工具包绪励。
2.Spring Cloud使用示例
工具列表:IDEA肿孵、Maven
項(xiàng)目構(gòu)成:服務(wù)注冊中心、服務(wù)提供者疏魏、服務(wù)消費(fèi)者停做。
項(xiàng)目結(jié)構(gòu)如下:
2.1.創(chuàng)建空白工程
為了方便管理,我們創(chuàng)建一個(gè)空白工程大莫,我們例子中的3個(gè)項(xiàng)目都作為這個(gè)空白工程的子模塊創(chuàng)建蛉腌。
主要步驟如下:
1.File->New->Project,選擇Maven
2.點(diǎn)擊Next只厘,輸入相關(guān)信息
3.創(chuàng)建完成后把其它文件都刪掉烙丛,只保留pom.xml即可。
2.2.服務(wù)注冊發(fā)現(xiàn)模塊
此模塊對應(yīng)項(xiàng)目結(jié)構(gòu)中的demo-eureka
主要步驟如下:
1.在主工程上File->New->Module懈凹,選擇Spring Initializr
2.點(diǎn)擊Next掏愁,輸入模塊信息
3.點(diǎn)擊Next磨总,選擇Cloud Discovery->Eureka Server
4.生成的pom文件部分配置
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</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>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
5.啟動(dòng)類,加上@EnableEurekaServer注解
@SpringBootApplication
@EnableEurekaServer
public class DemoEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(DemoEurekaApplication.class, args);
}
}
6.配置文件application.properties添加如下配置
# 端口號
server.port=8000
# 關(guān)閉自我保護(hù)
eureka.server.enable-self-preservation=false
# 清理服務(wù)器時(shí)間間隔[5s]
eureka.server.eviction-interval-timer-in-ms=5000
# 主機(jī)名
eureka.instance.hostname=localhost
# 是否將自己作為客戶端注冊到Eureka Server[當(dāng)前模塊只是作為Eureka Server服務(wù)端所以設(shè)為false]
eureka.client.register-with-eureka=false
# 是否從Eureka Server獲取注冊信息[當(dāng)前是單點(diǎn)的Eureka Server所以不需要同步其它節(jié)點(diǎn)的數(shù)據(jù)]
eureka.client.fetch-registry=false
# Eureka Server[查詢注冊服務(wù)]地址
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka
2.3.服務(wù)提供者模塊
此模塊對應(yīng)項(xiàng)目結(jié)構(gòu)中的demo-provider
1.創(chuàng)建過程不再贅述航罗,與創(chuàng)建服務(wù)注冊發(fā)現(xiàn)模塊的區(qū)別是爬舰,依賴中選擇:
- Web->Web
- Cloud Discovery->Eureka Server
2.pom文件依賴配置如下
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</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>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3.啟動(dòng)類们陆,加上@EnableDiscoveryClient,表示其作為服務(wù)發(fā)現(xiàn)客戶端
@SpringBootApplication
@EnableDiscoveryClient
public class DemoProviderApplication {
public static void main(String[] args) {
SpringApplication.run(DemoProviderApplication.class, args);
}
}
4.application.properties添加如下配置
# 端口號
server.port=8010
# 應(yīng)用名稱
spring.application.name=provider
# Eureka Server服務(wù)器地址
eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
5.定義MyController類
@RestController
public class MyController {
@RequestMapping(value = "/info", method = RequestMethod.GET)
public String getDefaultInfo() {
try {
//休眠2秒情屹,測試超時(shí)服務(wù)熔斷[直接關(guān)閉服務(wù)提供者亦可]
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello provider";
}
@RequestMapping(value = "/info/{name}", method = RequestMethod.POST)
public String getInfo(@PathVariable String name) {
return "Hello " + name;
}
}
2.3.服務(wù)消費(fèi)者模塊
此模塊對應(yīng)項(xiàng)目結(jié)構(gòu)中的demo-consumer
1.創(chuàng)建過程不再贅述坪仇,與創(chuàng)建服務(wù)注冊發(fā)現(xiàn)模塊的區(qū)別是,依賴中選擇:
- Web->Web
- Cloud Discovery->Eureka Server
- Cloud Routing->Feign
2.pom文件依賴配置如下
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</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>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3.啟動(dòng)類垃你,加上@EnableFeignClients和@EnableEurekaClient
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class DemoConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(DemoConsumerApplication.class, args);
}
}
4.application.properties添加如下配置
# 端口號
server.port=8020
# 應(yīng)用名稱
spring.application.name=consumer
# Eureka Server服務(wù)器地址
eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
# 高版本spring-cloud-openfeign請求分為兩層椅文,先ribbon控制,后hystrix控制.
# Ribbon請求連接的超時(shí)時(shí)間
ribbon.ConnectionTimeout=5000
# Ribbon請求處理的超時(shí)時(shí)間.
ribbon.ReadTimeout=5000
# 設(shè)置服務(wù)熔斷超時(shí)時(shí)間[默認(rèn)1s]
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
# 開啟hystrix以支持服務(wù)熔斷[高版本默認(rèn)false關(guān)閉]惜颇,如果置為false皆刺,則請求超時(shí)交給ribbon控制.
# feign.hystrix.enabled=true
5.定義服務(wù)接口類InfoClient,作為調(diào)用遠(yuǎn)程服務(wù)的本地入口
/**
* FeignClient配置說明
* 1.name:被調(diào)用的服務(wù)應(yīng)用名稱
* 2.fallback: InfoFallBack作為熔斷實(shí)現(xiàn)凌摄,當(dāng)請求provider失敗時(shí)調(diào)用其中的方法
* 3.configuration: feign配置
*/
@FeignClient(name = "provider", fallback = InfoFallBack.class, configuration = MyFeignConfig.class)
public interface InfoClient {
@RequestMapping(value = "/info", method = RequestMethod.GET)
String getDefaultInfo();
@RequestMapping(value = "/info/{name}", method = RequestMethod.POST)
String getInfo(@PathVariable("name") String name);
}
6.定義熔斷類InfoFallBack羡蛾,如果遠(yuǎn)程服務(wù)無法成功請求,則調(diào)用指定的本地邏輯方法
@Component
public class InfoFallBack implements InfoClient {
@Override
public String getDefaultInfo() {
return "fallback info";
}
@Override
public String getInfo(String name) {
return "fallback default info";
}
}
7.定義feign配置類MyFeignConfig
@Configuration
public class MyFeignConfig {
/**
* Feign打印日志等級
*
* @return
*/
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
注意這里的Logger用的是feign下面的锨亏,需要引入
import feign.Logger;
8.定義服務(wù)調(diào)用類ConsumerController,通過本地方法入口調(diào)用遠(yuǎn)程服務(wù)
@RestController
public class ConsumerController {
@Autowired
private InfoClient infoClient;
@RequestMapping(value = "/call/info", method = RequestMethod.GET)
public String consumerInfo(){
return infoClient.getDefaultInfo();
}
@RequestMapping(value = "/call/info/{name}", method = RequestMethod.GET)
public String consumerInfo(@PathVariable String name){
return infoClient.getInfo(name);
}
}
2.4.測試
1.依次啟動(dòng)demo-eureka痴怨、demo-provider忙干、demo-consumer
2.訪問http://127.0.0.1:8000/
你會(huì)看到我們的提供者、消費(fèi)者都已經(jīng)注冊
3.訪問消費(fèi)者
- http://127.0.0.1:8020/call/info/
-
http://127.0.0.1:8020/call/info/wander
你會(huì)看到消費(fèi)者成功訪問了提供者的API并返回了正確的結(jié)果浪藻。
4.測試服務(wù)熔斷捐迫,application.properties配置修改如下
# 設(shè)置服務(wù)熔斷超時(shí)時(shí)間[默認(rèn)1s]
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=1000
# 開啟hystrix以支持服務(wù)熔斷[高版本默認(rèn)false關(guān)閉],如果置為false珠移,則請求超時(shí)交給ribbon控制.
feign.hystrix.enabled=true