Spring Cloud Alibaba笔记

😀😀😀创作不易,各位看官点赞收藏.

文章目录

  • Spring Cloud Alibaba 笔记
    • 1、Nacos 服务注册和配置中心
      • 1.1、Nacos 之下载启动
      • 1.2、Nacos 之注册中心
      • 1.3、Nacos 之服务发现
      • 1.4、Nacos 之配置中心
      • 1.5、Nacos 之分类配置
      • 1.6、Nacos 之集群配置
        • 1.6.1、Nacos 之持久化配置
        • 1.6.2、Nacos 之集群配置
    • 2、Sentinel 熔断与限流
      • 2.1、Sentinel 之基本使用
      • 2.2、Sentinel 之流量监控
      • 2.3、Sentinel 之服务降级
      • 2.4、Sentinel 之热点限流
      • 2.5、Sentinel 之系统规则
      • 2.6、Sentinel 之`@SentinelResource`注解
    • 3、 OpenFeign 远程服务调用
      • 3.1、Openfeign 之基本使用
      • 3.2、Openfeign 之超时控制
      • 3.3、Openfeign 之异常处理
    • 4、Gateway 服务网关
      • 4.1、Gateway 之网关简介
      • 4.2、Gateway 之配置路由
      • 4.3、Gateway 之配置断言
      • 4.4、Gateway 之配置过滤器

Spring Cloud Alibaba 笔记

Spring Cloud Alibaba 旨在为微服务开发提供一站式解决方案。该项目包括开发分布式应用程序和服务所需的组件,以便开发人员可以使用 Spring Cloud 编程模型轻松开发分布式应用程序。

使用Spring Cloud Alibaba,您只需添加一些注解和配置,您的应用程序就可以使用阿里巴巴的分布式解决方案,并通过阿里巴巴中间件构建您自己的分布式系统。

Spring Cloud 阿里巴巴的特点:

  1. 流量控制和服务降级:支持WebServlet、WebFlux、OpenFeign、RestTemplate、Dubbo接入限流降级功能。可以在运行时通过控制台实时修改限流和降流规则,还支持对限流和降流Metrics的监控。
  2. 服务注册和发现:可以注册服务,客户端可以使用 Spring 管理的 bean,自动集成 Ribbon 发现实例。
  3. 分布式配置:支持分布式系统的外部化配置,配置变化时自动刷新。
  4. Rpc Service:扩展 Spring Cloud 客户端 RestTemplate 和 OpenFeign 以支持调用 Dubbo RPC 服务。
  5. 事件驱动:支持构建与共享消息系统连接的高度可扩展的事件驱动微服务。
  6. 分布式事务:支持高性能、易用的分布式事务解决方案。
  7. 阿里云对象存储:海量、安全、低成本、高可靠的云存储服务。支持随时随地在任何应用程序中存储和访问任何类型的数据。
  8. 阿里云SchedulerX:精准、高可靠、高可用的定时作业调度服务,响应时间秒级。
  9. 阿里云短信:覆盖全球的短信服务,阿里短信提供便捷、高效、智能的通信能力,帮助企业快速联系客户。

1、Nacos 服务注册和配置中心

Nacos: 是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。

Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。

Nacos官网:https://nacos.io/zh-cn/index.html

1.1、Nacos 之下载启动

​ 安装方式有很多,可以去github上去下载对应的压缩包,但是下载慢。也可以去gitee上去找一个别人fork下源码,然后通过maven自己打包(要确定自己电脑上有Java环境和Maven环境)。

git clone https://github.com/alibaba/nacos.git
cd nacos/
# 打包命令
mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U  # 进入到这个文件下,会发现打包好的文件
cd distribution/target/nacos-server-$version/nacos/bin

image-20221012215510643

Windows启动方式:

# 启动命令(standalone代表着单机模式运行,非集群模式):
startup.cmd -m standalone

image-20221012215845577

image-20221012220037926

注意:启动目录路劲不能包含中文,启动后就可以访问:127.0.0.1:8848/nacos/index.html,出现下面的页面就是启动成功了。

image-20221012220231874

Linux启动:

# Linux/Unix/Mac
sh startup.sh -m standalone 
# ubuntu系统
bash startup.sh -m standalone

1.2、Nacos 之注册中心

父spring-cloudalibaba的pom引入依赖:

<dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2021.0.4.0</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>

本地引入nacos的pom依赖:

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

编写yaml文件:

server:port: 8081spring:application:name:  pay-application-01 # 注册名称cloud:nacos:server-addr: 127.0.0.1:8848 # 注册地址management:endpoints:web:exposure:include: '*'

主启动类:

@SpringBootApplication
@EnableDiscoveryClient // 开启服务发现
public class PayApplication01 {public static void main(String[] args) {SpringApplication.run(PayApplication01.class,args);}
}

启动服务并注册到Nacos中:

image-20221101145044875

1.3、Nacos 之服务发现

​ nacos可以进行服务的调用,也可以自己进行负载均衡。将服务消费者注册到nacos中,并使用RestTemplate进行服务调用。

yaml文件编写:

server:port: 80# 服务消费者
spring:application:name:  consumer-application # 注册名称cloud:nacos:server-addr: 127.0.0.1:8848 # 注册地址# 消费者将要访问的微服务名称
service-url:nacos-pay-service-name: pay-application-01

