官网:https://spring.io/projects/spring-cloud/
微服务定义:
官方定义:微服务就是由一系列围绕自己业务开发的微小服务构成,他们独立部署运行在自己的进程里,基于分布式的管理
通俗定义:微服务是一种架构,这种架构是将单个的整体应用程序分割成更小的项目关联的独立的服务。一个服务通常实现一组独立的特性或功能,包含自己的业务逻辑和适配器。各个微服务之间的关联通过暴露api来实现。这些独立的微服务不需要部署在同一个虚拟机,同一个系统和同一个应用服务器中。
SpringCloud定义:
springcloud为开发人员提供了在分布式系统中快速构建一些通用模式的工具〈例如配置管理、服务发现、断路器、智能路由、微代理、控制总线)。
分布式系统的协调导致了锅炉板模式,使用springcloud开发人员可以快速地建立实现这些模式的服务和应用程序。
核心架构及其组件
#1.核心组件说明
eurekaserver、consul、nacos 服务注册中心组件
rabbion & openfeign 服务负载均衡和服务调用组件
hystrix & hystrix dashboard 服务断路器和服务监控组件
zuul、gateway 服务网关组件
config 统一配置中心组件
bus 消息总线组件
.....
服务注册中心
所谓服务注册中心就是在整个的微服务架构中单独提出一个服务,这个服务不完成系统的任何的业务功能,仅仅用来
完成对整个微服务系统的服务注册和服务发现,以及对服务健康状态的监控和管理功能。
#1.服务注册中心
可以对所有的微服务的信息进行存储,如微服务的名称、IP、端口等
可以在进行服务调用时通过服务发现查询可用的微服务列表及网络地址进行服务调用
可以对所有的微服务进行心跳检测,如发现某实例长时间无法访珂,就会从服务注册表移除该实例。
常用的注册中心
springcloud支持的多种注册中心Eureka(netflix)、Consul、Zookeeper、以及阿里巴巴推出Nacos组件。
这些注册中心在本质上都是用来管理服务的注册和发现以及服务状态的检查的。
1.Eureka
Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务。SpringCloud将它集成在其子项目spring-cloud-netflix中以实现SpringCloud的服务注册和发现功能。
Eureka包含两个组件:Eureka Server和Eureka Client。
创建eureka(2版本不开源,停止维护)服务注册中心
1.创建springboot项目,在pox.xml文件中引入:
<properties>
<!-- 引入的springcloud版本 -->
<spring.cloud-version>Hoxton.SR6</spring.cloud-version>
</properties>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</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>
修改配置文件(application.properties):
server.port=8761
spring.application.name=eurekaServer
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
#不再将自己同时作为客户端进行注册
eureka.client.register-with-eureka=false
#关闭作为客户端时从eureka server获取服务信息
eureka.client.fetch-registry=false
修改启动程序:
@EnableEurekaServer
访问:浏览器地址:http://localhost:8761
开发eureka client
pom.xml:
<properties>
<!-- 引入的springcloud版本 -->
<spring.cloud-version>Hoxton.SR6</spring.cloud-version>
</properties>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</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>
修改配置文件(application.properties):
server.port=8888
spring.application.name=eurekaclient
eureka.client.service-url.default=http://localhost:8761/eureka
修改启动程序:
@EnableEurekaClient
eureka自我保护机制
默认情况下,如果Eureka Server在一定时间内(默认90秒〉没有接收到某个微服务实例的心跳,Eureka Server将会移除该实例。但是当网络分区故障发生时,
微服务与Eureka Server之间无法正常通信,而微服务本身是正常运行的,此时不应该移除这个微服务,所以引入了自我保护机制。Eureka Server在运行期间会去统计心跳失败比例在15分钟之内是否低于85%,
如果低于85%,Eureka Server 会将这些实例保护起来,让这些实例不会过期。这种设计的哲学原理就是""宁可信其有不可信其无 "。
自我保护模式正是一种针对网络异常波动的安全保护措施,使用自我保护模式能使Eureka集群更加的健壮、稳定的运行。
常用命令:
eureka.server.enable-self-preservation=false #关闭自我保护
eureka.server.eviction-interval-timer-in-ms=3000 #超时3s自动清除
eureka .instance.lease-expiration-duration-in-seconds=10 #用来修改eureka server默认接受心跳的最大时间默认是90
seureka.instance. lease-renewal-interval-in-seconds=5 #指定客户端多久向eureka server发送一次心跳默认是30s
服务注册中心(consul)
官网地址:https://www.consul.io/
运行(windows):不能双击,进入该exe文件目录,运行命令:consul agent -dev或者consul agent -dev -ui -node=cy
开发consulClient
springbot项目
pom.xml
<properties>
<!-- 引入的springcloud版本 -->
<spring.cloud-version>Hoxton.SR6</spring.cloud-version>
</properties>
<!-- 引入consul客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- 必须引入健康检查依赖,否则即使服务可用,但是在consul注册中心获取不到服务状态 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</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>
修改配置文件(application.properties):
server.port=8889
spring.application.name=consulclient
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
修改启动程序 :
@EnableDiscoveryClient
不同服务注册中心的区别:
1.CAP定理
CAP定理:CAP定理又称CAP原则,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
一致性(C)︰在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
可用性(A)︰在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
分区容忍性(P),就是高可用性,一个节点崩了,并不影响其它的节点(100个节点,挂了几个,不影响服务,越多机器越好)
#2.Eureka特点
Eureka中没有使用任何的数据强一致性算法保证不同集群间的Server的数据一致,仅通过数据拷贝的方式争取注册中心数据的最终一致性,虽然放弃数据强一致性但是换来了Server的可用性,降低了注册的代价,提高了集群运行的健壮性。
# 3. consul特点
基于Raft算法,Consul提供强一致性的注册中心服务,但是由于Leader节点承担了所有的处理工作,势必加大了注册和发现的代价,降低了服务的可用性。通过Gossip协议,Consul可以很好地监控Consul集群的运行,同时可以方便通知各类事件,如Leader选择发生、Server地址变更等。
#4.zookeeper特点
基于Zab协议,Zookeeper可以用于构建具备数据强一致性的服务注册与发现中心,而与此相对地牺牲了服务的可用性和提高了注册需要的时间。
服务间的通信方式
在springcloud中服务间调用方式主要是使用http restful方式进行服务间调用
基于RestTemplate的服务调用
spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接,我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。
使用方法:
// 第一种服务端调用方式
RestTemplate restTemplate = new RestTemplate();
// 参数1:请求路径 参数2:返回值类型
String msg = restTemplate.getForObject("http://localhost:9998/product/showMsg", String.class);
restTemplate直接调用存在问题
1.直接使用restTemplate方式调用没有经过服务注册中心获取服务地址,代码写死不利于维护,当服务宕机时不能高效剔除
2.调用服务时没有负载均衡需要自己实现负载均衡策略
基于Ribbon的服务调用:
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。
1. RestTemplate方式进行服务调用,服务之间直接通信,不经过consul
RestTemplate restTemplate = new RestTemplate();
// 参数1:请求路径 参数2:返回值类型
String msg = restTemplate.getForObject("http://localhost:9998/product/showMsg", String.class);
2.discoveryClient方式,经过consul,但是只能自己做服务之间的负载均衡
@Autowired
private DiscoveryClient discoveryClient;
List<ServiceInstance> serverInstances = discoveryClient.getInstances("products");
for (ServiceInstance serviceInstance : serverInstances){
System.out.println(serviceInstance.getHost());
System.out.println(serviceInstance.getPort());
}
3. loadBalancerClient 得到已经均衡好的ServiceInstance
ServiceInstance serviceInstance = loadBalancerClient.choose("products");
RestTemplate restTemplate = new RestTemplate();
String url = serviceInstance.getUri()+"/product/findAll";
String template = restTemplate.getForObject(url, String.class);
4.LoadBalance + RestTemplate
新建一个类
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced // 代表ribbon负载均衡的RestTemplate客户端对象
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
// http://products/product/findAll products为注册到consul的服务
String template = restTemplate.getForObject("http://products/product/findAll", String.class);
ribbon负载均衡策略:
负载均衡算法:
RoundRobinRule 轮训策略按顺序循环选择Server
RandomRule 随机策略随机选择Server
AvailabilityFilteringRule 可用过滤策略
会先过滤由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问
WeightedResponseTimeRule 响应时间加权策略
根据平均响应的时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高,刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够会切换到
RetryRule 重试策略
先按照RoundRobinRule的策略获取服务,如果获取失败则在制定时间内进行重试,获取可用的服务。
BestAviableRule 最低并发策略
会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
修改服务默认随机策略:服务id为注册中心的服务名
服务id.ribbon. NFLoadBalancerRuleclassName=com.netflix.loadbalancer.RandomRule
OpenFeign组件的使用
1.pom.xml
<!--引入open feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2. 启动程序:
@EnableFeignClients // 开启支持open feign调用
3.feign接口
@FeignClient(value = "products") // 作用:用来标识当前接口是一个feign组件 value:书写调用服务id,服务名字
public interface ProductClient {
@GetMapping("/product/showMsg")
String showMsg();
}
openFeign传参
//调用商品服务的open feign
@FeignClient(value = "products") // 作用:用来标识当前接口是一个feign组件 value:书写调用服务id,服务名字
public interface ProductClient {
@GetMapping("/product/showMsg")
String showMsg();
//根据商品id查询商品
@GetMapping("/product/findOne") //注意:使用openfeign的GET方式传递参数参数变量必须通过@requestParam注解进行修饰
Map<String,Object> findOne(@RequestParam("productId") String productId);
@PostMapping("/product/save") //注意:使用openfeign的POST方式传递参数参数变量必须通过@requestParam注解进行修饰
Map<String,Object> save(@RequestParam("name") String name);
@PostMapping("/product/update") //注意:使用openfeign的post方式传递对象信息,要求服务提供方和服务调用方都必须使用@RequestBody进行声明
public Map<String,Object> update(@RequestBody Product product);
//调用文件上传服务注意;使用openfeign传递参数含有文件类型时必须指定consumes = MediaType .MULTIPART_FORM_DATA_VALUE
@PostMapping(value = "/file/upload" ,consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
Map<string,object> upload(@RequestPart ( "photo" ) MultipartFile photo);
}
feign.client.config. products.connectTimeout=5000 #配置指定服务连接超时,服务名:products
feign.client.config.products.readTimeout=5000 #配置指定服务等待超时
feign.client.config.default.connectTimeout=5000 #配置所有服务连接超时
feign.client.config.default.readTineout=5000 #配置所有服务等待超时
openFeign日志配置
说明:
-往往在服务调用时我们需要详细展示feign的日志,默认feign在调用是并不是最详细日志输出,因此在调试程序时应该开启feign的详细日志展示。
feign对日志的处理非常灵活可为每个feign客户端指定日志记录策略,每个客户端都会创建一个logger默认情况下logger的名称是feign的全限定名需要注意的是,feign日志的打印只会DEBUG级别做出响应。
-我们可以为feign客户端配置各自的logger. level对象,告诉feign记录那些日志logger,level有以下的几种值
NONE不记录任何日志
BASIC仅仅记录请求方法,url,响应状态代码及执行时间
HEADERS记录Basic级别的基础上,记录请求和响应的header
FULL记录请求和响应的header,body和元数据
feign.client.config.PRODUCTS.loggerLevel=full #开启指定服务日志展示
#feign.client.config.default.loggerLevel=full #全局开启服务日志展示
logging.level.com.xiuzhiwu.feignclients=debug#指定feign调用客户端对象所在包,必须是debug级别
Hystrix(服务已经进入维护状态)
在分布式环境中,许多服务依赖项不可避免地会失败。Hystrix是一个库,它通过添加延迟容忍和容错逻辑来帮助您控制这些分布式服务之间的交互。
Hystrix通过隔离服务之间的访问点、停止它们之间的级联故障以及提供后备选项来实现这一点,所有这些都可以提高系统的整体弹性。
通俗定义:Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统中,许多依赖不可避免的会调用失败,超时、异常等,
Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障(服务雪崩现象),提高分布式系统的弹性。
服务雪崩:(JMeter可以做压力测试)
在微服务之间进行服务调用是由于某一个服务故障,导致级联服务故障的现象,称为雪崩效应。雪崩效应描述的是提供方不可用,导致消费方不可用并将不可用逐渐放大的过程。
服务熔断:
"熔断器"本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控,某个异常条件被触发,直接熔断整个服务。
向调用方法返回士个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,就保证了服务调用方的线程不会被长时间占用,避免故障在分布式系统中蔓延,乃至雪崩。
如果目标服务情况好转则恢复调用。服务熔断是解决服务雪崩的重要手段。
服务降级:
服务压力剧增的时候根据当前的业务情况及流量对一些服务和页面有策略的降级,以此环节服务器的压力,以保证核心任务的进行。同时保证部分甚至大部分任务客户能得到正确的相应。也就是当前的请求处理不了了或者出错了,给一个默认的返回。
降级和熔断总结:
#1.工共同点
-目的很一致,都是从可用性可靠性着想,为防止系统的整体缓慢甚至崩溃,采用的技术手段;
-最终表现类似,对于两者来说,最终让用户体验到的是某些功能暂时不可达或不可用;
-粒度一般都是服务级别,当然,业界也有不少更细粒度的做法,比如做到数据持久层(允许查询,不允许增删改);
-自治性要求很高,熔断模式一般都是服务基于策略的自动触发,降级虽说可人工干预,但在微服务架构下,完全靠人显然不可能,开关预置、配置中心都是必要手段;
#2.异同点
-触发原因不太一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;
-管理目标的层次不太一样,熔断其实是一个框架级的处理,每个微服务都需要(无层级之分),而降级一般需要对业务有层级之分(比如降级一般是从最外围服务开始)
#3.总结
-熔断必会触发降级,所以熔断也是降级一种,区别在于熔断是对调用链路的保护,而降级是对系统过载的一种保护处理
服务熔断的实现:
1.引入Hystrix依赖
<!-- 引入Hystrix依赖 spring-cloud-starter-netflix-hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2. 启动程序添加:
@EnableCircuitBreaker
3.具体实现,指定方法降级,容易造成代码冗余
@GetMapping("/product/break")
//@HystrixCommand(fallbackMethod = "testBreakFallback") //指定方法降级,容易造成代码冗余
@HystrixCommand(defaultFallback = "testBreakFallback") // 默认方法进行熔断,减少代码冗余
public String testBreak(int id){
if (id < 0){
throw new RuntimeException("非法参数,id不能小于0");
}
return "访问成功,当前id为:"+id;
}
// 熔断方法
public String testBreakFallback(int id){
return "当前传入的id:"+id+",不是有效参数";
}
服务降级的实现:
#1.客户端openfeign + hystrix实现服务降级实现
-引入hystrix依赖
-配置文件开启feign支持hystrix
-在feign客户端调用加入fallback指定降级处理
-开发降级处理方法
#2.开启openfeign支持服务降级
feign.hystrix.enabled=true #开启openfeign支持降级
具体实现
FallbackClient 类
@Component
public class FallbackClient implements ProductClient {
@Override
public String showMsg() {
return "当前服务已经被降级";
}
@Override
public Map<String, Object> findOne(String productId) {
Map<String,Object> map = new HashMap<>();
map.put("status",false);
map.put("msg","当亲服务已经被降级");
return map;
}
}
接口ProductClient :
@FeignClient(value = "products",fallback = FallbackClient.class) // 作用:用来标识当前接口是一个feign组件 value:书写调用服务id,服务名字
public interface ProductClient {
GateWay(服务网关)组件使用:
什么是网关服务:
#1.说明:
-网关统一服务入口,可方便实现对平台众多服务接口进行管控,对访问服务的身份认证、防报文重放与防数据篡改、功能调用的业务鉴权、响应数据的脱敏、流量与并发控制,甚至基于API调用的计量或者计费等等。
-网关=路由转发+过滤器
-路由转发︰接收一切外界请求,转发到后端的微服务上去;
-在服务网关中可以完成一系列的横切功能,例如权限校验、限流以及监控等,这些都可以通过过滤器完成
#2.为什么需要网关
-1.网关可以实现服务的统一管理
-2.网关可以解决微服务中通用代码的冗余问题(如权限控制,流量监控,限流等)
#3.gateway实现:
pom.xml:引入了Hoxton sr8,2.2.5springboot版本
<!-- 引入gateway依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--consul依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--监控检查依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
启动程序:
@EnableDiscoveryClient
配置文件Yml方式:
server:
port: 8989
spring:
application:
name: gateway
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
gateway:
routes:
- id: user_route #指定路由唯一标识
uri: http://localhost:9999/ #指定路由服务地址
predicates:
- Path=/feign/** #指定路由规则
- id: product_route #指定路由唯一标识
uri: http://localhost:9998/ #指定路由服务地址
predicates:
- Path=/product/** #指定路由规则
#这一段是默认受保护的,不建议开启
management:
endpoints:
web:
exposure:
include: "*" #暴露路由规则web端点
配置成功:http://localhost:8989/actuator/gateway/routes 显示配置的路由
http://localhost:8989/feign/test1
配置网关服务进行负载均衡:
spring:
application:
name: gateway
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
gateway:
routes:
- id: user_route #指定路由唯一标识
uri: lb://users #指定路由服务地址,lb://注册到consul的服务名
predicates:
- Path=/feign/** #指定路由规则
- id: product_route #指定路由唯一标识
uri: lb://products #指定路由服务地址
predicates:
- Path=/product/** #指定路由规则
discovery:
locator:
enabled: true #开启更据服务动态获取路由地址
filters的使用
自定义filters的使用:
//自定义全局filter
@Configuration
@Slf4j
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("进入自定义filter");
if (exchange.getRequest().getQueryParams().get("userName") != null){
return chain.filter(exchange); //放行请求
}
log.info("非法用户,拒绝访问");
return exchange.getResponse().setComplete();
}
@Override
public int getOrder() {
return -1;
}
}
Config统一配置中心组件
#0.说明:
config(配置)又称为统一配置中心顾名思义,就是将配置统一管理,配置统一管理的好处是在日后大规模集群部署服务应用时相同的服务配置一致,日后再修改配置只需要统一修改全部同步,不需要一个一个服务手动维护。
config-server的开发
新建springboot项目:
https://gitee.com/xiuzhiwu/springcloudconfig.git
在这个项目里,有master和dev分支,文件有clients.properties,clients-dev.properties,clients-prod.properties
pom.xml:
<properties>
<spring.cloud-version>Hoxton.SR8</spring.cloud-version>
</properties>
<!--引入consul-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--引入健康检查机制-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--引入configserver依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<!-- 引入springcloud版本,下载地址。放在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>
启动程序:
@EnableDiscoveryClient
@EnableConfigServer
配置文件:
server.port=7878
spring.application.name=configserver
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
spring.cloud.consul.discovery.service-name=${spring.application.name}
spring.cloud.config.server.git.uri=https://gitee.com/xiuzhiwu/springcloudconfig.git
#一定要是空目录,首次启动会清空
spring.cloud.config.server.git.basedir=E:/springCloud/configserver7878/src/main/resources/localconfig
#默认从master分支获取配置,指定从远程仓库中那个分支获取内容
spring.cloud.config.server.git.default-label=mater
#只有私有仓库才会套用户名和密码
#spring.cloud.config.server.git.username=
#spring.cloud.config.server.git.password=
config-client开发:
pom.xml: 引入springcloud版本后
<!--引入consul-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--引入健康检查机制-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--引入hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!--config client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
启动程序:
@EnableDiscoveryClient
bootstrap.properties:
这是consul启动在本地的配置
spring.application.name=configclient
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=configserver
spring.cloud.config.label=dev
spring.cloud.config.name=clients
spring.cloud.config.profile=dev
这是consul启动不在本地的配置:
#微服务名称
spring.application.name=configClient
#config配置中心的uri地址
spring.cloud.config.uri=http://localhost:7878
#远程GitHub仓库中配置文件所在的分支
spring.cloud.config.label=master
#远程GitHub仓库中主配置文件的名字
spring.cloud.config.name=clients
#远程GitHub仓库中副配置文件的类型
spring.cloud.config.profile=dev
自动刷新配置:
手动刷新:
官网地址:https://curl.se/windows/
手动刷新命令:curl -X POST http://localhost:7879/actuator/refresh
bootstrap.properties: yml配置文件下include="*",需要加双引号
#开启所有web端点暴露
management.endpoints.web.exposure.include=*
控制器:
@RestController
@RefreshScope //开启手动刷新配置
public class ClientController {
Bus消息总线:
#0.定义;
springcloudbus使用轻量级消息代理将分布式系统的节点连接起来。然后,可以使用它来广播状态更改(例如配置更改)或其他管理指令。
AMOQP和Kafka broker实现包含在项目中。或者,在类路径上找到的任何springcloudstream绑定器都可以作为传输使用。
通俗定义:
bus称之为springcloud中消息总线,主要用来在微服务系统中实现远端配置更新时通过广播形式通知所有客户端刷新配置信息,避免手动重启服务的工作
开启自动刷新:
手动刷新命令:curl -X POST http: // localhost:7878/actuator/bus-refresh
自动刷新需要一个config-server,在上面的基础上
application.properties:
#连接主机
spring.rabbitmq.host=192.168.1.31
#连接mq端口
spring.rabbitmq.port=5672
#连接目前用户名
spring.rabbitmq.username=admin
#用户名密码
spring.rabbitmq.password=admin
#暴露所有端点
management.endpoints.web.exposure.include=*
pom.xml:
<!--引入rabbitmq-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
使用webhook+natapp内网穿透进行自动配置:
注册natapp,下载客户端,通过cmd进入下载的客户端所在的目录,执行命令:natapp -authtoken=natapp隧道的authtoken
Forwarding http://cd2tim.natappfree.cc -> 127.0.0.1:7878 我穿透的是7878端口
在gitee或github上点击管理,找到webhook,添加,http://cd2tim.natappfree.cc/actuator/bus-refresh
webhook添加完成之后,修改任意配置,就可以自动刷新了。
springcloudalibaba
环境搭建:
pomxml
<properties>
<java.version>11</java.version>
<spring.cloud.alibaba.version>2.2.1.RELEASE</spring.cloud.alibaba.version>
</properties>
<!--全局引入springcloudalibaba 下载依赖地址,并不会下载依赖-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>{project-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
nacos注册中心:
官网:https://github.com/alibaba/nacos/releases
启动:bin目录下进入cmd,命令: startup.cmd -m standalone
web界面:http://localhost:8848/nacos/index.html 账号密码均为:nacos
nacosclient开发:
pom.xml:在环境搭建的基础上
<!--引入nacos依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
application.properties:nacos启动在本地
server.port=9099
spring.application.name=users
spring.cloud.nacos.server-addr=localhost:8848
spring.cloud.nacos.discovery.server-addr=${spring.cloud.nacos.server-addr}
启动程序:这个注解默认开启
@EnableDiscoveryClient
nacos配置中心:
自动刷新:
在nacos中默认实现了配置自动刷新功能,如果需要刷新配置直接在控制器中加入@RefreshScope注解即可
pom.xml
<!--引入nacos依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--引入nacos config依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
bootstrap.properties:配置已经放在了nacos上
#nacos命名规则
#${spring.application.name}-${spring.profiles.active}.${file-extension}
#config server addr
spring.cloud.nacos.server-addr=localhost:8848
spring.cloud.nacos.discovery.server-addr=${spring.cloud.nacos.server-addr}
#读取配置的分组
spring.cloud.nacos.config.group=DEFAULT_GROUP
#指定读取文件的后缀
spring.cloud.nacos.config.file-extension=properties
#指定读取文件的前缀
spring.application.name=configclient
#指定读取文件的具体环境
spring.profiles.active=prod
Sentinel 流量卫兵
sentinel提供了两个服务组件:
一个是sentinel用来实现微服务系统中服务熔断、降级等功能。这点和hystrix类似
一个是sentinel dashboard 用来监控微服务系统中流量调用等情况。这点和hystrix类似
官网下载地址:https://github.com/alibaba/Sentinel/releases
默认端口为8080,也可以自己下载源码,修改端口后打包成jar包
启动jar包 jar -Dserver.port=9191 -jar xxxxx(jar包的名字)
sentinel监控服务:
pom.xml:
<!--引入nacos依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--引入sentinel依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
配置文件:本地
#sentinel dashboard & sentinel logs
#默认开启
spring.cloud.sentinel.enabled=true
spring.cloud.sentinel.transport.port=8719
spring.cloud.sentinel.transport.dashboard=http://localhost:9191
虚拟机或远程地址
# 连接dashboard
spring.cloud.sentinel.transport.dashboard=虚拟机或者服务器的ip地址:9191
spring.cloud.sentinel.enabled=true
# 与dashboard通信的端口
spring.cloud.sentinel.transport.port=8719
#本机的IP地址
spring.cloud.sentinel.transport.clientIp=本机的IP地址
@SentinelResource
value 资源名称(必填项,需要通过 value 值找到对应的规则进行配置)
blockHandler 处理BlockException的函数名称(可以理解为对Sentinel的配置进行方法兜底)。函数要求:
1.必须是 public 修饰
2.返回类型与原方法一致
3. 参数类型需要和原方法相匹配,并在最后加 BlockException 类型的参数。
4. 默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 blockHandlerClass ,并指定blockHandlerClass里面的方法。
fallback 用于在抛出异常的时候提供fallback处理逻辑(可以理解为对Java异常情况方法兜底)。
fallback函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。函数要求:
1.返回类型与原方法一致
2.参数类型需要和原方法相匹配,Sentinel 1.6开始,也可在方法最后加 Throwable 类型的参数。
3.默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 fallbackClass ,并指定fallbackClass里面的方法。
fallbackClass 存放fallback的类。对应的处理函数必须static修饰,否则无法解析,其他要求:同fallback。
@GetMapping("/testB")
@SentinelResource(value = "testB",blockHandler = "exceptionMethod",fallback = "fallbackMethod",fallbackClass = CustomerFallback.class)
public String testB() {
return "-----testB";
}
public String exceptionMethod(BlockException exception) {
return "限流@SentinelResource value 属性的兜底方法:" + exception。getClass().getSimpleName();
}
public class CustomerFallback {
public static String fallbackMethod(Throwable e) {
return "限流请求连接(Java类异常)的兜底方法:" + e.getMessage();
}
}