SpringCloud微服务架构(eureka、nacos、ribbon、feign、gateway等组件的详 ...

打印 上一主题 下一主题

主题 558|帖子 558|积分 1674

一、微服务演变

1、单体架构(Monolithic Architecture)

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

  • 利用缓存:引入缓存机制,将经常请求的数据缓存起来,减少对数据库等后端体系的访问,以进步性能。
  • 数据库优化:进行数据库性能调优,包括建立索引、优化查询语句、利用合适的数据库引擎等,以进步数据库的响应速度。
  • 利用消息队列:引入消息队列来解耦耗时操作,将其转化为异步的处理处罚任务。如允许以进步并发处理处罚本领和体系的响应性能。
  • 程度扩展:通过复制多个实例来处理处罚更多的请求。可以利用负载均衡器将请求分发到不同的实例上,从而进步体系的团体性能和容量。
  • 引入分布式架构:将应用程序拆分为多个独立的服务,并通过网络进行通讯和协作。如允许以将负载分散到多个节点上,进步团体性能和可伸缩性。

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

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

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


  • 服务拆分到什么程度?
  • 服务集群地址怎样维护?
  • 服务之间怎样实现远程调用?
  • 服务康健状况怎样感知?

 3、微服务

 微服务是一种经过改精良的架构设计的分布式架构方案,微服务架构特性:

  • 单一职责:微服务拆分力度更小,每个服务都对应唯一的服务本领,做的单一职责,制止重复开发
  • 面向服务:微服务对外袒露业务接口
  • 自治:团队独立、技能独立、数据独立、摆设独立
  • 隔离性强:服务调用做好隔离、容错、降级,制止出现级联问题
如果我们有一个电商体系,此中有以下一些微服务:

  • 用户服务(User Service)负责用户的注册、登录、信息管理等功能。
  • 商品服务(Product Service)负责商品的查询、添加、更新等功能。
  • 订单服务(Order Service)负责订单的创建、支付、取消等功能。
现在假设用户服务依赖于商品服务来获取商品信息,并且订单服务依赖于用户服务来获取用户信息。这里我们可以看到微服务的几个特性是怎样应用的:

  • 单一职责:每个微服务都具有清晰的职责。例如,用户服务只负责用户相关的功能,而不涉及商品或订单。
  • 面向服务:每个微服务都对外袒露业务接口,其他微服务可以通过调用这些接口来访问所需的功能。例如,用户服务可以提供获取用户信息的接口给订单服务利用。
  • 自治:每个微服务的团队在技能和数据上都是独立的。例如,用户服务的团队可以独立开发、测试、摆设和扩展该服务,无需依赖其他团队。
  • 隔离性强:微服务之间的调用需要做好隔离、容错和降级,以制止出现级联问题。例如,当商品服务不可用时,用户服务可以利用缓存或默认数据来制止影响用户操作。
这个例子中提供了不同的微服务来处理处罚不同的功能,并且彼此解耦、独立运行。每个微服务都具有单一职责,对外提供明确定义的业务接口,团队在技能和数据上具有自治本领,同时接纳适当的隔离步伐来包管体系的弹性和稳定性。这些特性有助于进步开发效率、机动性和可维护性,使得微服务架构在构建大型、复杂体系时具有优势。

4、 总结

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


  • 优点:拆分粒度更小、服务更独立、耦合更低
  • 缺点:架构非常复杂,运维、监控、摆设岂非更高
5、微服务架构

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

5.1、 微服务技能对比


 Dubbo、Spring Cloud、Spring Cloud和Spring Cloud Alibaba都是用于构建分布式体系的开源框架。只管它们的目标相同,但它们在实现方式和功能特点上有所不同。

  • Dubbo:Dubbo是一个高性能的分布式服务框架,由阿里巴巴开发。它基于传统的服务治理理念,提供了服务注册、发现、路由、负载均衡、容错等功能。Dubbo的核心特点是高性能和低延迟的RPC调用,实用于大规模的微服务架构。Dubbo提供了对多种协议(如Dubbo协议、REST协议)和注册中心(如ZooKeeper、Consul)的支持。
  • Spring Cloud:Spring Cloud是一个由Pivotal开发的微服务框架,构建在Spring Framework之上,使得构建分布式体系更加便捷。它提供了一系列的组件和模块,用于实现服务注册与发现、负载均衡、断路器、设置管理、消息总线等功能。Spring Cloud接纳了Spring Boot作为底层的开发框架,提供了更简洁、快速搭建分布式体系的解决方案。
  • Spring Cloud Alibaba:Spring Cloud Alibaba是Spring Cloud与Alibaba开放平台互助的效果,提供了一些在云原生应用开发中常用的解决方案。它主要基于Spring Cloud框架,联合了一些Alibaba技能栈,如Nacos(服务注册与发现)、Sentinel(流量控制和熔断降级)、RocketMQ(消息驱动)等。Spring Cloud Alibaba旨在提供云原生应用开发的全栈解决方案。
虽然Dubbo和Spring Cloud都是用于构建分布式体系的框架,但Dubbo更加注重于高性能的RPC调用和服务治理,而Spring Cloud则提供了一整套更全面的微服务解决方案。而Spring Cloud Alibaba则是在Spring Cloud的基础上,进一步整合了Alibaba的一些技能,为云原生应用提供更全面的开发支持。选择适合的框架取决于详细的需求、技能栈和团队偏好。
5.2、企业需求




  • Spring Cloud + Spring Cloud Alibaba:Spring Cloud提供了丰富的微服务组件和解决方案,包括服务注册与发现、负载均衡、断路器、设置管理等。Spring Cloud Alibaba扩展了Spring Cloud,整合了阿里巴巴技能栈,如Nacos(服务注册与发现)、Sentinel(流量控制和熔断降级)、RocketMQ(消息驱动)等。组合利用这两个框架可以获得全面的云原生应用开发解决方案,实用于构建当代化的微服务架构。
  • Dubbo原生模式 + Spring Cloud Alibaba:Dubbo是一个高性能的RPC框架,提供了服务治理、负载均衡、容错等功能。Spring Cloud Alibaba扩展了Dubbo,为Dubbo提供了更多云原生的支持,如Nacos作为注册中心、Sentinel用于流量控制和熔断降级等。通过将Dubbo和Spring Cloud Alibaba集成,可以获得高性能的RPC调用和全面的云原生的服务治理解决方案。
无论是利用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服务器构成,它们构成了服务注册中心。每个微服务实例都将自己的信息注册到Eureka服务器,包括服务名、主机名、端标语等。
  • 服务注册:微服务启动时,会向Eureka服务器发送注册请求,将自己的信息注册到注册中心。注册中心维护一个服务注册表,记载全部已注册的微服务实例。
  • 服务发现:其他微服务需要调用某个服务时,起首向注册中心发送查询请求,获得目标服务的实例列表。注册中心将会返回全部可用的服务实例信息,包括IP地址、端标语等。
  • 服务监控:Eureka服务器会定期向已注册的微服务实例发送心跳请求,微服务实例返回响应以证实自己的康健状态。如果一个微服务长时间未发送心跳消息或返回异常状态,Eureka服务器将从注册表中删除该实例。
  • 服务同步:Eureka服务器之间会相互复制注册表信息,以包管数据的划一性。当有新的微服务实例注册或注销时,注册中心会关照其他服务器进行注册表更新。
通过Eureka提供的服务注册和发现机制,微服务之间可以动态地发现和调用其他微服务,从而实现了服务之间的解耦和机动性。Eureka还提供了负载均衡、故障规复等一些附加功能,使得微服务架构更加可靠和高效。

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

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


  • 服务提供者启动时向eureka注册自己的信息
  • eureka保存这些信息
  • 斲丧者根据服务名称向eureka拉取提供者信息
如果有多个服务提供者,斲丧者该怎样选择?


  • 服务斲丧者利用负载均衡算法,从服务列表中挑选一个
斲丧者怎样感知服务提供者康健状态?


  • 服务提供者会每隔30秒向EurekaServer发送心跳请求,陈诉康健状态
  • eureka会更新记载服务列表信息,心跳不正常会被剔除
  • 斲丧者就可以拉取到最新的信息
 总结

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


  • 记载服务信息
  • 心跳监控
   2、EurekaClient: 客户端
         1)Provider:服务提供者,例如案例中的 user-service


  •               注册自己的信息到EurekaServer
  •               每隔30秒向EurekaServer发送心跳
         2)consumer:服务斲丧者,例如案例中的 order-service


  •                     根据服务名称从EurekaServer拉取服务列表
  •                     基于服务列表做负载均衡,选中一个微服务后发起远程调用
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.服务注册


  • 引入eureka-client依赖
  • 在application.yml中设置eureka地址
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


  • 引入eureka-server依赖
  • 添加@EnableEurekaServer注解
  • 在application.yml中设置eureka地址
