ToB企服应用市场:ToB评测及商务社交产业平台

标题: SpringCloud微服务架构(eureka、nacos、ribbon、feign、gateway等组件的详 [打印本页]

作者: 李优秀    时间: 2024-10-13 06:34
标题: SpringCloud微服务架构(eureka、nacos、ribbon、feign、gateway等组件的详
一、微服务演变

1、单体架构(Monolithic Architecture)

是一种传统的软件架构模式,应用程序的全部功能和组件都会合在一个单一的应用中。
在单体架构中,应用程序通常由一个大型的、单一的代码库构成,此中包含了全部的功能模块和业务逻辑。这个应用程序作为一个团体摆设和运行在一个应用服务器上,并共享相同的内存和数据库。
当单体架构项目标性能无法满意需求时,但又希望继续相沿单体架构的话,你可以接纳以下一些优化本领来改善性能,如以下方法:

 接下来就说一下单体架构优化中的引入分布式架构。
2、分布式架构

将体系的各个组件摆设在不同的盘算机节点上,并通过网络进行通讯和协作的软件架构模式。在分布式架构中,各个节点可以独立运行和处理处罚任务,并通过消息传递、远程过程调用或其他通讯机制进行数据交换和和谐。

 在利用分布式时,我们就会有一下的疑问:


 3、微服务

 微服务是一种经过改精良的架构设计的分布式架构方案,微服务架构特性:
如果我们有一个电商体系,此中有以下一些微服务:
现在假设用户服务依赖于商品服务来获取商品信息,并且订单服务依赖于用户服务来获取用户信息。这里我们可以看到微服务的几个特性是怎样应用的:
这个例子中提供了不同的微服务来处理处罚不同的功能,并且彼此解耦、独立运行。每个微服务都具有单一职责,对外提供明确定义的业务接口,团队在技能和数据上具有自治本领,同时接纳适当的隔离步伐来包管体系的弹性和稳定性。这些特性有助于进步开发效率、机动性和可维护性,使得微服务架构在构建大型、复杂体系时具有优势。

4、 总结

单体架构特点:简单方便,高度耦合,扩展性差,合适小型项目。如:学生管理体系。
分布式架构特点:松耦合,扩展性好,但架构复杂,岂非大,适合大型互联网项目。如:京东、淘宝
微服务:一种精良的分布式架构方案。

5、微服务架构

微服务这方案需要技能框架来落地实现,全球的互联网公司都在积极尝试自己的微服务落地技能。在国内最知名的就是SpringCloud和阿里巴巴的Dubbo

5.1、 微服务技能对比


 Dubbo、Spring Cloud、Spring Cloud和Spring Cloud Alibaba都是用于构建分布式体系的开源框架。只管它们的目标相同,但它们在实现方式和功能特点上有所不同。
虽然Dubbo和Spring Cloud都是用于构建分布式体系的框架,但Dubbo更加注重于高性能的RPC调用和服务治理,而Spring Cloud则提供了一整套更全面的微服务解决方案。而Spring Cloud Alibaba则是在Spring Cloud的基础上,进一步整合了Alibaba的一些技能,为云原生应用提供更全面的开发支持。选择适合的框架取决于详细的需求、技能栈和团队偏好。
5.2、企业需求



无论是利用Spring Cloud + Spring Cloud Alibaba还是Dubbo原生模式 + Spring Cloud Alibaba,都可以受益于Spring Cloud和Spring Cloud Alibaba提供的丰富的微服务功能和云原生支持。详细选择哪种组合取决于企业需求、技能栈和团队现实情况。需要评估技能要求、性能需求、开发复杂度等因素,选择适合的框架组合来构建稳定、高效的分布式体系。
二、spring cloud

SpringCloud是现在国内利用最广泛的微服务框架。官网地址:
                                                Spring Cloud

SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了精良的开箱即用体验:

 springCloud与SpringBoot的版本兼容关系


 本文学习版本是Hoxton.SR10,因此对应的springboot版本是2.3.x版本。
1、服务拆分及远程调用

1.1、服务拆分

1.1.1、服务拆分注意事项


1.1.2、项目实战


实战代码:阿里云下载
把数据库文件那到数据库管理工具里实行和idea中导入cloud-demo项目
终极数据库结构:

 对与cloud-demo这个项目主要看一下用户和订单怎样进行项目拆分的,联合这单体架构的效果对比一下有什么变革和不同。
1.1.3、总结

1.2、远程调用

 需求:根据订单id查询订单的同时,把订单所属的用户信息一起返回。

1.2.1、远程调用方法


 在我们的controller类中利用@GetMapping("/user/{id}")向外袒露了一个接口来访问,可以将user信息放回为json数据格式,我们可以想一下欣赏器可以发一个Ajax请求来获取数据,我们的订单服务可不可以发一个Ajax请求来获取数据呢?
1.2.2、实现远程调用步骤

1)注册RestTemplate

  1. Spring Cloud中也使用了RestTemplate类。RestTemplate是Spring框架中的一部分,它在Spring Cloud项目中被广泛用于进行微服务之间的通信。
  2. 在微服务架构中,各个微服务之间通常通过RESTful API进行通信。为了简化这个过程,Spring Cloud对RestTemplate进行了增强,以便更好地支持微服务架构。在Spring Cloud中,RestTemplate被称为"服务调用"的一部分。
  3. 通过使用RestTemplate,开发人员可以方便地发起HTTP请求来调用其他微服务的API。Spring Cloud还提供了一些增强功能,例如服务发现和负载均衡。开发人员可以使用服务名代替具体的URL,Spring Cloud会自动根据服务名找到可用的实例并进行负载均衡,从而实现更灵活和高效的服务调用。
  4. 需要注意的是,自Spring Cloud 2020.0.0版本(即Hoxton.SR9及之后的版本)开始,官方推荐使用WebClient替代RestTemplate作为HTTP客户端,因为WebClient提供了更强大、更灵活的功能,并且更适用于非阻塞的响应式编程模型。但是,为了向后兼容,RestTemplate仍然可以继续使用并被支持。
复制代码
在order-service的OrderApplication中注册ResteTemplate,将ResteTemplate用@Bean注解注册为spring管理的对象,以后不管在什么地方都可以利用到RestTemplate对象。


 完成调用主要是在service层中实现,向被调用服务发起一个Rest请求,在需要调用其他服务的服务中利用,实现步骤:
1、在服务启动类中注册RestTemplate,如这里是在order的启动类中
2、在要调用其他服务的服务中的service层中自动装配RestTemplate对象
3、利用RestTemplate的api来实现即可,里面有很多api,这里我利用的是getForObject()方法
4、将远程调用返回的数据封装到要封装的对象中即可,这里我利用的是将远程调用获取的user对象信息封装到order对象中。
1.3、提供者与斲丧者

 服务提供者:一次业务中,被其他微服务调用的服务。(提供接口给其他服务调用)如:user服务
服务斲丧者:一次业务中,调用其他微服务的服务。(调用其他微服务提供的接口)如order服务
总结:
1.服务调用关系

三、Eureka注册中心

1、服务调用出现的问题

在前面我们利用RestTemplate来实现服务远程调用,在写url时利用的是硬编码方式,就会产生以下的问题,这些问题是值得我们考虑一下的。


2、 Eureka基本原理

Eureka是Netflix开源的服务治理框架,在Spring Cloud中广泛应用。它的基本原理是建立了一个分布式的服务注册中心,用于管理和维护各个微服务实例的注册和发现。
以下是Eureka的基本原理:
通过Eureka提供的服务注册和发现机制,微服务之间可以动态地发现和调用其他微服务,从而实现了服务之间的解耦和机动性。Eureka还提供了负载均衡、故障规复等一些附加功能,使得微服务架构更加可靠和高效。

回顾之前我们的几个问题:

斲丧者该怎样获取服务提供者详细信息?

如果有多个服务提供者,斲丧者该怎样选择?

斲丧者怎样感知服务提供者康健状态?

 总结

在Eureka架构中,微服务角色有两类:
   1、EurekaServer:服务端,注册中心

   2、EurekaClient: 客户端
         1)Provider:服务提供者,例如案例中的 user-service

         2)consumer:服务斲丧者,例如案例中的 order-service

