第十二章 微服务核心(二)

一、Spring Cloud

1. 服务注册中心
常见的服务注册中心组件如下
- Eureka
- Consul
- Zookeeper
- Etcd
- Nacos
  
2. Eureka
SpringCloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务治理。
  
什么是服务治理:在传统的 RPC 远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
   
Eureka 采用了 CS 的设计架构,Eureka Sever 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用 Eureka 的客户端连接到 Eureka Server 并维持心跳连接。这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行。
  
在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息比如服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地 RPC 调用。RPC 远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何 RPC 远程框架中,都会有一个注册中心存放服务地址相关信息(接口地址)。
   
Eureka 采用 CS(Client/Server,客户端/服务器) 架构,它包括以下两大组件:
- Eureka Server:Eureka 服务注册中心,主要用于提供服务注册功能。当微服务启动时,会将自己的服务信息注册到 Eureka Server。Eureka Server 维护了一个可用服务列表,存储了所有注册到 Eureka Server 的可用服务节点的信息,服务节点的信息可以在 Eureka Server 的管理界面中直观看到。
- Eureka Client:Eureka 客户端,通常指的是微服务系统中各个微服务,主要用于和 Eureka Server 进行交互。在微服务应用启动后,Eureka Client 会向 Eureka Server 发送心跳(默认周期为 30 秒)。若 Eureka Server 在多个心跳周期内没有接收到某个 Eureka Client 的心跳,Eureka Server 将它从可用服务列表中移除(默认 90 秒)。
     
默认情况下,Eureka Server 同时也是 Eureka Client。多个 Eureka Server 实例,互相之间通过增量复制的方式,来实现服务注册表中数据的同步。Eureka Server 默认保证在 90 秒内,Eureka Server 集群内的所有实例中的数据达到一致。从这个架构来看,Eureka Server 所有实例所处的角色都是对等的,没有类似 Zookeeper、Consul、Etcd 等注册中心的选举过程,也不存在主从,所有的节点都是主节点。Eureka 官方将 Eureka Server 集群中的所有实例称为 “对等体”。
  
Eureka Client 会缓存服务注册表中的信息。这种方式有一定的优势——首先,微服务无需每次请求都查询 Eureka Server,从而降低了 Eureka Server 的压力;其次,即使 Eureka Server 所有节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者并完成调用。
  
2.1 服务注册与发现的流程
Eureka 实现服务注册与发现的流程如下:
1. 搭建一个 Eureka Server 作为服务注册中心;
2. 服务提供者 Eureka Client 启动时,会把当前服务器的信息以服务名(spring.application.name)的方式注册到服务注册中心;
3. 服务消费者 Eureka Client 启动时,也会向服务注册中心注册;
4. 服务消费者还会获取一份可用服务列表,该列表中包含了所有注册到服务注册中心的服务信息(包括服务提供者和自身的信息);
5. 在获得了可用服务列表后,服务消费者通过 `HTTP` 或消息中间件远程调用服务提供者提供的服务。
   
2.2 环境配置
1. 创建 Spring Initializr 项目

   
   <?xml version="1.0" encoding="UTF-8"?>
   <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <parent>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-parent</artifactId>
           <version>2.6.10</version>
           <relativePath/> <!-- lookup parent from repository -->
       </parent>
       <groupId>com.gupaoedu</groupId>
       <artifactId>eureka_demo</artifactId>
       <version>0.0.1-SNAPSHOT</version>
       <name>eureka_demo</name>
       <description>Demo project for Spring Boot</description>
       <properties>
           <java.version>1.8</java.version>
           <spring-cloud.version>2021.0.3</spring-cloud.version>
       </properties>
       <dependencies>
           <dependency>
               <groupId>org.springframework.cloud</groupId>
               <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
           </dependency>
   
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-test</artifactId>
               <scope>test</scope>
           </dependency>
       </dependencies>
       <dependencyManagement>
           <dependencies>
               <dependency>
                   <groupId>org.springframework.cloud</groupId>
                   <artifactId>spring-cloud-dependencies</artifactId>
                   <version>${spring-cloud.version}</version>
                   <type>pom</type>
                   <scope>import</scope>
               </dependency>
           </dependencies>
       </dependencyManagement>
   
       <build>
           <plugins>
               <plugin>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-maven-plugin</artifactId>
               </plugin>
           </plugins>
       </build>
   
   </project>
    