由于Spring Cloud2020.0.1.0之后不再使用netflix,所以不使用Ribbon做负载均衡,采用下面方式进行服务调用。

我们使用LoadBalancerClient作为负载均衡,首先引入依赖。

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
@RestController
public class TestController {@Resourceprivate RestTemplate restTemplate;@Resourceprivate LoadBalancerClient loadBalancerClient;@Value("${service-url.nacos-pay-service-name}")private String SERVICE_NAME;@GetMapping("/test")public String test(){ServiceInstance serviceInstance = loadBalancerClient.choose(SERVICE_NAME);// 服务调用地址String path = String.format("http://%s:%s/%s",serviceInstance.getHost(),serviceInstance.getPort(),"test");System.out.println("request path:" +path);// 通过RestTemplate调用服务return restTemplate.getForObject(path,String.class);}
}

image-20221101162929657

每刷新一次,就会由不同服务提供者进行提供,这就实现了轮询的负载均衡。

1.4、Nacos 之配置中心

​ Nacos可以作为一个配置中心实时更新项目中的配置文件,这样就可以只需修改一处配置文件使所有服务的配置文件都修改。Nacos在项目初始化时要先从配置中心拉取配置之后,才能保证项目的正常启动。

引入依赖:

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 配置中心依赖-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

编写配置文件:

一般有两种配置文件bootstrap.yamlapplication.yaml,但是前者优先级高于后者,所以将全局的配置放在bootstrap中,自己配置文件放在application中。(写一个就可以了)

server:port: 7001spring:profiles:active: dev # 设置成开发环境application:name: config-applicationcloud:nacos:discovery:server-addr: 127.0.0.1:8848  # 服务注册地址config:server-addr: 127.0.0.1:8848 # 配置中心地址file-extension: yml # 配置文件后缀名

编写好配置模块后,在Nacos中创建配置文件:

image-20221101172744991

image-20221101172831527

Data ID命名规则:
命名公式 ${spring.cloud.nacos.config.prefix}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension},注意每一个不能省略,中间使用 - 隔开。

  • spring.cloud.nacos.config.prefix: 前缀,默认是项目名称,可以通过spring.cloud.nacos.config.prefix修改。
  • spring.profiles.active:在bootstrap中配置的环境类型。
  • spring.cloud.nacos.config.file-extension:在bootstrap中配置文件扩展名。

可能新版的nacos不支持bootstrap文件,需要导入依赖。

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

以上的Data ID就该命名为:config-application-dev.yml

image-20221101175131444

配置文件动态刷新:

@RestController
@RefreshScope // 配置文件动态刷新,当修改nacos中心的配置文件发布后,不用重启项目就会发现配置发生变化了
public class TestController {@Value("${test.value}")private String values;@GetMapping("/test")public String test(){return values;}
}

1.5、Nacos 之分类配置

​ 在分布式开发中存在多环境,通常在实际开发中都会准备不同的开发环境,例如dev开发环境、test测试环境、prod生产环境,如何进行管理这些环境配置保证每个服务读取到正确的配置文件,这就需要Nacos的分类配置。

Namespace、group、Data ID三者之间的关系:

image-20221101202047935

Namespace区分部署环境,Group和Data ID逻辑上区分两个目标对象。相当于Java中的包名、类名。默认的Namespace是public,Group是DEFAULT_GROUP。

Nacos三种分配配置方式:(开发环境、测试环境、生产环境)

  1. 基于Data ID配置:通过切换项目的开发环境去配置中心拉取不同Data ID的配置文件。(常用)
# 项目切换不同环境
spring:profiles:active: dev # 设置成开发环境,对应配置中心Data ID为config-application-dev.yml# active: test # 设置成测试环境,对应配置中心Data ID为config-application-test.yml# active: prod # 设置成生产环境,对应配置中心Data ID为config-application-prod.yml

配置中心创建对应的配置文件,是在默认的public的Namespace下,默认的DEFAULT_GROUP分组下,分别切换对应环境就可以实现不能拉取不同环境的配置文件。

image-20221101225318164

  1. 基于GROUP分组配置:去拉取不同分组下同一个Data ID配置文件。

创建两个相同Data ID的配置文件,但是在不同的分组下。

image-20221101230225223

spring:profiles:active: dev # 设置成开发环境,对应配置中心Data ID为config-application-dev.yml# active: test # 设置成测试环境,对应配置中心Data ID为config-application-test.yml# active: prod # 设置成生产环境,对应配置中心Data ID为config-application-prod.ymlapplication:name: config-applicationcloud:refresh:enabled: truenacos:discovery:server-addr: 127.0.0.1:8848  # 服务注册地址config:server-addr: 127.0.0.1:8848 # 配置中心地址file-extension: yml # 配置文件后缀名group: DEV_GROUP # 切换对应分组
  1. 基于Namespace命名空间:创建不同的命名空间,然后在不同的命名空间去查找对应的配置文件。

创建两个不同的命名空间,并创建两个GROUP和Data ID相同的配置文件,默认有一个public命名空间不能够删除。

image-20221101230945978

image-20221101231859038

image-20221101231303729

在不同分组中创建了两个相同GROPU和Data ID的配置文件,并修改配置文件来切换不同的命名空间。

