写点什么

肝了很久,冰河整理出这份 4 万字的 SpringCloud 与 SpringCloudAlibaba 学习笔记!!

用户头像
冰河
关注
发布于: 2021 年 03 月 02 日
肝了很久,冰河整理出这份4万字的SpringCloud与SpringCloudAlibaba学习笔记!!

写在前面


不少小伙伴让我整理下有关 SpringCloud 和 SpringCloudAlibaba 的知识点,经过 3 天的收集和整理,冰河整理出这份 4 万字的 SpringCloud 与 SpringCloudAlibaba 学习笔记!!


文章已收录到:


https://github.com/sunshinelyz/technology-binghe


https://gitee.com/binghe001/technology-binghe


SpringCloud


服务注册中心


eureka


ap 高可用 分布式容错


<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency><dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>eureka:  instance:    hostname: eureka7003.com #eureka服务端的实例名称    instance-id: payment8001     prefer-ip-address: true  client:    register-with-eureka: false     #false表示不向注册中心注册自己。    fetch-registry: false     #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务    service-url:      #集群指向其它eureka      #defaultZone: http://eureka7002.com:7002/eureka/      #单机就是7001自己      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/    #server:    #关闭自我保护机制,保证不可用服务被及时踢除    #enable-self-preservation: false    #eviction-interval-timer-in-ms: 2000
复制代码


Ribbon 启用负载均衡


@EnableEurekaServer@EnableDiscoveryClient
@LoadBalancedpublic RestTemplate getTemp() { return new RestTemplate();}
复制代码


zookepper


cp 强一致 分布式容错


<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>    <exclusions>        <exclusion>            <groupId>org.apache.zookeeper</groupId>            <artifactId>zookeeper</artifactId>        </exclusion>    </exclusions></dependency><dependency>    <groupId>org.apache.zookeeper</groupId>    <artifactId>zookeeper</artifactId>    <version>3.6.1</version></dependency>spring:  application:    name: cloud-zoo-consumer-order  cloud:    zookeeper:      connect-string: 192.168.10.58:2181@SpringBootApplication@EnableDiscoveryClient
复制代码


consul


cp 强一致 分布式容错


<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-consul-discovery</artifactId></dependency>spring:  application:    name: consul-payment-provider  cloud:    consul:      host: 192.168.10.58      port: 8500      discovery:        service-name: ${spring.application.name}@SpringBootApplication@EnableDiscoveryClient
复制代码


服务调用负载均衡


Ribbon


Ribbon 切换 负载规则


  1. 在 springboot 包扫描外层建立 配置


@Configurationpublic class Myrule {    @Bean    public IRule initRule() {        return new RandomRule();    }}
复制代码


  1. 启动类给指定服务加载随机方法


@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = Myrule.class)
复制代码


OpenFeign


  1. 添加 maven 依赖


<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
复制代码


  1. 启动类启用 Feign


@SpringBootApplication@EnableEurekaClient@EnableDiscoveryClient@EnableFeignClients
复制代码


  1. 新建接口 并注册 Feign 信息


@Component@FeignClient(value = "CLOUD-PAYMENT-SERVICE")  //提供方服务名public interface Service {    @GetMapping(value = "/payment/get/{id}")    Response<Payment> getPaymentById(@PathVariable("id") Long id);}
复制代码


  1. 提供方接口演示


@GetMapping(value = "/payment/get/{id}")public Response<Payment> getPaymentById(@PathVariable("id") Long id) {    Payment payment = paymentService.getPaymentById(id);
if (payment != null) { return Result.success(200, "查询成功,serverPort: " + serverPort, payment); } else { return Result.success(444, "没有对应记录,查询ID: " + id, null); }}
复制代码


OpenFeign 超时设置


ribbon:#指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间  ReadTimeout: 5000#指的是建立连接后从服务器读取到可用资源所用的时间  ConnectTimeout: 5000
复制代码


OpenFeign 日志打印功能


  1. 配置 Openfeign 日志级别


@Configurationpublic class FeignLogConfig {    @Bean    public Logger.Level getLevel() {        return Logger.Level.FULL;    }}
复制代码


  1. yml 项目配置文件中,给指定 Feign interface 配置日志级别


logging:  level:    ml.ytooo.feignservice.Service: debug
复制代码


Hystrix 服务治理


  • 服务降级 出险异常时,返回友好提示,防止程序异常或者阻塞

  • 服务熔断 保险丝,当超出服务承载能力时,返回提示,拒绝请求

  • 服务限流 闸门,配置服务承载能力