2. 添加 @EnableEurekaServer 注解;
   package com.gupaoedu;
   
   import org.springframework.boot.SpringApplication;
   import org.springframework.boot.autoconfigure.SpringBootApplication;
   import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
   
   @EnableEurekaServer
   @SpringBootApplication
   public class EurekaDemoApplication {
   
       public static void main(String[] args) {
           SpringApplication.run(EurekaDemoApplication.class, args);
       }
   
   }
   
3. 启动服务;

  
4. 解决报错问题,application.properties 添加如下配置
# Eureka Server 默认端口地址
server.port=8761

# Eureka Server 默认注册地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
  

  
5. 不注册自己
   # 应用名称,应用名称会在Eureka中作为服务名称
   spring.application.name=spring-cloud-eureka-server
   # Eureka Server 默认端口地址
   server.port=8761
   # Eureka Server 默认注册地址
   #eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
   # 当前自己就是server,不需要注册自己
   eureka.client.register-with-eureka=false
   # 查询获取注册中心的服务信息,自己就是Server,所以不需要获取
   eureka.client.fetch-registry=false
  
2.3 服务提供者实现注册
1. 新建一个 spring-cloud-product-service 的 Spring Initializr 项目;
- 添加 Web --> Spring Web 依赖
- 添加 Spring Cloud Discovery --> Eureka Discovery Client 依赖
   <?xml version="1.0" encoding="UTF-8"?>
   <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <parent>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-parent</artifactId>
           <version>2.6.10</version>
           <relativePath/> <!-- lookup parent from repository -->
       </parent>
       <groupId>com.gupaoedu</groupId>
       <artifactId>spring-cloud-product-service</artifactId>
       <version>0.0.1-SNAPSHOT</version>
       <name>spring-cloud-product-service</name>
       <description>Demo project for Spring Boot</description>
       <properties>
           <java.version>1.8</java.version>
           <spring-cloud.version>2021.0.3</spring-cloud.version>
       </properties>
       <dependencies>
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-web</artifactId>
           </dependency>
           <dependency>
               <groupId>org.springframework.cloud</groupId>
               <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
           </dependency>
   
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-test</artifactId>
               <scope>test</scope>
           </dependency>
       </dependencies>
       <dependencyManagement>
           <dependencies>
               <dependency>
                   <groupId>org.springframework.cloud</groupId>
                   <artifactId>spring-cloud-dependencies</artifactId>
                   <version>${spring-cloud.version}</version>
                   <type>pom</type>
                   <scope>import</scope>
               </dependency>
           </dependencies>
       </dependencyManagement>
   
       <build>
           <plugins>
               <plugin>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-maven-plugin</artifactId>
               </plugin>
           </plugins>
       </build>
   
   </project>
   
2. 新建 ProductController.java 文件
   package com.gupaoedu.controller;
   
   import org.springframework.web.bind.annotation.GetMapping;
   import org.springframework.web.bind.annotation.PathVariable;
   import org.springframework.web.bind.annotation.RestController;
   
   @RestController
   public class ProductController {
   
       @GetMapping("/product/{id}")
       public String findById(@PathVariable("id") Integer id) {
           return "Success";
       }
   
   }
  
3. 配置 application.properties 文件;
   spring.application.name=spring-cloud-product-service
   server.port=8080
   eureka.client.service-url.defaultZone=http://localhost:8761/eureka
  
4. 运行。

  
2.4 服务消费者的远程调用
1. 新建一个 spring-cloud-user-service 的 Spring Initializr 项目;
- 添加 Web --> Spring Web 依赖
- 添加 Spring Cloud Discovery --> Eureka Discovery Client 依赖
   <?xml version="1.0" encoding="UTF-8"?>
   <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   	<modelVersion>4.0.0</modelVersion>
   	<parent>
   		<groupId>org.springframework.boot</groupId>
   		<artifactId>spring-boot-starter-parent</artifactId>
   		<version>2.1.14.RELEASE</version>
   		<relativePath/> <!-- lookup parent from repository -->
   	</parent>
   	<groupId>com.gupaoedu</groupId>
   	<artifactId>spring-cloud-user-service</artifactId>
   	<version>0.0.1-SNAPSHOT</version>
   	<name>spring-cloud-user-service</name>
   	<description>Demo project for Spring Boot</description>
   	<properties>
   		<java.version>1.8</java.version>
   		<spring-cloud.version>Greenwich.SR6</spring-cloud.version>
   	</properties>
   	<dependencies>
   		<dependency>
   			<groupId>org.springframework.boot</groupId>
   			<artifactId>spring-boot-starter-web</artifactId>
   		</dependency>
   		<dependency>
   			<groupId>org.springframework.cloud</groupId>
   			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
   		</dependency>
   
   		<dependency>
   			<groupId>org.springframework.boot</groupId>
   			<artifactId>spring-boot-starter-test</artifactId>
   			<scope>test</scope>
   		</dependency>
   	</dependencies>
   	<dependencyManagement>
   		<dependencies>
   			<dependency>
   				<groupId>org.springframework.cloud</groupId>
   				<artifactId>spring-cloud-dependencies</artifactId>
   				<version>${spring-cloud.version}</version>
   				<type>pom</type>
   				<scope>import</scope>
   			</dependency>
   		</dependencies>
   	</dependencyManagement>
   
   	<build>
   		<plugins>
   			<plugin>
   				<groupId>org.springframework.boot</groupId>
   				<artifactId>spring-boot-maven-plugin</artifactId>
   			</plugin>
   		</plugins>
   	</build>
   
   </project>
    
