版權聲明:本文爲CSDN博主「封玉書」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zhou199252/article/details/80745151
一、spring cloud簡介
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的開發便利性巧妙地簡化了分佈式系統基礎設施的開發,如服務發現註冊、配置中心、消息總線、負載均衡、斷路器、數據監控等,都可以用Spring Boot的開發風格做到一鍵啓動和部署。Spring Cloud並沒有重複製造輪子,它只是將目前各家公司開發的比較成熟、經得起實際考驗的服務框架組合起來,通過Spring Boot風格進行再封裝屏蔽掉了複雜的配置和實現原理,最終給開發者留出了一套簡單易懂、易部署和易維護的分佈式系統開發工具包。
二、創建服務註冊中心
我們需要用的的組件上Spring Cloud Netflix的Eureka ,eureka是一個服務註冊和發現模塊。
1、創建一個web-app的maven工程。此處命名爲:springcloud
2、在該工程下創建module。
選擇springboot的快速創建。
勾上Eureka Server。以便自動導入包
3、可以檢查一下pom文件,這裏的依賴如下:
<!--eureka server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.4.2.RELEASE</version>
</dependency>
<!-- spring boot test-->
<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-netflix-eureka-server</artifactId>
</dependency>
4、在application中加入註解@EnableEurekaServer,申明此處爲服務註冊中心。
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/2019083014354037.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1MjUzOTcw,size_16,color_FFFFFF,t_70)
5、yml中的加入如下配置:registerWithEureka 和 fetchRegistry 設置爲false,表明自己屬於服務中心主體
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
6、啓動服務,登陸瀏覽器查看。http://localhost:8761/
紅框內爲已經註冊的服務。這裏我們只有服務中心,沒有寫生產者,所以紅框中的內容應該是空。
三、創建生產者
創建的過程如server一樣即可。
1、創建完成之後檢查一下pom文件,這裏提供依賴如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>
<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-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2、在application中加入註解@EnableEurekaClient,表明自己屬於一個生產者。
這裏爲了方便測試,直接使用@RestController獲取返回值。
@SpringBootApplication
@EnableEurekaClient
@RestController
public class ServiceHiApplication
{
public static void main(String[] args)
{
SpringApplication.run(ServiceHiApplication.class, args);
}
@Value("${server.port}")
String port;
@RequestMapping("/hi")
public String home(@RequestParam String name)
{
return "hi " + name + ",i am from port:" + port;
}
}
3、yml配置
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8763
spring:
application:
name: service-hi
端口不能與上面的相同。這裏的服務name:service-hi 可以根據自己情況定義。
4、運行服務,登陸環境 http://localhost:8765/hi?name=fys
可以看到如下信息。這裏用postman進行測試:
在8761這個端口中,也能看到,該信息已經在服務中心進行了註冊。名字爲我們yml中進行配置的名字。
三、創建消費者
1.1 方式一:服務消費者(rest+ribbon)
1、創建消費者modul,流程如上述工程創建流程。
2、引入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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--斷路器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>
</dependencies>
3、yml配置
在工程的配置文件指定服務的註冊中心地址爲http://localhost:8761/eureka/ 。
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8764
spring:
application:
name: service-ribbon
4、application中加入註解:@EnableDiscoveryClient並且加入restTemplate以消費相關的服務。
@SpringBootApplication
@EnableDiscoveryClient
public class ServiceRibbonApplication
{
public static void main(String[] args)
{
SpringApplication.run(ServiceRibbonApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate()
{
return new RestTemplate();
}
}
5、創建service和controller。
@RestController
public class HelloControler
{
@Autowired
HelloService helloService;
@RequestMapping(value = "/hi")
public String hi(@RequestParam String name)
{
return helloService.hiService(name);
}
}
@Service
public class HelloService
{
@Autowired
RestTemplate restTemplate;
public String hiService(String name)
{
return restTemplate.getForObject("http://SERVICE-HI/hi?name=" + name, String.class);
}
}
這裏利用字符串進行傳輸。當然restTemplate也是可以以對象進行傳輸的。
例如:
service-hi中的返回如下:
調用界面如下。
可以看到,都是能成功獲取到相關的返回內容。這裏用object的封裝是爲了方法的通用性。(這裏key值如果爲數字,只測試過字符串的數字,會引起報錯。有興趣的可以進一步研究)。
測試結果如下:
6、增加斷路器
在微服務架構中,根據業務來拆分成一個個的服務,服務與服務之間可以相互調用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign來調用。爲了保證其高可用,單個服務通常會集羣部署。由於網絡原因或者自身的原因,服務並不能保證100%可用,如果單個服務出現問題,調用這個服務就會出現線程阻塞,此時若有大量的請求涌入,Servlet容器的線程資源會被消耗完畢,導致服務癱瘓。服務與服務之間的依賴性,故障會傳播,會對整個微服務系統造成災難性的嚴重後果,這就是服務故障的“雪崩”效應。爲了解決這個問題,業界提出了斷路器模型。
Netflix開源了Hystrix組件,實現了斷路器模式,SpringCloud對這一組件進行了整合。 在微服務架構中,一個請求需要調用多個服務是非常常見的,如下圖:
較底層的服務如果出現故障,會導致連鎖故障。當對特定的服務的調用的不可用達到一個閥值(Hystric 是5秒20次) 斷路器將會被打開。
斷路打開後,可用避免連鎖故障,fallback方法可以直接返回一個固定值。
首先。需要引入斷路器的pom依賴:
<!--斷路器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>
在application中增加@EnableHystrix註解表示開啓斷路器
在上一小節基礎上增加斷路器所需的fallback方法:
代碼如下:
@Service
public class HelloService
{
@Autowired
RestTemplate restTemplate;
// 斷路器配置,當無法調用如下方法時,就會調用自定的hiError方法。
@HystrixCommand(fallbackMethod = "hiError")
public String hiService(String name)
{
// ResponseEntity<Object> forEntity = restTemplate.getForEntity("http://SERVICE-HI/hi?name=" + name, Object.class);
Object forObject = restTemplate.getForObject("http://SERVICE-HI/hi?name=" + name, Object.class);
return forObject.toString();
}
public String hiError(String name)
{
return "hey " +
name + ", there is some problem with hi page";
}
}
完成上述工作後,將service-hi服務關閉,調用service-ribbon 的hi方法。可以看到hiError的輸出結果。