2.服务注册


  • 引入eureka-client依赖
  • 在application.yml中设置连接eureka服务注册中心地址
3.服务发现


  • 引入eureka-client依赖
  • 在application.yml中设置eureka服务注册中心地址
  • 给RestTemplate添加@LoadBalanced注解
  • 用服务提供者的服务名称远程调用
四、Ribbon负载均衡

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


 Ribbon的负载均衡原理可以概括如下:

  • 服务注册:Ribbon起首需要与服务注册中心(如Eureka、Consul等)进行交互,获取可用的服务实例列表。
  • 负载均衡策略:Ribbon支持多种负载均衡策略,如随机策略、轮询策略、权重策略等。根据选择的策略,Ribbon会根据服务实例的状态、性能等因素来选择一个合适的服务实例。
  • 服务调用:一旦选择了一个服务实例,Ribbon会将请求发送给该实例。它会维护一个与服务实例的长连接,并在需要时将请求发送给该实例。
  • 失败处理处罚:如果请求在与服务实例的通讯中失败,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负载均衡规则



  • 规则接口是IRule
  • 默认实现是ZoneAvoidanceRule,根据zone选择服务列表,然后轮询
2.负载均衡自定义方式



  • 代码方式:设置机动,但修改时需要重新打包布
  • 设置方式:直观,方便,无需重新打包发布但是无法做全局设置
3.饥饿加载



  • 开启饥饿加载
  • 指定饥饿加载的微服务名称
五、Nacos注册中心

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

Nacos和Eureka是两个常用的服务发现和注册工具,它们都具有类似的功能,但在一些方面存在一些差异。以下是Nacos和Eureka的一些对比:

  • 开发者生态圈:Nacos是由Alibaba开发并开源,拥有巨大的Alibaba生态圈支持,而Eureka是由Netflix开发并开源,得到了Netflix和Spring Cloud社区的广泛应用。
  • 功能和特性:Nacos提供了更多的功能和特性,除了服务注册与发现外,还包括设置管理、动态DNS、动态路由和流量管理等功能。Eureka主要关注服务注册与发现的功能。
  • 容错性:Nacos具有更强的容错性,支持多数据中心的分布式摆设,可以包管在网络分区和节点故障情况下的高可用性。Eureka在这方面的容错性相对较弱。
  • 数据划一性:Nacos利用Raft算法来实现数据划一性和高可用性,而Eureka利用的是AP模子,即优先包管可用性而不包管强划一性。
  • 社区活跃度: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下安装的。

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

 目录说明:


  • - bin:启动脚本
  • - conf:设置文件
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服务搭建



  • 下载安装包
  • 解压
  • 在bin目录下运行指令:startup.cmd -mstandalone