3、手动实战

3.1、搭建eureka服务注册中心(服务名称)


1、创建项目,引入spring-cloud-starter-netflix-eureka-server的依赖
  1.     <dependency>
  2.         <groupId>org.springframework.cloud</groupId>
  3.         <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
  4.     </dependency>
复制代码
 2、启用Eureka服务器:创建一个启动类,并利用@EnableEurekaServer注解来启用Eureka服务器功能。
  1. @SpringBootApplication
  2. @EnableEurekaServer
  3. public class EurekaApplication {
  4.     public static void main(String[] args) {
  5.         SpringApplication.run(EurekaApplication.class,args);
  6.     }
  7. }
复制代码
3、设置Eureka服务器:在应用程序的设置文件(如application.properties或application.yml)中设置Eureka服务器的相关信息,例如:
  1. # 服务器配置
  2. server:
  3.   port: 10001   # Eureka服务器运行的端口号
  4. # Spring应用程序配置
  5. spring:
  6.   application:
  7.     name: eurekaserver   # Eureka服务器应用程序的名称
  8. # Eureka客户端配置
  9. eureka:
  10.   client:
  11.     service-url:
  12.       defaultZone: http://localhost:10001/eureka/
  13.       # Eureka客户端注册自身的Eureka服务器的URL
  14.       # 在本例中,将Eureka服务器的URL设置为运行在10001端口的本地服务器
复制代码
3.2、注册user-service

这个操作是在user-service项目下实现的,主要是将服务信息注册到Eureka服务端,eureka将这些服务信息保存到注册表中进行管理。
将user-service服务注册到EurekaServer步骤:

1、在user-service项目中引入spring-cloud-starter-netflix-eureka-client的依赖

  1.    <dependency>
  2.          <groupId>org.springframework.cloud</groupId>
  3.          <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  4.    </dependency>
复制代码
2、在application.yml位置文件中编写设置

  1. spring:
  2.   application:
  3.     name: userservice  #配置服务名称
  4. eureka:
  5.   client:
  6.     service-url:
  7.       defaultZone: http://localhost:10001/eureka/   #配置eureka服务地址信息
复制代码
其实orderservice的注册也是这两个步骤,我就写了。
做完之后,我我们可以欣赏一下eureka的服务网站看一下:http://localhost:10001
这里的端标语是你在自己的eureka的设置文件application.yml设置的eureka端标语划一。

 总结:

1.服务注册

2.无论是斲丧者还是提供者,引入eureka-client依赖
知道eureka(服务注册中心)地址后,都可以完成服务注册
3.3、在order-service完成服务拉取

服务拉取是基于服务名称获取服务列表,然后在对服务列表做负载均衡
1.修改OrderService的代码,修改访问的url路径,用服务名代替ip、端口:

  1. String url ="http://userservice/user/" + order.getUserId();
复制代码
2.在order-service项目标启动类OrderApplication中的RestTemplate添加负载均衡注解:

  1. @Bean
  2. @LoadBalanced  #负载均衡
  3. public RestTemplate restTemplate() {
  4.     return new RestTemplate();
  5. }
复制代码
总结

1.搭建EurekaServer

2.服务注册

3.服务发现

四、Ribbon负载均衡

Ribbon是一个负载均衡解决方案,主要用于在分布式体系中将负载均匀地分发给多个服务实例。它是Netflix开 源的一个组件,常用于微服务架构中。
1、负载均衡流程


 Ribbon的负载均衡原理可以概括如下:
Ribbon还可以与其他组件配合利用,例如Netflix的Hystrix熔断器,用于实现服务的容错和故障掩护。
总之,Ribbon通过动态获取服务实例列表并根据负载均衡策略选择合适的实例来进行负载均衡,从而进步体系的性能、可用性和可扩展性。
源码实行流程:


 2、Ribbon负载均衡策略

Ribbon负载均衡规则是一个叫做IRule的接口来实现的,每个子接口都是一种规则:

2.1、 负载均衡策略


 2.2、调整负责均衡策略的规则

通过定义IRule实现可以修改负载均衡规则,有两种方式:
方式一:代码方式

如斲丧者服务order-service,只要在OrderApplication类中定义一个新的IRule:
  1. @Bean
  2. public IRule iRule(){
  3.     return new RandomRule();
  4. }
复制代码
其实也不一定要在OrderApplication启动类中设置,也可以自己创建一个设置类来设置,在有@configuration注解的类就可以。
这种设置方案是全局的设置,只要利用了这种设置方案,以后不管你调用的是user-service服务还是order-service服务都是利用这里的设置方案。
方式二:设置文件方式

在order-service的application.yml文件中,添加新的设置也可以修改规则:
  1. userservice: #被调用微服务器的服务名称
  2.   ribbon:
  3.     NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #负载均衡规则
复制代码
这种设置方案是只针对某个微服务的,是局部设置。
3、Ribbon饿加载

Ribbon默认是接纳懒加载,即第一次访问才会创建LoadBalanceClient,请求时间会很长。
而饿加载则会在项目启动时创建,降低每一次访问的耗时
3.1、设置开启设置饥饿加载

  1. #当服务饥饿加载
  2. ribbon:
  3.   eager-load:
  4.     enabled: true #开启饥饿加载
  5.     clients: userservice #指定对userservice这个服务饥饿加载
  6. #当有多个服务需要饥饿加载可以用下面的方式:
  7. ribbon:
  8.   eager-load:
  9.     enabled: true #开启饥饿加载
  10.     clients:  #指定对userservice这个服务饥饿加载
  11.         - userservice
  12.         - xxservice
复制代码
总结

1.Ribbon负载均衡规则


