SpringCloud微服务入门与基础使用


引言

2021.8.21更新~~
经历了毕业设计的摧残,秋招春招的毒打,进入工作岗位上的我更加坚定的认为,生命不息,学习不止。SpringCloud作为优秀的微服务架构,其中包含了许多的优秀设计理念。最近再次捡起SpringCloud学习,在这里做点笔记,也让大家能稍微了解一下微服务中SpringCloud中的组件(微服务也可以使用Dubbo与Zookeeper)。
首先声明!!!!!
Eureka 停止更新进入维护 ——> Nacos
Ribbon 停止更新进入维护 ——> OpenFeign
Hystrix 停止更新进入维护 ——> Sentinel
Zuul 停止更新正在开发Zuul2 ——> gateway

明确一点,netflex微服务五大组件大多已经停止了维护,在我们后序引入依赖时要注意,netflex组件maven依赖为spring-cloud-strater-netflex-xxxx,而其他的大多为spring-cloud-strter-xxxx,或者是alibaba,以下是netflex的五大组件。
SpringCloud开发五大组件

  • 服务发现——Netflix Eureka
  • 客服端负载均衡——Netflix Ribbon
  • 断路器——Netflix Hystrix
  • 服务网关——Netflix Zuul
  • 分布式配置——Spring Cloud Config

SpringCloud中的大多数组件都停止了更新,只在被动的维护Bug,大多数的组件都推荐更加优秀的SpringCloud Alibaba组件代替,如Eureka可以使用Nacos代替,Hystrix可以使用Sentinal代替。

PS:使用SpringCloud时,一定要注意与SpringBoot的版本配置,其中版本对应才可以。进入SpringCloud官网可以查到
在这里插入图片描述
其中推荐大家使用稳定版,也就是RELEASE版本。

这里给大家推荐一下建立一个微服务工程简单的步骤,参考尚硅谷周阳。

  • 建Moudle(可以考虑建立一个父级Moudle,之后使用DependencyManagement进行版本管理)
  • 改Pom(导入SpringBoot以及Cloud依赖、MySQL、MyBatis等)
  • 创Yml(将需要的配置写入,这里可以上网百度,但是一定要先看好引入的依赖是什么)
  • 启动类(需要开启什么服务,就加什么注解,如@EnableEurekaClient、@EnableEurekaServer等)
  • 写业务(具体业务,CRUD)

#### 前言
  • 近年来,随着分布式以及微服务的盛行,使用Java语言进行开发的程序员从最初的Spring到SpringBoot,最终都会来到SpringCloud。
  • SpringCloud是什么呢?很多人都有这个疑惑,微服务到底和分布式有什么区别,这是大多数刚接触SpringCloud的人都会有的问题,微服务是通过多个SpringBoot服务,通过每个SpringBoot项目上部署不同的服务(也可以理解成为某个功能),通过Eureka Server进行调度,Zuul网关进行转发,Ribbon进行服务发现,通过RabbitMQ或者Kafka进行服务间通信,使用Hystrix进行熔断策略、服务降级,这些不同的功能去完成,关
    于微服务,可以在单节点进行部署,也可以在多节点进行部署,而分布式,则是在创建项目开始,就进行多节点的部署,比如Redis集群,通过多节点部署,通过Sentinel进行监控以及故障转移等,所以,分布式也算作微服务
  • SpringCloud目前我们使用的分为两种派系,首先是以SpringCloud Eureka为代表的的SpringClou,另外一种是以Dubbo为代表的SpringCloud Alibaba。

SpringCloud Eureka

简介:Eureka作为SpringCloud的服务注册中心,微服务通过注册到Eureka来完成整个服务的搭建,Eureka提供了心跳检测、负载均衡等服务,通过不断的询问各微服务是否存活来进行心跳检测。
使用方法:在注册中心的SpringBoot项目入口类声明 @EnableEurekaServer,在其他微服务入口类上声明 @EnableEurekaClient,并且进行yml文件配置。

Pom依赖

Spring-cloud-starter-netflex-eureka-server   #eureka服务端依赖
Spring-cloud-starter-netflex-eureka-client   #客户端依赖