2.Nacos服务注册或发现



  • 引入nacos.discovery依赖
  • 设置nacos地址spring.cloudnacos.server-addr
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服务分级存储模子



  • 一级是服务,例如userservice
  • 二级是集群,例如杭州或上海
  • 三级是实例,例如杭州机房的某台摆设了userservice的服务器
2.怎样设置实例的集群属性



  • 修改application.yml文件,添加spring.cloud.nacos.discovery.cluster-name属性即可
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中进行服务发现,并且它们有不同的实例数和性能设置。在这种情况下,可以通过基于权重的负载均衡来实现对这些服务实例的合理请求分配。以下是一些示例场景:

  • 不同实例性能差异较大:
    假设商品服务有3个实例,此中实例A和实例B设置较高,实例C设置较低。此时,可以设置实例A和实例B的权重为2,实例C的权重为1。如许,每次有请求到来时,有较高性能的实例A和实例B将会处理处罚更多的请求,而较低性能的实例C将会处理处罚较少的请求,从而实现了性能调控。
  • 服务实例容量不均衡:
    假设订单服务有5个实例,此中实例A、B和C的容量比实例D和E大。可以为实例A、B和C设置较高的权重值,如3,而为实例D和E设置较低的权重值,如1。如许,请求将均衡分配到实例A、B和C之间,并保持实例D和E的请求数较少。
  • 降低故障实例的负载:
    假设用户服务有4个实例,此中实例A由于某种缘故原由,出现了故障或不稳定情况。为了减少对实例A的请求分配,可以为其设置较低的权重值,如0,而将其他正常的实例设置为较高的权重值,如3。如许,请求将主要被分配给其他正常的实例,降低了对故障实例A的负载。
通过在Nacos中设置服务实例的权重,可以根据现实情况动态调整请求的负载比例。如许可以或许充实利用资源、进步体系性能、包管服务稳定性,并对不同实例进行合理分配。
Nacos提供了权重设置来控制访问频率,权重越大则访问频率越高。
设置


 

 4.5、环境隔离-namespace

1、认识环境隔离-namvespace

应用场景:
假设有一个电商平台,该平台设计了一个基于Nacos的命名空间设置和服务注册方案,以支持环境隔离和多租户功能。
起首,假设该电商平台有三个环境:开发环境、测试环境和生产环境。每个环境都有独立的设置和服务需求。

  • 环境隔离和设置管理:

    • 利用Nacos的命名空间功能,平台管理员可以创建三个命名空间:dev-namespace、test-namespace和prod-namespace。
    • 在dev-namespace中,可以设置开发环境所需的各种参数,如数据库连接信息、调试模式等。
    • 在test-namespace中,可以设置测试环境所需的参数,如测试数据库连接信息、测试数据源等。
    • 在prod-namespace中,可以设置生产环境所需的参数,如正式数据库连接信息、生产级别的服务设置等。
    • 每个命名空间下的设置项是相互隔离的,如许就包管了不同环境设置的独立性,并且可根据需求机动管理和更新设置信息。

  • 服务注册和版本管理:

    • 在每个命名空间中,可以注册相应环境需要的服务实例,如商品服务、订单服务等。
    • 平台管理员可以利用命名空间功能来管理不同环境的服务注册表,确保每个环境只能访问属于自己的服务实例。
    • 每个命名空间可以独立管理服务实例的版本,例如,在开发环境中可以注册和测试新的服务版本,而在生产环境中则利用稳定的服务版本。

通过如许的命名空间设置和服务注册方案,电商平台可以或许实现对不同环境的设置和服务进行隔离,并支持多租户功能。开发团队可以独立管理各自环境的设置和服务,而不会相互干扰。此外,平台还可以利用灰度发布和版本管理功能,在不同命名空间中进行服务版本控制,确保体系稳定性和可用性。
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相联合)

  • pull:服务斲丧者会每隔30秒定时自动向服务注册中心发起请求,来拉取服务信息,在服务斲丧者中有一个服务列表缓存,用于缓存从服务注册中心拉取下的服务信息。
  • push:当有服务停掉后服务注册中心会自动推送变动信息给斲丧者,斲丧者就会更新服务列表缓存。
心跳与康健检查:也是有两种(对临时实力和非临时实例)

  • 临时实例:接纳心跳检测,是临时实例自动向注册中心发送心跳检测,如果一段时间注册中心没有收到临时实例心跳检测,就会剔除该临时实例。
  • 非临时实例:接纳nacos自动扣问,nacos自动扣问非临时实例的康健状态,如果非临时实例制止了,也不会剔除非临时实例,只是修改非临时实例的康健转态,会等待非临时实例康健。

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

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


  • 非临时实例是指注册到Nacos注册中心的服务实例,其生命周期不会受到外部因素的影响,除非自动取消注册或服务下线。
  • 这种实例实用于通常情况下稳定运行的服务,它们的注册信息会被长期化存储在Nacos服务器中,提供长期性的服务发现和注册功能。