2.负载均衡自定义方式


3.饥饿加载


五、Nacos注册中心

微服务的注册中心我们已经学了eureka,大家肯定会有疑问,为啥还有学校nacos呢?
其实nacos不但有服务注册中心和服务发现功能,还有更加强盛的功能。
1、nacos和eureka对比

Nacos和Eureka是两个常用的服务发现和注册工具,它们都具有类似的功能,但在一些方面存在一些差异。以下是Nacos和Eureka的一些对比:
选择利用Nacos还是Eureka可以根据详细需求和项目背景来决定。如果需要更多的功能和特性,以及较强的容错性和高可用性,Nacos大概是更好的选择。如果项目已经依赖于Netflix和Spring Cloud生态圈,大概对于服务注册和发现的简单功能需求,Eureka大概是更适合的选项。
2、Nacos下载安装服务注册中心

2.1下载nacos

在Nacos的GitHub页面,提供有下载链接,可以下载编译好的Nacos服务端大概源代码:
GitHub主页:https://github.com/alibaba/nacos
GitHub的Release下载页:https://github.com/alibaba/nacos/releases
这里我提供了阿里云盘下载:Nacos1.4.1
2.2、解压Nacos

 我这里利用的是在Windows下安装的。

直接解压到一个没有中笔墨符的路径下。

 目录说明:

2.2.1、设置端口

Nacos的默认端口是8848,如果你电脑上的其它历程占用了8848端口,请先尝试关闭该历程。
**如果无法关闭占用8848端口的历程**,也可以进入nacos的conf目录,修改设置文件中的端口:

修改此中的内容修改为一个没有被占用的端标语。
2.2.2.启动nacos服务注册中心

启动非常简单,进入bin目录,进入cmd窗口实行下面的命令
  1. startup.cmd -m standalone
  2. #startup.cmd -m standalone 的含义是执行Nacos服务器的启动脚本,并使用独立模式启动Nacos服务器。
  3. #这将在单个节点上运行Nacos,并使用默认的配置文件和端口。这个命令适用于简单部署或测试,并非生产环境下常见的集群模式启动命令。
复制代码
实行后的效果如图: 

在欣赏器输入地址:http://127.0.0.1:8848/nacos即可:
用户名和暗码都是:nacos

 网页直接就是中文的,对于英语不太好的比eureka的友爱。
3、将服务注册到nacos服务注册中心

1、在cloud-demo父工程中添加spring-cloud-alibaba的管理依赖:
  1.             <!--nacos版本管理-->
  2.             <dependency>
  3.                 <groupId>com.alibaba.cloud</groupId>
  4.                 <artifactId>spring-cloud-alibaba-dependencies</artifactId>
  5.                 <version>2.2.5.RELEASE</version>
  6.                 <type>pom</type>
  7.                 <scope>import</scope>
  8.             </dependency>
复制代码
2、注释掉order-service和user-service中原有的eureka依赖。
3、添加nacos的客户端依赖:
  1.         <!-- nacos客户端依赖包 -->
  2.         <dependency>
  3.             <groupId>com.alibaba.cloud</groupId>
  4.             <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  5.         </dependency>
复制代码
4、修改user-service & order-service中的application.yml文件,注释掉eureka的地址,添加nacos地址:
  1. spring:
  2.   cloud:
  3.     nacos:
  4.       server-addr: localhost:8848
复制代码
启动项目测试:


 其实eureka和nacos在spring-cloud中除了依赖和端标语设置不同外其他的利用都是一样的,他们底层利用的接口都是一样的,所以代码其他地方根本不用做改变。
总结:

1.Nacos服务搭建


2.Nacos服务注册或发现


4、Nacos服务分级存储模子

之前我们在学中,我们的服务分层都是只有两层的,第一层是服务,第二层是实例(如user-service、order-service),在我们摆设时,都是将这些服务我实例摆设到一个机器上大概一个机房里,但是如果这个机房收到破坏(地动、火警)时,服务就无法访问了。

  而nacos服务分层存储模子则引出了集群的概念,一个集群就好比是我们的一个机房,而我们的一个服务下面就可以摆设很多个集群,每个集群就可以摆设在全球各地(北京、上海、深圳等),因此服务的层次结构就变成了三层(服务、集群、实例)。

4.1、服务跨集群调用问题



 4.2、服务集群实现

1、修改application.yml,添加如下内容,设置服务集群名称
  1. spring:
  2.   cloud:
  3.     nacos:
  4.       server-addr: localhost:8848
  5.   #nacos 服务端地址      cluster-name: YN #设置集群名称,也就是机房位置,例如:YN ,云南
复制代码
2、在Nacos控制台可以看到集群变革

 现在的集群变成了yn,在没有设置集群名称是default。
总结

1.Nacos服务分级存储模子


2.怎样设置实例的集群属性


4.3、Nacos集群负载均衡

Nacos集群负载均衡的规则其实是优先选择本集群内的服务,如果本服务挂了,才会去选择其他集群的服务来访问。
设置

1、修改order-service中的application.yml,设置集群为HZ:
  1. spring:
  2.   cloud:
  3.     nacos:
  4.       server-addr: Localhost:8848    # nacos 服务端地加discovery:cLuster-name: HZ
  5.       discovery:
  6.         cluster-name: bj    #配集群名称,也就是机房位置
复制代码
2、然后在order-service中设置负载均衡的IRule为NacosRule,这个规则优先会探求与自己同集群的服务:
  1. userservice:    #服务名称
  2.   ribbon:
  3.     NFLoadBalancerRulecassName: com.alibaba.cloud.nacos.ribbon.NacosRule #负载均衡规则
复制代码
3、注意将user-service的权重都设置为1
总结:

1.NacosRule负载均衡策略

4.4、根据权重负载均衡

假设有一个微服务架构的电子商务网站,此中包括以下几个服务:商品服务、订单服务和用户服务。这些服务都注册到了Nacos中进行服务发现,并且它们有不同的实例数和性能设置。在这种情况下,可以通过基于权重的负载均衡来实现对这些服务实例的合理请求分配。以下是一些示例场景:
通过在Nacos中设置服务实例的权重,可以根据现实情况动态调整请求的负载比例。如许可以或许充实利用资源、进步体系性能、包管服务稳定性,并对不同实例进行合理分配。
Nacos提供了权重设置来控制访问频率,权重越大则访问频率越高。
设置


 

 4.5、环境隔离-namespace

1、认识环境隔离-namvespace

应用场景:
假设有一个电商平台,该平台设计了一个基于Nacos的命名空间设置和服务注册方案,以支持环境隔离和多租户功能。
起首,假设该电商平台有三个环境:开发环境、测试环境和生产环境。每个环境都有独立的设置和服务需求。
通过如许的命名空间设置和服务注册方案,电商平台可以或许实现对不同环境的设置和服务进行隔离,并支持多租户功能。开发团队可以独立管理各自环境的设置和服务,而不会相互干扰。此外,平台还可以利用灰度发布和版本管理功能,在不同命名空间中进行服务版本控制,确保体系稳定性和可用性。
2、设置命名空间

