單體應用存在的問題
- 隨著業(yè)務的發(fā)展樟遣,開發(fā)變得越來越復雜。
- 修改身笤、新增某個功能豹悬,需要對整個系統(tǒng)進行測試、重新部署液荸。
- 一個模塊出現(xiàn)問題瞻佛,很可能導致整個系統(tǒng)崩潰。
- 多個開發(fā)團隊同時對數(shù)據(jù)進行管理娇钱,容易產(chǎn)生安全漏洞伤柄。
- 各個模塊使用同一種技術進行開發(fā),各個模塊很難根據(jù)實際情況選擇更合適的技術框架文搂,局限性很大响迂。
- 模塊內容過于復雜,如果員工離職细疚,可能需要很長時間才能完成工作交接蔗彤。
分布式、集群
集群:一臺服務器無法負荷高并發(fā)的數(shù)據(jù)訪問量疯兼,那么就設置十臺服務器一起分擔壓力然遏,十臺不行就設置一百臺(物理層面)。很多人干同一件事情吧彪,來分攤壓力待侵。
分布式:將一個復雜問題拆分成若干個簡單的小問題,將一個大型的項目架構拆分成若干個微服務來協(xié)同完成姨裸。(軟件設計層面)秧倾。將一個龐大的工作拆分成若干個小步驟怨酝,分別由不同的人完成這些小步驟,最終將所有的結果進行整合實現(xiàn)大的需求那先。
服務治理的核心又三部分組成:服務提供者农猬、服務消費者、注冊中心售淡。
在分布式系統(tǒng)架構中斤葱,每個微服務在啟動時,將自己的信息存儲在注冊中心揖闸,叫做服務注冊揍堕。
服務消費者從注冊中心獲取服務提供者的網(wǎng)絡信息,通過該信息調用服務汤纸,叫做服務發(fā)現(xiàn)俘枫。
Spring Cloud 的服務治理使用 Eureka 來實現(xiàn)拳话,Eureka 是 Netflix 開源的基于 REST 的服務治理解決方案,Spring Cloud 集成了 Eureka,提供服務注冊和服務發(fā)現(xiàn)的功能妖谴,可以和基于 Spring Boot 搭建的微服務應用輕松完成整合狂魔,開箱即用起意,Spring Cloud Eureka诺凡。
Spring Cloud Eureka
- Eureka Server,注冊中心
- Eureka Client议惰,所有要進行注冊的微服務通過 Eureka Client 連接到 Eureka Server慎颗,完成注冊。
Eureka Server代碼實現(xiàn)
- 創(chuàng)建父工程言询,pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.7.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 解決 JDK 9 以上沒有 JAXB API 的問題 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 在父工程下創(chuàng)建 Module俯萎,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 創(chuàng)建配置文件 application.yml,添加 Eureka Server 相關配置运杭。
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://localhost:8761/eureka/
屬性說明
server.port
:當前 Eureka Server 服務端口夫啊。
eureka.client.register-with-eureka
:是否將當前的 Eureka Server 服務作為客戶端進行注冊。
eureka.client.fetch-fegistry
:是否獲取其他 Eureka Server 服務的數(shù)據(jù)辆憔。
eureka.client.service-url.defaultZone
:注冊中心的訪問地址撇眯。
- 創(chuàng)建啟動類
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class,args);
}
}
注解說明:
@SpringBootApplication
:聲明該類是 Spring Boot 服務的入口。
@EnableEurekaServer
:聲明該類是一個 Eureka Server 微服務虱咧,提供服務注冊和服務發(fā)現(xiàn)功能熊榛,即注冊中心。
Eureka Client 代碼實現(xiàn)
- 創(chuàng)建 Module 腕巡,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 創(chuàng)建配置文件 application.yml玄坦,添加 Eureka Client 相關配置
server:
port: 8010
spring:
application:
name: provider
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
屬性說明:
spring.application.name
:當前服務注冊在 Eureka Server 上的名稱。
eureka.client.service-url.defaultZone
:注冊中心的訪問地址。
eureka.instance.prefer-ip-address
:是否將當前服務的 IP 注冊到 Eureka Server煎楣。
- 創(chuàng)建啟動類
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class,args);
}
}
- 實體類
package com.southwind.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private long id;
private String name;
private int age;
}
- Repository
package com.southwind.repository;
import com.southwind.entity.Student;
import java.util.Collection;
public interface StudentRepository {
public Collection<Student> findAll();
public Student findById(long id);
public void saveOrUpdate(Student student);
public void deleteById(long id);
}
- RepositoryImpl
package com.southwind.repository.impl;
import com.southwind.entity.Student;
import com.southwind.repository.StudentRepository;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@Repository
public class StudentRepositoryImpl implements StudentRepository {
private static Map<Long,Student> studentMap;
static {
studentMap = new HashMap<>();
studentMap.put(1L,new Student(1L,"張三",22));
studentMap.put(2L,new Student(2L,"李四",23));
studentMap.put(3L,new Student(3L,"王五",24));
}
@Override
public Collection<Student> findAll() {
return studentMap.values();
}
@Override
public Student findById(long id) {
return studentMap.get(id);
}
@Override
public void saveOrUpdate(Student student) {
studentMap.put(student.getId(),student);
}
@Override
public void deleteById(long id) {
studentMap.remove(id);
}
}
- Handler
package com.southwind.controller;
import com.southwind.entity.Student;
import com.southwind.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;
@RestController
@RequestMapping("/student")
public class StudentHandler {
@Autowired
private StudentRepository studentRepository;
@GetMapping("/findAll")
public Collection<Student> findAll(){
return studentRepository.findAll();
}
@GetMapping("/findById/{id}")
public Student findById(@PathVariable("id") long id){
return studentRepository.findById(id);
}
@PostMapping("/save")
public void save(@RequestBody Student student){
studentRepository.saveOrUpdate(student);
}
@PutMapping("/update")
public void update(@RequestBody Student student){
studentRepository.saveOrUpdate(student);
}
@DeleteMapping("/deleteById/{id}")
public void deleteById(@PathVariable("id") long id){
studentRepository.deleteById(id);
}
}
RestTemplate 的使用
- 什么是 RestTemplate豺总?
RestTemplate 是 Spring 框架提供的基于 REST 的服務組件,底層是對 HTTP 請求及響應進行了封裝择懂,提供了很多訪問 RETS 服務的方法喻喳,可以簡化代碼開發(fā)。
- 如何使用 RestTemplate休蟹?
1沸枯、創(chuàng)建 Maven 工程日矫,pom.xml赂弓。
2、創(chuàng)建實體類
package com.southwind.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private long id;
private String name;
private int age;
}
3哪轿、Handler
package com.southwind.controller;
import com.southwind.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.Collection;
@RestController
@RequestMapping("/rest")
public class RestHandler {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/findAll")
public Collection<Student> findAll(){
return restTemplate.getForEntity("http://localhost:8010/student/findAll",Collection.class).getBody();
}
@GetMapping("/findAll2")
public Collection<Student> findAll2(){
return restTemplate.getForObject("http://localhost:8010/student/findAll",Collection.class);
}
@GetMapping("/findById/{id}")
public Student findById(@PathVariable("id") long id){
return restTemplate.getForEntity("http://localhost:8010/student/findById/{id}",Student.class,id).getBody();
}
@GetMapping("/findById2/{id}")
public Student findById2(@PathVariable("id") long id){
return restTemplate.getForObject("http://localhost:8010/student/findById/{id}",Student.class,id);
}
@PostMapping("/save")
public void save(@RequestBody Student student){
restTemplate.postForEntity("http://localhost:8010/student/save",student,null).getBody();
}
@PostMapping("/save2")
public void save2(@RequestBody Student student){
restTemplate.postForObject("http://localhost:8010/student/save",student,null);
}
@PutMapping("/update")
public void update(@RequestBody Student student){
restTemplate.put("http://localhost:8010/student/update",student);
}
@DeleteMapping("/deleteById/{id}")
public void deleteById(@PathVariable("id") long id){
restTemplate.delete("http://localhost:8010/student/deleteById/{id}",id);
}
}
4盈魁、啟動類
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class RestTemplateApplication {
public static void main(String[] args) {
SpringApplication.run(RestTemplateApplication.class,args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
服務消費者 consumer
- 創(chuàng)建 Maven 工程,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 創(chuàng)建配置文件 application.yml
server:
port: 8020
spring:
application:
name: consumer
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
- 創(chuàng)建啟動類
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- Handler
package com.southwind.controller;
import com.southwind.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.Collection;
@RestController
@RequestMapping("/consumer")
public class ConsumerHandler {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/findAll")
public Collection<Student> findAll(){
return restTemplate.getForEntity("http://localhost:8010/student/findAll",Collection.class).getBody();
}
@GetMapping("/findAll2")
public Collection<Student> findAll2(){
return restTemplate.getForObject("http://localhost:8010/student/findAll",Collection.class);
}
@GetMapping("/findById/{id}")
public Student findById(@PathVariable("id") long id){
return restTemplate.getForEntity("http://localhost:8010/student/findById/{id}",Student.class,id).getBody();
}
@GetMapping("/findById2/{id}")
public Student findById2(@PathVariable("id") long id){
return restTemplate.getForObject("http://localhost:8010/student/findById/{id}",Student.class,id);
}
@PostMapping("/save")
public void save(@RequestBody Student student){
restTemplate.postForEntity("http://localhost:8010/student/save",student,null).getBody();
}
@PostMapping("/save2")
public void save2(@RequestBody Student student){
restTemplate.postForObject("http://localhost:8010/student/save",student,null);
}
@PutMapping("/update")
public void update(@RequestBody Student student){
restTemplate.put("http://localhost:8010/student/update",student);
}
@DeleteMapping("/deleteById/{id}")
public void deleteById(@PathVariable("id") long id){
restTemplate.delete("http://localhost:8010/student/deleteById/{id}",id);
}
}
服務網(wǎng)關
Spring Cloud 集成了 Zuul 組件窃诉,實現(xiàn)服務網(wǎng)關杨耙。
- 什么是 Zuul?
Zuul 是 Netflix 提供的一個開源的 API 網(wǎng)關服務器飘痛,是客戶端和網(wǎng)站后端所有請求的中間層珊膜,對外開放一個 API,將所有請求導入統(tǒng)一的入口宣脉,屏蔽了服務端的具體實現(xiàn)邏輯车柠,Zuul 可以實現(xiàn)反向代理的功能,在網(wǎng)關內部實現(xiàn)動態(tài)路由塑猖、身份認證竹祷、IP 過濾、數(shù)據(jù)監(jiān)控等羊苟。
- 創(chuàng)建 Maven 工程塑陵,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 創(chuàng)建配置文件 application.yml
server:
port: 8030
spring:
application:
name: gateway
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
zuul:
routes:
provider: /p/**
屬性說明:
zuul.routes.provider
:給服務提供者 provider 設置映射
- 創(chuàng)建啟動類
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@EnableZuulProxy
@EnableAutoConfiguration
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class,args);
}
}
注解說明:
@EnableZuulProxy
:包含了 @EnableZuulServer
,設置該類是網(wǎng)關的啟動類蜡励。
@EnableAutoConfiguration
:可以幫助 Spring Boot 應用將所有符合條件的 @Configuration
配置加載到當前 Spring Boot 創(chuàng)建并使用的 IoC 容器中令花。
- Zuul 自帶了負載均衡功能,修改 provider 的代碼凉倚。
package com.southwind.controller;
import com.southwind.entity.Student;
import com.southwind.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;
@RestController
@RequestMapping("/student")
public class StudentHandler {
@Autowired
private StudentRepository studentRepository;
@Value("${server.port}")
private String port;
@GetMapping("/findAll")
public Collection<Student> findAll(){
return studentRepository.findAll();
}
@GetMapping("/findById/{id}")
public Student findById(@PathVariable("id") long id){
return studentRepository.findById(id);
}
@PostMapping("/save")
public void save(@RequestBody Student student){
studentRepository.saveOrUpdate(student);
}
@PutMapping("/update")
public void update(@RequestBody Student student){
studentRepository.saveOrUpdate(student);
}
@DeleteMapping("/deleteById/{id}")
public void deleteById(@PathVariable("id") long id){
studentRepository.deleteById(id);
}
@GetMapping("/index")
public String index(){
return "當前端口:"+this.port;
}
}
Ribbon 負載均衡
- 什么是 Ribbon彭则?
Spring Cloud Ribbon 是一個負載均衡解決方案,Ribbon 是 Netflix 發(fā)布的負載均衡器占遥,Spring Cloud Ribbon 是基于 Netflix Ribbon 實現(xiàn)的俯抖,是一個用于對 HTTP 請求進行控制的負載均衡客戶端。
在注冊中心對 Ribbon 進行注冊之后瓦胎,Ribbon 就可以基于某種負載均衡算法芬萍,如輪詢尤揣、隨機、加權輪詢柬祠、加權隨機等自動幫助服務消費者調用接口北戏,開發(fā)者也可以根據(jù)具體需求自定義 Ribbon 負載均衡算法。實際開發(fā)中漫蛔,Spring Cloud Ribbon 需要結合 Spring Cloud Eureka 來使用嗜愈,Eureka Server 提供所有可以調用的服務提供者列表,Ribbon 基于特定的負載均衡算法從這些服務提供者中選擇要調用的具體實例莽龟。
- 創(chuàng)建 Module蠕嫁,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 創(chuàng)建配置文件 application.yml
server:
port: 8040
spring:
application:
name: ribbon
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
- 創(chuàng)建啟動類
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class RibbonApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonApplication.class,args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
@LoadBalanced
:聲明一個基于 Ribbon 的負載均衡。
- Handler
package com.southwind.controller;
import com.southwind.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Collection;
@RestController
@RequestMapping("/ribbon")
public class RibbonHandler {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/findAll")
public Collection<Student> findAll(){
return restTemplate.getForObject("http://provider/student/findAll",Collection.class);
}
@GetMapping("/index")
public String index(){
return restTemplate.getForObject("http://provider/student/index",String.class);
}
}
Feign
- 什么是 Feign毯盈?
與 Ribbon 一樣剃毒,F(xiàn)eign 也是由 Netflix 提供的,F(xiàn)eign 是一個聲明式搂赋、模版化的 Web Service 客戶端赘阀,它簡化了開發(fā)者編寫 Web 服務客戶端的操作,開發(fā)者可以通過簡單的接口和注解來調用 HTTP API脑奠,Spring Cloud Feign基公,它整合了 Ribbon 和 Hystrix,具有可插拔宋欺、基于注解轰豆、負載均衡、服務熔斷等一系列便捷功能迄靠。
相比較于 Ribbon + RestTemplate 的方式秒咨,F(xiàn)eign 大大簡化了代碼的開發(fā),F(xiàn)eign 支持多種注解掌挚,包括 Feign 注解雨席、JAX-RS 注解、Spring MVC 注解等吠式,Spring Cloud 對 Feing 進行了優(yōu)化陡厘,整合了 Ribbon 和 Eureka,從而讓 Feign 的使用更加方便特占。
- Ribbon 和 Feign 的區(qū)別
Ribbon 是一個通用的 HTTP 客戶端工具糙置,F(xiàn)eign 是基于 Ribbon 實現(xiàn)的。
- Feign 的tedian
1是目、Feign 是一個聲明式的 Web Service 客戶端谤饭。
2、支持 Feign 注解、Spring MVC 注解揉抵、JAX-RS 注解亡容。
3、Feign 基于 Ribbon 實現(xiàn)冤今,使用起來更加簡單闺兢。
4、Feign 集成了 Hystrix戏罢,具備服務熔斷的功能屋谭。
- 創(chuàng)建 Module,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 創(chuàng)建配置文件 application.yml
server:
port: 8050
spring:
application:
name: feign
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
- 創(chuàng)建啟動類
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class FeignApplication {
public static void main(String[] args) {
SpringApplication.run(FeignApplication.class,args);
}
}
- 創(chuàng)建聲明式接口
package com.southwind.feign;
import com.southwind.entity.Student;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Collection;
@FeignClient(value = "provider")
public interface FeignProviderClient {
@GetMapping("/student/findAll")
public Collection<Student> findAll();
@GetMapping("/student/index")
public String index();
}
- Handler
package com.southwind.controller;
import com.southwind.entity.Student;
import com.southwind.feign.FeignProviderClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
@RestController
@RequestMapping("/feign")
public class FeignHandler {
@Autowired
private FeignProviderClient feignProviderClient;
@GetMapping("/findAll")
public Collection<Student> findAll(){
return feignProviderClient.findAll();
}
@GetMapping("/index")
public String index(){
return feignProviderClient.index();
}
}
- 服務熔斷龟糕,application.yml 添加熔斷機制桐磁。
server:
port: 8050
spring:
application:
name: feign
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
feign:
hystrix:
enabled: true
feign.hystrix.enabled
:是否開啟熔斷器。
- 創(chuàng)建 FeignProviderClient 接口的實現(xiàn)類 FeignError翩蘸,定義容錯處理邏輯所意,通過
@Component
注解將 FeignError 實例注入 IoC 容器中淮逊。
package com.southwind.feign.impl;
import com.southwind.entity.Student;
import com.southwind.feign.FeignProviderClient;
import org.springframework.stereotype.Component;
import java.util.Collection;
@Component
public class FeignError implements FeignProviderClient {
@Override
public Collection<Student> findAll() {
return null;
}
@Override
public String index() {
return "服務器維護中......";
}
}
- 在 FeignProviderClient 定義處通過
@FeignClient
的 fallback 屬性設置映射催首。
package com.southwind.feign;
import com.southwind.entity.Student;
import com.southwind.feign.impl.FeignError;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Collection;
@FeignClient(value = "provider",fallback = FeignError.class)
public interface FeignProviderClient {
@GetMapping("/student/findAll")
public Collection<Student> findAll();
@GetMapping("/student/index")
public String index();
}
Hystrix 容錯機制
在不改變各個微服務調用關系的前提下,針對錯誤情況進行預先處理泄鹏。
- 設計原則
1郎任、服務隔離機制
2、服務降級機制
3备籽、熔斷機制
4舶治、提供實時的監(jiān)控和報警功能
5、提供實時的配置修改功能
Hystrix 數(shù)據(jù)監(jiān)控需要結合 Spring Boot Actuator 來使用车猬,Actuator 提供了對服務的健康健康霉猛、數(shù)據(jù)統(tǒng)計,可以通過 hystrix.stream 節(jié)點獲取監(jiān)控的請求數(shù)據(jù)珠闰,提供了可視化的監(jiān)控界面惜浅。
- 創(chuàng)建 Maven,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 創(chuàng)建配置文件 application.yml
server:
port: 8060
spring:
application:
name: hystrix
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
feign:
hystrix:
enabled: true
management:
endpoints:
web:
exposure:
include: 'hystrix.stream'
- 創(chuàng)建啟動類
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrixDashboard
public class HystrixApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixApplication.class,args);
}
}
注解說明:
@EnableCircuitBreaker
:聲明啟用數(shù)據(jù)監(jiān)控
@EnableHystrixDashboard
:聲明啟用可視化數(shù)據(jù)監(jiān)控
- Handler
package com.southwind.controller;
import com.southwind.entity.Student;
import com.southwind.feign.FeignProviderClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
@RestController
@RequestMapping("/hystrix")
public class HystrixHandler {
@Autowired
private FeignProviderClient feignProviderClient;
@GetMapping("/findAll")
public Collection<Student> findAll(){
return feignProviderClient.findAll();
}
@GetMapping("/index")
public String index(){
return feignProviderClient.index();
}
}
- 啟動成功之后伏嗜,訪問
http://localhost:8060/actuator/hystrix.stream
可以監(jiān)控到請求數(shù)據(jù)坛悉, - 訪問
http://localhost:8060/hystrix
,可以看到可視化的監(jiān)控界面承绸,輸入要監(jiān)控的地址節(jié)點即可看到該節(jié)點的可視化數(shù)據(jù)監(jiān)控裸影。
Spring Cloud 配置中心
Spring Cloud Config,通過服務端可以為多個客戶端提供配置服務军熏。Spring Cloud Config 可以將配置文件存儲在本地轩猩,也可以將配置文件存儲在遠程 Git 倉庫,創(chuàng)建 Config Server,通過它管理所有的配置文件均践。
本地文件系統(tǒng)
- 創(chuàng)建 Maven 工程画饥,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 創(chuàng)建 application.yml
server:
port: 8762
spring:
application:
name: nativeconfigserver
profiles:
active: native
cloud:
config:
server:
native:
search-locations: classpath:/shared
注解說明
profiles.active
:配置文件的獲取方式
cloud.config.server.native.search-locations
:本地配置文件存放的路徑
- resources 路徑下創(chuàng)建 shared 文件夾,并在此路徑下創(chuàng)建 configclient-dev.yml浊猾。
server:
port: 8070
foo: foo version 1
- 創(chuàng)建啟動類
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableConfigServer
public class NativeConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(NativeConfigServerApplication.class,args);
}
}
注解說明
@EnableConfigServer
:聲明配置中心抖甘。
創(chuàng)建客戶端讀取本地配置中心的配置文件
- 創(chuàng)建 Maven 工程,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 創(chuàng)建 bootstrap.yml葫慎,配置讀取本地配置中心的相關信息衔彻。
spring:
application:
name: configclient
profiles:
active: dev
cloud:
config:
uri: http://localhost:8762
fail-fast: true
注解說明
cloud.config.uri
:本地 Config Server 的訪問路徑
cloud.config.fail-fase
:設置客戶端優(yōu)先判斷 Config Server 獲取是否正常。
通過spring.application.name
結合spring.profiles.active
拼接目標配置文件名偷办,configclient-dev.yml艰额,去 Config Server 中查找該文件。
- 創(chuàng)建啟動類
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class NativeConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(NativeConfigClientApplication.class,args);
}
}
- Handler
package com.southwind.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/native")
public class NativeConfigHandler {
@Value("${server.port}")
private String port;
@Value("${foo}")
private String foo;
@GetMapping("/index")
public String index(){
return this.port+"-"+this.foo;
}
}
Spring Cloud Config 遠程配置
- 創(chuàng)建配置文件椒涯,上傳至 GitHub
server:
port: 8070
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: configclient
- 創(chuàng)建 Config Server柄沮,新建 Maven 工程,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 創(chuàng)建配置文件 application.yml
server:
port: 8888
spring:
application:
name: configserver
cloud:
config:
server:
git:
uri: https://github.com/southwind9801/aispringcloud.git
searchPaths: config
username: root
password: root
label: master
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
- 創(chuàng)建啟動類
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class,args);
}
}
創(chuàng)建 Config Client
- 創(chuàng)建 Maven 工程废岂,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 創(chuàng)建 bootstrap.yml
spring:
cloud:
config:
name: configclient
label: master
discovery:
enabled: true
service-id: configserver
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
注解說明
spring.cloud.config.name
:當前服務注冊在 Eureka Server 上的名稱祖搓,與遠程倉庫的配置文件名對應。
spring.cloud.config.label
:Git Repository 的分支湖苞。
spring.cloud.config.discovery.enabled
:是否開啟 Config 服務發(fā)現(xiàn)支持拯欧。
spring.cloud.config.discovery.service-id
:配置中心在 Eureka Server 上注冊的名稱。
- 創(chuàng)建啟動類
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class,args);
}
}
- Handler
package com.southwind.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hello")
public class HelloHandler {
@Value("${server.port}")
private String port;
@GetMapping("/index")
public String index(){
return this.port;
}
}
服務跟蹤
Spring Cloud Zipkin
Zipkin 是一個可以采集并且跟蹤分布式系統(tǒng)中請求數(shù)據(jù)的組件财骨,讓開發(fā)者可以更加直觀的監(jiān)控到請求在各個微服務所耗費的時間等镐作,Zipkin:Zipkin Server、Zipkin Client隆箩。
創(chuàng)建 Zipkin Server
- 創(chuàng)建 Maven 工程该贾,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<version>2.9.4</version>
</dependency>
</dependencies>
- 創(chuàng)建配置文件 application.yml
server:
port: 9090
- 創(chuàng)建啟動類
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import zipkin.server.internal.EnableZipkinServer;
@SpringBootApplication
@EnableZipkinServer
public class ZipkinApplication {
public static void main(String[] args) {
SpringApplication.run(ZipkinApplication.class,args);
}
}
注解說明
@EnableZipkinServer
:聲明啟動 Zipkin Server
創(chuàng)建 Zipkin Client
- 創(chuàng)建 Maven 工程,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 創(chuàng)建配置文件 application.yml
server:
port: 8090
spring:
application:
name: zipkinclient
sleuth:
web:
client:
enabled: true
sampler:
probability: 1.0
zipkin:
base-url: http://localhost:9090/
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
屬性說明
spring.sleuth.web.client.enabled
:設置開啟請求跟蹤
spring.sleuth.sampler.probability
:設置采樣比例捌臊,默認是 1.0
srping.zipkin.base-url
:Zipkin Server 地址
- 創(chuàng)建啟動類
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ZipkinClientApplication {
public static void main(String[] args) {
SpringApplication.run(ZipkinClientApplication.class,args);
}
}
- Handler
package com.southwind.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/zipkin")
public class ZipkinHandler {
@Value("${server.port}")
private String port;
@GetMapping("/index")
public String index(){
return this.port;
}
}
更多詳情
設置為vip可見的都可訪問下面鏈接地址杨蛋,即可觀看原文
更多詳情請訪問: juntech