Hystrix


服务降级


当服务处理超时或者运行异常时,启动备选方案返回给调用者预期结果


主方法


@EnableCircuitBreaker
复制代码


需要降级处理的程序


其中


  • paymentInfo_TimeOut 为预计超时程序

  • paymentInfoTimeOutHandler 为超时备选方案


@HystrixCommand(fallbackMethod = "paymentInfo_TimeOut_Handler", commandProperties = {            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")})public String paymentInfo_TimeOut(Integer id) {
int time = 5; try { TimeUnit.MILLISECONDS.sleep(time * 1000); } catch (InterruptedException e) { e.printStackTrace(); } return "线程池: " + Thread.currentThread().getName() + " paymentInfo_TimeOut,id: " + id + "\t" + "O(∩_∩)O哈哈~" + " 耗时(秒): " + time;}
public String paymentInfo_TimeOut_Handler(Integer id) { return "线程池: " + Thread.currentThread().getName() + " paymentInfo_TimeOut_Handler,id: " + id + "\t" + "o(╥﹏╥)o";}
复制代码


全局降级处理


配置 defaultFallback 的走自己的降级方法,未配置的走 默认 @DefaultProperties 指定的降级方法


@RestController@Slf4j@DefaultProperties(defaultFallback = "globle",commandProperties = {        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")})public class Controller {    @HystrixCommand    @GetMapping("/timeout/{id}")    public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {        String result = feignService.paymentInfo_TimeOut(id);        log.info("*****result: " + result);        return result;    }    public String globle() {        return "全局";    }}
复制代码


通过 OpenFeign 配置其提供方全局降级配置


  1. 新增 feign 调用接口的实现类 FeignServiceImpl,实现全部方法并做降级处理


@Servicepublic class FeignServiceImpl implements FeignService {    @Override    public String paymentInfo_OK(Integer id) {        return "降级 -- paymentInfo_OK";    }    @Override    public String paymentInfo_TimeOut(Integer id) {        return "降级 -- paymentInfo_TimeOut";    }}
复制代码


  1. feign 调用接口添加注解


@FeignClient(value = "CLOUD-PROVIDER-HYSTYRIX-PAYMENT",fallback = FeignServiceImpl.class)
复制代码


服务熔断


  • 服务过载时,拒绝连接请求直接调用降级方法,返回异常

  • 请求下降时,慢慢恢复该服务访问,直达完全恢复


配置服务的熔断:


一下配置在 10s 内 ,10 次请求有 60% 失败,则熔断


HystrixProperty 配置位于 HystrixCommandProperties.class 类中


//=====服务熔断@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = { //        @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),// 是否开启断路器        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),// 请求次数        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 时间窗口期        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),// 失败率达到多少百分百后跳闸})public String paymentCircuitBreaker(@PathVariable("id") Integer id){    if(id < 0)    {        throw new RuntimeException("******id 不能负数");    }    String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName()+"\t"+"调用成功,流水号: " + serialNumber;}public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) //熔断后降级方法{ return "id 不能负数,请稍后再试,/(ㄒoㄒ)/~~ id: " +id;}
复制代码


效果: 当连续使用 -100 请求时, 返回 "id 不能负数", 使用 100 请求也返回 "id 不能负数" ,继续连续使用 100 请求, 服务慢慢恢复


服务限流


使用 springcloud 阿里巴巴 sentinel 替代


Gateway 网关


Gateway


Gateway 项目配置


  1. 添加 maven 依赖


<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-gateway</artifactId></dependency>
复制代码


  1. 移除以下依赖


<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>
复制代码


  1. yml 配置 (后续移步配置中心)


spring:  application:    name: cloud-gateaway-gateaway  cloud:    gateway:      discovery:        locator:          enabled: true      routes:        - id: payment_get        #   uri: http://127.0.0.1:8001    #单一节点          uri : lb://CLOUD-PAYMENT-SERVICE  /#启用 注册中心集群          predicates:            - Path=/payment/get/**
复制代码


  1. 注册进 Eureka 注册中心


Gateway 动态路由


  1. 开启 网关发现注册中心服务


spring:  application:    name: cloud-gateaway-gateaway  cloud:    gateway:      discovery:        locator:          enabled: true
复制代码


Gateway 断言


断言是判断转发请求的条件


predicates: - After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]
复制代码


  1. After,Before,Between 配置转发生效时间


public static void main(String[] args) {    ZonedDateTime now = ZonedDateTime.now();    System.out.println(now);}// 2020-08-24T14:23:57.171+08:00[Asia/Shanghai]
复制代码


  1. Cookie 请求需携带指定 Cookie 才可以访问


predicates:  - Cookie=name,ytooo   # key,value
复制代码


  1. Header ≈ Cookie


predicates:  - Header=name,ytooo   # key,value
复制代码


Gateway 过滤器


  1. (默认过滤器) 官方提供一系列过滤器,供我们 在请求转发之前,对请求进行加工处理


filters:  - AddRequestParamter=rowid,1024
复制代码


  1. 自定义过滤器


自定义全局过滤器


@Component@Slf4jpublic class GatewayLogFilter implements GlobalFilter, Ordered {
@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("=====================进入全局过滤器====================="); String name = exchange.getRequest().getQueryParams().getFirst("name"); if (null == name) { exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN); return exchange.getResponse().setComplete(); } return chain.filter(exchange); }
@Override public int getOrder() { return 0; }}
复制代码