1)创建命名空间(在nacos服务页面创建)




 2、将服务设置到指定的命名空间中(修改application.yml设置文件)

  1. server:
  2.   port: 8081
  3. spring:
  4.   datasource:
  5.     url: jdbc:mysql://192.168.10.130:3306/cloud-user?useSSL=false
  6.     username: root
  7.     password: root
  8.     driver-class-name: com.mysql.jdbc.Driver
  9.   application:
  10.     name: userservice  #配置服务名称
  11.   cloud:
  12.     nacos:
  13.       server-addr: localhost:8848
  14.       discovery:
  15.         cluster-name: yn #集群名称,地址在云南
  16.         namespace: 074da7cb-c3e3-4848-b893-3d15114e8729  #命令空间id
复制代码

 此时,设置了namespace的服务已经被设置到dev中了

 如果此时利用order-service去调用user-service就会报错了
  1. Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No instances available for userservice] with root cause
  2. servlet .service()的servlet [dispatcherServlet]在上下文与路径[]抛出异常[请求处理失败;嵌套异常是java.lang.IllegalStateException: No instances available for userservice],有根本原因
复制代码
5、nacos注册中介细节分析


 服务注册:服务提供者启动时,会向服务注册中心发起注册请求,包括服务名、IP 地址、端口等。注册中心会将这些信息保存起来。
服务发现:服务发现有两种(pull和push相联合)
心跳与康健检查:也是有两种(对临时实力和非临时实例)

负载均衡:负载均衡和流量控制是由服务斲丧者一侧的客户端组件来实现的,而不是由注册中心来处理处罚。当客户端从Nacos注册中心获取到可用的服务实例列表后,负载均衡和流量控制的责任落在了客户端的实现上。
5.1、临时实例与非临时实例

Nacos中的实例分为临时实例和非临时实例,它们在生命周期和用途上有所不同:
1、非临时实例(Persistent Instance):

2、临时实例(Ephemeral Instance):

临时实例和非临时实例在实践中有不同的应用场景:

需要注意的是,临时实例的自动注销是基于与Nacos注册中心之间的心跳连接,而非基于服务实例的详细运行状态。因此,在利用临时实例时,需要相应地设置和管理心跳连接,以包管实例的不间断注册和注销。
5.2、设置临时实例与非临时实例(默认是临时实例)

服务注册到nacos时,可以选择注册为临时或非临时实例,通过在application.yml文件中添加下面的设置来设置:
  1. spring:
  2.   cloud:
  3.     nacos:
  4.       discovery:   #discovery:发现,透露 ; ephemeral:短暂的
  5.         ephemeral: false  #设置为非临时实例
复制代码

 总结

1.Nacos与eureka的共同点


2.Nacos与Eureka的区别


6、Nacos设置管理

以下是几个利用Nacos设置管理的现实业务场景的例子:
这些例子只是Nacos设置管理功能的一部分,Nacos还提供了更多的特性,例如设置监听、设置推送等,可以根据详细的业务需求进行机动利用。
6.1、统一设置管理

6.1.1、设置更改热更新


 在Nacos中添加设置信息:

 在弹出表单中填写设置信息:

 在nacos服务页面中设置,让服务找到nacos的设置:
1、引入nacos的设置管理客户依赖:

  1.         <!--nacos配置管理依赖-->
  2.         <dependency>
  3.             <groupId>com.alibaba.cloud</groupId>
  4.             <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  5.         </dependency>
复制代码
2、在userservice中的resource目录添加一个bootstrap.yml文件,这个文件是引导文件,优先级高于application.yml:

  1. spring:
  2.   application:
  3.     name: userservice  #配置服务名称
  4.   cloud:
  5.     nacos:
  6.       server-addr: localhost:8848   #配置nacos服务地址
  7.       config:
  8.         file-extension: yaml  #文件后缀
  9.   profiles:
  10.     active: dev  #开发环境,这里是dev
复制代码
可以在Usercontroller类中获取一下nacos设置的信息来验证一下:
  1.     @Value("${pattern.dateformat}")
  2.     private String dateformat;
  3.     @GetMapping("/now")
  4.     public String now(){
  5.         return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));
  6.     }
复制代码
6.1.2、设置自动刷新

nacos中的设置文件变动后,微服务无需重新启动就可以感知。不过需要通过下面两种设置实现:
方式一:在@Value注入的变量所在类上添加注解@RefreshScope


 方式二:利用@ConfigurationProperties注解

这种方式利用的是约束大于设置的设置方法。
  1. @Data
  2. @Component
  3. @ConfigurationProperties(prefix = "pattern")
  4. public class PatternProperties {
  5.     private String dateformat;
  6. }
复制代码
利用了Spring框架的注解(Data,Component,ConfigurationProperties)。这段代码定义了一个名为PatternProperties的类。
@ConfigurationProperties注解是Spring框架中用于绑定设置属性的注解。它的prefix属性指定了设置文件中的属性前缀为"pattern",这意味着在设置文件中,全部以"pattern"开头的属性会被绑定到PatternProperties类的对应属性上。
PatternProperties类中只有一个私有的String类型属性dateformat,它对应设置文件中的"pattern.dateformat"属性。在设置文件中,你可以设置这个属性的值,例如:
  1. pattern:
  2.   dateformat: yyyy-MM-dd HH:mm:ss
复制代码
如许,当你运行程序时,Spring框架会自动将设置文件中的值绑定到PatternProperties类的dateformat属性上,你可以通过获取PatternProperties实例的方式来访问并利用这个属性的值。
在类中利用nacos中设置时可以通过以下方式获取:

 总结

Nacos设置更改后,微服务可以实现热更新,方式:


注意事项:


7、Nacos集群搭建

7.1、集群结构图

官方给出的Nacos集群图:

此中包含3个nacos节点,然后一个负载均衡器署理3个Nacos。这里负载均衡器可以利用nginx。