启动类声明

  • 使用Eureka必须创建注册端以及客户端,将所有的客户端注册在服务端。
  • 在服务端入口类加上@EnableEurekaServer
  • 在客户端入口类加上@EnableEurekaClient

服务器端YAML配置

server:
  port: 9000
eureka:
  instance:
    hostname: localhost #声明当前微服务的名称
  client:
    #表示是否从eureka server 获取注册信息,默认是true,如果这是一个单节点的Eureka Server,不需要同步其他节点的数据 ,则设置为false。
    fetch-registry: false
    #是否将自己注册到Eureka Server 默认是true ,因为当前是单节点的,所以设置为false。
    register-with-eureka: false
    #设置 Eureka Server的所在的地址,查询服务和注册服务都要依赖这个地址
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

客户端微服务YAML配置

server:
  port: 8000
eureka:
  client:
    service-url:
      #标识向哪个Eureka服务器进行注册
      defaultZone: http://server1:${port}/eureka/

配置完后之后,就可以通过访问在Eureka中声明的路径去查看当前SpringCloud中的微服务了,可以看到当前注册在Server上的所有的微服务。

Eureka的高可用

在生产环境中,我们通常会配置多个Eureka Server节点来保证微服务的高可用,防止因为Eureka Server挂掉而导致整个系统挂掉,在单机情况下,我们可以通过修改Eureka Server的的port以及注册地址来部署多个Eureka Server,从而实现高可用。这里要注意,当某微服务注册在Server1上,而Server1和Server2相互注册时,在Server2上也会显示注册在Server1上的微服务。
所谓相互注册,就是defaultZone加上其他注册中心的地址。
配置了注册中心高可用后,在客户端中需要向两个注册中心都去注册,有几个注册中心写几个URL。

客户端集群配置(高可用)

客户端集群可以使我们实现高可用以及负载均衡,在客户端的YML文件中编写
eureka-instance-hostname: XXXX
声明相同的服务名称,注册到Eureka上即可。


eureka:
  client:
    service-url:
      #标识向哪个zk服务器进行注册
      defaultZone: http://localhost:2181

其他注册中心

Zookeeper

ZK也是一款优秀的注册中心,可以配合Dubbo实现微服务,可以注册Kafka。
使用zk的方式也比较简单,下载Zookeeper,进行配置后启动,将微服务客户端中的defaultZone地址改成zookeeper的地址,即可注册,这里推荐使用Docker来安装zk镜像之后启动
启动之后,要在注册到zk的客户端上添加依赖。

		<dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.5.8</version>
        </dependency>

<!--            一定搞清楚是哪个厂家的-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            <!--            把自带的zookeeper去除掉,装和当前本机装的zookeeper软件一致的jar包-->
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

之后更改配置文件向zk注册

spring:
  application:
    name: 服务名
  cloud:
    zookeeper:
      connect-string: localhost:2181

Consul

Consul也是一款注册中心,同eureka相同的是他们都有直观的界面,可以观察到各个微服务注册情况;同zk相同的是他们都需要下载后启动,并不需要配置一个注册中心微服务。百度直接下载即可。其他同Nacos相似。

Nacos

Nacos作为未来替代Eureka的一款非常优秀的注册中心,同时实现了服务配置,消息总线,注册中心的功能,在SpringCloud Alibaba中会提到,感兴趣的可以去我博客中看看。

SpringCloud Feign/OpenFeign

Ribbon作为一款优秀的服务调用框架,很不幸的是它也进入了维护状态,未来代替它的是OpenFeign。

微服务应用间通信:在传统的微服务框架中,有两种通信方式,一种是基于RPC协议的Dubbo,另外一种是基于HTTP的SpringCloud。SpringCloud在服务间进行通信有两种方式,首先是通过RestTemplate,以及Feign(Feign是在Ribbon的基础上进行了增强,同样都是进行服务发现)。

Ribbon

Ribbon负载均衡:Ribbon通过客户端负载均衡来实现面对微服务多实例下的负载均衡,有服务发现(通过实例名称发现服务),服务选择规则(通过某种算法进行服务的选择),服务监听(检测失效的服务,进行剔除)。ServerList进行服务发现,通过ServerListFilter进行服务筛选,通过IRule进行服务的选择。

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflex-ribbon</artifactId>
        </dependency>