2. 新建 TestController;
   package com.gupaoedu.controller;
   
   import com.netflix.discovery.converters.Auto;
   import org.springframework.beans.factory.annotation.Autowired;
   import org.springframework.cloud.client.loadbalancer.LoadBalanced;
   import org.springframework.context.annotation.Bean;
   import org.springframework.web.bind.annotation.GetMapping;
   import org.springframework.web.bind.annotation.PathVariable;
   import org.springframework.web.bind.annotation.RestController;
   import org.springframework.web.client.RestTemplate;
   
   @RestController
   public class TestController {
   
   
       @Autowired
       RestTemplate restTemplate;
   
       @Bean
       @LoadBalanced
       public RestTemplate restTemplate(){
           return new RestTemplate();
       }
   
       @GetMapping("/product/{id}")
       public String queryProductInfo(@PathVariable("id")int id){
   
           return restTemplate.getForObject("http://product-service/product/"+id, String.class);
       }
   }
  
3. 配置 application.properties 文件;
   spring.application.name=user-service
   server.port=8081
   eureka.client.service-url.defaultZone=http://localhost:8761/eureka
  
2.5 Eureka Server 的高可用
1. 新建一个 spring-cloud-eureka-server-replicate 的 Spring Initializr 项目;
- 添加 Spring Cloud Discovery --> Eureka Server 依赖
   <?xml version="1.0" encoding="UTF-8"?>
   <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <parent>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-parent</artifactId>
           <version>2.6.10</version>
           <relativePath/> <!-- lookup parent from repository -->
       </parent>
       <groupId>com.gupaoedu</groupId>
       <artifactId>spring-cloud-eureka-replica</artifactId>
       <version>0.0.1-SNAPSHOT</version>
       <name>spring-cloud-eureka-replica</name>
       <description>Demo project for Spring Boot</description>
       <properties>
           <java.version>1.8</java.version>
           <spring-cloud.version>2021.0.3</spring-cloud.version>
       </properties>
       <dependencies>
           <dependency>
               <groupId>org.springframework.cloud</groupId>
               <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
           </dependency>
   
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-test</artifactId>
               <scope>test</scope>
           </dependency>
       </dependencies>
       <dependencyManagement>
           <dependencies>
               <dependency>
                   <groupId>org.springframework.cloud</groupId>
                   <artifactId>spring-cloud-dependencies</artifactId>
                   <version>${spring-cloud.version}</version>
                   <type>pom</type>
                   <scope>import</scope>
               </dependency>
           </dependencies>
       </dependencyManagement>
   
       <build>
           <plugins>
               <plugin>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-maven-plugin</artifactId>
               </plugin>
           </plugins>
       </build>
   
   </project>
    
2. 相互注册;
- 项目 spring-cloud-eureka-replica 的 Eureka 注册地址指向 8761 端口
     spring.application.name=spring-cloud-eureka-replica
     eureka.client.service-url.defaultZone=http://localhost:8761/eureka
     server.port=8762
  
- 项目 eureka_demo 的 Eureka 注册地址指向 8762 端口
     # 应用名称,应用名称会在Eureka中作为服务名称
     spring.application.name=spring-cloud-eureka-server
     # Eureka Server 默认端口地址
     server.port=8761
     # Eureka Server 默认注册地址
     eureka.client.service-url.defaultZone=http://localhost:8762/eureka/
     # 当前自己就是server,不需要注册自己
     eureka.client.register-with-eureka=false
     # 查询获取注册中心的服务信息,自己就是Server,所以不需要获取
     eureka.client.fetch-registry=false
  