DNS(Domain Name System)、SLB(Server Load Balancer)和Nacos可以一起利用来构建一个完整的服务发现和负载均衡的体系。
DNS是用于将域名解析为对应的IP地址的体系。在服务发现和负载均衡中,DNS可以被用来解析服务名称为对应的服务实例的IP地址。例如,假设有一个服务名为"my-service",通过将其注册到DNS中,可以将"my-service"解析为详细的服务实例的IP地址。
SLB是一种负载均衡器,用于将流量分发到多个后端服务实例上,从而实现负载均衡和高可用性。SLB可以接收客户端请求,并根据负载均衡算法将请求分发到多个服务实例上。例如,当有多个服务实例提供相同的服务时,SLB可以根据负载情况,将请求分发到负载较低的实例上,以实现流量的均衡分布。
Nacos是一个用于服务发现、设置管理和服务治理的开源项目。在服务发现和负载均衡中,Nacos作为服务注册中心和设置中心,可以用来管理各个服务实例的注册和注销,以及维护服务实例的元数据信息。Nacos可以提供给SLB和DNS所需的服务实例信息,从而实现服务发现和负载均衡的功能。
联合这三个组件,团体的架构可以如下所示:
通过如许的结构,客户端可以通过DNS解析获取到服务实例的IP地址,并通过SLB将请求发送到可用的服务实例上,实现负载均衡。同时,Nacos作为服务注册中心和设置中心,可以管理服务实例的注册和设置信息,以确保服务的可用性和设置的划一性。如许的架构既提供了可靠的服务发现和负载均衡,也包管了设置的会合管理和动态更新本领。
我们计划的集群结构:


 三个nacos节点的地址:
  1. | 节点   | ip            | port |
  2. | nacos1 | 192.168.150.1 | 8845 |
  3. | nacos2 | 192.168.150.1 | 8846 |
  4. | nacos3 | 192.168.150.1 | 8847 |
复制代码
7.2、集群搭建

搭建集群的基本步骤:
  1. - 搭建数据库,初始化数据库表结构
  2. - 下载nacos安装包
  3. - 配置nacos
  4. - 启动nacos集群
  5. - nginx反向代理
复制代码
















六、Feign远程调用

RestTemplate方法调用存在的问题

先看一下我们从前利用RestTemplate发起远程调用的代码:

存在下面的问题:

1、Feign的介绍

Feign 提供了一种简单且优雅的方式来定义和调用基于HTTP的远程服务。通过利用Feign,您可以在客户端代码中定义接口,然后Feign会根据这些接口的定义自动生成现实的HTTP请求,并将其转发到远程服务。如许,您可以像调用本地方法一样调用远程服务的方法,无需显式地处理处罚HTTP请求和响应。
Feign 还支持对请求进行编码和解码、错误处理处罚、请求和响应拦截器等功能,使得在微服务架构中处理处罚远程服务变得更加方便和高效。
利用Feign的一些优点包括:
在利用Feign时,您需要定义一个Java接口,该接口包含与远程服务相对应的方法和参数。然后,通过在应用程序的设置中启用Feign并利用Spring的依赖注入功能,您可以将Feign客户端注入到您的代码中,从而实现对远程服务的调用。
Feign作为一个声明式的HTTP客户端,在微服务架构和分布式体系中有许多应用场景。以下是一些常见的利用场景:
总体而言,Feign实用于任何需要在微服务架构中进行HTTP通讯的场景,特殊是当您希望简化远程服务调用的代码并增加可读性和可维护性时,Feign是一个非常有用的工具。
2、定义和利用Feign客户端

在之前我是在调用其他服务提供的接口是利用的是RestTempale,为什么还要学Feign呢?
Feign和RestTemplate都是在Spring框架中用于进行HTTP请求的工具,但它们在利用方式和特点上有一些区别。
综上所述,如果您在利用Spring Cloud和微服务架构,特殊是在Feign与Ribbon、Eureka等组件进行集成时,Feign大概是更好的选择,因为它提供了一种简单且声明式的方式来定义和调用远程服务。然而,如果您在非微服务环境或不需要Spring Cloud提供的其他功能,RestTemplate仍然是一个可行的选择,尤其是当您需要更多的机动性和对HTTP请求的直接控制时。
2.1、Feign实战

定义和利用Feign客户端需要以下步骤:
1、添加依赖:起首,您需要在项目中添加Feign的依赖。如果您是利用Spring Boot项目,可以在pom.xml中添加以下依赖:
  1. <dependency>
  2.     <groupId>org.springframework.cloud</groupId>
  3.     <artifactId>spring-cloud-starter-openfeign</artifactId>
  4. </dependency>
复制代码
2、启用Feign客户端:为了使Feign客户端生效,您需要在Spring Boot应用程序的主类上添加@EnableFeignClients注解,这将启用Feign客户端的自动设置和发现。
  1. @MapperScan("cn.itcast.order.mapper")
  2. @SpringBootApplication
  3. @EnableFeignClients
  4. public class OrderApplication {
  5.     public static void main(String[] args) {
  6.         SpringApplication.run(OrderApplication.class, args);
  7.     }
  8. }
复制代码
3、创建Feign客户端接口:接下来,您需要定义一个Java接口,该接口将包含与远程服务相对应的方法和参数。这些方法的定义类似于平凡的Spring组件接口,但是您可以利用Spring的注解来定义远程服务的URL、HTTP方法和其他相关信息。
  1. package cn.itcast.order.clients;
  2. import cn.itcast.order.pojo.User;
  3. import org.springframework.cloud.openfeign.FeignClient;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.PathVariable;
  6. @FeignClient("userservice")  //使用@FeignClient来指导这个接口所有接口方法要访问的服务名称
  7. public interface UserClient {
  8.     //定义调用接口
  9.     @GetMapping("/user/{id}")  
  10.     User findUserById(@PathVariable("id") Long id);
  11. }
复制代码

 4、利用Feign客户端:现在您可以在其他组件或服务中注入Feign客户端,并利用它来调用远程服务的方法。
  1. package cn.itcast.order.service;
  2. import cn.itcast.order.clients.UserClient;
  3. import cn.itcast.order.mapper.OrderMapper;
  4. import cn.itcast.order.pojo.Order;
  5. import cn.itcast.order.pojo.User;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.stereotype.Service;
  8. @Service
  9. public class OrderService {
  10.     @Autowired
  11.     private OrderMapper orderMapper;
  12.     @Autowired
  13.     private UserClient userClient;   //注入User的Feign客户端
  14.     public Order queryOrderById(Long id){
  15.         Order order = orderMapper.findById(id);
  16.         Long userId = order.getUserId();
  17.         //使用Feign远程调用
  18.         User user = userClient.findUserById(userId);
  19.         order.setUser(user);
  20.         return order;
  21.     }
  22. }
复制代码
总结

Feign的利用步骤
3、自定义Feign的设置

Feign运行自定义设置来覆盖默认设置,可以修改的设置如下:

 一样平常我们需要设置的就是日志级别。
日志级别

Feign支持四种不同的日志级别,您可以根据需要选择适合的日志级别。这些日志级别用于控制Feign在发送请求和接收响应时记载的日志信息的详细程度。
3.1自定义Feign的设置方式

方式一:设置文件方式

当利用设置文件的方式来设置Feign的自定义设置时,您可以借助Spring Boot的属性设置功能来实现。通过在设置文件(如application.properties或application.yml)中添加特定的属性,您可以自定义Feign的行为。
起首,您需要在设置文件中添加Feign的相关属性。以YAML格式的设置文件为例,假设您想要设置Feign的日志级别为FULL,可以如许写:
1、全局生效

  1. # application.yml
  2. feign:
  3.   client:
  4.     config:
  5.       default: #这里用default就是全局配置,如果是写服务器名称,则是针对在某个微服务的配置
  6.         loggerLevel: full  #日志级别