2、临时实例(Ephemeral Instance):


  • 临时实例是指服务实例在持有连接的客户端断开连接时,会自动从Nacos注册中心上注销的一种实例类型。
  • 当客户端与Nacos注册中心建立心跳连接后,临时实例会周期性地向注册中心进行连接进行检测。如果一段时间注册中心没有收到临时实例的心态检测,注册中心会将对应的实例注销。
  • 临时实例实用于动态扩缩容、临时性访问等场景,允许实例根据连接状态进举措态管理。
临时实例和非临时实例在实践中有不同的应用场景:


  • 对于稳定运行的服务,应利用非临时实例。如许服务实例的注册信息将长期存在于注册中心中,纵然服务发生故障或重启,也能包管注册信息的长期性,其他服务可以或许继续发现和利用该实例。
  • 对于临时性的任务,如定时任务、临时数据处理处罚服务等,可以选择利用临时实例。如许在任务完成后,实例会自动注销,降低注册中心中无用实例的数目,也能更好地适应动态需求变革。
需要注意的是,临时实例的自动注销是基于与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的区别



  • Nacos支持服务端自动检测提供者状态:临时实例接纳心跳模式,非临时实例接纳自动检测模式
  • 临时实例心跳不正常会被剔除,非临时实例则不会被剔除
  • Nacos支持服务列表变动的消息推送模式,服务列表更新更实时
  • Nacos集群默认接纳AP方式,当集群中存在非临时实例时,接纳CP模式;Eureka接纳AP方式
6、Nacos设置管理

以下是几个利用Nacos设置管理的现实业务场景的例子:

  • 微服务设置管理:
    假设你的公司接纳了微服务架构,有多个微服务需要连接到不同的数据库。通过利用Nacos设置管理,你可以将每个微服务的数据库连接信息存储在Nacos中,并动态地更新设置。例如,当你需要更改数据库的连接地址或暗码时,你可以直接在Nacos中修改设置,而无需重新摆设微服务,全部微服务将自动获取最新的设置信息。
  • 多环境设置管理:
    假设你的应用在开发、测试和生产环境中运行,并且每个环境都有不同的设置。利用Nacos设置管理,你可以为每个环境创建不同的设置文件,并通过Nacos的命名空间和设置组进行组织。开发人员可以通过选择不同的命名空间和设置组,轻松地切换到不同的环境,而不必手动修改设置文件。
  • 动态路由设置:
    假设你的微服务架构中利用了Spring Cloud Gateway作为API网关,并且你希望可以或许动态路由请求到不同的后端服务。通过利用Nacos设置管理,你可以将路由规则存储在Nacos中,并通过Spring Cloud Gateway与Nacos集成。当需要更新路由规则时,你可以直接在Nacos中修改设置,Spring Cloud Gateway将自动更新路由,并将请求动态地转发到相应的后端服务。
  • 定时任务设置:
    假设你的应用需要实行定时任务,例如生成报表或清理数据。通过利用Nacos设置管理,你可以将定时任务的触发时间、任务参数等信息存储在Nacos中,并由任务调度器定期从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设置更改后,微服务可以实现热更新,方式:



  • 通过@Value注解注入,联合@RefreshScope来刷新
  • 通过@ConfigurationProperties注入,自动刷新
注意事项:



  • 不是全部的设置都适合放到设置中心,维护起来比力贫苦
  • 发起将一些关键参数,需要运行时调整的参数放到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所需的服务实例信息,从而实现服务发现和负载均衡的功能。
联合这三个组件,团体的架构可以如下所示:

  • 服务实例注册:服务实例可以将自己的元数据信息注册到Nacos中,包括服务名称、IP地址、端口等信息。
  • Nacos服务注册中心:Nacos注册中心负责存储和管理全部服务实例的元数据信息。
  • Nacos设置中心:Nacos设置中心负责存储和管理应用程序的设置信息。
  • DNS解析:客户端可以通过DNS解析服务名称为详细的服务实例的IP地址。
  • SLB负载均衡器:SLB可以接收客户端请求,并根据负载均衡算法将请求分发到多个服务实例上。
通过如许的结构,客户端可以通过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发起远程调用的代码:

存在下面的问题:


  • 代码可读性差,编程体验不统一
  • 参数复杂URL难维护
1、Feign的介绍

Feign 提供了一种简单且优雅的方式来定义和调用基于HTTP的远程服务。通过利用Feign,您可以在客户端代码中定义接口,然后Feign会根据这些接口的定义自动生成现实的HTTP请求,并将其转发到远程服务。如许,您可以像调用本地方法一样调用远程服务的方法,无需显式地处理处罚HTTP请求和响应。
Feign 还支持对请求进行编码和解码、错误处理处罚、请求和响应拦截器等功能,使得在微服务架构中处理处罚远程服务变得更加方便和高效。
利用Feign的一些优点包括:

  • 简化了客户端代码,使其更易于维护和理解。
  • 减少了手动处理处罚HTTP请求和响应的工作量。
  • 支持多种编解码器,可处理处罚多种数据格式。
  • 可与Spring Cloud等微服务框架无缝集成。