3. 高可用配置
- 项目 eureka_demo 配置 application.properties
     # 应用名称,应用名称会在Eureka中作为服务名称
     spring.application.name=spring-cloud-eureka-server
     # Eureka Server 默认端口地址
     server.port=8761
     eureka.instance.hostname=eureka1
     # Eureka Server 默认注册地址
     eureka.client.service-url.defaultZone=http://eureka2:8762/eureka/
     # 当前自己就是server,不需要注册自己
     eureka.client.register-with-eureka=false
     # 查询获取注册中心的服务信息,自己就是Server,所以不需要获取
     eureka.client.fetch-registry=false
  
- 项目 spring-cloud-eureka-replica 配置 application.properties
     spring.application.name=spring-cloud-eureka-replica
     server.port=8762
     eureka.instance.hostname=eureka2
     eureka.client.service-url.defaultZone=http://eureka1:8761/eureka
  
- 项目 spring-cloud-product-service 配置 application.properties
     spring.application.name=spring-cloud-product-service
     server.port=8080
     eureka.client.service-url.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka
  
- 项目 spring-cloud-user-service 配置 application.properties
     spring.application.name=spring-cloud-user-service
     server.port=8081
     eureka.client.service-url.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka
  
2.6 自我保护机制
Eureka 服务端会检查最近 15 分钟内所有 Eureka 实例正常心跳占比,如果低于 85% 就会触发自我保护机制。触发了保护机制,Eureka 将暂时把这些失效的服务保护起来,不让其过期,但这些服务也并不是永远不会过期。Eureka 在启动完成后,每隔 60 秒会检查一次服务健康状态,如果这些被保护起来失效的服务过一段时间后(默认 90 秒)还是没有恢复,就会把这些服务剔除。如果在此期间服务恢复了并且实例心跳占比高于 85%时,就会自动关闭自我保护机制。
  
为什么会有自我保护机制?

Eureka 服务端为了防止 Eureka 客户端本身是可以正常访问的,但是由于网路通信故障等原因,造成 Eureka 服务端失去于客户端的连接,从而形成的不可用。因为网络通信是可能恢复的,但是 Eureka 客户端只会在启动时才去服务端注册。如果因为网络的原因而剔除了客户端,将造成客户端无法再注册到服务端。

    
3. Ribbon
3.1 创建注册中心
1. 创建一个 eureka-service 的 Spring Initializr 项目;
- 添加 Web --> Spring Web 依赖
- 添加 Spring Cloud Discovery --> Eureka Server 依赖

配置 eureka.server.enable-self-preservation = false 关闭自我保护机制。

   <?xml version="1.0" encoding="UTF-8"?>
   <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <parent>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-parent</artifactId>
           <version>2.6.10</version>
           <relativePath/> <!-- lookup parent from repository -->
       </parent>
       <groupId>com.gupaoedu</groupId>
       <artifactId>eureka-service</artifactId>
       <version>0.0.1-SNAPSHOT</version>
       <name>eureka-service</name>
       <description>Demo project for Spring Boot</description>
       <properties>
           <java.version>1.8</java.version>
           <spring-cloud.version>2021.0.3</spring-cloud.version>
       </properties>
       <dependencies>
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-web</artifactId>
           </dependency>
           <dependency>
               <groupId>org.springframework.cloud</groupId>
               <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
           </dependency>
   
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-test</artifactId>
               <scope>test</scope>
           </dependency>
       </dependencies>
       <dependencyManagement>
           <dependencies>
               <dependency>
                   <groupId>org.springframework.cloud</groupId>
                   <artifactId>spring-cloud-dependencies</artifactId>
                   <version>${spring-cloud.version}</version>
                   <type>pom</type>
                   <scope>import</scope>
               </dependency>
           </dependencies>
       </dependencyManagement>
   
       <build>
           <plugins>
               <plugin>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-maven-plugin</artifactId>
               </plugin>
           </plugins>
       </build>
   
   </project>
     
2. 开启 @EnableEurekaServer 注解
   package com.gupaoedu;
   
   import org.springframework.boot.SpringApplication;
   import org.springframework.boot.autoconfigure.SpringBootApplication;
   import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
   
   @EnableEurekaServer
   @SpringBootApplication
   public class EurekaServiceApplication {
   
       public static void main(String[] args) {
           SpringApplication.run(EurekaServiceApplication.class, args);
       }
   
   }
  