复制代码
2、局部生效

  1. # application.yml
  2. feign:
  3.   client:
  4.     config:
  5.       orderservice:    #这里用服务名称,则只针对这个服务的配置
  6.         loggerLevel: full   #日志级别
复制代码
方式二:java代码方式,需要先声明一个Bean:

在利用Feign时,您可以通过自定义设置来修改其行为和属性。为了自定义Feign的设置,您需要创建一个设置类,并在此中添加相关的Bean定义。下面是一个简单的示例来说明怎样自定义Feign的设置:
  1. package cn.itcast.order.config;
  2. import feign.Logger;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. @Configuration
  6. public class FeignConfig {
  7.     @Bean
  8.     public Logger.Level feignLogLevel(){
  9.         return Logger.Level.BASIC;
  10.     }
  11. }
复制代码
全局设置:

如果是全局设置,则把它放到@EnableFeignClients这个注解中:
  1. @EnableFeignClients(defaultConfiguration = FeignConfig.class)
复制代码
局部设置:

如果是局部设置,则把它放到@FeignClient这个注解中:
  1. @FeignClient(value = "userservice",configuration = FeignConfig.class)  
复制代码
总结

Feign的日志设置
1.方式一是设置文件,feign.client.config.xxx.loggerLevel
2.方式二是java代码设置Logger.Level这个Bean
4、Feign的性能优化

Feign的底层客户端实现是通过集成了其他HTTP客户端库来实现的。详细来说,Feign支持两种主要的HTTP客户端实现:JDK的URLConnection和Apache HttpClient。
Feign的这种设计使得您可以根据需要机动地选择底层的HTTP客户端。默认情况下,如果项目中没有引入其他HTTP客户端库,Feign将利用JDK的URLConnection作为底层客户端。如果您希望利用Apache HttpClient或OkHttp,只需在项目中添加相应的依赖,Feign会自动检测并利用它们作为底层实现。
通过这种方式,Feign可以同时满意不同项目对HTTP客户端的需求,并提供简便的远程服务调用方式。
因此优化Feign的性能主要包括:

4.1、 Feign性能优化HttpClient的支持:

1、Feign添加HttpClient的支持:

引入依赖:
  1.         <dependency>
  2.             <groupId>io.github.openfeign</groupId>
  3.             <artifactId>feign-httpclient</artifactId>
  4.         </dependency>
复制代码
设置连接池:
  1. #feign自定义配置,配置日志级别
  2. feign:
  3.   client:
  4.     config:
  5.       default:  #这里用default就是全局配置,如果是写服务器名称,则是针对在某个微服务的配置
  6.         loggerLevel: basic  #日志级别
  7.   httpclient:
  8.     enabled: true   #开启feign对HttpClient的支持
  9.     max-connections: 200   #最大连接数量
  10.     max-connections-per-route: 50   #每个路径的最大连接数量
复制代码
总结

Feign的优化
1.日志级别尽量用basic
2.利用HttpClient或OKHttp代替URLConnection
5、Feign的最佳现实

方式一(继承):给斲丧者的FeignClient和提供者的controller体系定义一个父接口作为标准。



这种实现方式虽然可以让Controller和Feign Client共享同一个接口定义,但存在一些问题和注意事项:
综上所述,虽然共享接口可以在一定程度上减少重复代码,但也会引入潜在的问题和复杂性。在现实开发中,更常见的做法是将Controller和Feign Client分别定义独立的接口,通过接口定义来规范各自的功能和职责。在需要共享方法定义的情况下,可以利用Java接口继承来实现方法的复用,而制止在Feign Client中直接实现Controller的方法。如允许以更好地保持代码的清晰和可维护性,并符合单一职责原则。



方式二(抽取):将FeignClient抽取为独立模块,并且把接口有关的POJO、默认的Feign设置都放到这个模块中,提供给全部斲丧者利用


从前实现 

如果:我们有order-service、pay-service和user-service两个服务,现在order-service和pay-service都要去调用user-service提供的接口,我们就得order-service和pay-service服务里都要实现UserClient,如果我们不止只有这两个服务调用user-service呢,有10个、20个服务都要调用,那UserClient就得写10遍、20遍,就会重复的开发代码了。

现在

我们独立创建一个项目,将哪些重复的代码编写的东西全部放到这个项目/模块中(如UserClient、User实体类、DefaultConfig等),我们可以把这个项目标内容打成jar包,如果以后服务需要的时候直接引用依赖就可以

 总结

Feign的最佳实践
 抽取FeignClient

实现最佳实践方式二的步骤如下:

1、创建一个module,命名为feign-api,然后引入feign的starter依赖


引入feign的starter依赖:
  1.     <dependency>
  2.         <groupId>org.springframework.cloud</groupId>
  3.         <artifactId>spring-cloud-starter-openfeign</artifactId>
  4.     </dependency>
复制代码
2、将order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中


 之前在order-service服务模块中饿这些东西就可以删除了。
 3、在order-service中引入feign-api的依赖

  1.         <!--引入feign的同一api-->
  2.         <dependency>
  3.             <groupId>cn.itcast.demo</groupId>
  4.             <artifactId>feign-api</artifactId>
  5.             <version>1.0</version>
  6.         </dependency>
复制代码
这个依赖是我们项目中的feign-api模块里的内容。
4、修改order-service中的全部与上述三个组件有关的import部分,改成导入feign-api中的包


5、重启测试


当定义的FeignClient不在springApplication的包扫描范围时,这些FeignClient无法利用问题

重启order-service服务后我们会发现报错了
  1. Field userClient in cn.itcast.order.service.OrderService required a bean of type 'cn.itcast.feign.clients.UserClient' that could not be found.
  2. 该错误信息表明在OrderService类中的userClient字段的类型为cn.itcast.feign.clients.UserClient,但是Spring容器中找不到该类型的Bean。
复制代码
说明我们在自动装配UserClient时是找不到这个对象的实例的,缘故原由是我们现在在order-service模块中利用的UserClient是通过添加了feign-api依赖而导进来的,在order-service模块启动时spring只会对启动类所在目录及这个目录里全部类进行扫描注册到spring容器中的,而UserClient所在的包就没有被扫描到,所在在order-service这个模块中的spring容器中就找不到了对于的对象实例了。
解决办法方式一:指定FeignClient所在包

  1. @EnableFeignClients(basePackages = "cn.itcast.feign.clients")
复制代码
解决办法方式二:指定FeignClient字节码

  1. @EnableFeignClients(clients = {UserClient.class})
复制代码
总结

不同包的FeignClient的导入有两种方式
七、Gateway服务网关

网关(Gateway)服务在微服务架构中起着重要的作用。它是位于客户端和后端微服务之间的中间层,用于处理处罚和转发请求。为什么要利用网关服务呢?以下是一些主要的缘故原由:
综上所述,网关服务在微服务架构中饰演了一个重要的角色,它提供了统一入口、路由和负载均衡、安全控制、聚合和分解请求、缓存、降级和容错、监控和日志等功能,为整个体系提供了更高效、更安全、更稳定的请求处理处罚和管理本领。