SpringCloud Config 分布式配置中心, BUS 消息总线


分布式配置中心 SpringCloud Config


服务端配置


  1. 建立 git 仓库 https://github.com/sunshinelyz/cloud-config

  2. 引入 maven


<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-config-server</artifactId></dependency>
复制代码


3.启动类使配置生效


@SpringBootApplication@EnableEurekaClient@EnableConfigServerpublic class ConfigMain3344 {    public static void main(String[] args) {        SpringApplication.run(ConfigMain3344.class, args);    }}
复制代码


  1. 配置 配置文件


spring:  application:    name: cloud-config-center  cloud:    config:      server:        git:          uri: https://github.com/sunshinelyz/cloud-config          search-paths:            - cloud-config      label: master
复制代码


  1. 请求访问 : http://127.0.0.1:3344/master/config-dev.yml


客户端配置


  1. 引入 maven


<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-config-client</artifactId></dependency>
复制代码


  1. 配置 配置文件


spring:  application:    name: cloud-condig-client  cloud:    config:      label: master  # 分支      name: config # 配置文件名称      profile: dev   # 版本      uri: http://127.0.0.1:3344 # config服务端地址
复制代码


手动刷新客户端配置


不建议使用


消息总线 Bus


设计逻辑


使用消息总线触发服务端的 bus/refresh 端点,刷新所有客户端 config 配置


初始条件


客户端,服务端都需要实现 Springcloud Config 功能


服务端配置


  1. 引入 maven 依赖


<dependency>  <groupId>org.springframework.cloud</groupId>  <artifactId>spring-cloud-starter-bus-amqp</artifactId></dependency>
复制代码


  1. 配置文件中配置消息队列信息


# 配置消息队列rabbitmq:  host: 192.168.10.58  port: 5672  username: ytooo  password: ytooo
复制代码


  1. 配置文件中配置 BUS 总线暴露信息


# 配置bus暴露端点management:  endpoints:    web:      exposure:        include: "bus-refresh"
复制代码


  1. 配置文件预览


server:  port: 3344spring:  application:    name: cloud-config-center  cloud:    config:      server:        git:          uri: https://github.com/sunshinelyz/cloud-config          search-paths:            - cloud-config      label: master  # 配置消息队列  rabbitmq:    host: 192.168.10.58    port: 5672    username: ytooo    password: ytoooeureka:  instance:    prefer-ip-address: true    instance-id: cloud-config-center-3344  client:    fetch-registry: true    register-with-eureka: true    service-url:      defaultZone: http://eureka7001.com:7001/eureka/ #,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/# 配置bus暴露端点management:  endpoints:    web:      exposure:        include: "bus-refresh"
复制代码


客户端配置


  1. 引入 maven 依赖


<dependency>  <groupId>org.springframework.cloud</groupId>  <artifactId>spring-cloud-starter-bus-amqp</artifactId></dependency>
复制代码


  1. 配置文件中配置消息队列信息


# 配置消息队列rabbitmq:  host: 192.168.10.58  port: 5672  username: ytooo  password: ytooo
复制代码


  1. 配置暴露端点


# 配置暴露端点management:  endpoints:    web:      exposure:        include: "*"
复制代码


  1. 调用配置类添加 @RefreshScope


@RestController@RefreshScopepublic class Controller {    @Value("${config.info}")    private String configInfo;    @GetMapping(value = "/test")    public String test() {        return configInfo;    }}
复制代码