在利用Feign时,您需要定义一个Java接口,该接口包含与远程服务相对应的方法和参数。然后,通过在应用程序的设置中启用Feign并利用Spring的依赖注入功能,您可以将Feign客户端注入到您的代码中,从而实现对远程服务的调用。
Feign作为一个声明式的HTTP客户端,在微服务架构和分布式体系中有许多应用场景。以下是一些常见的利用场景:

  • 微服务间的通讯:在微服务架构中,各个服务之间需要频繁地进行通讯,Feign可以帮助简化服务间的HTTP通讯,使得调用远程服务更加方便。
  • 服务斲丧者:当一个服务需要调用其他服务提供的API时,可以利用Feign来作为客户端来斲丧这些服务,而无需手动处理处罚HTTP请求和响应。
  • 署理远程API:Feign可以将远程服务的API映射为本地接口,使得调用远程服务的过程就像调用本地方法一样简单。
  • 负载均衡:联合负载均衡的工具(如Ribbon),Feign可以实现在多个服务实例之间进行负载均衡,从而进步体系的可用性和性能。
  • 声明式的错误处理处罚:Feign支持定义统一的错误处理处罚逻辑,使得在发生错误时可以接纳划一的处理处罚方式,从而减少重复代码。
  • 数据格式处理处罚:Feign支持多种编解码器,可以处理处罚不同的数据格式,例如JSON、XML等,使得数据的传输和解析更加机动和便捷。
  • 请求拦截与日志:Feign支持请求和响应拦截器,可以在发送请求和接收响应时进行拦截和处理处罚,例如记载日志、鉴权等。
总体而言,Feign实用于任何需要在微服务架构中进行HTTP通讯的场景,特殊是当您希望简化远程服务调用的代码并增加可读性和可维护性时,Feign是一个非常有用的工具。
2、定义和利用Feign客户端

在之前我是在调用其他服务提供的接口是利用的是RestTempale,为什么还要学Feign呢?
Feign和RestTemplate都是在Spring框架中用于进行HTTP请求的工具,但它们在利用方式和特点上有一些区别。

  • 声明式 vs. 编程式:

    • Feign是一个声明式的HTTP客户端,它允许您通过定义接口来描述对远程服务的请求,并自动生成底层HTTP调用。Feign利用注解来设置请求的URL、HTTP方法、请求参数等信息,使得代码更加简洁和易读。
    • RestTemplate是一个编程式的HTTP客户端,您需要在代码中显式地构建HTTP请求,包括指定URL、HTTP方法、请求头、请求体等信息。虽然可以通过RestTemplate机动地控制请求细节,但相比Feign,代码大概会更冗长和复杂。

  • 整合Spring Cloud vs. 单独利用:

    • Feign是Spring Cloud项目标一部分,它与Spring Cloud的其他组件(如Eureka、Ribbon、Hystrix等)紧麋集成,使得在微服务架构中利用Feign更加方便,并且提供了一些额外的特性,如负载均衡、服务发现等。
    • RestTemplate是Spring Framework的一部分,它可以单独利用,没有与Spring Cloud的深度集成。如果您在非微服务环境中,大概不需要Spring Cloud提供的其他功能,RestTemplate是一个不错的选择。

  • 自动化的负载均衡:

    • Feign与Ribbon(Spring Cloud中的负载均衡组件)集成,可以自动进行负载均衡,使得在多个服务实例中选择合适的目标服务。
    • RestTemplate在默认情况下不支持自动的负载均衡,您需要手动编写代码来实现负载均衡,大概联合Ribbon来实现自动化负载均衡。

  • 请求拦截器和错误处理处罚:

    • Feign允许您定义请求和响应拦截器,从而可以在发送请求和接收响应时进行拦截和处理处罚,例如记载日志、鉴权等。它还提供了声明式的错误处理处罚机制,让您可以统一处理处罚请求错误。
    • RestTemplate也支持请求和响应拦截器,但是在处理处罚错误时大概相对繁琐,需要通过捕捉异常等方式来处理处罚请求错误。

综上所述,如果您在利用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的利用步骤

  • 引入依赖
  • 添加@EnableFeignClients注解
  • 编写FeignClient接口
  • 利用FeignClient中定义的方法代替RestTemplate
3、自定义Feign的设置

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

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

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

  • NONE:该日志级别最低,不记载任何日志信息。如果您不想在控制台输出任何关于Feign请求和响应的日志,可以选择此级别。
  • BASIC:在BASIC级别下,Feign仅记载请求方法、URL和响应状态码的基本信息。这对于快速相识请求的基本情况很有帮助,但不会记载请求和响应的详细内容。
  • HEADERS:在HEADERS级别下,Feign将记载请求和响应的头部信息,包括请求头和响应头。如允许以更详细地查看请求和响应的头部信息,有助于调试和相识请求的上下文。
  • FULL:FULL级别是最详细的日志级别,它会记载请求和响应的全部详细信息,包括请求头、请求体、响应头和响应体。如果您需要完整的请求和响应信息来进行详细的调试和排查问题,FULL级别是最合适的选择。
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

  • O如果xxx是default则代表全局
  • 如果xxx是服务名称,例如userservice则代表某服务
2.方式二是java代码设置Logger.Level这个Bean

  • 如果在@EnableFeignClients注解声明则代表全局
  • 如果在@FeignClient注解中声明则代表某服务
4、Feign的性能优化

Feign的底层客户端实现是通过集成了其他HTTP客户端库来实现的。详细来说,Feign支持两种主要的HTTP客户端实现:JDK的URLConnection和Apache HttpClient。

  • JDK的URLConnection:这是Java标准库中提供的用于HTTP通讯的API。Feign可以直接利用JDK的URLConnection来发送HTTP请求。它是轻量级的,对于简单的HTTP通讯,大概足够满意需求。如果您在项目中没有引入其他HTTP客户端库,Feign会默认利用JDK的URLConnection作为底层的客户端实现。
  • Apache HttpClient:Apache HttpClient是Apache基金会提供的一个功能丰富、机动的HTTP客户端库。它提供了许多高级功能,如连接池、重试机制、认证等。如果您在项目中引入了Apache HttpClient的依赖,Feign会自动选择利用Apache HttpClient作为底层的客户端实现。
  • OkHttp:OkHttp是Square公司开发的一款高效的HTTP客户端库。它支持HTTP/2、连接池、拦截器等当代特性。如果您在项目中引入了OkHttp的依赖,Feign会自动切换到OkHttp作为底层实现。