1、网关技能

 在springcloud中网关的实现有两种:gateway和zuul
Zuul和Spring Cloud Gateway都是常用的网关实现,用于在微服务架构中处理处罚和转发请求。它们都可以作为反向署理和请求路由器,但在设计和功能上有一些区别。
综合来说,Zuul和Spring Cloud Gateway都是成熟的网关实现,各有优势。如果您在利用Spring Cloud项目,推荐利用Spring Cloud Gateway,特殊是在需要高并发和响应本领的场景下。而如果您在利用Netflix项目,可以选择利用Netflix Zuul 2.x版本或更高的版本,或考虑迁徙到Spring Cloud Gateway。选择哪个网关取决于您的项目需求、技能栈和预期的性能要求。
总结

网关的作用:

2、搭建网关服务

2.1、搭建网关服务的步骤:

  1. <dependencies>
  2.     <!-- Spring Cloud Gateway -->
  3.     <dependency>
  4.         <groupId>org.springframework.cloud</groupId>
  5.         <artifactId>spring-cloud-starter-gateway</artifactId>
  6.     </dependency>
  7.     <!-- Spring Cloud Nacos 作为服务注册和发现中心 -->
  8.     <dependency>
  9.         <groupId>com.alibaba.cloud</groupId>
  10.         <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  11.     </dependency>
  12.     <!-- 其他依赖 -->
  13. </dependencies>
复制代码
3、设置网关路由:在application.yml中设置网关的路由规则,将请求路由到对应的微服务。例如:
  1. server:
  2.   port: 10009  # 配置服务端口
  3. spring:
  4.   application:
  5.     name: gateway  # 服务名称
  6.   cloud:
  7.     nacos:
  8.       server-addr: localhost:8848  # 配置Nacos注册中心的地址和端口
  9.     gateway:
  10.       routes:
  11.         - id: userservice_route   # 路由规则的唯一标识,用于识别该路由规则。自定义的标识可以方便管理和维护。
  12.           uri: lb://userservice   # 指定目标微服务的服务名。lb://前缀表示使用负载均衡器来选择目标微服务的实例。这里目标微服务的服务名是userservice。
  13.           predicates:    # 断言条件列表,用于匹配请求是否符合该路由规则。
  14.             - Path=/user/**      # 匹配的URL路径,当请求的URL路径以/user/开头时,该路由规则会匹配。**表示匹配任意后续路径。
  15.         - id: orderservice_route   # 另一个路由规则的唯一标识,用于识别该路由规则。
  16.           uri: lb://orderservice  # 指定目标微服务的服务名。这里目标微服务的服务名是orderservice。
  17.           predicates:             # 断言条件列表,用于匹配请求是否符合该路由规则。
  18.             - Path=/order/**      # 匹配的URL路径,当请求的URL路径以/order/开头时,该路由规则会匹配。**表示匹配任意后续路径。
复制代码
4、启动nacos服务
  1. #Windows系统命令
  2. startup.cmd -m standalone
  3. #Linux系统命令
  4. sh startup.sh -m standalone
复制代码
就可以直接利用gateway的ip+端口来访问数据了,可以直接让gateway来将这些访问地址转发到相应的服务实例上,从而来访问数据(如访问地址:localhost:10009/order/101)
2.2、搭建网关服务流程图



通过服务注册中心(如Nacos)来进行服务发现,Gateway可以或许动态地获取微服务的实例信息,从而实现请求的动态转发和负载均衡。如许,Gateway就能找到相应的服务并将请求转发给它们。感谢您的指正,希望这次的回答更加准确。
总结

网关搭建步骤

路由设置包括

3、路由断言工厂Route Predicate Factory


3.1、spring提供了11种基本的Predicate工厂


 当利用其他的Predicate工厂时,可到spring官网上看怎样利用:spring route

 总结


        读取用户定义的断言条件,对请求做出判断

        路径是以/user开头的就认为是符合的
4、路由过滤器(Route Filter)

路由过滤器(Route Filter)是Spring Cloud Gateway中的另一个重要组件,它用于在请求被路由到目标服务之前或之后,对请求或响应进行一系列的处理处罚操作。通过路由过滤器,您可以对请求和响应进行修改、加强或验证,从而实现更加机动和强盛的网关功能。


 例如:
假设我们有一个微服务架构,包含多个服务,此中一个是认证服务(Authentication Service),负责处理处罚用户的身份认证。其他服务(如用户服务、订单服务等)需要掩护某些资源,只允许经过认证的用户访问。
在这种情况下,我们可以利用Spring Cloud Gateway作为网关,通过路由过滤器来实现请求认证和授权:
如许,通过路由过滤器,我们可以实现全局的请求认证,并对需要授权访问的服务进行权限控制。用户在发起请求时,起首经过全局过滤器进行认证,然后再经过局部过滤器进行权限验证。只有通过认证和授权的请求才能继续访问后端的微服务。
这种方式使得认证和授权逻辑从业务服务中剥离出来,统一交给网关进行处理处罚,简化了业务服务的实现和管理,同时进步了体系的安全性和可维护性。
4.1、过滤工厂 GratewayFilterFactory

在Spring Cloud Gateway中,过滤工厂(Filter Factory)是用于创建过滤器的工厂类,它用于生成过滤器实例并设置过滤器的行为。过滤工厂是一种更高级别的抽象,它将过滤器的创建和设置过程封装在一起,使得设置网关过滤器更加简单和机动。
过滤工厂与过滤器的区别在于:

过滤工厂的优势在于,它提供了一些预定义的工厂,可以轻松地为常见的过滤器场景创建过滤器,而无需开发者自己编写过滤器的实现。通过简单的设置,开发者可以利用这些预定义的过滤工厂创建自定义的过滤器,从而实现特定的路由和请求处理处罚逻辑。
spring提供了31种不同的路由过滤器工厂,一些常用的过滤工厂包括:

通过利用过滤工厂,您可以在网关中快速设置和管理过滤器,实现对请求和响应的机动处理处罚。过滤工厂是Spring Cloud Gateway提供的一种高级设置方式,帮助开发者更加方便地定制和扩展网关的功能。
如果想利用其他的可以到过往进行学习:spring GatewayFilterFactory

4.1.1、案例

 给全部进入userservice的请求添加一个请求头


 默认过滤器


总结


                对路由的请求或响应做加工处理处罚,比如添加请求头
                设置在路由下的过滤器只对当前路由的请求生效

                对全部路由都生效的过滤器
5、全局过滤器 GlobalFilter

全局过滤器(Global Filter):我们可以创建一个全局过滤器来拦截全部的请求,在这个过滤器中进行用户身份认证的检查。比如,我们可以检查请求中是否包含有效的身份令牌(Token),以确定请求是否是经过认证的用户发起的。
全局过滤器的作用也是处理处罚一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。区别在于GatewayFilter通过设置定义,处理处罚逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。定义方式是实现GlobalFilter接口。


5.1、实现步骤

自定义来,实现GlobalFilter接口,添加@Order注解
  1. import org.springframework.cloud.gateway.filter.GlobalFilter;
  2. import org.springframework.core.Ordered;
  3. import org.springframework.http.HttpStatus;
  4. import org.springframework.stereotype.Component;
  5. import org.springframework.util.MultiValueMap;
  6. import org.springframework.web.server.ServerWebExchange;
  7. import reactor.core.publisher.Mono;
  8. /**
  9. * 自定义全局过滤器:用于校验请求中的authorization参数是否合法
  10. */
  11. @Component
  12. @Order(-1)
  13. public class AuthorizeFilter implements GlobalFilter {
  14.     /**
  15.      * 过滤器方法,用于校验请求中的authorization参数是否合法
  16.      * @param exchange 服务器WebExchange对象,包含请求和响应信息
  17.      * @param chain GatewayFilterChain对象,用于传递请求给下一个过滤器或路由处理器
  18.      * @return Mono<Void>,表示请求的处理结果
  19.      */
  20.     @Override
  21.     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  22.         // 获取请求参数
  23.         MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
  24.         // 获取authorization参数
  25.         String authorization = params.getFirst("authorization");
  26.         // 校验authorization参数
  27.         if ("ltc".equals(authorization)) {
  28.             // 授权通过,请求继续传递给下一个过滤器或路由处理器
  29.             return chain.filter(exchange);
  30.         } else {
  31.             // 授权不通过,设置响应状态码为403(禁止访问),并结束处理,返回禁止访问的响应
  32.             exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
  33.             return exchange.getResponse().setComplete();
  34.         }
  35.     }
  36. }