RestTemplate+LoadBalancerClient进行服务间通讯,使用LoadBalancerClient获取服务名称对应的IP以及Port组合成套接字,通过RestTemplate访问套接字进行服务请求。这种方式也是使用了Ribbon的组件。

配置RestTemplate

/**
* 让Spring将RestTemplate管理起来
* LoadBalance实现负载均衡,默认是轮询机制
* 使用RestTepmlate的getForObject/PostForObject来进行HTTP通信
*/

@Configuration
public class ApplicationContextConfiguration{

	@Bean
	@LoadBalance
	public RestTemplate getTemplate(){
		return new RestTemplate();
	}
    LoadBalance比较重要,开启负载均衡
}
@Autowried
private RestTemplate rest;

Object o = rest.getForObject("http://服务名/请求",返回值类型);

配置IRule规则

代码创建

@Configuration
public class RibbonConfiguration {
    @Bean
    public IRule ribbonRule(){
        // 负载均衡规则改为随机
        return new RandomRule();
    }
}
注意:该类不应该被应用程序上下文的@ComponentScan注解扫描到
@SpringBootApplication
@RibbonClient(name = "xxx",configuration = RibbonConfiguration.class)
public class MainApplitcaion{
    public static void main(String[] args){
    	SpringAppliction.run(MainApplitcaion.class,args);
    }
}
这样就可以为指定的客户端:xxx服务配置指定的负载均衡策略

负载均衡策略

  • com.netflex.loadBanalancer.RoundRobinRule 轮询
  • com.netflex.loadBanalancer.RandomRule 随机
  • com.netflex.loadBanalancer.RetryRule 先按照RoundRobinRule的策略获取服务,如果过去服务失败则在指定时间内进行重试,获取可用的服务
  • WeightResponseTimeRule 对RoundRobinRule的扩展,相应速度越快的实力权重越多大,越容易被选择
  • BestAvailableRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
  • AvailabilityFilteringRule 先过滤掉故障实例,再选择并发较小的实例
  • ZoneAvoidanceRule 默认规则,复合判断service所在区域的性能和server的可用性选择服务器

Feign与OpenFeign

前言:Ribbon已经进入了老年期,只会被动的维护自己,Feign在Ribbon的基础上添加了功能,而OpenFeign则是Feign的升级版,可以更好的完成服务调用。

  • Feign进行服务发现:首先引入Feign依赖Spring-cloud-starter-OpenFeign,之后在主类上声明注解@EnableFeignClient,最后编写一个接口用来调用对应的微服务,在该接口上添加@FeignClient(name="xxx"),并且将对应微服务的接口方法重新在该接口中声明一遍,使用@Autowried进行调用即可

Feign是一种声明式的REST客户端,看起来很像RPC(RPC是一种接口调用模式,比如直接调用其他微服务的接口方法),但实际是HTTP请求,并且其采用了基于接口的注解方式进行使用。
在使用Feign进行服务间功能调用时,要注意引入的Feign依赖,引入Feign依赖之后,必须引入Spring-boot-starter-web否则会报错,无法启动微服务,另外,要注意SpringCloud与Feign的版本问题,否则也会出现无法启动的问题。

OpenFeign配置文件YAML

 		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflex-eureka-client</artifactId>
        </dependency>

<!--        踩坑,使用Feign必须要加入web支持,否则会报错-->
		 <dependency>
		     <groupId>org.springframework.boot</groupId>
		     <artifactId>spring-boot-starter-web</artifactId>
		 </dependency>
		

OpenFeign主启动类

@EnableFeignClients
@SpringBootAplitcaion
public class MainApplitcaion{
    public static void main(String[] args){
    	SpringAppliction.run(MainApplitcaion.class,args);
    }
}

OpenFeign业务接口

该接口中定义着其他微服务的方法

@FeignClient(name="微服务名称")
public interface getMessage{
	这里直接将服务提供方的controller粘贴过来就行,不过要接口方式

}