Feign的这种设计使得您可以根据需要机动地选择底层的HTTP客户端。默认情况下,如果项目中没有引入其他HTTP客户端库,Feign将利用JDK的URLConnection作为底层客户端。如果您希望利用Apache HttpClient或OkHttp,只需在项目中添加相应的依赖,Feign会自动检测并利用它们作为底层实现。
通过这种方式,Feign可以同时满意不同项目对HTTP客户端的需求,并提供简便的远程服务调用方式。
因此优化Feign的性能主要包括:


  • 利用连接池代替默认的URLConnection
  • 日志级别,做好利用basic大概none
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

  • 引入feign-httpClient依赖
  • 设置文件开启httpClient功能,设置连接池参数
5、Feign的最佳现实

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



这种实现方式虽然可以让Controller和Feign Client共享同一个接口定义,但存在一些问题和注意事项:

  • 潜在的耦合:共享同一个接口定义会让Controller和Feign Client在代码层面产生耦合,导致它们精密地关联在一起。一旦接口定义发生变革,两者都需要进行相应的修改,这大概影响到多个模块。
  • 不符合单一职责原则:Controller负责处理处罚HTTP请求和返回响应,而Feign Client负责远程服务调用。将它们共享同一个接口大概会让代码功能变得紊乱,违反了单一职责原则。
  • 难以做到完全解耦:只管接口定义可以共享,但是在Feign Client的实现中,仍然需要涉及到远程服务调用的逻辑。这会让Feign Client的实现和Controller之间仍然有一定的耦合。
  • 接口定义大概会变得复杂:为了适应不同的调用场景,共享接口大概会变得复杂,大概需要添加各种参数和注解,从而导致接口的冗长和不易维护。
  • 功能不划一问题:在Controller和Feign Client共享同一个接口的情况下,两者的功能大概不完全划一。在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的最佳实践

  • 让controller和FeignClient继承同一接口
  • 将FeignClient、poJo、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的导入有两种方式

  • 在@EnableFeignClients注解中添加basePackages,指定FeignClient所在的包
  • 在@EnableFeignClients注解中添加clients,指定详细FeignClient的字节码
七、Gateway服务网关

网关(Gateway)服务在微服务架构中起着重要的作用。它是位于客户端和后端微服务之间的中间层,用于处理处罚和转发请求。为什么要利用网关服务呢?以下是一些主要的缘故原由:

  • 统一入口:网关服务提供了一个统一的入口,客户端只需要向网关发送请求,而不需要直接调用各个微服务。如许简化了客户端的调用逻辑,同时也方便地对请求进行统一管理和处理处罚。
  • 路由和负载均衡:网关服务可以根据请求的URL路径或其他条件将请求路由到相应的微服务实例。它还可以配合负载均衡算法,确保请求被均匀地分发给不同的服务实例,进步了体系的可用性和性能。
  • 安全控制:通过网关服务,可以实现对请求进行安全控制和认证。网关可以验证请求的身份、权限以及合法性,确保只有授权的请求可以或许访问相应的微服务。
  • 聚合和分解请求:网关服务可以聚合多个微服务的请求,将它们归并为一个请求返回给客户端,从而减少了客户端与后端服务之间的请求次数,降低了网络开销。
  • 缓存:网关服务可以对请求的响应进行缓存,从而减少重复请求对后端服务的压力,进步了体系的性能和响应速度。
  • 降级和容错:网关服务可以实现对后端服务的降级和容错处理处罚。当某个微服务出现故障或不可用时,网关可以提供默认的响应或调用备用服务,制止了体系级的故障。
  • 监控和日志:通过网关服务,可以实现对请求和响应进行监控和日志记载。这有助于实时追踪请求的流程和性能,发现问题并进行实时的处理处罚。
综上所述,网关服务在微服务架构中饰演了一个重要的角色,它提供了统一入口、路由和负载均衡、安全控制、聚合和分解请求、缓存、降级和容错、监控和日志等功能,为整个体系提供了更高效、更安全、更稳定的请求处理处罚和管理本领。

1、网关技能

 在springcloud中网关的实现有两种:gateway和zuul
Zuul和Spring Cloud Gateway都是常用的网关实现,用于在微服务架构中处理处罚和转发请求。它们都可以作为反向署理和请求路由器,但在设计和功能上有一些区别。

  • Zuul:
    Zuul是Netflix提供的网关服务,被称为Netflix Zuul。它是一个基于Servlet的网关实现,构建在传统的Spring Cloud项目上。Zuul 1.x版本接纳阻塞式I/O模子,Zuul 2.x版本接纳非阻塞式I/O模子,基于Netty。
    特点:

    • Zuul 1.x的阻塞式I/O模子限定了并发性能,虽然可以通过多实例摆设来进步吞吐量,但对于高并发场景大概不敷高效。
    • Zuul 2.x基于非阻塞式I/O模子,可以提供更好的性能和吞吐量。
    • Zuul支持动态路由和过滤器等功能,可以实现请求的动态转发和预处理处罚。
    • 设置方式较为机动,可以利用Groovy或Java DSL设置路由和过滤器。

  • Spring Cloud Gateway:
    Spring Cloud Gateway是Spring Cloud项目中的网关服务,从Spring Cloud 2.x版本开始引入。它是基于Spring 5和Spring Boot 2构建的,接纳了WebFlux框架,支持响应式编程。
    特点:

    • Spring Cloud Gateway接纳基于异步非阻塞的WebFlux框架,提供了更好的性能和响应本领,实用于高并发场景。
    • 支持动态路由和过滤器等功能,可以实现请求的动态转发和预处理处罚。
    • 提供了丰富的过滤器,支持全局和局部过滤器的定义和利用。
    • 设置方式机动,可以利用YAML或Java设置路由和过滤器。