复制代码
总结

全局过滤器的作用是什么?

实现全局过滤器的步骤?
6、过滤器实行顺序

请求进入网关会遇到三类过滤器: 当前路由的过滤器、DefaultFilter、GlobalFilter
请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,归并到一个过滤器链(集合)中,排序后依次实行每个过滤器。
这是我们就会想,这三个过滤器相同吗?怎么就可以放在同一个集合中进行排序了,别发急。
 对于当前路由过滤器和DefaultFilter的设置方法黑白常相似的,区别就是当前路由过滤器放在路由内,而DefaultFilter是放在默认的过滤器内的。从java的底层来看他两个本质是一样的,只是作用范围不一样而已。

 在设置文件中设置的当前路由过滤器和DefaultFilter(默认过滤器)都是由AddRequestHeaderGatewayFilterFactory过滤器工厂来读取,然后生成了GatewayFilter过滤器,所以这两个过滤器本质都是同一类,他们两个都叫GatewayFilter过滤器。

但是GlobalFilter全局过滤器为什么又可以和GatewayFilter来进行设置实行呢?
在网关中有一个适配器GatewayFilterAdapter,他就可以将GlobalFilter适配成GatewayFilter来用。

 GatewayFilterAdapter适配器这个类就实现了GatewayFilter接口,他内部还接收了GlobalFilter全局过滤器,如果我们给他传入一个GlobalFilter全局过滤器,他就会将GlobalFilter适配成GatewayFilter来用。所以在网关中全部的过滤器都会被适配成Gateway来利用,所以这些过滤器就可以放到一个集合中来进行排序了。

这时就会出现一个新的问题了,那放到了一个集合后,有怎么进行排序呢?
6.1、过滤器执怎样排序


 多余多个路由过滤器 和多个默认路由器:


但是当默认过滤器、路由过滤器和GlobalFilter全局过滤器的order值相同呢,那又该怎么办呢?

底层源码中有两个类是用来加载这三种过滤器的:

当服务启动后RouteDefinitionRouteLocator类的getFilter()方法会起首实行,会先去设置文件中加载defaultFilters,然后才会去加载某个路由的route的filter,然后归并。 
当getFilter()方法实行完后,FilteringWebHandler类的handle()方法才会进行加载全局过滤器,加载后会与之前加载的过滤器归并后更具order排序,组织过过滤器链
总结

路由过滤器、defaultFilter、全局过滤器的实行顺序?
7、跨域问题处理处罚

7.1、超干涉题

跨域问题(Cross-Origin Issue)是由欣赏器的同源策略引起的。同源策略是一种安全机制,限定了网页文档或脚本从一个源(协议、域名、端标语的组合)加载或操作另一个源的内容。如果两个网页的协议、域名和端标语都相同,它们就是同源的,否则就被认为是跨域的。
跨域:域名不划一就是跨域,主要包括:

超干涉题:欣赏器禁止请求的发起者和服务端发生跨域Ajax请求,请求被欣赏器拦截的问题。
跨域问题的出现是为了防止恶意网站利用客户端的漏洞进行攻击,掩护用户的隐私和安全。欣赏器会欺压实行同源策略,禁止网页在不同源之间进行以下操作:
举个例子来说明跨域问题:假设网站A的域名是 https://www.example.com,网站B的域名是 https://api.example.com。如果网站A的网页中利用 XMLHttpRequest 或 Fetch API 向网站B发送请求,那么由于它们不是同源的,欣赏器会阻止这个请求,返回一个错误。这就是跨域问题。
7.2、超干涉题解决办法 CORS

只需要在application.yml文件中添加下面的设置即可。
  1. spring:
  2.   cloud:
  3.     gateway:
  4.       globalcors:
  5.         corsConfigurations:
  6.           '[/**]': # 配置所有路径的全局CORS设置
  7.             allowedOrigins: "https://example.com" # 允许的跨域请求源,这里设置为https://example.com
  8.             allowedMethods: "GET, POST, PUT, DELETE" # 允许的请求方法,这里设置为GET、POST、PUT、DELETE
  9.             allowedHeaders: "*" # 允许的请求头,这里设置为"*"表示允许任意请求头
  10.             allowCredentials: true # 是否允许发送凭证信息(如Cookie),这里设置为true表示允许发送凭证信息
  11.             maxAge: 3600 # 预检请求的缓存时间(单位:秒),这里设置为3600秒
  12.         add-to-simple-url-handler-mapping: true  #处理option请求被拦截问题
复制代码
 设置详细介绍:
通过以上设置,Spring Cloud Gateway 将会在响应中添加相应的CORS响应头,允许来自 https://example.com 域名的跨域请求,允许的方法有 GET、POST、PUT、DELETE,允许任意请求头,允许发送凭证信息(如 Cookie),并且预检请求的缓存时间为 3600 秒。
总结

·CORS跨域要设置的参数包括哪几个?

 此篇是在学习黑马课springcloud程是做的详细的条记,内容是自己总结事后,易懂,但是就是篇幅有点多,需要大家多花时间去看。

---------------------
作者:m0_62498006
来源:CSDN
原文:https://blog.csdn.net/m0_62498006/article/details/131927338
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4