OpenFeign超时控制

Feign因为整合了Ribbon,所以其天生具有Feign的超市控制,在YMAL中定义超时设置。

#配置ribbon超时设置
ribbon:
#  建立连接的时间,默认是一秒钟
  ReadTimeout: 5000
#  建立连接后从服务器读取到可用资源所用的时间
  ConnectTimeout: 5000

OpenFeign日志设置

设置具体Feign的接口路径,就可以设置对应的日志管理

logging:
  level:
#    类路径
    com.atguigu.springcloud.service.PaymentFeignService: debug

SpringCloud Config | SpringCloud Bus

在企业级开发中,我们经常会遇到不同开发团队开发的不同服务,在项目上线或者是平常测试时,对项目的配置进行改变,如我们要将本地的MySQL换成云服务器上的MySQL。这就需要我们将配置文件修改,但是面对众多的微服务,我们又不可能一个一个去修改,并且下线,这样显然是不好的。
在这里插入图片描述
以上图片为我们介绍了SpringCloud Config配置中心的原理,首先,我们将配置文件存放在GIT上,并且通过WebHooks绑定git更新接口,当我们的git进行更新时,会发送请求到server-config配置中心,收到请求时,server会远程拉取仓库中的新配置文件,并且通过MQ将消息发送到各个微服务,从而达到不重启微服务的情况下完成配置文件的更新。

Config服务端配置

引入依赖

首先引入pom依赖,一定要引入spring-boot-starter-web,否则会出现找不到容器的错误,这里引入的是spring-cloud-starter-config-server的依赖,是服务端。

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>

<!--        web-->
        <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>


        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

修改yaml文件

server:
  port: 3344

spring:
  application:
    name: cloud-config-center
  cloud:
    config:
      server:
        git:     这里要注意,要输入当前的git地址
          uri: https://gitee.com/xxxx/springcloud-config.git #github上的git名字
          #搜索目录
          search-paths:
            - springcloud-config
          username: xxxx
          password: xxxx
      label: master
#服务注册到eureka上
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka

开启config功能

在主启动类上添加@EnableConfigServer

@EnableEurekaClient
@EnableConfigServer
@SpringBootApplication
public class configServerMain3344 {

    public static void main(String[] args) {
        SpringApplication.run(configServerMain3344.class,args);
    }
}

配置git文件

在gitEE或者gitHub上新建仓库,在其中添加yml文件
请添加图片描述

按地址访问yaml文件

请添加图片描述
如果访问成功,则说明服务端配置成功。

Config客户端

引入依赖

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

配置YAML(bootstrap.yml)

server:
  port: 3355
spring:
  application:
    name: config-client
  cloud:
    config:
      label: master # 分支名称
      name: config #配置文件名称
      profile: dev # 读取后缀名称
      uri: http://localhost:3344 #配置中心地址


eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka
# 暴露监控端口,方便配置动态更新
management:
  endpoints:
    web:
      exposure:
        include: "*"

配置自动刷新

在需要使用动态刷新的类上加上@RefreshScope,系统会自动强制刷新最新版的配置文件属性,

@RestController
@RefreshScope
public class ConfigClientController {


    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/configInfo")
     public String getConfigInfo(){
        return configInfo;
    }
}
动态刷新Webhook

但是这样还需要外部向该客户端发送一条post请求才能强制刷新
localhost:3355/actuator/refresh
这就需要配置webhook了
webhook在gitee和github上都是在更新文件后,自动向所配置地址发送一条post请求
配置webhook需要一个外网地址映射到本机的localhost(如果实在本机部署的话),这时就可以使用netapp来进行外网穿透

SpringCloud Bus

上面说了如何实现配置更改后的自动刷新,但是对于一个大的微服务分布式集群来说,每次更换配置文件总不能一个一个发送请求,而webhook也可以配置多个,为此,springcloud使用消息总线来进行配置更换后的广播操作,使得每次 在服务端config更新后,将消息推送到各个订阅的微服务中(订阅模式可以很好地解决指定微服务更新配置的操作)。目前springcloud仅支持两种消息总线的配置(Kafka和RabbitMQ)