综合来说,Zuul和Spring Cloud Gateway都是成熟的网关实现,各有优势。如果您在利用Spring Cloud项目,推荐利用Spring Cloud Gateway,特殊是在需要高并发和响应本领的场景下。而如果您在利用Netflix项目,可以选择利用Netflix Zuul 2.x版本或更高的版本,或考虑迁徙到Spring Cloud Gateway。选择哪个网关取决于您的项目需求、技能栈和预期的性能要求。
总结

网关的作用:


  • 对用户请求做身份认证、权限校验
  • 将用户请求路由到微服务,并实现负载均衡
  • 对用户请求做限流
2、搭建网关服务

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


  • 创建Gateway项目:起首,创建一个新的Spring Boot项目作为Gateway服务网关。
  • 添加依赖:在Gateway项目中,添加Spring Cloud Gateway和Nacos的依赖,以便利用Gateway和Nacos的功能。在pom.xml文件中添加以下依赖:
  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、搭建网关服务流程图




  • 客户端发起请求:客户端(如Web应用、移动端应用、或其他服务)发起HTTP请求。
  • 请求到达Gateway:请求起首到达Gateway服务网关。
  • Gateway进行路由匹配:Gateway根据预先设置的路由规则,匹配请求的URL路径、请求头等信息,找到对应的微服务实例。
  • 服务发现:Gateway需要通过服务注册中心(如Nacos)来获取微服务实例的信息。它向Nacos发送服务发现请求,Nacos会返回目标微服务的实例列表。
  • 负载均衡:Gateway利用负载均衡算法从目标微服务实例列表中选择一个实例,将请求转发给该微服务实例。
  • 微服务接收请求:目标微服务实例接收到请求。
  • 微服务处理处罚请求:微服务实例处理处罚请求,并根据业务逻辑实行相应的操作。
  • 微服务返回响应:微服务实例生成响应效果,并将响应返回给Gateway。
  • Gateway接收响应:Gateway接收到微服务实例的响应。
  • Gateway处理处罚响应:Gateway可以对微服务实例的响应进行处理处罚,如添加响应头、日志记载等。
  • 响应返回客户端:Gateway将处理处罚后的响应返回给客户端。
通过服务注册中心(如Nacos)来进行服务发现,Gateway可以或许动态地获取微服务的实例信息,从而实现请求的动态转发和负载均衡。如许,Gateway就能找到相应的服务并将请求转发给它们。感谢您的指正,希望这次的回答更加准确。
总结

网关搭建步骤


  • 创建项目,引入nacos服务发现和gateway依赖
  • 设置application.yml,包括服务基本信息、nacos地址、路由
路由设置包括


  • 路由id:路由的唯一标示
  • 路由目标 (uri):路由的目标地址,http代表固定地址,lb代表根据服务名负载均衡
  • 路由断言 (predicates): 判断路由的规则
  • 路由过滤器 (filters):对请求或响应做处理处罚