spring:profiles:active: dev # 设置成开发环境,对应配置中心Data ID为config-application-dev.yml# active: test # 设置成测试环境,对应配置中心Data ID为config-application-test.yml# active: prod # 设置成生产环境,对应配置中心Data ID为config-application-prod.ymlapplication:name: config-applicationcloud:refresh:enabled: truenacos:discovery:server-addr: 127.0.0.1:8848  # 服务注册地址config:server-addr: 127.0.0.1:8848 # 配置中心地址file-extension: yml # 配置文件后缀名group: TEST_GROUP # 切换对应分组namespace: module-dev # 切换不同的Namespace,填创建时的命名空间ID

1.6、Nacos 之集群配置

1.6.1、Nacos 之持久化配置

​ 在0.7版本之前,在单机模式时nacos使用嵌入式数据库(derby)实现数据的存储,不方便观察数据存储的基本情况。0.7版本增加了支持mysql数据源能力。对于搭建Nacos集群数据库为了保证数据的一致性,也是使用MySQL数据库来存放数据保证数据高可用。

初始化Nacos数据库脚本:在Nacos的conf目录下有一个nacos-mysql.sql脚本,复制后在MySQL来执行。

image-20221102110331668

image-20221102111215304

修改Nacos的数据源:修改conf目录下的application.properties文件,在文件最下面添加下面一句话。

# 一定要是mysql
spring.datasource.platform=mysqldb.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=1234567