RabbitMQ安装

docker可以很好的帮助我们安装RabbitMQ,安装docker之后,使用docker命令。

docker search rabbitmq

这时会出现以下的各种镜像,选择最上面的官方镜像,执行命令

docker pull rabbitmq

即可拉取镜像,之后使用Docker Dashboard启动镜像,在浏览器中输入http://localhost:15672,输入账号密码guest即可进入。

请添加图片描述

服务端引入消息总线

在我们的configServer中引入依赖

<!--        添加消息总线RabbitMQ支持-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

配置application.yml文件

注意别放在spring下面
rabbitmq:
  port: 15672
  host: localhost
  password: guest
  username: guest
# RabbitMQ相关配置,暴露bus刷新配置的端点

management:
  endpoints: #暴露bus刷新配置的端点
    web:
      exposure:
        include: 'bus-refresh'

客户端引入消息总线

引入依赖

<!--        添加消息总线RabbitMQ支持-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

配置bootstrap.yml

注意别放在spring下面
rabbitmq:
  port: 15672
  host: localhost
  password: guest
  username: guest

配置完成后,启动所有客户端和服务端,更改git上的文件,之后向服务端发送在yml中配置好的请求(这里是bus-refresh),其他的客户端都会被自动的刷新。如果是单机练习,建议使用git的webhook配和netapp来自动发送请求。 也可以查看rabbitmq是否成功发送信息。
请添加图片描述

实现定点刷新

如果只想通知其中某个微服务改变配置,需要发送指定的POST请求,请求格式为 http://localhost:配置中心的端口号/actuator/bus-refresh/{destination} /bus/refresh请求不再发送到具体的服务实例上,而是发给config server并通过destination参数类指定需要更新配置的服务或实例。
例子:curl -X POST “http://localhost:3344/actuator/bus-refresh/config-client:3355” 只刷新了3355


微服务中的消息传递(SpringCloud Stream)

在微服务中,微服务间传递与接收纤细的方式有同步异步两种,同步方法就如同我们在上面一样,直接去调用其他微服务的接口,用时才调用,但是在一定的情况下,同步会产生一定的等待,而异步可以让我们在该服务A发生变化时就想其他服务B发布信息,等微服务B要调用时,直接消费发布的信息即可,并且再次将信息异步的发送到之前的微服务A。
目前比较使用广泛的消息队列有Kafka、RabbitMQ,通过引入消息队列并且对消息队列进行监听而得到消息。

  • Kafka:Kafka作为一款优秀的消息队列,可以起到在微服务中传递消息,从而实现异步通信的工作。使用Kafka时,我们首先要下载kafka的压缩包,并且解压,之后安装zookeeper,并且通过zookeeper启动kafka,此后在java项目中配置kafka依赖,使用kafka的监听器监听消息队列。
  • RabbitMQ:rabbitMQ作为另外一款优秀的消息队列。这里推荐使用docker版的rabbitMQ,Mac中使用Docker,关于docker如何下载,我另外的博客有提到。在项目中,首先引入MQ的依赖,此外使用@RabbitListener监听器进行启动以及监听消息队列,关于如何启动,可以参照该注解中的参数,这里不再赘述。

作为SpringCloud简化MQ使用过程,Stream支持Kafka与RabbitMQ,使用过程十分简单。
首先将Spring-cloud-starter-stream-rabbit依赖引入,其次,配置一个channel类,用于建立一个channel进行通信,一个channel既可以发送也可以接受,不同种类的channel全部继承自MessageChannel。


服务端配置Stream

引入依赖

首先,引入依赖,如上文所讲,引入Spring-cloud-starter-stream-rabbit

配置yaml文件

server:
  port: 8801