3. 配置 application.properties;
   server.port=8761
   eureka.client.service-url.defaultZone=http://localhost:8761/eureka
   eureka.client.register-with-eureka=false
   eureka.client.fetch-registry=false
  
4. 启动工程。
  
3.2 创建服务提供者
1. 创建一个 provider-service 的 Spring Initializr 项目;
- 添加 Web --> Spring Web 依赖
- 添加 Spring Cloud Discovery --> Eureka Discovery Client 依赖
   <?xml version="1.0" encoding="UTF-8"?>
   <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <parent>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-parent</artifactId>
           <version>2.6.10</version>
           <relativePath/> <!-- lookup parent from repository -->
       </parent>
       <groupId>com.gupaoedu</groupId>
       <artifactId>provider-service</artifactId>
       <version>0.0.1-SNAPSHOT</version>
       <name>provider-service</name>
       <description>Demo project for Spring Boot</description>
       <properties>
           <java.version>1.8</java.version>
           <spring-cloud.version>2021.0.3</spring-cloud.version>
       </properties>
       <dependencies>
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-web</artifactId>
           </dependency>
           <dependency>
               <groupId>org.springframework.cloud</groupId>
               <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
           </dependency>
   
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-test</artifactId>
               <scope>test</scope>
           </dependency>
       </dependencies>
       <dependencyManagement>
           <dependencies>
               <dependency>
                   <groupId>org.springframework.cloud</groupId>
                   <artifactId>spring-cloud-dependencies</artifactId>
                   <version>${spring-cloud.version}</version>
                   <type>pom</type>
                   <scope>import</scope>
               </dependency>
           </dependencies>
       </dependencyManagement>
   
       <build>
           <plugins>
               <plugin>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-maven-plugin</artifactId>
               </plugin>
           </plugins>
       </build>
   
   </project>
  
2. 创建 HelloController.java
   package com.gupaoedu.controller;
   
   import org.springframework.web.bind.annotation.GetMapping;
   import org.springframework.web.bind.annotation.RestController;
   
   @RestController
   public class HelloController {
   
       @GetMapping("hello")
       public String Hello() {
           System.out.println("接收到请求");
           return "Hello ......";
       }
   
   }
  
3. 修改 application.properties 配置文件
   spring.application.name=provider-service
   server.port=8080
   eureka.client.service-url.defaultZone=http://localhost:8761/eureka
  
4. Edit Configurations

  
5. 启动 ProviderService-01 和 ProviderService-02 。
  
3.3 创建服务消费者
1. 创建一个 consumer-service 的 Spring Initializr 项目;
- 添加 Web --> Spring Web 依赖
- 添加 Spring Cloud Discovery --> Eureka Discovery Client 依赖
   <?xml version="1.0" encoding="UTF-8"?>
   <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <parent>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-parent</artifactId>
           <version>2.1.14.RELEASE</version>
           <relativePath/> <!-- lookup parent from repository -->
       </parent>
       <groupId>com.gupaoedu</groupId>
       <artifactId>consumer-service</artifactId>
       <version>0.0.1-SNAPSHOT</version>
       <name>consumer-service</name>
       <description>Demo project for Spring Boot</description>
       <properties>
           <java.version>1.8</java.version>
           <spring-cloud.version>Greenwich.SR6</spring-cloud.version>
       </properties>
       <dependencies>
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-web</artifactId>
           </dependency>
           <dependency>
               <groupId>org.springframework.cloud</groupId>
               <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
           </dependency>
   
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-test</artifactId>
               <scope>test</scope>
           </dependency>
       </dependencies>
       <dependencyManagement>
           <dependencies>
               <dependency>
                   <groupId>org.springframework.cloud</groupId>
                   <artifactId>spring-cloud-dependencies</artifactId>
                   <version>${spring-cloud.version}</version>
                   <type>pom</type>
                   <scope>import</scope>
               </dependency>
           </dependencies>
       </dependencyManagement>
   
       <build>
           <plugins>
               <plugin>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-maven-plugin</artifactId>
               </plugin>
           </plugins>
       </build>
   
   </project>
  