重启Nacos并插入数据观察数据库是否增加数据记录,如果增加数据库就切换成功,这样新增的数据存放在数据库中,重启Nacos数据就不会丢失。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4tvtSrau-1692611041818)(https://jx-image-storage.oss-cn-hangzhou.aliyuncs.com/image/image-20221102112013186.png)]

1.6.2、Nacos 之集群配置

​ 在生产环境中Nacos都已集群的形式存在,这样保证了服务高可用。一般集群模式是客户端请求到代理服务器,然后代理服务器转发到每一台Nacos上。下面介绍使用1台Nginx+3台Nacos+1台MySQL做Nacos集群。

  1. 在Linux下安装Nacos压缩包并解压,并初始化持久化Sql脚本修改对应数据源,修改每一台Nacos启动端口和开启连接密码(都在application.properties)。

image-20221102130059493

image-20221102132906176

  1. 修改cluster.conf文件,配置集群组。

image-20221102130730338

  1. 安装Nginx代理服务器:https://blog.redis.com.cn/install

安装编译环境:

# g++环境
yum -y install gcc automake autoconf libtool make
yum install gcc gcc-c++
# 安装pcre、zlib、openssl
yum install pcre -y
yum install pcre-devel -y
yum install zlib -y
yum install zlib-devel -y
yum install openssl -y
yum install openssl-devel -y

下载tar包,并解压,默认解压后的路径是 /usr/local/nginx

#解压
cd /usr/local
tar -zxvf nginx-1.16.0.tar.gz
#进行configure配置,查看是否报错
cd nginx-1.16.0/
./configure
#编译
make
#安装
make install
#在 /usr/local/nginx目录下,可以看到如下4个目录:
#conf配置文件,html网页文件,logs日志文件,sbin主要二进制程序

修改Nginx配置文件并启动:

image-20221102142143199

#指定配置文件启动
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
  1. 启动每一台Nacos服务
# 使用内置数据源
sh startup.sh -p embedded
# 使用外置数据源,我们使用这个
sh startup.sh 

image-20221102143959250

由于Nacos集群服务器启动需要很大内存,一般普通的云服务跑不起来,可以修改启动命令,将初始化的内存值改小。

image-20221102150504494

避坑端口偏移:Nacos 2.x 新增了 gRPC 协议的通讯端口,在启动时会自动在原有端口 port 的基础上根据偏移量 10001001 再打开另外两个端口。所以在一台服务器上去跑两个nacos不要使用相邻的端口号和不要使用偏移端口号,同时打开这两个端口。

2、Sentinel 熔断与限流

​ 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。

下载地址:https://github.com/alibaba/Sentinel/releases/tag/v1.8.0

java -Dsentinel.dashboard.auth.username=admin -Dsentinel.dashboard.auth.password=admin123 -jar sentinel-dashboard-1.8.1.jar &

启动:下载完成后是一个Jar包,直接通过 java -Dserver.port=7777 -jar sentinel-dashboard-1.8.0.jar 命令启动后就可以直接访问sentinel的控制面板,账号和密码都是sentinel,不指定端口就是默认8080端口。

在Centos中运行jar包:nohup java -Dserver.port=7777 -jar sentinel-dashboard-1.8.0.jar >sentinel.log 2>&1 &

  • nohup意思是不挂断运行命令,当账户退出或终端关闭时,程序仍然运行

  • >spring.log代表将命令的输出定向存储到spring.log这个文件中,文件名可以自己定义。

  • &代表在后台运行

image-20221103132229284

2.1、Sentinel 之基本使用

导入依赖:

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

修改yaml,使用sentinel监控服务:

server:port: 8081spring:profiles:active: devapplication:name: sentinel-application-01cloud:nacos:discovery:server-addr: xxxxxxx:8001config:server-addr: xxxxxxxx:8001 # 配置中心地址file-extension: yml # 配置文件后缀名sentinel:transport:# sentinel的地址dashboard: 127.0.0.1:8080# 默认端口号,如果被占用自动+1扫描,直到未被占用端口port: 8719management:endpoints:web:exposure:include: '*'

启动服务,需要请求服务服务的某个接口,不然sentinel是空白页面。

image-20221103140058735

2.2、Sentinel 之流量监控

簇点链路:访问服务对应的访问路径,也会监控QPS、线程数等数据

image-20221103143954575

流控规则:对某个簇点设置对应的流控规则。

image-20221103144656730

  • 资源名:簇点访问路径
  • 针对来源:Sentinel可以针对调用者进行限流,默认是default(不分来源),一般填写微服务名称。
  • 阈值类型:
    • QPS:当api的每秒的请求数量达到阈值时进行限流。
    • 线程数:当调用api的线程数达到阈值时进行限流。
  • 是否集群:是否在集群中进行限流。
  • 流控模式:
    • 直接:当api达到限流条件时,直接限流。
    • 关联:当关联的api达到限流条件时,就限流自己。
    • 链路:只记录链路上的流量(如果api是从某个链路来的流量,当流量达到阈值就进行限流自己)。
  • 流控效果:
    • 快速失败:直接失败,抛出异常。
    • Warm Up:(预热),有一个默认的冷却因子3,当QPS、线程数达到 阈值 = 阈值\3 之前开始预热,会设置一个预热时间,在这个时间阈值有一个缓冲上升直到达到设置阈值。
    • 排队等待:匀速排队,设置请求超时时间(毫秒),这时阈值类型必须是QPS,否则无效。

QPS:指每一秒中请求api的次数。

线程数:
指服务中处理请求的线程数。

2.3、Sentinel 之服务降级

​ Sentinel熔断降级会在调用链路中某个资源出现不稳定状态(调用超时或异常比例升高),会对这个资源的请求进行限制,让请求快速失败,以避免影响到其它资源导致联错误。当服务降级后,在降级时间窗口之内,调用该资源就会自动熔断抛出异常(DegradeException)。

image-20221103165906979

现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。

  • 慢调用比例:(响应时间)
    • 最大RT:最大响应时间,当一个请求的响应时间超过这个阈值就是一个异常请求(单位:秒),这个服务进入准降级状态。
    • 最小请求数:当出现一个异常请求后,在一个单位时间内(默认是1s)会统计请求数,如果超过最小请求数,则统计时间内异常请求数的比例是否操作比例阈值,超过就进行服务降级。
    • 熔断时长:当服务发生熔断时,在熔断时长内所有请求自动抛出异常,时长过后服务继续使用,再出现熔断继续抛出异常。
    • 比例阈值:单位时间内,异常比例超过这个值就发生熔断。

image-20221103180246280

  • 异常比例:
    • 比例阈值:当请求出现异常时,在单位时间(1s)就会统计请求数量,如果请求数量超过最小请求数并且异常请求比例超过比例阈值,服务就会进行熔断。(如果熔断后恢复,第一次请求出现异常会继续熔断)

image-20221103183037189

  • 异常数:
    • 异常数:当请求出现异常,会在单位时间(1s)统计请求数量,如果请求数量大于最小请求数并且异常数量超过异常数,服务就进行降级。

2.4、Sentinel 之热点限流

​ 热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。

编写一个热点限流接口:

@GetMapping("/hot")
// 作为热点限流的唯一标识,一般写rest接口名
// blockHandler:指定一个限流后的处理方法
@SentinelResource(value = "hot",blockHandler = "paramFlowExceptionHandler")
public String hotKey(@RequestParam(value = "p1", required = false) String p1,@RequestParam(value = "p2", required = false) String p2){return "success test";
}public static String paramFlowExceptionHandler(String p1, String p2, BlockException blockException){return p1+"热点数据被限流";
}

配置热点参数限流:

image-20221106155029278

image-20221106155126458

上面就表示,当访问的接口为url为:127.0.0.1:8081/hot?p1=xxx时,只要p1这个参数不为空,并且QPS超过阈值就会进行热点限流。如果p1为空就没有限流规则。参数索引就是指定需要进行热点参数的下标位置,从0开始。

参数例外项:当有时候我们希望热点参数为某个值时,对应的QPS的限流不一样,可以通过参数例外项进行控制。

image-20221106165223268

2.5、Sentinel 之系统规则

​ Sentinel 系统自适应保护从整体维度对应用入口流量进行控制,结合应用的 Load、总体平均 RT、入口 QPS 和线程数等几个维度的监控指标,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

image-20221106171656918

​ 系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量,比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。

  • Load(仅对 Linux/Unix-like 机器生效):当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的 maxQps * minRt 计算得出。设定参考值一般是 CPU cores * 2.5
  • CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0)。
  • RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
  • 线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

2.6、Sentinel 之@SentinelResource注解

基于资源名的流控、降级、热点:将@SentinelResource的value属性作为资源名,之前使用的rest地址作为资源名。

@GetMapping("/resource/test1")
@SentinelResource(value = "test1",blockHandler = "handlerTest1")
public String test(){return "test1";
}public static String handlerTest1(BlockException e){return "处理test1的sentinel异常";
}

image-20221106174315732

blockHandler属性:
用于处理当满足在sentinel设置的规则进行处理时,自定义处理方法名,设置后不再使用sentine默认的返回值。

  • 处理方法必须在同一个类中。
  • 处理方法的返回值类型和参数必须与对应接口相同,并且需要再后面新增一个BlockException参数。
  • 处理方法必须使用static修饰,不然不会被解析,方法也必须是public修饰。