3、路由断言工厂Route Predicate Factory



  • 路由断言工厂(Route Predicate Factory)是Spring Cloud Gateway中的一种设置方式,用于根据请求的条件来进行路由匹配。它可以根据请求的不同属性(例如URL路径、请求头、请求方法等)来判断请求是否匹配某个路由规则,如果匹配成功,则将请求转发到相应的目标地址(服务实例)。
  • 例如:Path=/order/**是按照路径匹配,这个规则是由org.springframework.cloud.gateway.handler.predicata.PathRoutePredicateFactory类来处理处罚
  • 像这种短语工厂在SpringCloudGateway还有十几个
3.1、spring提供了11种基本的Predicate工厂


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

 总结



  • PredicateFactory的作用是什么?
        读取用户定义的断言条件,对请求做出判断


  • Path=/user/**是什么寄义?
        路径是以/user开头的就认为是符合的
4、路由过滤器(Route Filter)

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


 例如:
假设我们有一个微服务架构,包含多个服务,此中一个是认证服务(Authentication Service),负责处理处罚用户的身份认证。其他服务(如用户服务、订单服务等)需要掩护某些资源,只允许经过认证的用户访问。
在这种情况下,我们可以利用Spring Cloud Gateway作为网关,通过路由过滤器来实现请求认证和授权:

  • 全局过滤器(Global Filter):我们可以创建一个全局过滤器来拦截全部的请求,在这个过滤器中进行用户身份认证的检查。比如,我们可以检查请求中是否包含有效的身份令牌(Token),以确定请求是否是经过认证的用户发起的。
  • 局部过滤器(Route-Specific Filter):对于特定需要授权访问的服务,我们可以在路由设置中利用局部过滤器。在这个过滤器中,我们可以对请求进行权限验证,检查用户是否有权限访问该服务提供的资源。如果用户没有合法的权限,则可以拒绝请求或返回相应的错误信息。
如许,通过路由过滤器,我们可以实现全局的请求认证,并对需要授权访问的服务进行权限控制。用户在发起请求时,起首经过全局过滤器进行认证,然后再经过局部过滤器进行权限验证。只有通过认证和授权的请求才能继续访问后端的微服务。
这种方式使得认证和授权逻辑从业务服务中剥离出来,统一交给网关进行处理处罚,简化了业务服务的实现和管理,同时进步了体系的安全性和可维护性。
4.1、过滤工厂 GratewayFilterFactory

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


  • 过滤器:是过滤器现实的实行逻辑,它需要开发者自己实现并继承特定的Filter接口(如GlobalFilter或GatewayFilter),完成请求和响应的处理处罚。
  • 过滤工厂:是用于创建过滤器的工厂类,它将过滤器的创建和设置封装起来,通过设置工厂的参数,可以快速创建不同类型的过滤器,并指定过滤器的行为。
过滤工厂的优势在于,它提供了一些预定义的工厂,可以轻松地为常见的过滤器场景创建过滤器,而无需开发者自己编写过滤器的实现。通过简单的设置,开发者可以利用这些预定义的过滤工厂创建自定义的过滤器,从而实现特定的路由和请求处理处罚逻辑。
spring提供了31种不同的路由过滤器工厂,一些常用的过滤工厂包括:

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

4.1.1、案例

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


 默认过滤器


总结



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


  • defaultFilters的作用是什么?
                对全部路由都生效的过滤器
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. }
复制代码
总结

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


  • 对全部路由都生效的过滤器,并且可以自定义处理处罚逻辑
实现全局过滤器的步骤?

  • 实现GlobalFilter接口
  • 添加@Order注解或实现Ordered接口
  • 编写处理处罚逻辑
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、过滤器执怎样排序



  •  每个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,实行顺序越靠前。
  • GlobalFilter通过实现Order接口,大概添加@Order注解来指定order值,由我们自己指定。
  • 路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增。
 多余多个路由过滤器 和多个默认路由器:


  • 如果有多个路由过滤器,那他们是按照声明的顺序来递增order的值的,来排序他们的实行顺序。
  • 多个默认路由也是如此的,也是按声明的顺序来递增order的值,来排序他们的实行顺序。

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


  • 当过滤器的order值一样时,会按照defaultFilter > 路由过滤器 > GlobalFilter全局过滤器的顺序实行。
底层源码中有两个类是用来加载这三种过滤器的:

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

路由过滤器、defaultFilter、全局过滤器的实行顺序?

  • order值越小,优先级越高
  • 当order值一样时,顺序是defaultFilter最先,然后是局部的路由过滤器,最后是全局过滤器
7、跨域问题处理处罚

7.1、超干涉题

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


  • 域名不同:www.taobao.com和 www.taobao.org 和 wwwjd.com 和 miaoshajd.com
  • 域名相同,端口不同: localhost:8080和localhost8081
超干涉题:欣赏器禁止请求的发起者和服务端发生跨域Ajax请求,请求被欣赏器拦截的问题。
跨域问题的出现是为了防止恶意网站利用客户端的漏洞进行攻击,掩护用户的隐私和安全。欣赏器会欺压实行同源策略,禁止网页在不同源之间进行以下操作:

  • 通过 XMLHttpRequest 或 Fetch API 发送跨域请求。
  • 访问其他源的 Cookie、LocalStorage 和 IndexedDB。
  • 获取其他源的 DOM 元素。
  • 在其他源的窗口中实行脚本。
举个例子来说明跨域问题:假设网站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请求被拦截问题
复制代码
 设置详细介绍:

  • corsConfigurations: 这个属性用于设置全局的CORS设置。[/**] 表示匹配全部路径,也就是对全部请求生效的全局CORS设置。
  • allowedOrigins: 允许的跨域请求源。这里设置为 https://example.com,表示只允许来自 https://example.com 域名的请求进行跨域访问。你可以根据现实需求设置允许的域名,也可以利用通配符 * 表示允许全部域名的请求。
  • allowedMethods: 允许的请求方法。这里设置为 GET, POST, PUT, DELETE,表示只允许这些HTTP方法的请求进行跨域访问。你可以根据需要添加或删除允许的方法。
  • allowedHeaders: 允许的请求头。这里设置为 *,表示允许任意请求头。你也可以设置详细的请求头名称,比如 "Content-Type, Authorization",只允许这些请求头进行跨域访问。
  • allowCredentials: 是否允许发送凭证信息(如Cookie)。这里设置为 true,表示允许发送凭证信息。如果设置为 false,则不允许发送凭证信息。
  • maxAge: 预检请求的缓存时间(单位:秒)。预检请求是指欣赏器在发送跨域请求前先发送一个 OPTIONS 请求来检查服务器是否允许跨域访问。这里设置为 3600 秒,表示预检请求的效果在 3600 秒内可以被缓存,减少预检请求的次数。
  • add-to-simple-url-handler-mapping: 这个属性设置为 true,将CORS设置添加到简单URL处理处罚程序映射中。这是一个内下属性,通常不需要手动设置。
通过以上设置,Spring Cloud Gateway 将会在响应中添加相应的CORS响应头,允许来自 https://example.com 域名的跨域请求,允许的方法有 GET、POST、PUT、DELETE,允许任意请求头,允许发送凭证信息(如 Cookie),并且预检请求的缓存时间为 3600 秒。
总结

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


  • 允许哪些域名跨域?
  • 允许哪些请求头?
  • 允许哪些请求方式?
  • 是否允许利用cookie?
  • 有效期是多久?
 此篇是在学习黑马课springcloud程是做的详细的条记,内容是自己总结事后,易懂,但是就是篇幅有点多,需要大家多花时间去看。

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

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

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

李优秀

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表