spring:
  application:
    name: cloud-stream-privider
  cloud:
    stream:
      binders: #在此处配置要绑定的rabbitmq的服务信息
        defaultRabbit: #表示定义的名称,用于binding整和
          type: rabbit #设置组件类型
          environment: #设置rabbitmq的相关管径的配置
            spring:
              rabbitmq:
                host: localhost
                port: 5672
                username: guest
                password: guest
      bindings: #服务的整和处理
        output: #这个名字是一个通道的名字
          destination: studyExchange #表示要使用的exchange名称定义
          content-type: application/json #设置消息类型
          binder: defaultRabbit #设置要绑定的消息服务的具体设置
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
  instance:
    lease-expiration-duration-in-seconds: 5 #如果现在超过了5秒的间隔
    lease-renewal-interval-in-seconds: 2 #设置心跳的时间间隔
    instance-id: send-8801.com
    prefer-ip-address: true #访问的路径变为IP地址

这里我踩了一个大坑,rabbitMQ的端口要配成5672,否则会出现无法连接mq而超时的问题,是因为15672是访问mq网页端的端口,而我们要访问客户端的话,必须使用5672。。。

编写通信service

编写接口

public interface SenderService {

    public String send();
}

编写实现类

package com.atguigu.springcloud.service.impl;

import com.atguigu.springcloud.service.SenderService;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;

import javax.annotation.Resource;
import java.util.UUID;

@EnableBinding(Source.class) 注意这里的Source引的是什么包
public class SenderServiceImpl implements SenderService {

    @Resource
    private MessageChannel output;

    @Override
    public String send() {
        String serial = UUID.randomUUID().toString();
        output.send(MessageBuilder.withPayload(serial).build());
        return null;
    }
}

调用该方法即可向配置文件中配置的的topic发送消息。

客户端配置Stream

首先,引入stream的包,同上一样

到这里,SpringCloud对于Channel的使用已经结束了,如果微服务是多实例部署的话,想让多实例共享一个消息队列,则需要配置配置文件。

配置yml文件

server:
  port: 8802
spring:
  application:
    name: cloud-stream-privider
  cloud:
    stream:
      binders:   #自此处配置要绑定的rabbitmq的服务信息
        defaultRabbit: #表示定义的名称,用于binding整合
          type: rabbit #消息组件类型
          environment:  # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
                host: localhost
                port: 5672
                username: guest
                password: guest
      bindings:   #服务的整合处理
        input: #这个名字是一个通道的名称
          destination: studyExchange #表示要使用的exchange名称定义
          content-type: application/json #设置消息类型,本次为json
          binder: defaultRabbit  #设置要绑定的消息服务的具体设置
          group: atguiguA
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
  instance:
    lease-expiration-duration-in-seconds: 5 #如果现在超过了5秒的间隔
    lease-renewal-interval-in-seconds: 2 #设置心跳的时间间隔
    instance-id: send-8802.com
    prefer-ip-address: true #访问的路径变为IP地址

消息接收类

@Component
@EnableBinding(Sink.class)
public class StreamConsumeController {


    @Value("${server.port}")
    private String serverPort;

    @StreamListener(Sink.INPUT)
    public void input(Message<String> message){
        System.out.println("我是消费者1号,-----》接受到的消息是:"+message.getPayload()+"\t"+serverPort);
    }
}

分组消费与持久化

分组消费

注意在stream中,一个group中的多个消费者是竞争关系,消息只能被一个消费者消费。不同的group可以重复消费。
而我们不配置组的话,会默认认为是不同的组。
如果当前消费端挂了,但是它还在这个组中,当他在重启过程中,生产端一直在发消息,当服务重新启动后,该消费者会自动消费刚才错过的消息,所以分组是一个非常重要的事情。


SpringCloud Zuul

Zuul在SpringCloud Gateway出现之后已经基本不再更新,而Zuul2目前Spring官方也没有纳入Spring体系,未来更多的是Gateway
zuul作为SpringCloud一站式微服务的网关,负责代理以及分发请求,提供负载均衡,让用户感受不到微服务的存在,通过访问网关定义的端口来访问各个微服务,网关服务如同web项目中的过滤器一般,可以在请求发起前、返回响应后、请求出错时进行处理。
SpringCloud Zuul使用时同样要配置SpringCloud Config(所有的微服务除了Eureka,都需要配置在Config中,为了解决热部署配置文件的问题),并且要引入Zuul的依赖spring-cloud-starter-netflix-zuul,在主类声明@EnableZuulProxy,之后就可以根据需求进行请求的拦截,分发。
SpringCloud Zuul解决跨域问题,由于浏览器的同源策略,在进行前后端分离的项目时必须要进行跨域处理,而Zuul为我们提供了简便的方案。