刷新配置


POST 请求 config 服务端 http://127.0.0.1:3344/actuator/bus-refresh


刷新成功


定点通知


POST 请求 config 服务端 http://127.0.0.1:3344/actuator/bus-refresh/{destination}


destination: 注册中心服务名称:端口号


🌰: http://127.0.0.1:3344/actuator/bus-refresh/cloud-condig-client:3366


SpringCloud Stream 消息驱动


消息驱动,统一各种消息中间件中的差异,提供统一简单的调用方式,屏蔽消息中间件具体调用实现


SpringCloud Stream 消息提供者项目配置 (简单使用)


  1. 添加 maven 依赖


<dependency>  <groupId>org.springframework.cloud</groupId>  <artifactId>spring-cloud-starter-stream-rabbit</artifactId></dependency>
复制代码


  1. 配置文件添加 Stream 配置


spring:  application:    name: cloud-stream-provider  cloud:    stream:      binders: # 在此处配置要绑定的rabbitmq的服务信息;        defaultRabbit: # 表示定义的名称,用于于binding整合          type: rabbit # 消息组件类型          environment: # 设置rabbitmq的相关的环境配置            spring:              rabbitmq:                host: 192.168.10.58                port: 5672                username: ytooo                password: ytooo      bindings: # 服务的整合处理        output: # 这个名字是一个通道的名称          destination: studyExchange # 表示要使用的Exchange名称定义          content-type: application/json # 设置消息类型,本次为json,文本则设置“text/plain”          binder: defaultRabbit # 设置要绑定的消息服务的具体设置
复制代码


  1. 定义消息推送管道


@EnableBinding(Source.class) //定义消息推送管道public class MsgProviderImpl implements MsgProvider {}
复制代码


  1. 定义消息发送管道


@Autowiredprivate MessageChannel out; //定义消息发送管道
复制代码


  1. build 消息实体并发送


Message<String> message = MessageBuilder.withPayload(msg).build();out.send(message);
复制代码


  1. 消息接收方 yml 配置


spring:  application:    name: cloud-stream-rabbitmq-consumer  cloud:    stream:      binders: # 在此处配置要绑定的rabbitmq的服务信息;        defaultRabbit: # 表示定义的名称,用于于binding整合          type: rabbit # 消息组件类型          environment: # 设置rabbitmq的相关的环境配置            spring:              rabbitmq:                host: 192.168.10.58                port: 5672                username: ytooo                password: ytooo      bindings: # 服务的整合处理        input: # 这个名字是一个通道的名称                                             destination: studyExchange # 表示要使用的Exchange名称定义       需与提供方相同          content-type: application/json # 设置消息类型,本次为json,文本则设置“text/plain”          binder: defaultRabbit # 设置要绑定的消息服务的具体设置
复制代码


  1. 接收方监听接口配置


@EnableBinding(Sink.class)public class ReceiveMsgImpl implements ReceiveMsg {}
复制代码


  1. 接收方注解


@StreamListener(Sink.INPUT)public void receive(Message<String> message) {    System.out.println("客服端8803收到消息: " + message.getPayload());}
复制代码


SpringCloud Stream 分组消费 & 持久化


  • 对于不同的组中,消息是会被重复消费的(重复消费)

  • 同一个组内,服务之间存在竞争关系,只被消费一次(集群环境,避免重复消费)


分组配置文件配置


bindings: # 服务的整合处理  input: # 这个名字是一个通道的名称    destination: studyExchange # 表示要使用的Exchange名称定义    content-type: application/json # 设置消息类型,本次为json,文本则设置“text/plain”    binder: defaultRabbit # 设置要绑定的消息服务的具体设置    group: ytooo           #  配置接收方所在组
复制代码


group 分组 持久化


当不配置分组时,重启服务,不会自动获取之前未消费的服务

反之,配置了分组,启动时,自动获取之前未消费的消息


Sleuth 分布式请求链路跟踪


在服务中加上依赖


<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-zipkin</artifactId></dependency>
复制代码


修改 application.yml 配置文件,添加以下内容


spring:    zipkin:    base-url: http://localhost:9411  sleuth:    sampler:      probability: 1 # 采样率值介于0~1之间,1表示全部采集
复制代码


SpringCloud Alibaba


Nacos 注册中心


添加依赖


<dependency>  <groupId>com.alibaba.cloud</groupId>  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
复制代码


项目配置文件


