文章目录
- 6、Ribbon
- 6.1、Ribbon是什么
- 6.2、Ribbon能干什么
- 6.3、Ribbon实现负载均衡环境搭建
- 6.4、Ribbon实现负载均衡
- 6.5、自定义负载均衡算法
- 7、Feign负载均衡
- 7.1、简介
- 7.2、Feign使用步骤
- 8、Hystrix
- 8.1、什么是Hystrix
- 8.2、服务熔断
- 8.3、服务降级
- 8.4、服务熔断与服务降级的比较
- 8.5、Dashboard流量监控
- 9、Zuul
- 9.1、什么是Zuul
- 9.2、配置Zuul步骤
- 10、Spring Cloud Config分布式配置
- 10.1、概述
- 10.2、什么是Spring Cloud Config
- 10.3、配置我们的服务端
- 10.4、配置我们的客户端
- 10.5、远程实战
- 11、完结
本实验中所涉及的所有代码的码云链接:
传送门
6、Ribbon
6.1、Ribbon是什么
SPringle Cloud Ribbon是一个基于Netflix Ribbon实现的一套客户端的负载均衡的工具。
Ribbon使Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon的客户端组件提供一系列完整的配置项目:连接超时、重试等等。简单的说,就是在配置文件中列出LoadBalance(简称LB:负载均衡)后面所有的机器,Ribbon会自动地帮助你基于某种规则(如简单轮询,随机连接等等)去连接这些机器。我们也很容易使用Ribbon实现自定义地负载均衡算法
6.2、Ribbon能干什么
- LB,即负载均衡(Load Balance),在微服务或者分布式集群中经常用地一种应用
- 负载均衡简单的说,就是将用户的请求平坦的分配到多个服务上,从而达到系统的HA(高可用)
- 常见的负载均衡软件有Nginx,Lvs等等
- Dubbo、SpringCloud中均给我们提供了负载均衡,SpringCloud的负载均衡算法可以自定义
- 负载均衡简单分类:
- 集中式LB:在服务的消费方和提供方之间使用独立的LB设施,如Nginx(反向代理服务器),由该设施负责把访问请求通过某种策略转发至服务的提供方
- 进程LB:1)将LB逻辑集成到消费方,消费方从服务注册中心获得哪些地址是可用的,然后自己再从这些地址中选择一个合适的服务器。 2)Ribbon属于进程LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址
6.3、Ribbon实现负载均衡环境搭建
1、在消费者(80端口)中加入相应的依赖(ribbon、eureka),实现负载均衡
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
2、将消费者的config配置类配置对应的信息
package pers.mobian.springcloud.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration //等价于spring的applicationContext.xml
public class ConfigBean {
//配置负载均衡实现RestTemplate
@Bean
@LoadBalanced //Ribbon
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
3、修改消费者类的对应的映射器类
//private static final String REST_URL_PREFIX = "http://localhost:8001";
//修改访问的路径。由于使用的负载均衡,所以访问的应该是对应的服务,而非是具体的端口
private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
4、开启对应的服务(由于电脑性能原因,只开了两个服务器7001和7002)
5、测试结果
服务器开启成功
客户端访问测试成功
由于当前只有一个数据库,所以无法查看出具体访问的是哪一个服务器,不过按道理是实现了负载均衡的
6.4、Ribbon实现负载均衡
由于需要负载均衡需要根据自己的算法,随机分配访问,所以我们需要再新建后台
1、新建两个数据库db02、db03
2、再新建两个一样的后台,端口分别修改为8002、8003
3、将提供者端口为8001的所有信息,全部复制一份(注意修改配置文件和启动类的信息)
4、开启集群(三个)、开启后台服务(三个)
5、开启端口为80的消费者项目,再访问对应的信息(默认算法是轮询)
6、总结
对应前台的同一个url,Ribbon通过负载均衡的算法,将请求进行一个分配,然后访问不同的后台服务
此时我们就完成了使用Ribbon实现负载均衡的此时
6.5、自定义负载均衡算法
由之前的测试可知,Ribbon实现负载均衡的算法是轮询算法,但是它还有其他的很多种算法,甚至是自定义算法
使用随机查询算法
1、修改端口为80的消费者项目的配置类,修改使用随机算法
package pers.mobian.springcloud.config;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration //等价于spring的applicationContext.xml
public class ConfigBean {
//配置负载均衡实现RestTemplate
@Bean
//实现IRule接口
//RoundRobinRule: 轮询算法(默认)
//RandomRule: 随机查询
//AvailabilityFilteringRule: 会先过滤访问故障的服务
//RetryRule: 会先按照轮询获取服务,如果服务获取失败,就会再指定的事件内进行重试
@LoadBalanced //Ribbon
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
@Bean
public IRule myRule(){
return new RandomRule();
}
}
2、重启项目,即可实现随机查询算法
自定义查询算法
1、在指定的路径下新建一个我们的算法类 (下图来自官网说明)
2、编写我们的自定义算法类(基于随机算法的修改)MobianRule
package pers.mobian.myrule;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class MobianRule extends AbstractLoadBalancerRule {
private int total = 0;//被调用的次数
private int currentIndex = 0;//当前是谁在提供服务
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
Server server = null;
while (server == null) {
if (Thread.interrupted()) {
return null;
}
List<Server> upList = lb.getReachableServers();//获得活着的服务
List<Server> allList = lb.getAllServers();//获得全部的服务
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
// int index = chooseRandomInt(serverCount); //生成区间的随机数
// server = upList.get(index);//从活着的服务中,随机获取一个
// =========================================
//一个简单的每执行五次就换一次的算法
if (total < 5) {
server = upList.get(currentIndex);
total++;
} else {
total = 0;
currentIndex++;
if (currentIndex > upList.size()) {
currentIndex = 0;
}
server = upList.get(currentIndex);//从活着的服务中,获取指定的服务来执行
}
// =========================================
if (server == null) {
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}
server = null;
Thread.yield();
}
return server;
}
protected int chooseRandomInt(int serverCount) {
return ThreadLocalRandom.current().nextInt(serverCount);
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
// TODO Auto-generated method stub
}
}
3、编写对应的配置类MobianRandomRule
package pers.mobian.myrule;
import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MobianRandomRule {
//自定义使用自己的算法
@Bean
public IRule myIRule(){
return new MobianRule();
}
}
4、在启动类中添加相应的注解,用于表明我们自定义的算法类
package pers.mobian.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import pers.mobian.myrule.MobianRule;
@SpringBootApplication
@EnableEurekaClient
//在微服务启动的时候,就能够去自动加载我们自定义算法的类
@RibbonClient(name="SPRINGCLOUD-PROVIDER-DEPT",configuration = MobianRule.class)
public class DeptConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_80.classargs);
}
}
5、启动测试即可
由于我们算法的缺陷,所以只能访问一个轮回,即会报错,这里只是体验自定义算法的一个过程
7、Feign负载均衡
7.1、简介
Feign是声明式的web service客户端,它可以让微服务之间的调用变得更加简单。类似于controller调用service层。SpringCloud集成了Ribbon和Eureka,可以再使用Feign时提供负载均衡的http客户端。
只需要创建一个接口,然后添加注解即可!
Feign,主要是社区,我们都习惯了面向接口编程(类似于用注解实现mybatis的方式)。这个是很多开发人员的规范。调用微服务访问的两种方式
- 微服务名字(Ribbon)
- 接口和注释(Feign)
Feign作用
- Feign可以使编写的Java Http客户端变得更容易
- 之前使用的Ribbon + RestTemplate时,利用RestTemplate对Http请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常会针对每个微服务自行防撞一些客户端类来包装这些依赖服务调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义,在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它(类似于以前Dao接口上标注的Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可)。即可完成对服务提供方的接口绑定,简化了使用Spring Cloud Ribbon时,自动封装服务调用用客户端的开发量
Feign继承了Ribbon
- 利用Ribbon维护了MicroServiceCloud-Dept的服务列表信息,并且通过轮询实现了客户端的负载均衡,而与Ribbon不同的是,通过Feign只需要定义服务绑定接口且以声明式的方法,就可以简单的实现了服务调用。
7.2、Feign使用步骤
1、在springcloud-api项目入对应的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
2、在springcloud-api项目中新建一个service层,并且编写一个DeptClientService接口类
package pers.mobian.springcloud.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import pers.mobian.springcloud.pojo.Dept;
import java.util.List;
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
public interface DeptClientService {
@PostMapping("/dept/add")
public boolean addDept(Dept dept);
@GetMapping("dept/get/{id}")
public Dept queryById(@PathVariable("id") Long id);
@GetMapping("/dept/list")
public List<Dept> queryAll();
}
3、新建一个springcloud-consumer-dept-feign项目,用于测试feign(大体内容与springcloud-consumer-dept-80类似)
4、修改对应的控制器类DeptConsumerController
package pers.mobian.springcloud.controller;
import org.springframework.beans.factory.annotation.Autowired;
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 pers.mobian.springcloud.FeignDeptConsumer_80;
import pers.mobian.springcloud.pojo.Dept;
import pers.mobian.springcloud.service.DeptClientService;
import java.util.List;
@RestController
public class DeptConsumerController {
//次控制器类来自消费者,访问对应的端口,就能够访问到指定的提供者的信息
//RestTemplate 注册到Spring容器中,供我们调用对应的方法即可
@Autowired
private RestTemplate restTemplate;
@Autowired
private DeptClientService deptClientService;
@RequestMapping("/consumer/dept/add")
public boolean add(Dept dept) {
return this.deptClientService.addDept(dept);
}
@RequestMapping("/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
return this.deptClientService.queryById(id);
}
@RequestMapping("/consumer/dept/list")
public List<Dept> list() {
//getForObject:表示对应的访问方式为get
//参数列表:访问的提供者的路径,以及返回的类型
return this.deptClientService.queryAll();
}
}
5、修改对应的项目启动类(加上Feign的对应注解)
package pers.mobian.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"pers.mobian.springcloud"})
@ComponentScan("pers.mobian.springcloud")
public class FeignDeptConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(FeignDeptConsumer_80.class, args);
}
}
6、访问测试
使用Feign的方式,和Mybatis的用xml文件实现还是注解实现CRUD类似,降低了代码的复杂性,使代码看起来更加的精简,但与此同时,牺牲了一部分的性能(毕竟多添加了一层)
8、Hystrix
复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。
服务雪崩
多个微服务之间调用地时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他地微服务,这就是所谓地“扇出”、如果扇出地链路上某个微服务地调用相应时间过长或者不可用,对微服务A的调用就会占用越来越多地系统资源,进而引起系统崩溃,所谓地“雪崩效应”。
对于高流量地应用来说,单一地后端依赖可能会导致所有服务器上的所有资源都能在几秒钟之内饱和。比失败更糟糕的是,这些应用程序可能会导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。
我们需要丢车保帅
8.1、什么是Hystrix
下载地址:https://github.com/Netflix/Hystrix
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统中,许多依赖不可避免地会调用失败,比如超时,异常等,Hystrix能够保证在一个依赖出问题地情况下,不会导致整体服务失败,避免级联过账,以提高分布式系统地弹性
“断路器”本身是一种开关装置,当某个服务但愿发生故障之后,通过断路器地故障监控(类似熔断保险丝),向调用方返回一个服务预期地,可处理地备选相应(FallBack),而不是长时间地等待或者抛出调用方法无法处理地异常,这样就可以保证了服务调用方地线程不会被长时间,不必要的占用,从而避免了故障在分布式系统种的蔓延,乃至雪崩
更多的细节可以查看官网
作用:
- 服务降级
- 服务熔断
- 服务限流
- 接近实时的监控
8.2、服务熔断
熔断机制是一种对应雪崩效应的一种微服务链路保护机制。
当链路的某个微服务不可用或者相应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回,错误的响应信息。当检测到该节点微服务调用响应正常后回复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20此调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand
测试步骤
1、新建一个项目springcloud-provider-dept-hystrix-8001(与springcloud-provider-dept-8001项目环境搭建相同)
2、引入对应的pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
3、修改对应的控制器类(这里我们只做测试,所以只新建一个查询)
package pers.mobian.springcloud.controller;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import pers.mobian.springcloud.pojo.Dept;
import pers.mobian.springcloud.service.DeptService;
import java.util.List;
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@GetMapping("/dept/get/{id}")
@HystrixCommand(fallbackMethod = "hystrixGet")
public Dept get(@PathVariable("id") Long id) {
Dept dept = deptService.queryById(id);
if (dept == null) {
throw new RuntimeException("对应的" + id + "不存在");
}
return dept;
}
//出错以后的备选方案
public Dept hystrixGet(@PathVariable("id") Long id) {
return new Dept()
.setDeptno(id)
.setDname(id + "没有找到")
.setDb_source("没有找到这个数据库");
}
}
4、在对应的启动类上添加相应的注解
package pers.mobian.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
//启动类
@SpringBootApplication
@EnableEurekaClient //在服务启动后,自动注册到Eureka
@EnableDiscoveryClient
@EnableCircuitBreaker//添加对熔断的支持
public class DeptProviderHystrix_8001 {
public static void main(String[] args) {
//SpringApplication.run(new Class[] { MusicApp.class,CommonApp.class }, args);
SpringApplication.run(DeptProviderHystrix_8001.class,args);
}
}
5、测试代码
8.3、服务降级
1、在springcloud-api项目的service层新建一个DeptClientServiceFallbackFactory类,用于处理服务降级(由于我们只是测试,所以我们只重写了一个方法)
package pers.mobian.springcloud.service;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import pers.mobian.springcloud.pojo.Dept;
import java.util.List;
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory {
public DeptClientService create(Throwable cause) {
return new DeptClientService() {
public boolean addDept(Dept dept) {
return false;
}
public Dept queryById(Long id) {
return new Dept()
.setDeptno(id)
.setDname(id + "没有找到")
.setDb_source("没有找到这个数据库");
}
public List<Dept> queryAll() {
return null;
}
};
}
}
2、在同项目下的DeptClientService接口类种添加服务降级
package pers.mobian.springcloud.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import pers.mobian.springcloud.pojo.Dept;
import java.util.List;
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
@PostMapping("/dept/add")
public boolean addDept(Dept dept);
@GetMapping("dept/get/{id}")
public Dept queryById(@PathVariable("id") Long id);
@GetMapping("/dept/list")
public List<Dept> queryAll();
}
3、在springcloud-consumer-dept-feign项目下修改他的核心配置文件
server:
port: 80
#开启服务降级
feign:
hystrix:
enabled: true
eureka:
client:
register-with-eureka: false #不向Eureka注册自己
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
4、启动7001的集群端口、8003端口的提供者、以及80端口的消费者
此时依然能够访问,与服务熔断不同的是,当后台的服务器断开后,消费者访问指定的端口时,会提示对应的信息
8.4、服务熔断与服务降级的比较
服务熔断:
- 当我们访问的服务对应的服务器因为超时或异常时,系统的服务器会主动的返回我们之前准备好的提示。主动产生。
- 可以类比为保险丝,因为外部情况所以产生的一种反馈
服务降级:
- 当我们的需要访问的服务对应的服务器出现熔断或者关闭时,对应的服务器不再被调用,我们准备的FallbackFactory类,会返回一个我们之前准备好的错误处理。被动产生。
- 可以类比为你要去拜访别人,别人不在家,但是却给每一个拜访者留了一封信,表明了原因。
8.5、Dashboard流量监控
1、新建一个端口为9001的springcloud-consumer-hystrix-dashboard项目
2、导入对应的pom依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>pers.mobian</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
3、修改核心配置文件,将端口号修改为9001
4、编写对应的启动类DeptConsumerDashboard_9001
package pers.mobian.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication
@EnableHystrixDashboard //开启监控信息
public class DeptConsumerDashboard_9001 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerDashboard_9001.class,args);
}
}
5、访问对应的端口http://localhost:9001/hystrix,即可出现一只豪猪的标志
至此监控页面配置完成
6、修改含有熔断的8001端口的项目springcloud-provider-dept-hystrix-8001
7、在它的pom种添加对应的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
8、修改需要监控的项目的启动类,此处我们修改的是springcloud-provider-dept-hystrix-8001项目的启动类
package pers.mobian.springcloud;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
//启动类
@SpringBootApplication
@EnableEurekaClient //在服务启动后,自动注册到Eureka
@EnableDiscoveryClient
@EnableCircuitBreaker//添加对熔断的支持
public class DeptProviderHystrix_8001 {
public static void main(String[] args) {
//SpringApplication.run(new Class[] { MusicApp.class,CommonApp.class }, args);
SpringApplication.run(DeptProviderHystrix_8001.class,args);
}
//增加一个Servlet
@Bean
public ServletRegistrationBean hystrixMetricsStreamSeevlet(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
registrationBean.addUrlMappings("/actuator/hystrix.stream");
return registrationBean;
}
}
9、一次启动端口为7001、9001、8001端口的项目
10、在监控主界面输入对应的路径,再点击监控
11、不断的访问我们被监控的资源路径,然后的到的动态数据
流量监控界面的解释
记住七色,一点,一圈
七色:
一圈:
实心圆,共有两种含义,他通过颜色的变化代表了实例的健康程度
他的健康程度从绿色到黄色再到橙色再到红色依次递减
该实心圆除了颜色的变化之外,它的大小也会根据实例的请求流量发生变化,流量越大,该实心圆就越大,所以通过该实心圆的展示,就可以看到在大量的实例中快速发现故障实例和高压实例。
一线:
曲线用来记录两分钟内流量的相对变化,可课通过它来观察到流量的上升和下降趋势
9、Zuul
官网地址:https://github.com/Netflix/zuul
9.1、什么是Zuul
Zuul包含了对请求的路由和过滤两个主要的功能
其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问同一入口的基础,而过滤功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等于功能的基础。Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka种获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。
注意:Zuul服务最终还是会注册进Eureka
提供:代理 + 路由 + 过滤 三大功能
9.2、配置Zuul步骤
1、我们在我们的本地访问路径种新添加一个路径:127.0.0.1 www.mobian.com
2、新建一个Zuul的项目springcloud-zuul-9527
3、配置对应的pom依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>pers.mobian</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
4、配置对应的核心配置文件
server:
port: 9527
spring:
application:
name: springcloud-zuul
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: zuul9527.com
prefer-ip-address: true
info:
app.name: mobian-springcloud
company.name: blog.mobian.com
5、在pers.mobian.springcloud包路径下新建一个主启动类
package pers.mobian.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy//开启
public class ZuulApplication_9527 {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication_9527.class, args);
}
}
6、依次开启端口7001、8001、9527
次此我们会发现多了一个zuul服务
7、访问对应的端口地址也可以变成
但是我们正常的使用则会将微服务的项目名字进行替换成其他的显示效果
8、修改9527端口的核心配置文件
server:
port: 9527
spring:
application:
name: springcloud-zuul
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: zuul9527.com
prefer-ip-address: true
info:
app.name: mobian-springcloud
company.name: blog.mobian.com
#配置对应的zuul信息
zuul:
routes:
mydept.serviceId: springcloud-provider-dept
mydept.path: /mydept/**
9、再次重启该服务
此时的访问路径为:http://www.mobian.com:9527/mydept/dept/get/2
此时的问题是,我们使用之前的路径http://www.mobian.com:9527/springcloud-provider-dept/dept/get/2也可以访问,所以我们可以再次修改核心配置文件
10、修改核心配置文件
server:
port: 9527
spring:
application:
name: springcloud-zuul
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: zuul9527.com
prefer-ip-address: true
info:
app.name: mobian-springcloud
company.name: blog.mobian.com
zuul:
routes:
mydept.serviceId: springcloud-provider-dept
mydept.path: /mydept/**
#忽略这个访问路径
ignored-services: springcloud-provider-dept
#也可以设置成使用通配符进行
ignored-services: "*"
#可以设置对应的前缀,我们每次访问的时候都需要再添加一段前缀才能范围跟
prefix: /mobian
至此,使用Zuul配置网关也就完成了
10、Spring Cloud Config分布式配置
10.1、概述
分布式系统面临的问题:配置文件问题
微服务意味着要将单体应用种的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施必不可少的。SpringCloud提供了ConfigServer来解决这个问题,我们每一个微服务自己带着一个application.yml,那如果有上百个配置文件,修改起来也十分麻烦
10.2、什么是Spring Cloud Config
Spring Cloud Config为微服务架构中心提供集中化的外部配置支持,配置服务端为各个不同微服务应用的所有环节提供了一个中心化的外部配置。
Spring Cloud Config分为服务端和客户端两部分
服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密,解密信息等访问接口
客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息,配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容。
Spring Cloud Config分布式配置中心的作用
- 集中管理配置文件
- 不同的环境、不同的配置,动态化的配置跟新,分环境部署,比如/dev /test/ /prod
- 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息
- 当配置发生变动时,服务不需要重启,即可感知到配置的变化,并应用新的配置
- 将配置信息以REST接口的形式暴露
Spring Cloud Config分布式配置中心与Github整合
由于Spring Cloud Config默认使用Git来存储配置文件(也有其他的方式,比如支持SVN和本地文件),但更推荐使用Git,而且使用的是http/https访问的形式
10.3、配置我们的服务端
1、在自己的码云上新建一个仓库(application为我后来建立的文件夹)
2、利用下载的git将这个仓库克隆到我们本地
3、新建一个application.yml文件,并添加相应的配置信息(一定要注意英文状态的冒号以及格式)
spring:
profiles:
active: dev
---
spring:
profiles: dev
application:
name: springcloud-config-dev
---
spring:
profiles: test
application:
name: springcloud-config-test
4、在我们的客户端新建一个端口为3344的服务端项目:springcloud-config-server-3344
5、导入相关的pom依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-config-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
</dependencies>
6、配置我们服务端的端口及连接信息
server:
port: 3344
spring:
application:
name: springcloud-config-server
cloud:
config:
server:
git:
uri: https://gitee.com/mobianjava/springcloud-config.git #使用http的方式
7、配置该项目的启动类
package pers.mobian.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
//开启该注解
@EnableConfigServer
public class Config_Server_3344 {
public static void main(String[] args) {
SpringApplication.run(Config_Server_3344.class, args);
}
}
8、访问对应的端口,进行查询测试
服务端配置完成
10.4、配置我们的客户端
1、在我们的本地仓库文件中新增加一个config-client.yml配置文件
spring:
profiles:
active: dev
---
server:
port: 8201
#Spring配置
spring:
profiles: dev
application:
name: springcloud-provider-dept
#Eureka的配置,服务注册到的目的地
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
---
server:
port: 8202
#Spring配置
spring:
profiles: test
application:
name: springcloud-provider-dept
#Eureka的配置,服务注册到的目的地
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
2、将我们的文件提交到远程的git仓库
3、新建一个客户端的程序springcloud-config-client-3355
4、添加对应的pom依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-config -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
5、编写对应的配置文件
这里我们使用bootstrap.yml
#系统级别的配置
spring:
cloud:
config:
name: config-client
profile: test
label: master
uri: http://localhost:3344
同时可以使用application.yml设置项目的名字
spring:
application:
name: springcloud-config-client-3355
bootstrap.yml与application.yml都是能够被识别的配置文件,前者是属于系统级别的配置,后者属于用户级别的配置
6、在该项目中新增加一个控制器类(controller层下建立)ConfigClientController
package pers.mobian.springcloud.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ConfigClientController {
@Value("${spring.application.name}")
private String applicationName;
@Value("${eureka.client.service-url.defaultZone}")
private String eurekaServer;
@Value("${server.port}")
private String port;
@RequestMapping("/config")
public String getConfig() {
return "applicationName" + applicationName + "eurekaServer" + eurekaServer + "port" + port;
}
}
7、编写对应的启动类ConfigClient_3355
package pers.mobian.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ConfigClient_3355 {
public static void main(String[] args) {
SpringApplication.run(ConfigClient_3355.class,args);
}
}
8、访问对应的端口http://localhost:8202/config (这个8202端口,来源于最开始我们在bootstrap.yml文件中的配置)
9、在服务端启动时,访问其他端口http://localhost:3344/master/config-client-dev.yml
10.5、远程实战
关于其它的一系列配置,本质都差不多。
1、我们在仓库中新建一个配置文件
2、提交到远程的仓库
3、修改我们的本地配置文件(bootstrap.yml),用来指定我们在远程仓库的对应的环境
4、启动测试,用于完成测试
11、完结
加油!!!