2. 创建 TestContrlller ;
   package com.gupaoedu.controller;
   
   import org.springframework.beans.factory.annotation.Autowired;
   import org.springframework.cloud.client.loadbalancer.LoadBalanced;
   import org.springframework.context.annotation.Bean;
   import org.springframework.web.bind.annotation.GetMapping;
   import org.springframework.web.bind.annotation.RestController;
   import org.springframework.web.client.RestTemplate;
   
   @RestController
   public class TestContrlller {
   
       @Autowired
       RestTemplate restTemplate;
   
       @Bean
       @LoadBalanced
       public RestTemplate restTemplate() {
           return new RestTemplate();
       }
   
       @GetMapping("/test")
       public String test() {
           return restTemplate.getForObject("http://provider-service/hello", String.class);
       }
   
   }
  
3. 修改 application.properties 配置文件;
   spring.application.name=consumer-service
   server.port=8083
   eureka.client.service-url.defaultZone=http://localhost:8761/eureka
   
4. OpenFeign
1. 基于 consumer-service 项目,修改 pom.xml 文件;
   <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter-openfeign</artifactId>
   </dependency>
   <?xml version="1.0" encoding="UTF-8"?>
   <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <parent>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-parent</artifactId>
           <version>2.6.10</version>
           <relativePath/> <!-- lookup parent from repository -->
       </parent>
       <groupId>com.gupaoedu</groupId>
       <artifactId>consumer-service</artifactId>
       <version>0.0.1-SNAPSHOT</version>
       <name>provider-service</name>
       <description>Demo project for Spring Boot</description>
       <properties>
           <java.version>1.8</java.version>
           <spring-cloud.version>2021.0.3</spring-cloud.version>
       </properties>
       <dependencies>
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-web</artifactId>
           </dependency>
           <dependency>
               <groupId>org.springframework.cloud</groupId>
               <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
           </dependency>
           <dependency>
               <groupId>org.springframework.cloud</groupId>
               <artifactId>spring-cloud-starter-openfeign</artifactId>
           </dependency>
   
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-test</artifactId>
               <scope>test</scope>
           </dependency>
       </dependencies>
       <dependencyManagement>
           <dependencies>
               <dependency>
                   <groupId>org.springframework.cloud</groupId>
                   <artifactId>spring-cloud-dependencies</artifactId>
                   <version>${spring-cloud.version}</version>
                   <type>pom</type>
                   <scope>import</scope>
               </dependency>
           </dependencies>
       </dependencyManagement>
   
       <build>
           <plugins>
               <plugin>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-maven-plugin</artifactId>
               </plugin>
           </plugins>
       </build>
   
   </project>
  
2. 创建 IHelloControllerFeign 接口
   package com.gupaoedu.controller;
   
   import org.springframework.cloud.openfeign.FeignClient;
   import org.springframework.web.bind.annotation.GetMapping;
   
   @FeignClient("provider-service")
   public interface IHelloControllerFeign {
   
       @GetMapping("hello")
       String Hello();
   
   }
      
3. ConsumerServiceApplication 开启 @EnableFeignClients;
   package com.gupaoedu;
   
   import org.springframework.boot.SpringApplication;
   import org.springframework.boot.autoconfigure.SpringBootApplication;
   import org.springframework.cloud.openfeign.EnableFeignClients;
   
   @EnableFeignClients
   @SpringBootApplication
   public class ConsumerServiceApplication {
   
       public static void main(String[] args) {
           SpringApplication.run(ConsumerServiceApplication.class, args);
       }
   
   }
  
4. 新建 TestHelloController;
   package com.gupaoedu.controller;
   
   import org.springframework.beans.factory.annotation.Autowired;
   import org.springframework.web.bind.annotation.GetMapping;
   import org.springframework.web.bind.annotation.RestController;
   
   @RestController
   public class TestHelloController {
   
       @Autowired
       IHelloControllerFeign helloControllerFeign;
   
       @GetMapping("/hello")
       public String test() {
           return helloControllerFeign.Hello();
       }
   
   }
  
5. Spring Cloud Gateway
Spring Cloud Gateway 底层使用了高性能的通信框架 Netty。
  
5.1 SpringCloud Gateway 特征
SpringCloud 官方,对 SpringCloud Gateway 特征介绍如下:
(1)基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0。
(2)集成 Hystrix 断路器。
(3)集成 Spring Cloud DiscoveryClient。
(4)Predicates 和 Filters 作用于特定路由,易于编写的 Predicates 和 Filters。
(5)具备一些网关的高级功能:动态路由、限流、路径重写。
  
从以上的特征来说,和 Zuul 的特征差别不大。SpringCloud Gateway 和 Zuul 主要的区别,还是在底层的通信框架上。
  
