一、Spring Cloud简介
Spring Cloud是在Spring Boot基础上构建的,用于快速构建分布式系统的通用模式的工具集。
使用Spring Cloud开发的应用程序非常适合在Docker或者PaaS上部署,所以又叫做云原生应用。云原生可以简单理解为面向云环境的软件架构。
相比Dubbo等RPC框架,Spring Cloud提供了全套的分布式系统解决方案。
Spring Cloud 为开发者提供了在分布式系统(配置管理,服务发现,熔断,路由,微代理,控制总线,一次性
Token,全局,Leader 选举,分布式 Session,集群状态)中快速构建的工具,使用 Spring Cloud 的开发者可以快速的启动服务或构建应用、同时能够快速和云平台资源进行对接。
二、Eureka
1、简介
Eureka 是 Netflix 出品的用于实现服务注册和发现的工具。 Spring Cloud 集成了 Eureka,并提供了开箱即用的支持。其中, Eureka 又可细分为 Eureka Server 和 Eureka Client。Eureka是Spring Cloud Netflix微服务套件中的一部分,可以与Springboot构建的微服务很容易的整合起来。
EureKa在Spring Cloud全家桶中担任着服务的注册与发现的落地实现。Netflix在设计EureKa时,基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移,功能类似于Dubbo的注册中心Zookeeper。
2、实现原理
EureKa采用C-S的设计架构,即包括了Eureka Server(服务端),EureKa client(客户端)。
1.EureKa Server 提供服务注册,各个节点启动后,在EureKa server中进行注册;
2 EureKa Client 是一个Java客户端,用于和服务端进行交互,同时客户端也是一个内置的默认使用轮询负载均衡算法的负载均衡器。在应用启动后,会向Eueka Server发送心跳(默认30秒)。如果EureKa Server在多个心跳周期内没有接受到某个节点的心跳,EureKa Server将会从服务注册表中将这个服务移出(默认90秒)。
3、和Zookeeper的联系与区别
1.Eureka和Zookepper都可以作为注册中心
2.Eureka取CAP中的AP,注重可用性。Zookepper取CAP理论中的CP强调高的一致性
3.Cloud官网Eureka架构图指出,Eureka是去中心化的,当网络出现分区故障时,可以独立的为各自的子网下的机器提供服务。 Zookepper中,当出现分区故障,Zookepper集群进行各自服务的提出,然后根据规定在各自的集群下进行Leader选举, 但参选人数不过半时,此集群挂掉。(脑裂中就存在这种问题导致它不具有可用性)
4.Eureka常用于SpringCloud下产物的注册中心,如:微服务的注册中心;Zookepper是分布式下的注册中心,如:Dubbo、Hadoop类似的集群的服务注册中心
5.Eureka和Zookeeper的选取:看自己程序的需要,是需要AP还是CP,根据具体的场景来选取。
4、创建Eureka注册中心
4.1 创建项目
新建一个Maven POM项目名为springcloud_demo
pom.xml
<?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>
<modules>
<module>eureka</module>
<module>student-service</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.14.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.qianfeng</groupId>
<artifactId>springcloud_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud_demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR5</spring-cloud.version>
</properties>
<!--<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</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>
<!-- <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>-->
</project>
需要添加spring-cloud依赖。
4.2 新建eureka、eureka2、eureka3模块
- 右键新建一个maven模块名为eureka
pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud_demo</artifactId>
<groupId>com.qianfeng</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
添加spring-cloud-starter-netflix-eureka-server这个依赖
- 新建一个包,在这个包下创建一个启动类
package com.qianfeng;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @author huwen
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
这个类之上加上两个注解:@SpringBootApplication表明这个类是SpringBoot的启动类,@EnableEurekaServer开启Eureka服务器。
- 在resources目录下新建一个application.yml文件
server:
port: 20000
spring:
application:
name: eureka-server
eureka:
client:
#使得当前的微服务不注册到注册中心上
register-with-eureka: false
#当前的微服务就是注册中心,注册中心不能从注册中心抓取服务,所以该配置需要配置成false
fetch-registry: false
#注册地址
service-url:
defaultZone: http://eureka:20000/eureka/,http://eureka2:20001/eureka/,http://eureka3:20002/eureka/
这个yml文件指定了端口、应用名。还进行了一些eureka的配置,客户端与服务端的配置是不一样的,客户端不需要配置register-with-eureka: false与fetch-registry: false,然后就是配置注册地址,因为我在这里配置了eureka集群,所有定义了三个地址,没有使用localhost的原因是伪集群,通过修改hosts文件的方式让这三个域名指向同一个ip:127.0.0.1。
4.3 新建student-service模块
- 右键新建maven模块,名为student-service
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud_demo</artifactId>
<groupId>com.qianfeng</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>student-service</artifactId>
<dependencies>
<!-- 微服务需要对外提供功能,所以需要添加web依赖 -->
<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>
</dependencies>
<!-- 打包插件,如果不写运行不会出问题,但是打包会出问题 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
不同于上面的模块,这个模块因为是一个微服务,所以添加了eureka-client依赖,并且添加了web的依赖。
- 在java目录下新建一个包,在这个包中新建一个启动类
package com.qianfeng;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class StudentServiceApplication {
public static void main(String[] args) {
SpringApplication.run(StudentServiceApplication.class,args);
}
}
这个启动类添加的不是@EnableEurekaServer注解,而是@EnableEurekaClient注解
- 在这个包下新建一个包controller,新建一个类
package com.qianfeng.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author huwen
*/
@RestController
@RequestMapping("/stu")
public class StudentController {
@GetMapping("/{stuId}")
public String getStudentNameById(@PathVariable("stuId") Integer id){
return "student"+id;
}
}
三、Ribbon
Spring Cloud有两种服务调用方式,一种是ribbon+restTemplate,另一种是feign。feign的底层还是使用rebbon.
1、简介
Spring Cloud Ribbon是基于Netfix Ribbon实现的一套 客户端 负载均衡工具(Ribbon对服务实例节点的增减也
能动态感知)
2、负载均衡
Load Balance负载均衡是用于解决一台机器(一个进程)无法解决所有请求而产生的一种算法。像nginx可以使用负载均衡分配流量,ribbon为客户端提供负载均衡,dubbo服务调用里的负载均衡等等,很多地方都使用到了负载均衡。
2.1 ribbon与nginx的区别
- ribbon是进程内负载均衡,集成在消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。nginx是集中式负载均衡,作为一个独立的服务器,没有集成在消费方或者提供方,而是位于两者之间,将消费方的请求按照一定的策略转发至服务的提供方
2.2 ribbon实现
现在的需求是在student-service中调用class-service,查询学生所在的班级信息,所以前者是消费方,后者是提供方,ribbon集成在消费方,所以无需修改class-service的代码,只需要修改student-service的代码。
- 添加依赖
由于ribbon的依赖已经在spring-cloud-starter-netflix-eureka-client这个以来中包含了,所以此处不需要添加任何依赖。
- 修改启动类
package com.qianfeng;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @author huwen
*/
@SpringBootApplication
@EnableEurekaClient
public class StudentServiceApplication {
public static void main(String[] args) {
SpringApplication.run(StudentServiceApplication.class,args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
@Bean
public IRule iRule(){
return new RandomRule();
}
}
加了两个方法,一个方法返回值是RestTemplate,这个类就是和HttpClient一样的作用,用来发送HTTP请求。加上@Bean注解交给Spring进行管理,这是Spring IoC的体现,加上@LoadBalanced注解使用负载均衡。另一个方法的返回值是IRule,这是一个接口,指定了负载均衡的策略,默认的负载均衡策略是轮询。
2.3 ribbon负载均衡策略
通过查看IRule接口的实现类的继承关系,我们发现有很多实现类,不同的类对应着不同的负载均衡策略,都是继承AbstractLoadBalancerRule,我们想要自定义负载均衡策略也需要继承这个类并重写方法。
-
BestAvailableRule:选择一个最小的并发请求的Server,逐个考察Server,如果Server被tripped了,则跳过。
-
AvailabilityFilteringRule:过滤掉那些一直连接失败的被标记为circuit tripped的后端Server,并过滤掉那些高并发的的后端Server或者使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个Server的运行状态。
-
ZoneAvoidanceRule:复合判断Server所在区域的性能和Server的可用性选择Server。
-
RandomRule:随机选择一个Server。
-
RoundRobinRule:轮询选择, 轮询index,选择index对应位置的Server。(默认策略)
-
RetryRule:对选定的负载均衡策略机上重试机制,在一个配置时间段内当选择Server不成功,则一直尝试使用subRule的方式选择一个可用的server。
-
ResponseTimeWeightedRule:作用同WeightedResponseTimeRule,二者作用是一样的,ResponseTimeWeightedRule后来改名为WeightedResponseTimeRule。
-
WeightedResponseTimeRule:根据响应时间分配一个weight(权重),响应时间越长,weight越小,被选中的可能性越低。
2.4 修改controller
package com.qianfeng.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
/**
* @author huwen
*/
@RestController
@RequestMapping("/stu")
public class StudentController {
@Resource
private RestTemplate restTemplate;
@GetMapping("/{stuId}")
public String getStudentNameById(@PathVariable("stuId") Integer id){
String result = null;
if(id==1){
String s = restTemplate.getForObject("http://CLASS-SERVICE/class/1", String.class);
result = "小明在"+s;
}
else if(id==2){
String s = restTemplate.getForObject("http://CLASS-SERVICE/class/2", String.class);
result = "小红在"+s;
}
else {
result = "查无此人";
}
return result;
}
}
注入RestTemplate,这个类可以通过get、post、delete等方式发送HTTP请求并获得响应。
2.5 模板模式
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。模板模式中的模板方法应当被声明为final类型,不能重写,在这个方法中调用了这个类的其他方法并规定顺序。这样就封装了不可变部分,可以扩展可变部分。
简单来说就是完成一件事情,有固定的数个步骤,但是每个步骤根据对象的不同,而实现细节不同;就可以在父类中定义一个完成该事情的总方法,按照完成事件需要的步骤去调用其每个步骤的实现方法。每个步骤的具体实现,由子类完成。
四、Feign
1、简介
- Feign是Netflix开发的声明式,模板化的HTTP客户端,它使得编写web服务客户端变得更加容易
- Feign可帮助我们更加便捷,优雅的调用HTTP API。
- 在SpringCloud中,使用Feign非常简单——创建一个接口,并在接口上添加一些注解,代码就完 成了。 Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。
- SpringCloud对Feign进行了增强,使Feign支持了SpringMVC注解,并整合了Ribbon和Eureka, 从而让Feign的使用更加方便。
2、Feign实现
使用Feign了就不再需要使用RestTemplate和ribbon了,因为Feign是对Ribbon的增强。
我们现在想要实现的是在class-service模块中调用teacher-service,所以只需要修改class-service模块
2.1 添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
添加openfeign的依赖
2.2 创建一个接口
package com.qianfeng.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient("teacher-service")
public interface ITeacherFeign {
@GetMapping("/teacher/{tid}")
String getTeacherNameById(@PathVariable("tid") Integer tid);
}
这个接口之上加上@FeignClient注解,注解中的值是需要调用的服务名,接口中的方法保持和需要调用的微服务中的controller中的方法一致。
2.3 修改启动类
package com.qianfeng;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class ClassServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ClassServiceApplication.class,args);
}
}
增加一个@EnableFeignClients注解,由于这个注解和@SpringBootApplication这个注解的功能一样,都是扫描这个类所在的包及其子包,所以如果接口和启动类不在一个包下需要指定扫描的包。
2.4 修改controller
package com.qianfeng.controller;
import com.qianfeng.feign.ITeacherFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author huwen
*/
@RestController
@RequestMapping("/class")
public class ClassController {
@Autowired
private ITeacherFeign teacherFeign;
@GetMapping("/{classId}")
public String getClassNameById(@PathVariable("classId") Integer classId){
System.out.println("班级服务启动了");
String s = teacherFeign.getTeacherNameById(classId);
return classId+"班 "+s;
}
}
使用@Autowired注解将接口注入,然后就能像本地方法一样使用了。
2.5 设置超时时间与重试次数
Feign默认超时时间为1S,如果1S内,被调用方没有返回结果,就默认失败,然后重试1次。
有些时候,如果不加干预,可能引起请求的重复发送,导致出现各种问题。
注意:Feign自带超时和重试的功能,但是默认是关闭的。所以我们看到的超时和重试的效果,是
底层Ribbon提供的。如果开启了Feign的超时重试就会覆盖掉Ribbon的设置
server:
port: 8081
spring:
application:
name: class-service
eureka:
client:
service-url:
defaultZone: http://localhost:20000/eureka/
#配置ribbon的超时和重试
ribbon:
#配置连接超时
ConnecTimeout: 1000
#配置读超时
ReadTimeout: 1000
#配置ribbon对同一微服务节点的重试次数,默认是0
MaxAutoRetries: 0
#配置ribbon对微服务集群中节点的重试次数,默认是1
MaxAutoRetriesNextServer: 1
#设置了feign的超时时间ribbon的超时时间和重试次数就不起作用了
feign:
client:
config:
teacher-service:
connectTimeout: 1000
readTimeout: 3000
五、Hystrix
1、简介
Hystrix是由Netflix开源的一个针对分布式系统容错处理的开源组件。能够提供断路,降级,监控等多种服务。
在分布式环境中,许多服务依赖项中的一些必然会失败,或者我们的服务被突发性的高并发访问导致出现 问题。
Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。 Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高 系统的整体弹性。
2、应用场景
多系统和微服务的情况下,需要一种机制来处理延迟和故障,并保护整个系统处于可用稳定的状态。
3、Hystrix是如何解决服务间调用问题的
资源隔离:鸡蛋不要放在一个篮子里(线程池隔离、信号量隔离)
服务降级:当调用目标服务出问题(超时、报错....)时,会自动的调用一个本地的方法,返回一个默认值
请求熔断:一旦确定目标服务出问题(失败比例),Hystrix的熔断器会自动打开,拦截后续的所有请求,立刻判定失败,进行服务降级。过了单位时间之后,熔断器变成半开状态,放行一个请求,如果还是失败,继续全开,拦截请求,否则熔断器关闭。
4、Ribbon整合Hystrix(了解)
1)在Ribbon的工程中,添加Hystrix的依赖
<!-- hystrix 依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2)在启动类上添加注解
....
@EnableHystrix
...
3)在使用RestTemplate的地方,通过注解实现资源隔离
//使用注解,隔离其他服务的调用资源,被该注解标记的方法会被Hystrix提供的线程调用(线程池隔离)
//fallbackMethod就是指定降级方法,当资源不足或者服务报错时,会走降级方法
//熔断器默认已经开启
@HystrixCommand(fallbackMethod = "myFallBack")
@RequestMapping("/queryName")
public String getNameById(Integer sid){
......
}
/**
* 降级方法
* @param sid
* @return
*/
public String myFallBack(Integer sid){
return "服务异常,降级方法调用!!!";
}
5、Feign整合Hystrix(常用)
1)直接通过配置,开启Hystrix
#开启Feign的断路器功能
feign:
hystrix:
enabled: true
注意:Feign中已经整合了Hystrix,所以不需要添加任何依赖,Feign中的Hystrix功能默认关闭
2)配置Feign接口,编写降级实现类
@FeignClient(value = "MIRCO-TEACHER", fallback = ITeacherFeign.TeacherFeign.class)
public interface ITeacherFeign {
@RequestMapping("/tea/queryTeaName")
String queryTeaName(@RequestParam("tid") Integer tid);
/**
* Feign接口的实现类
*/
@Component
public static class TeacherFeign implements ITeacherFeign{
//就是对应的降级方法
@Override
public String queryTeaName(Integer tid) {
return "教师服务调用异常,服务进行降级!!!";
}
}
}
6、Hystrix的常用配置
#配置Hystrix的常用属性
hystrix:
command:
default:
execution:
isolation:
#资源隔离的策略,线程池隔离(默认)、信号量隔离(SEMAPHORE)
strategy: THREAD
#hystrix超时时间,默认1秒
thread:
timeoutInMilliseconds: 500
timeout:
#是否开启Hystrix的超时时间, 默认为true,如果设置为false,
#意为不超时,但是Feign的超时仍然起作用
enabled: true
#熔断器的相关配置,默认打开熔断器
circuitBreaker:
enabled: true
#单位时间内,失败的次数,如果达到这个阈值,那么熔断器就会打开,默认20次
requestVolumeThreshold: 5
#多久之后,熔断器进入半开状态,默认5S
sleepWindowInMilliseconds: 5000
注意:实际开发过程中,调用超时,需要结合Feign的超时和Hystrix的超时,哪个超时设置的小,哪个就起作用,默认都是1S。
7、Hystrix的仪表盘(图形化界面监控)
什么是Hystrix的仪表盘?
Hystrix提供了一个组件,可以监控Hystrix的微服务,来动态掌握各个微服务之间的请求调用情况。
配Hystrix的仪表盘
1)单独创建一个SPringBoot项目,作为仪表盘工程
2)该工程添加依赖仪表盘工程
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
3)配置启动注解仪表盘工程
@EnableHystrixDashboard
4)启动该工程
5)去到需要监控的工程,配置监控Servlet
//添加监控依赖
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-metrics-event-stream</artifactId>
<version>1.5.18</version>
<scope>compile</scope>
</dependency>
//启动类配置监控的Servlet
@Bean
public ServletRegistrationBean<HystrixMetricsStreamServlet> getServlet(){
HystrixMetricsStreamServlet hystrixMetricsStreamServlet
= new HystrixMetricsStreamServlet();
ServletRegistrationBean<HystrixMetricsStreamServlet>
servletRegistrationBean = new ServletRegistrationBean();
servletRegistrationBean.setServlet(hystrixMetricsStreamServlet);
servletRegistrationBean.addUrlMappings("/hystrix.stream");
servletRegistrationBean.setName("HystrixMetricsStreamServlet");
return servletRegistrationBean;
}
6)去到仪表盘工程,配置监控地址即可
注意:Hystrix的仪表盘,不需要注册到注册中心上,是一个独立的工程就可以了
六、路由网关
1、什么是路由网关?
简单来说,路由网关往往是微服务架构的入口组件,外来的所有的请求,都需要通过路由网关进行分发和过滤。路由网关的核心功能:请求的路由、请求的过滤
2、为什么需要路由网关?
路由网关提供了外部请求的访问入口,所有的外部请求都只需要知道路由网关的地址就行了,无需知道每个微服务的访问地址,路由网关可以将外部的请求负载分发给不同的微服务,这样可以对外屏蔽微服务架构内部的结构。因为路由网关往往是外部请求访问微服务架构的入口,所以可以在路由网关做请求过滤的工作。
SpringCloud默认提供了2个路由网关,Zuul和Gateway,Zuul是网飞(netflix)提供的路由组件,而Gateway是SpringCloud团队自己开发的一款路由组件,用来替换Zuul的
3、路由网关的请求路由实现
1)创建一个微服务工程,注意该微服务工程不能添加web依赖
2)添加Gateway依赖
<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-gateway</artifactId>
</dependency>
3)配置application.yml
server:
port: 18888
spring:
application:
name: gateway-server
#配置路由网关的路由规则
cloud:
gateway:
routes:
#id:规则的标识,是一个合法不重复的字符串即可
- id: guize1
#predicates:路由规则,什么样的请求,匹配当前这个规则
predicates:
# http://localhost:18888/stu/a/b
- Path=/stu/**
#当前的规则,分发给哪个微服务
#http://MICRO-STUDENT/stu/a/b
uri: lb://MICRO-STUDENT
eureka:
client:
service-url:
defaultZone: http://localhost:20000/eureka
七、分布式统一配置中心
1、统一配置中心的搭建(服务端)
1)创建一个工程(可以不是微服务,不用注册到注册中心上)
2)添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
3)启动类添加依赖
@EnableConfigServer
4)配置application.yml
server:
port: 40000
spring:
application:
name: config-server
#读取本地配置文件,强制需要配置该属性
profiles:
active: native
cloud:
config:
server:
#配置文件放到本地
native:
search-locations: classpath:config
#配置文件放到svn上的配置
# svn:
# uri: #svn仓库的地址
#配置文件放到git上的配置
# git:
# uri: xxxxxxxx #配git仓库的地址,git仓库里放的就是各种配置文件
5)在config文件夹中,随便准备一个配置文件
com:
name: zhangsan
6)运行配置中心,测试是否能都读到管理的配置信息
<img src="img/image-20200513162839248.png" alt="image-20200513162839248" style="zoom:50%;" />
2、微服务配置的统一管理(其他微服务的配置全部交由统一配置中心管理)
1)将所有微服务的application.yml放到统一配置中心的指定目录下(git、svn需要传到指定的仓库中)
2)所有微服务添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
3)所有的微服务,添加一个配置文件bootstrap.yml
注意:bootstrap.yml用法和application.yml的用法完全一致,但是在SpringBoot启动过程中,是先加载bootstrap.yml再加载application.yml
spring:
cloud:
config:
#配置统一配置中心的地址
uri: http://localhost:40000
#配置文件的名字
name: teacher
#配置文件的环境
profile: local
4)启动配置中心、再启动微服务
注意:这里有一个强制的顺序要求,必须先启动配置中心,再启动微服务
3、统一配置需要注意的一些地方
1、如果配置文件是放在Config Server本地管理的,那么每次修改配置文件,都必须重启Config Server才会生效
2、如果配置文件是放在Config Server的git、SVN仓库中管理的,那么每次修改配置文件,不用重启Config Server,会自动生效
3、不管配置文件放在哪里,每次修改配置文件,所有的Config Client(微服务),都必须重启才有效。原因在于Config Client只有在启动的时候会去抓一次配置,然后配置就缓存到本地了,后续所有的代码都是从本地获得配置,因此服务的变化,是无感知的,这也是一种优化的结果
网友评论