SpringCloud是一系列框架的集合,目的是將業(yè)務(wù)系統(tǒng)拆分成一個個微服務(wù),服務(wù)于服務(wù)之間相互獨立,支持水平擴展,高可用,微服務(wù)架構(gòu)主要的功能有服務(wù)發(fā)現(xiàn)注冊、配置中心、消息總線、負(fù)載均衡、斷路器、數(shù)據(jù)監(jiān)控等,Netflix雖然已經(jīng)過時了,但是他框架集和其他微服務(wù)框架集作用差不多
微服務(wù)整體架構(gòu)如下圖,看看就好:

Netflix主要使用下面的組件:
| 組件 | 描述 |
|---|---|
| Eureka | 服務(wù)注冊中心、服務(wù)發(fā)現(xiàn)中心 |
| Ribbon | 負(fù)載均衡,服務(wù)如果是一個集群,會通過Ribbon實現(xiàn)負(fù)載均衡 |
| Feign | 服務(wù)于服務(wù)之間的調(diào)用 |
| Hystrix | 監(jiān)控和熔斷器,服務(wù)降級與數(shù)據(jù)統(tǒng)計 |
| Zuul | 網(wǎng)關(guān),所有請求由網(wǎng)關(guān)轉(zhuǎn)發(fā)到具體的服務(wù) |
一、項目搭建
首先搭建一個聚合項目,結(jié)構(gòu)如下:

1. commons模塊
commons模塊是一個普通的Maven項目,存放JavaBean和工具類

2. dependency模塊
SpringBoot和SpringCloud版本是有對應(yīng)關(guān)系的,要保持版本對應(yīng),否則會出現(xiàn)運行不了的情況:
| Spring Cloud Alibaba Version | Spring Cloud Version | Spring Boot Version |
|---|---|---|
| 2021.0.1.0 | Spring Cloud 2021.0.1 | 2.6.3 |
| 2.2.7.RELEASE | Spring Cloud Hoxton.SR12 | 2.3.12.RELEASE |
| 2021.1 | Spring Cloud 2020.0.1 | 2.4.2 |
| 2.2.6.RELEASE | Spring Cloud Hoxton.SR9 | 2.3.2.RELEASE |
| 2.1.4.RELEASE | Spring Cloud Greenwich.SR6 | 2.1.13.RELEASE |
| 2.2.1.RELEASE | Spring Cloud Hoxton.SR3 | 2.2.5.RELEASE |
| 2.2.0.RELEASE | Spring Cloud Hoxton.RELEASE | 2.2.X.RELEASE |
| 2.1.2.RELEASE | Spring Cloud Greenwich | 2.1.X.RELEASE |
| 2.0.4.RELEASE(停止維護,建議升級) | Spring Cloud Finchley | 2.0.X.RELEASE |
| 1.5.1.RELEASE(停止維護,建議升級) | Spring Cloud Edgware | 1.5.X.RELEASE |
其他模塊都依賴于dependency模塊,主要做SpringBoot的版本控制:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<groupId>com.aruba</groupId>
<artifactId>dependency</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>dependency</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
</properties>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.7.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
3. eureka模塊
eureka模塊就是我們首先使用的組件,用于服務(wù)注冊和發(fā)現(xiàn)
二、Eureka
1. eureka服務(wù)端
eureka模塊單獨啟動,作為服務(wù)端
1.1 依賴
導(dǎo)入eureka服務(wù)依賴:
<parent>
<artifactId>dependency</artifactId>
<groupId>com.aruba</groupId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../dependency/pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--eureka服務(wù)-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
1.2 @EnableEurekaServer
SpringBoot啟動類上添加@EnableEurekaServer注解開啟Eureka:
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
啟動后可以訪問到eureka界面:

1.3 配置Eureka服務(wù)地址
此時雖然可以訪問頁面,但是eureka服務(wù)并沒有真正的啟動,yml文件需要配置,需要注意的是application.name將會作為服務(wù)名注冊到eureka中,后續(xù)調(diào)用方會使用該名稱:
spring:
application:
name: aruba-eureka
server:
port: 7000
eureka:
instance:
hostname: aruba-eureka
client:
service-url:
# 指定eureka服務(wù)的地址
defaultZone: http://127.0.0.1:7000/eureka
# 當(dāng)前項目關(guān)閉注冊服務(wù)
register-with-eureka: false
# 當(dāng)前項目關(guān)閉獲取服務(wù)
fetch-registry: false
2. eureka客戶端
再次新建一個dept模塊作為eureka的客戶端,用于注冊服務(wù)到eureka服務(wù)器
2.1 依賴
導(dǎo)入eureka客戶端依賴:
<parent>
<artifactId>dependency</artifactId>
<groupId>com.aruba</groupId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../dependency/pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--eureka客戶端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.aruba</groupId>
<artifactId>commons</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
2.2 @EnableEurekaClient
使用@EnableEurekaClient注解開啟Eureka客戶端
@SpringBootApplication
@EnableEurekaClient
public class DeptApplication {
public static void main(String[] args) {
SpringApplication.run(DeptApplication.class, args);
}
}
2.3 配置Eureka服務(wù)地址
spring:
application:
name: aruba-dept
server:
port: 8000
eureka:
client:
service-url:
# 指定eureka服務(wù)的地址
defaultZone: http://127.0.0.1:7000/eureka
2.4 啟動客戶端服務(wù)
啟動服務(wù)后,再次訪問Eureka管理頁面,可以看到新注冊的服務(wù):