若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。但是使用上面方式去处理会发现每一个接口都需要一个自定义处理方法,这样代码膨胀,需要全局去处理。

blockHandler和fallback的理解:

blockHandler:指定一个方法去处理违反了sentinel配置规则的请求,不在使用sentinel默认的处理方式。

fallback:指定一个方法去处理在请求接口时出现了Java异常时,进行异常处理,不在用户页面展示报错信息。

@GetMapping("/resource/test2")
// fallback:指定处理异常的方法
@SentinelResource(value = "test2",fallback = "fallbackHandler")
public String test1(){int i = 1/0;return "test1";
}// 方法名指定、static修饰、返回值类型相同、参数相同并且加一个Throwable、public修饰
public static String fallbackHandler(Throwable e){return "处理test1的Java异常"+e.getMessage();
}

image-20221107152803709

注意 blockHandler只处理在违背了sentinel配置错误时的异常,fallback只处理Java运行时的异常。

exceptionsToIgnore属性:参数是数组,当出现数组里面的异常时不进行处理

image-20221107154611842

Sentinel规则持久化:默认在Sentinel的规则都是临时的,只要关闭了服务所有的规则就会消失。下面介绍将Sentinel规则持久化进Nacos中。

  1. 引入依赖
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
  1. 修改pom

3、 OpenFeign 远程服务调用

​ Feign是一个声明式 Web 服务客户端。 它使编写 Web 服务客户端变得更加容易。 要使用Feign创建一个接口并对其进行注释。 它具有可插拔的注释支持,包括Feign注释和JAX-RS注释。 Feign还支持可插拔编码器和解码器。 Spring Cloud 增加了对 Spring MVC 注释的支持,并支持在 Spring Web 中默认使用相同注释。 Spring Cloud 集成了 Eureka 和 Spring Cloud LoadBalancer,以便在使用 Feign 时提供负载平衡的 http 客户端。HttpMessageConverters

导入依赖:

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

3.1、Openfeign 之基本使用

开启openfeign:使用@EnableFeignClients注解开启,basePackages数组属性:去指明应用程序A在启动的时候需要扫描服务B中的标注了@FeignClient注解的接口的包路径。

@SpringBootApplication
// 扫描com.cj包下所有带有@FeignClient的接口
@EnableFeignClients(basePackages = {"com.cj"})
public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class,args);}
}

编写接口:

// value:是调用哪个注册到nacos中心服务的服务名称
// contextId:这个是调用注入时是bean的名称
@FeignClient(value = SourceConstants.ORDER_SOURCE)
public interface OrderRemoteService {// 在这个服务下对应的调用的那个接口@GetMapping("/order")R order();
}

编写服务调用:

@RestController
public class ConsumerController {// 注入编写好的openfeign接口,然后直接可以进行调用方法@Resourceprivate OrderRemoteService orderRemoteService;@GetMapping("/1")public R consumer(){return orderRemoteService.order();}
}

总结:

  • Openfeign:是一个面向接口的远程服务调用,并且自带了负载均衡功能。
  • 使用:需要将服务注册到nacos中,并且在接口上指定调用服务的名称。

3.2、Openfeign 之超时控制

​ 在时机开发中,一些业务的处理时间可能和Openfeign默认的超时时间存在时间差,导致业务是正常时间完成但是Openfeign会报TimeOutException,所以需要我们自己去控制Openfeign的超时时间。

模拟超时异常:在业务逻辑让线程睡5s

@GetMapping("/timeOut")
public R timeOut(){try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}return R.success("端口获取成功",port);
}

远程调用:

@GetMapping("/2")
public R timeOut(){return orderRemoteService.timeOut();
}

image-20221106122726306

修改超时时间:

image-20221106122904288

3.3、Openfeign 之异常处理

配置日志:编写一个配置类,设置对应的日志等级。

@Configuration
public class OpenfeignConfig {@BeanLogger.Level openFeignLoggerLevel(){return Logger.Level.FULL;}
}
  • NONE:默认,不显示任何日志。
  • BASIC:仅记录请求方法、url、响应状态码、执行时间。
  • HEADERS:除BASIC中的内容,还有请求头、响应头信心。
  • FULL:所有请求信息。

配置日志:

logging:level:# 配置openfeign以什么级别去监控哪个接口com.jx.*: debug

Openfeign+Sentinel远程服务异常处理:

  1. 将服务注册进Sentinel中,并开启Openfeign的Sentinel支持。
feign:sentinel:enabled: trueclient:config:default:# 修改openfeign的超时时间readTimeout: 5000 # 修改为5sconnectTimeout: 5000
  1. 增加一个远程调用异常处理类