@Configuration
public class CorsConfig {


    @Bean
    public CorsFilter corsFilter(){
        final UrlBasedCorsConfigurationSource source =
                new UrlBasedCorsConfigurationSource();
        final CorsConfiguration conf = new CorsConfiguration();

        conf.setAllowCredentials(true);
        conf.setAllowedOrigins(Arrays.asList("*"));
        conf.setAllowedHeaders(Arrays.asList("*"));
        conf.setAllowedMethods(Arrays.asList("*"));
        conf.setMaxAge(300l);

        source.registerCorsConfiguration("/**",conf);

        return new CorsFilter(source);
    }
}


SpringCloud Hystrix

Hystrix已经进入了维护状态,不再更新以及合并新内容

服务降级

SpringCloud Hystrix(豪猪)是SpringCloud家族中的保护措施,也就是进行服务降级,当我们的微服务在进行层层调用时,如果某一层微服务出现了故障,很有可能就会造成级联雪崩效应,而Hystrix可以对微服务进行服务降级用来保护微服务,可以在出现错误时执行预先设定好的对应函数,或者在fallbackMethod中实现对应的处理措施。

哪些情况会触发降级

  • 程序运行异常
  • 超时
  • 服务熔断出发服务降级
  • 线程池/信号量也会导致服务降级(Tomcat线程池就是一个好例子)

Pom配置

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

YAML文件配置

在定义了Zuul网关的微服务中,我们可以同样在yml配置文件中直接设置Hystrix的HystrixCommand属性,定义其超时时间等。

重点:在Feign中开启Hystrix要在配置文件中写 feign.hystrix.enabled: true

PS:这里记录一下网关启动的一个坑,在我们启动微服务时,如果该微服务是第一次启动,系统会以懒汉模式进行启动,就是直到第一次访问才去加载对应的类,如果这时访问该微服务的时间超过了默认Hystrix的时间设置,就会报错(Zuul里集成了Hystrix),这时只要在配置文件中设置一下超时时间即可解决。

feign:
  hystrix:
    enabled: true

启动类配置

@SpringBootApplication
@EnableEurekaClient
//@EnableCircuitBreaker
@EnableHystrix
public class HistrixPaymentMain8001 {
   两个注解都是启用Hystrix的作用,下面的覆盖了上面的
    public static void main(String[] args) {
        SpringApplication.run(HistrixPaymentMain8001.class,args);
    }
}

单独使用

使用:首先在pom文件中加入Hystrix依赖spring-cloud-starter-netflix-hystrix,在要使用Hystrix的地方声明一个方法,并且在方法上添加@HystrixCommand注解,当该方法中发生异常或者是违反了HystrixCommand定义的一些参数配置时(如超过HystrixCommand定义的默认时间),就会发生服务降级,此刻,就会使用预先定义的策略来向外界发送反馈(如同线程池的拒绝策略一样,可以自定义)。

@RestController
@DefaultProperties(defaultFallback = "defaultFallback")
这里是指定降级方法,再最上面说明整个类的都需要这个方法去处理
public class HystrixController {

	这个注解说明要开启Hystrix
	@HystrixCommand
	@GetMapping("/getProductInfoList")
	public String getProductInfoList(@RequestParam("number") Integer number) {
		if (number % 2 == 0) {
			throw new RuntimeException("发送异常了");
//			return "success";

		}
		RestTemplate restTemplate = new RestTemplate();
		return restTemplate.postForObject("http://127.0.0.1:8081/product/listForOrder",
				Arrays.asList("157875196366160022"),
				String.class);

		}
	private String defaultFallback() {
		return "默认提示:太拥挤了, 请稍后再试~~";
	}
}

解耦合实现Hystrix

同样,hystrix已经集成在了Feign和Zuul的依赖包中,在添加了这两种依赖的微服务中,可以直接使用Hystrix。

package com.imooc.product.client;