spring:  application:    name: cloudalibaba-nacos-consumer-order  cloud:    nacos:      discovery:        server-addr: 192.168.10.58:8848
复制代码


主程序启动


@EnableDiscoveryClient
复制代码


结合 Openfeign 调用 服务


Nacos config 配置中心


  1. 添加 maven 依赖


<dependency>  <groupId>com.alibaba.cloud</groupId>  <artifactId>spring-cloud-alibaba-nacos-config</artifactId></dependency>
复制代码


  1. bootstrap.yml 中添加 配置中心相关配置


spring:  application:    name: cloudalibaba-nacos-config-cclient  cloud:    nacos:      discovery:        server-addr: 192.168.10.58:8848      config:        server-addr: 192.168.10.58:8848        file-extension: yaml  profiles:    active: dev
复制代码


  1. 业务类 添加 @RefreshScope 来自动刷新


@RestController@RefreshScopepublic class Controller {
复制代码


  1. 配置文件中配置格式


在 Nacos Spring Cloud 中,dataId 的完整格式如下:


prefix−{prefix}-prefix−{spring.profiles.active}.${file-extension}


  • prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix 来配置。

  • spring.profiles.active 即为当前环境对应的 profile,详情可以参考 Spring Boot 文档。 注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 prefix.{prefix}.prefix.{file-extension}

  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型。


本实例中文件名称应为: cloudalibaba-nacos-config-cclient-dev.yaml


Nacos config 配置中心 分类配置


Nacos 使用 3 层来隔离服务


  • NameSpace 命名空间,默认 public

  • Group 组, 默认 DEFAULT_GROUP

  • Service 微服务, 一个 Service 可以包含多个 Cluster 集群,默认 Cluster 为 DEFAULT 可以用了区分地域,来做地域容灾


yml 中配置分组信息 group ,和命名空间 namespace


spring:  application:    name: cloudalibaba-nacos-config-cclient  cloud:    nacos:      discovery:        server-addr: 192.168.10.58:8848      config:        server-addr: 192.168.10.58:8848        file-extension: yaml        group: dev        namespace: a2438b02-01e1-4a3c-959c-600d93183d22 # 使用命名空间ID
复制代码


Sentinel 服务熔断与降级


  • 单独的组件

  • 可以界面化,细粒度统一配置


Sentinel 服务被管方 配置


  1. maven 依赖


<dependency>  <groupId>com.alibaba.csp</groupId>  <artifactId>sentinel-datasource-nacos</artifactId>   <!-- Sentinel持久化 --></dependency><dependency>  <groupId>com.alibaba.cloud</groupId>  <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>
复制代码


  1. yml 中配置 sentinel dashboard 监控


spring:  application:    name: cloudalibaba-sentinel-service  cloud:    nacos:      discovery:        server-addr: 192.168.10.58:8848    sentinel:      transport:        dashboard: 192.168.10.58:8888 # sentinel dashboard 地址
复制代码


配置降级方法: 此方法只针对页面中配置的指定 降级限流热点等方法


@GetMapping(value = "/hot")@SentinelResource(value = "hot", blockHandler = "deal_hot")public String hot(String p1, String p2) {    return "========================== 热点通过 ==========================";}
public String deal_hot(String p1, String p2, BlockException e) { return "========================== 热点降级 ==========================";}
复制代码


seata 分布式事务


  • 全局事务 id

  • TC 事务协调者 维护全局和分支事务状态,驱动全局事务的提交或回滚

  • TM 事务管理器 定义全局事务的范围,开始全局事务.提交或回滚全局事务

  • RM 资源管理器 管理分支事务处理的资源,与 TC 交谈来注册分支事务和报告分支事务的状态,并驱动分支事务的提交或回滚


好了,今天就到这儿吧,我是冰河,大家有啥问题可以在下方留言,也可以加我微信:sun_shine_lyz,关注[冰河技术]微信公众号,我拉你进群,一起交流技术,一起进阶,一起牛逼~~


发布于: 2021 年 03 月 02 日阅读数: 27
用户头像

冰河

关注

公众号:冰河技术 2020.05.29 加入

Mykit系列开源框架发起者、核心架构师和开发者,《海量数据处理与大数据技术实战》与《MySQL开发、优化与运维实战》作者。【冰河技术】微信公众号作者。

评论

发布
暂无评论
肝了很久,冰河整理出这份4万字的SpringCloud与SpringCloudAlibaba学习笔记!!