// 当调用远程服务出异常时,通过这个类进行处理,实现FallbackFactory接口,并重写create方法
@Component
public class OrderRemoteFallbackFactory implements FallbackFactory<OrderRemoteService> {private static final Logger log = LoggerFactory.getLogger(OrderRemoteFallbackFactory.class);@Overridepublic OrderRemoteService create(Throwable cause) {log.error("order远程服务调用失败:{}", cause.getMessage());return new OrderRemoteService() {@Overridepublic R order() {// 在这个方法中返回出现异常后的远程调用结果return R.error("order远程服务调用失败:{}",cause.getMessage());}@Overridepublic R timeOut() {return R.error("order远程服务调用失败:{}",cause.getMessage());}@Overridepublic R exceptionTest() {System.out.println("============================================");return R.error("order远程服务调用失败:{}",cause.getMessage());}};}
}
  1. 修改远程接口,在@FeignClient注解上添加fallbackFactory属性
@FeignClient(contextId = "orderRemoteService",value = SourceConstants.ORDER_SOURCE,fallbackFactory = OrderRemoteFallbackFactory.class)
public interface OrderRemoteService {@GetMapping("/order")R order();@GetMapping("/timeOut")R timeOut();@GetMapping("/exception")R exceptionTest();
}
  1. 编写一个测试接口/exception
@GetMapping("/exception")
public R exceptionTest() throws Exception {R r = null;r.put("name","name");return r;
}

image-20221106143435464

4、Gateway 服务网关

服务网关:在微服务的架构中,所有请求需要先通过网关,再由网关将请求路由转发到对应的每一个服务上。

  • 使用网关可以简化客户端工作,这样客户端只需和网关进行交互,不再很麻烦去交互所有的微服务。
  • 降低客户端与服务之间的耦合度,修改了服务接口只需要修改网关的配置策略,不用修改客户端。
  • 网关可以统一管理请求,可以实现负载均衡、流控、熔断降级、认证等操作。

image-20221108130711556

4.1、Gateway 之网关简介

Spring Cloud Gateway 使用的是Webflux中的reactor-netty响应式编程组件,底层是一个Netty通讯框架。

image-20221108130613413

Webflux是一个异步非阻塞框架,那么Gateway也是一个异步非阻塞模型,对于高并发请求性能很好。它能与 SpringCloud 生态很好兼容,单从流式编程+支持异步上也足以让开发者选择它了

image-20221108132212406

Gateway的三大组件:

  • Route路由:路由是构建网关的基本模块,它由ID、目标URL、一系列断言和过滤器组成,如果断言为true则进行路由转发。
  • Predicate断言:开发人员可以匹配Http请求的信息,如果请求与断言相匹配则进行路由转发。
  • Filter过滤器:使用过滤器,可以在请求的前或后对请求进行修改。

4.2、Gateway 之配置路由

引入网关依赖:

<!-- 引入gateway网关 -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></exclusion></exclusions>
</dependency>

注意,需要去除掉spring-boot-starter-web,不然启动会报错。

路由配置:Route 主要由 路由id、目标uri、断言集合和过滤器集合组成

  • id: 路由的唯一标识,必须唯一,自己定义。
  • uri:请求转发的目标地址。
  • order:路由的优先级,数字越小优先级越高。
  • predicates:断言数组,就是判断是否满足转发条件,如果断言为true就进行路由转发。
  • filters:过滤器,在请求的传递过程中对请求做一些修改。
spring:profiles:active: devapplication:name: cloud-gatewaycloud:nacos:discovery:server-addr: 127.0.0.1:8001config:server-addr: 127.0.0.1:8001file-extension: ymlgateway:discovery:locator:lowerCaseServiceId: trueenabled: trueroutes: # 配置路由- id: order # id,唯一标识uri: http://127.0.0.1:8000 # 路由转发的目标地址# 如果访问地址为 http://127.0.0.1:9000/order/test,他就会路由断言成功,就会转发到http://127.0.0.1:8000/test(去除了一级访问地址)predicates: # 断言判断,如果满足就进行路由转发- Path=/order/**filters:- StripPrefix=1 # 原始路去除到一级,上面就去除到/order- id: payuri: http://127.0.0.1:9011predicates:- Path=/pay/**filters:- StripPrefix=1

Gateway动态路由配置:在服务架构中,服务可能是部署到多台服务上的,直接配置服务的url地址不方便,一旦服务ip地址发生变化就需要改配置,所以需要在注册中心去通过服务名称去发现服务并实现负载均衡的路由转发。

  1. 将Gateway网关注册进Nacos服务中心。
  2. 修改yaml配置文件
gateway:discovery:locator:# 路由的路径默认会使用大写ID,若想要使用小写ID,可将lowerCaseServiceId设置为truelowerCaseServiceId: true# 开启从注册中心动态创建路由功能enabled: trueroutes: # 动态配置路由- id: orderuri: lb://cj-order # 固定格式:lb://+服务名predicates:- Path=/order/**filters:- StripPrefix=1- id: payuri: lb://modules-pay-01predicates:- Path=/pay/**filters:- StripPrefix=1
  1. 引入依赖:因为带有负载均衡,需要引入loadbalancer
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

4.3、Gateway 之配置断言