简单说明一下上文中的三个术语:
(1)Filter(过滤器):
和 Zuul 的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。过滤器为 org.springframework.cloud.gateway.filter.GatewayFilter 类的实例。
(2)Route(路由):
网关配置的基本组成模块,和 Zuul 的路由配置模块类似。一个 Route 模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标 URI 会被访问。
(3)Predicate(断言):
这是一个 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。
    
5.2 路由配置方式
如果请求的目标地址,是单个的 URI 资源路径,配置文件示例如下:
server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        -id: url-proxy-1
          uri: http://localhost:8088
          predicates:
            -Path=/gateway
  
各字段含义如下:
id:我们自定义的路由 ID,保持唯一
uri:目标服务地址
predicates:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。
该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
  
上面这段配置的意思是,配置了一个 id 为 url-proxy-1 的 URI 代理规则,路由的规则为:
当访问地址 http://localhost:8080/gupao/1.jsp 时,会路由到上游地址 http://localhost:8088/1.jsp。
  
5.3 基于代码的路由配置方式
package com.gupaoedu.gateway;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
 
@SpringBootApplication
public class GatewayApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
 
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("path_route", r -> r.path("/gateway")
                        .uri("http://localhost:8088"))
                .build();
    }
 
}
   
5.4 gateWay 的主要功能之一是转发请求
转发规则的定义主要包含三个部分
|                         |                                                              |      |
| ----------------------- | ------------------------------------------------------------ | ---- |
| Route(路由)           | 路由是网关的基本单元,由ID、URI、一组Predicate、一组Filter组成,根据Predicate进行匹配转发。 |      |
| Predicate(谓语、断言) | 路由转发的判断条件,目前SpringCloud Gateway支持多种方式,常见如:Path、Query、Method、Header等,写法必须遵循 key=vlue的形式 |      |
| Filter(过滤器)        | 过滤器是路由转发请求时所经过的过滤逻辑,可用于修改请求、响应内容 |      |
  