import com.imooc.product.common.DecreaseStockInput;
import com.imooc.product.common.ProductInfoOutput;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;

@FeignClient(name = "product",fallback = ProductClient.ProductClientClientFallback.class)
public interface ProductClient {

    @PostMapping("/product/listForOrder")
    List<ProductInfoOutput> listForOrder(@RequestBody List<String> productIdList);

    @PostMapping("/product/decreaseStock")
    void decreaseStock(@RequestBody List<DecreaseStockInput> decreaseStockInputList);


    @Component
    static class ProductClientClientFallback implements ProductClient{

        @Override
        public List<ProductInfoOutput> listForOrder(List<String> productIdList) {
            return null;
        }

        @Override
        public void decreaseStock(List<DecreaseStockInput> decreaseStockInputList) {

        }
    }
}

以上定义了该微服务对其他微服务调用的接口,使用了Feign,此时只需要在@FeignClient注解中加上用于进行服务降级处理的类即可,该类继承自可能出现服务降级的接口,继承的方法就是该方法出问题时的应对策略。

服务限流

Sentinel中说明

服务熔断

在我们的服务访问达到了最大阈值的时候,如果此时再发送请求,就会导致失败,而服务熔断就是为了解决该问题,当请求达到阈值,服务会进行熔断处于关闭状态;当一定时间后,服务会尝试放过一些请求,当该请求成功后,服务此时切换到半开状态;再过一定时间,服务恢复到完全打开状态(就像是具有自动修复功能一样)。

 @HystrixCommand(fallbackMethod = "timeoutHandler",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000")  //超时设置5秒
            @HystrixProperty(name = "circuitBreaker.enabled",value = "true"), //是否开启断路器 
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"), //请求次数 
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), //时间窗口期 
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),//失败率达到多少后跳闸
    })
    @RequestMapping("/payment/hystrix/timeout/{id}")
    public String getFliedTimeout(@PathVariable("id") Integer id){
        String result = consumerService.getFliedTimeout(id);
        log.info("****result: " + result);
        return result;
    }

熔断类型

  • 熔断打开——请求不再调用当前服务,内部设置一般为MTTR(平均故障处理时间),当打开时间达到设置时钟是进入半开状态
  • 熔断关闭——熔断后不再进行请求阻挡
  • 熔断半开——请求访问当前服务,如果成功且服务断路器规定的规则,则服务恢复正常——达到完全关闭状态

断路器开启或者关闭条件

  1. 当满足一定阈值的时候(默认10秒超过20个请求)
  2. 当失败率达到一定的比例
  3. 到达以上阈值的时候
  4. 开启时,所有请求都不会进行转发
  5. 一段时间后(默认5秒),这个时候断路器是半开状态,会让其他的请求尝试进行转发,成功,断路器关闭,失败,继续开启断路器,重复4和5。

HystrixDashboard 监控中心

建Moudle

改Pom

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>

配置YAML

server:
	port: 9001

启动类

@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardMain9001{
	public static void main(String[] args){
		SpringApplication.run(HystrixDashboardMain9001.class,args);
	}
}

微服务提供类

所有要进行跟踪的微服务都需要添加actuator监控依赖以及打开@EnableHystrix

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

服务追踪(链路监控)

SpringCloud集成sleuth,通过可视化界面Zipkin进行服务追踪,在各个微服务组合完成全部任务时,有时我们需要了解各个微服务的运行状况,运行时间,Sleuth可以帮我们完成这项工作。
首先引入依赖spring-cloud-starter-zipkin,该依赖包含了Zipkin以及Sleuth的全部依赖。
其次配置配置文件,在配置文件中,我们要配置Zipkin的地址,以及日志以什么方式发送到zipkin,配置发送日志的多少到zinkin。

spring:
  zipkin:
    base-url: http://localhost:9411/
    sender:
      type: web
  sleuth:
    sampler:
      probability: 1
logging:
  level:
    org.springframework.cloud.openfeign: debug
    #这里是要追踪服务的包名以及要打印日志的slave(级别)

最后,下载Zipkin进入https://zipkin.io/即可。
在这里插入图片描述
打开Zipkin就可以看到了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值