 - id: payuri: lb://modules-pay-01predicates:# 表示这个路径需要在这个时间之后访问才有效- After=2022-11-08T17:22:39.520+08:00[Asia/Shanghai]# 在这个时间之前访问才有效- Before=2017-01-20T17:42:47.789-07:00[America/Denver]# 在这个时间时间段访问才有效- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2022-11-08T17:22:39.520+08:00[Asia/Shanghai]# 带有指定cookie名的请求,并且值是指定的(支持正则)- Cookie=chocolate, ch.p# 带有指定的Header的请求,并且值是指定的(支持正则)- Header=X-Request-Id, \d+# Host带有指定值的,且值是指定的(支持正则)- Host=**.somehost.org,**.anotherhost.org# 指定方法的请求才有效果,可以指定多个,用逗号隔开- Method=GET,POST# 匹配请求路径- Path=/pay/**# 必须参数和正则参数,必须参数请求必须带有指定参数值的参数,正则参数就是满足对应正则的参数即可- Query=green, gree.# 请求的远程地址符合指定地址- RemoteAddr=192.168.1.1/24# 同一个uri的通过group分组,值表示权重,权重越高在负载均衡的时候分配的流量越大- Weight=group1, 2

时间格式的获取:

public static void main(String[] args) {ZonedDateTime now = ZonedDateTime.now();System.out.println(now);// 2022-11-08T16:44:48.004+08:00[Asia/Shanghai]
}

4.4、Gateway 之配置过滤器

Gateway自己的过滤器分为局部过滤和全局过滤,每个过滤器都有pre和post,局部有34个全局有9个。

文档地址:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#global-filters]

image-20221108165341659

自定义局部过滤器:可以自己定义局部过滤器让对应过滤器在对应的路由上使用。

// 配置局部过滤器,需要继承AbstractGatewayFilterFactory,<C>可能后续版本有用
@Component
@Slf4j
public class PartFilter extends AbstractGatewayFilterFactory<Object> {// 进行过滤操作@Overridepublic GatewayFilter apply(Object config) {return (exchange, chain) ->{// 获取请求ServerHttpRequest request = exchange.getRequest();List<String> usernames = request.getQueryParams().get("username");System.out.println(usernames.toString());if (usernames==null || usernames.size()==0 || !usernames.get(0).equals("张三")){ServerHttpResponse response = exchange.getResponse();log.error("非法用户");// 直接拦截请求并返回错误信息return response.setComplete();}log.info("合法用户");// 放行请求return chain.filter(exchange);};}
}
filters:# 将局部filter设置到对应的路由中,过滤器的名称- PartFilter- StripPrefix=1

配置全局过滤器:全局过滤器回去过滤网关中所有的路由,直接注入就可使用,不用其它配置。

@Component
@Slf4j
public class FilterTest implements GlobalFilter, Ordered {// 自定义全局过滤操作@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 获取请求ServerHttpRequest request = exchange.getRequest();List<String> usernames = request.getQueryParams().get("username");System.out.println(usernames.toString());if (usernames==null || usernames.size()==0 || !usernames.get(0).equals("张三")){ServerHttpResponse response = exchange.getResponse();log.error("非法用户");// 直接拦截请求并返回错误信息return response.setComplete();}log.info("合法用户");// 放行请求return chain.filter(exchange);}// 设置过滤器的启动优先级,数字越小越先启动@Overridepublic int getOrder() {return 0;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/102073.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue Cli 脚手架安装

Vue Cli 脚手架安装 首先&#xff0c;改一下仓库地址&#xff0c;使用下面的命令cnpm淘宝镜像加速 npm install cnpm -g --registryhttps://registry.npm.taobao.org下载安装 vue 脚手架 npm install -g vue/cli查看 vue cli 脚手架是否安装成功&#xff0c;如果输入命令出现…

联想小新Pro 16笔记本键盘失灵处理方法

问题描述&#xff1a; 联想小新Pro 16新笔记本开机准备激活&#xff0c;到连接网络的时候就开始触控板、键盘失灵&#xff0c;但是有意思的是键盘的背光灯是可以调节关闭的&#xff1b;外接鼠标是正常可以移动的&#xff0c;但是只要拔掉外接鼠标再插回去的时候就不能用了&…

python自动化入门之Python编写脚本实现自动化爬虫详解

想知道如何使用Python轻松高效地获取网络上的信息&#xff1f; 本篇文章将探索Python自动化爬虫&#xff0c;并展示如何编写实用的脚本。 1. 什么是Python爬虫&#xff1f; 爬虫顾名思义&#xff0c;就是像蜘蛛一样在网络上爬行&#xff0c;抓取各种有用信息的一种程序。而Pyt…

【Win】Dell Command PowerShell Provider 一款强大的IT工具

Dell Command | PowerShell Provider 是一款强大的IT工具&#xff0c;它允许用户通过 Windows PowerShell 界面轻松管理 Dell 硬件平台的 BIOS 配置。它提供了一系列的 PowerShell cmdlets命令&#xff0c;这些命令可以帮助 IT 管理员对 Dell 硬件平台进行 BIOS 配置的控制和管…

jmeter进行业务接口并发测试,但登录接口只执行一次

业务接口性能测试&#xff0c;往往都是需要登录&#xff0c;才能请求成功&#xff0c;通常只需要登录一次&#xff0c;再对业务接口多次并发测试。 在测试计划中&#xff0c;添加setUp线程组 把登录请求放入到该线程组中&#xff0c;设置HTTP信息头&#xff0c;JSON提取(提取登…

Blazor 依赖注入妙用:巧设回调

文章目录 前言依赖注入特性需求解决方案示意图 前言 依赖注入我之前写过一篇文章&#xff0c;没看过的可以看看这个。 C# Blazor 学习笔记(10):依赖注入 依赖注入特性 只能Razor组件中注入所有Razor组件在作用域注入的都是同一个依赖。作用域可以看看我之前的文章。 需求 …

使用Nacos配置中心动态管理Spring Boot应用配置

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

微服务概述-7

Shiro 框架 Shiro 是一个用于 Java 应用程序的安全框架。它提供了身份验证、授权、加密和会话管理等功能&#xff0c;可以帮助开发人员构建安全可靠的应用程序。 Java 中针对权限管理常见的有 2 个著名的框架&#xff1a;spring security 和 shiro shiro 基本概念 credentia…

opencv 进阶17-使用K最近邻和比率检验过滤匹配(图像匹配)

K最近邻&#xff08;K-Nearest Neighbors&#xff0c;简称KNN&#xff09;和比率检验&#xff08;Ratio Test&#xff09;是在计算机视觉中用于特征匹配的常见技术。它们通常与特征描述子&#xff08;例如SIFT、SURF、ORB等&#xff09;一起使用&#xff0c;以在图像中找到相似…

程序员35岁的破局之道

微信公众号访问地址&#xff1a;程序员35岁的破局之道 近期热推文章&#xff1a; 1、springBoot对接kafka,批量、并发、异步获取消息,并动态、批量插入库表; 2、SpringBoot用线程池ThreadPoolTaskExecutor异步处理百万级数据; 3、基于Redis的Geo实现附近商铺搜索(含源码) 4、基…

【Java】常见面试题:HTTP/HTTPS、Servlet、Cookie、Linux和JVM

文章目录 1. 抓包工具&#xff08;了解&#xff09;2. 【经典面试题】GET和POST的区别&#xff1a;3. URL中不是也有这个服务器主机的IP和端口吗&#xff0c;为啥还要搞个Host&#xff1f;4. 补充5. HTTP响应状态码6. 总结HTTPS工作过程&#xff08;经典面试题&#xff09;7. H…

linux 免交互

Linux 免交互 1、免交互概念2、基本免交互的例子2.1命令行免交互统计2.2使用脚本免交互统计2.3使用免交互命令打印2.4免交互修改密码2.5重定向查看2.6重定向到指定文件2.7重定向直接指定文件2.8使用脚本完成重定向输入2.9免交互脚本完成赋值变量2.10关闭变量替换功能&#xff0…

ipad可以用别的品牌的手写笔吗?开学平价电容笔推荐

开学需要买什么呢&#xff1f;随着科技的不断进步&#xff0c;各种类型的iPad电容笔应运而生。一支好的电容笔&#xff0c;不仅能大大提高我们的工作效率&#xff0c;而且能大大提高我们的生产力。平替的这款电容笔&#xff0c;不管是在技术上&#xff0c;还是在品质上&#xf…

QT 使用图表

目录 1、概念 1.1 坐标轴-QAbstractAxis 1.2 系列-QAbstractSeries 1.3 图例-Legend 1.4 图表-QChart 1.5 视图-QChartView 2、 QT 折线图 2.1 Qt 折线图介绍 2.2 Qt 折线图实现 Qt 图表是专门用来数据可视化的控件 Qt 图表包含折线、饼图、棒图、散点图、范围图等。…

Day16-蜗牛影城后端开发

蜗牛影城后端开发 一 多表关联查询 电影集合movie的type(类别)字段关联到电影类别movieType表的_id(主键) 二 蜗牛影城后端开发 1 数据的导入导出 2 用户模块 UserModel.js //导入mongoose,并解构出Schema(类)和model(对象) const {Schema,model} =

详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优

4.详细了解G1&#xff1a; 4.1.一&#xff1a;什么是垃圾回收 4.2.了解G1 4.3.G1 Yong GC 4.4.G1 Mix GC 4.5.三色标记算法 4.6.调优实践 5.G1垃圾收集器详解 5.1.G1垃圾收集器 5.2.G1的堆内存划分 5.3.G1的运行过程 5.4.三色标记 5.4.1.漏标问题 5.5.记忆集与卡表 5.6.安全点与…

高并发内存池(centralcache)[2]

Central cache threadcache是每个线程独享&#xff0c;而centralcache是多线程共享&#xff0c;需要加锁&#xff08;桶锁&#xff09;一个桶一个锁 解决外碎片问题&#xff1a;内碎片&#xff1a;申请大小超过实际大小&#xff1b;外碎片&#xff1a;空间碎片不连续&#x…

python判断ip所属地区 python 判断ip 网段

前言 IP地址是互联网中唯一标识一个设备的地址&#xff0c;有时候需要判断一个IP地址所属的地区&#xff0c;这就需要用到IP地址归属查询。本文将介绍Python如何通过IP地址查询所属地区并展示代码。 一、 IP地址归属查询 IP地址归属查询又称IP地址归属地查询、IP地址归属地定…

【Unity3D】程序纹理简单应用

1 几何纹理应用 本文所有案例的完整资源详见→Unity3D程序纹理简单应用。 1.1 边框 1&#xff09;边框子图 Border.shadersubgraph 说明&#xff1a;Any 节点用于判断输入向量中是否存在一个分量非零&#xff0c;Branch 节点根据输入的真假走不同的分支&#xff0c;详见→Shad…

报名开启 | HarmonyOS第一课“营”在暑期系列直播

<HarmonyOS第一课>2023年再次启航&#xff01; 特邀HarmonyOS布道师云集华为开发者联盟直播间 聚焦HarmonyOS 4版本新特性 邀您一同学习赢好礼&#xff01; 你准备好了吗&#xff1f; ↓↓↓预约报名↓↓↓ 点击关注了解更多资讯&#xff0c;报名学习