> 其中Route和Predicate必须同时申明。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQLite中的隔离(八)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite版本3中的文件锁定和并发(七&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 数据库的“isolation”属性确定何时对 一个操作的数据库对其他并发操作可见。 数据库连接之间的隔离 如果使用两个不…

SpringBoot整合参数校验

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉🍎个人主页:Leo的博客💞当前专栏: 循序渐进学SpringBoot ✨特色专栏: MySQL学习 🥭本文内容:SpringBoot整合参数校验 📚个人知识库: Leo知识库,欢迎大家访问 目录 1.前言…

关于github提交失败的问题

问题描述 Username for https://github.com: LAL-Better Password for https://LAL-Bettergithub.com: remote: Support for password authentication was removed on August 13, 2021. remote: Please see https://docs.github.com/get-started/getting-started-with-git/abo…

QT资源添加调用

添加资源文件&#xff0c;新建资源文件夹&#xff0c;命名resource&#xff0c;然后点下一步&#xff0c;点完成 资源&#xff0c;右键add Prefix 添加现有文件 展示的label图片切换 QLabel *led_show; #include "mainwindow.h" #include<QLabel> #include&l…

Python应用JSON Web Tokens库之pyjwt使用详解

概要 JSON Web Tokens(JWT)是一种用于安全传输信息的开放标准(RFC 7519),它可以在网络应用之间传递声明。PyJWT是Python中用于创建、解析和验证JWT的库,它提供了丰富的功能和灵活性,能够轻松地在Python应用程序中实现JWT的各种功能。本文将深入探讨PyJWT库的各个方面,…

再见 mysql_upgrade

在数据库管理的世界里&#xff0c;随着技术的不断进步和业务的不断发展&#xff0c;数据库的版本升级成为了一个不可避免的过程。 MySQL 作为业界领先的开源关系型数据库管理系统&#xff0c;其版本迭代与功能优化同样不容忽视。 而在这个过程中&#xff0c;升级工具就显得尤为…

若依微服务nacos配置在哪里?

今天拿ruoyi-cloud项目拉下来看了下&#xff0c;发现nacos配置文件比较难找&#xff0c;这里说一下在哪里。 在项目sql脚本ry_config_20231204.sql里面&#xff0c;这个脚本执行会创建一个数据库叫ry-config。 安装好nacos以后&#xff0c;在nacos的配置文件application.proper…

ESP32-S3 集成了2.4GHz、Wi-Fi和BLE5.0的MCU芯片

智能家居无处不在&#xff0c;生活中一个不起眼的插座都有大讲究。那与全屋智能互相连通的WiFi智能插座内部到底是什么样呢&#xff1f; 一般的WiFi智能插座&#xff0c;由一个物理按键模块&#xff0c;负责物理上直接控制插座开关、重新配网等功能&#xff1b;WiFi模块&#x…

计数器的原理和应用

一、计数器的原理和应用 要求&#xff1a;每计数三次&#xff0c;数码管值加一 #include<reg51.h> unsigned char s[]{0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; unsigned char num0; void initcounter() {TMOD0x06;//0000 0110TH0256-3;TL0256-3;ET01;EA1;T…

OSX-02-Mac OS应用开发系列课程大纲和章节内容设计

本节笔者会详细介绍下本系统专题的大纲&#xff0c;以及每个专题章节的组织结构。这样读者会有一个全局的概念。 在开始前还是在再介绍一下下面这个框架图&#xff0c;因为比较重要&#xff0c;在这里再冗余介绍一下。开发Apple公司相关产品的软件时&#xff0c;主要有两个框架…

327京东一面

1.项目相关 2.手撕SQL 两道 3.JMeter性能测试 首先&#xff0c;进行基准测试&#xff1a; 单用户测试&#xff08;单用户循环多次得到的数据&#xff09;&#xff1b;为多用户并发执行提供参考 其次&#xff0c;进行负载测试&#xff1a; 通过逐步增加系统负载&#xff0…

爬虫逆向实战(38)-某空气质量平台(反调试,AES,DES,MD5)

一、数据接口分析 主页地址&#xff1a;某空气质量平台 1、抓包 (1) 反调试 该网站对鼠标右击以及F12进行了监听并拦截 虽然该网站无法打开Chrome控制台&#xff0c;导致我们无法抓包&#xff0c;但是道高一尺魔高一丈。既然我们无法在打开该网站的时候打开Chrome控制台&…

括号生成(回溯+剪枝)

22. 括号生成 - 力扣&#xff08;LeetCode&#xff09; 题目描述 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于能够生成所有可能的并且 有效的 括号组合。 样例输入 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;["((()))&q…

速通汇编(二)汇编mov、addsub指令

一&#xff0c;mov指令 mov指令的全称是move&#xff0c;从字面上去理解&#xff0c;作用是移动&#xff08;比较确切的说是复制&#xff09;数据&#xff0c;mov指令可以有以下几种形式 无论哪种形式&#xff0c;都是把右边的值移动到左边 mov 寄存器&#xff0c;数据&#…

竞赛 python+大数据校园卡数据分析

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于yolov5的深度学习车牌识别系统实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;4分工作量&#xff1a;4分创新点&#xff1a;3分 该项目较为新颖&am…

2024年 前端JavaScript 进阶 第1天 笔记

1.1-作用域和作用域链 1.2-JS垃圾回收机制以及算法 1.3-JS闭包 JS进阶-day1-154-JS闭包_哔哩哔哩_bilibili 1.4-变量和函数提升 1.5-函数剩余参数和展开运算符 运用场景&#xff1a; 1.6-ES6箭头函数的使用 1.7-数组解构 1.8-对象解构 最简写法&#xff1a; 1.9-forEach遍历数…

centos7配置阿里云的镜像站点作为软件包下载源

目录 1、备份 2、下载新的 CentOS-Base.repo 到 /etc/yum.repos.d/ 3、测试 阿里镜像提供的配置方法&#xff1a;centos镜像_centos下载地址_centos安装教程-阿里巴巴开源镜像站 1、备份 [rootlocalhost ~]# mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentO…

Nginx-记

Nginx是一个高性能的web服务器和反向代理服务器&#xff0c;用于HTTP、HTTPS、SMTP、POP3和IMAP协议。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。 &#xff08;1&#xff09;更快 这表现在两个方面&#xff1a;一方面&#xff0c;在正常情况下&…

Linux中安装JDK17.X

1、总体概述&#xff1f; 该操作方式适合centos或red hat环境 2.1、在线下载JDK安装包&#xff1f; 通过wget命令下载JDK17.X包 wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz 如果提示&#xff1a;没有wget命令就安装wget yum install w…

.Net 知识杂记

记录平日中琐碎的.net 知识点。不定期更新 目标框架名称(TFM) 我们创建C#应用程序时&#xff0c;在项目的工程文件(*.csproj)中都有targetFramework标签&#xff0c;以表示项目使用的目标框架 各种版本的TFM .NET Framework .NET Standard .NET5 及更高版本 UMP等 参考文档&a…