三、Feign
有了服務(wù)提供者,注冊中心,消費者就可以通過Feign調(diào)用提供者
1. 完善dept模塊
1.1 Javabean
commons模塊中創(chuàng)建實體類:WDept,用于服務(wù)與服務(wù)之間傳輸
@AllArgsConstructor
@NoArgsConstructor
@Data
public class WDept implements Serializable {
/**
* 部門編號
*/
private Integer deptId;
/**
* 部門名稱
*/
private String dName;
}
1.2 service層
dept模塊中編寫相應(yīng)的service層代碼
接口:
public interface DeptService {
String insertDept(WDept dept);
}
實現(xiàn):
@Service
public class DeptServiceImpl implements DeptService {
@Override
public String insertDept(WDept dept) {
return "收到:" + dept.toString();
}
}
1.3 提供Controller
Feign本質(zhì)上是通過http進(jìn)行調(diào)用的,controller層對外提供接口:
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@RequestMapping("/insertDept")
public String insertDept(@RequestBody WDept wDept) {
return deptService.insertDept(wDept);
}
}
2. 調(diào)用方模塊
新建模塊,作為調(diào)用方:

2.1 依賴
導(dǎo)入eureka客戶端和openFeign依賴:
<parent>
<artifactId>dependency</artifactId>
<groupId>com.aruba</groupId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../dependency/pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--eureka客戶端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.aruba</groupId>
<artifactId>commons</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
2.2 yml文件配置
需要配置的和dept模塊差不多:
spring:
application:
name: aruba-dept-api
server:
port: 8001
eureka:
client:
service-url:
# 指定eureka服務(wù)的地址
defaultZone: http://127.0.0.1:7000/eureka
2.3 @EnableFeignClients
使用@EnableFeignClients注解配置啟動類,表示作為服務(wù)調(diào)用方
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class DeptApiApplication {
public static void main(String[] args) {
SpringApplication.run(DeptApiApplication.class, args);
}
}
2.4 @FeignClient
使用@FeignClient注解接口,并指定調(diào)用服務(wù)名,對應(yīng)application.name,定義一個和調(diào)用方接口一樣的方法
@FeignClient("aruba-dept")
public interface DeptFeignClient {
@RequestMapping("/insertDept")
String insertDept(WDept dept);
}
2.5 使用Feign
在調(diào)用方controller層中,注入剛剛的接口,并調(diào)用:
@RestController
@CrossOrigin
public class DeptController {
@Autowired
private DeptFeignClient deptFeignClient;
@RequestMapping("/insertDept")
public String insertDept(@RequestParam("deptId") Integer id) {
return deptFeignClient.insertDept(new WDept(id, "Feign"));
}
}
嘗試調(diào)用:

四、Robbin
Feign集成了Robbin,默認(rèn)就支持負(fù)載均衡,默認(rèn)使用輪詢策略,一旦遇上服務(wù)集群就會觸發(fā)
1. 配置多個yml

修改端口為:
server:
port: 8010
server:
port: 8011
server:
port: 8012
2. 配置啟動

配置多個啟動項,并指定使用yml文件:--spring.profiles.active=xxx,這邊對應(yīng)就是1,2,3:

3. 調(diào)用接口
啟動多個服務(wù),并調(diào)用消費者接口:

效果:

五、Hystrix
hystrix作為保證整體服務(wù)可用的組件,擁有服務(wù)降級和服務(wù)熔斷功能,當(dāng)一個微服務(wù)無法訪問或長時間無響應(yīng),hystrix會自動幫助調(diào)用方進(jìn)行處理,防止出現(xiàn)服務(wù)雪崩,因為hystrix是集成在服務(wù)調(diào)用方
1. 依賴
dept-api模塊導(dǎo)入hystrix依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
2. yml配置
添加hystrix相關(guān)配置:
spring:
application:
name: aruba-dept-api
server:
port: 8001
eureka:
client:
service-url:
# 指定eureka服務(wù)的地址
defaultZone: http://127.0.0.1:7000/eureka
# 開啟hystrix
feign:
hystrix:
enabled: true
# 請求超時時間
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 2000
3. @EnableHystrix
啟動類添加@EnableHystrix注解:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableHystrix
public class DeptApiApplication {
public static void main(String[] args) {
SpringApplication.run(DeptApiApplication.class, args);
}
}
此時為服務(wù)提供方接口調(diào)用添加一個睡眠:
@Service
public class DeptServiceImpl implements DeptService {
@Override
public String insertDept(WDept dept) {
System.out.println(dept);
try {
Thread.sleep(13000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "收到:" + dept.toString();
}
}
再次調(diào)用接口,2秒后會出現(xiàn)500錯誤,表示hystrix生效了:

4. 失敗處理
接下來就要指定hystrix服務(wù)降級后,進(jìn)行自己的業(yè)務(wù)處理,實際上feign與hystrix已經(jīng)結(jié)合,我們之前定義了DeptFeignClient接口,需要實現(xiàn)一個該接口的類作為降級回調(diào)處理類:
@Component
public class DeptFeignFallCallback implements DeptFeignClient {
@Override
public String insertDept(WDept dept) {
return "服務(wù)發(fā)生錯誤";
}
}
接口類的@FeignClient注解添加fallback屬性值,指定為處理類:
@FeignClient(value = "aruba-dept", fallback = DeptFeignFallCallback.class)
public interface DeptFeignClient {
@RequestMapping("/insertDept")
String insertDept(WDept dept);
}
再次調(diào)用接口,會返回自定義回調(diào)處理的結(jié)果:

六、Hystrix儀表盤
Hystrix儀表盤是監(jiān)測觸發(fā)熔斷數(shù)據(jù)統(tǒng)計的管理頁面,配置好后可以方便查看信息
新建模塊:

1. 導(dǎo)入依賴
除了web外,還需要actuator和hystrix-dashboard依賴
<parent>
<artifactId>dependency</artifactId>
<groupId>com.aruba</groupId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../dependency/pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</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-hystrix-dashboard</artifactId>
</dependency>
</dependencies>
2. yml配置
spring:
application:
name: aruba-hystrix-client
server:
port: 9000
hystrix:
dashboard:
proxy-stream-allow-list: "localhost"
3. @EnableHystrixDashboard
使用@EnableHystrixDashboard注解在啟動類上:
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixClientApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixClientApplication.class, args);
}
}
啟動后訪問localhost:9000/hystrix,就可以看到管理界面了:

4. 模塊中配置
僅僅有上面的配置是不夠的,還需要指定監(jiān)測服務(wù)的一些配置,我們監(jiān)測的是使用hystrix的dept-api模塊,所以在該模塊中添加配置類:

配置類提供ServletRegistrationBean的注入,內(nèi)容為:
@Configuration
public class DeptActuator {
@Bean
public ServletRegistrationBean getServletRegistrationBean(){
HystrixMetricsStreamServlet mss = new HystrixMetricsStreamServlet();
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(mss);
servletRegistrationBean.setName("servletRegistrationBean");
servletRegistrationBean.setLoadOnStartup(1);
servletRegistrationBean.addUrlMappings("/hystrix.stream");
return servletRegistrationBean;
}
}
5. 輸入具體監(jiān)測地址
管理中輸入:http://localhost:8001/hystrix.stream,對應(yīng)提供配置的dept-api模塊的端口和配置的url

進(jìn)入后,嘗試訪問服務(wù)接口后,有了數(shù)據(jù),才會出現(xiàn)數(shù)據(jù)統(tǒng)計:

七、Zuul
Zuul是微服務(wù)中的網(wǎng)關(guān),在所有微服務(wù)內(nèi)部,所有請求都應(yīng)該由網(wǎng)關(guān)進(jìn)行轉(zhuǎn)發(fā)請求,網(wǎng)關(guān)提供統(tǒng)一的對外接口,功能概念和nginx差不多,但是nginx處于更上的接入層,性能方面沒有可比較性,而微服務(wù)的網(wǎng)關(guān)組件都和SpringBoot有著較好的融合,使用方便
新建模塊:

1. 依賴
導(dǎo)入zuul依賴以及eureka客戶端依賴:
<parent>
<artifactId>dependency</artifactId>
<groupId>com.aruba</groupId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../dependency/pom.xml</relativePath>
</parent>
<dependencies>
<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-netflix-zuul</artifactId>
</dependency>
</dependencies>
2. yml配置
爭對對外的微服務(wù)配置路由,可以配置多條,一般使用服務(wù)的application.name作為配置名,path為反向代理后的訪問前綴,serviceId為服務(wù)的application.name:
spring:
application:
name: aruba-zuul
server:
port: 8080
#配置一個路由器
zuul:
routes:
dept-api:
path: /oapi/**
serviceId: aruba-dept-api
#從eureka獲取我們的服務(wù)器的真實ip地址
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:7000/eureka
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${server.port}
3. @EnableZuulProxy
使用@EnableZuulProxy注解在啟動類上:
@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
啟動后,可以通過http://localhost:8080/oapi/xxx進(jìn)行對dept-api模塊的訪問:
