00.SpringCloud服务调用方式

news2024/10/5 14:54:52

服务调用方式

RPC和HTTP

无论是微服务还是SOA,都面临着服务间的远程调用。那么服务间的远程调用方式有哪些呢?

常见的远程调用方式有以下2种:

  • RPC:Remote Produce Call远程过程调用,类似的还有 。自定义数据格式,基于原生TCP通信,速度快,效率高。早期的webservice,现在热门的dubbo (12不再维护、17年维护权交给apache),都是RPC的典型代表

  • Http:http其实是一种网络传输协议,基于TCP,规定了数据传输的格式。现在客户端浏览器与服务端通信基本都是采用Http协议,也可以用来进行远程服务调用。缺点是消息封装臃肿,优势是对服务的提供和调用方没有任何技术限定,自由灵活,更符合微服务理念。现在热门的Rest风格,就可以通过http协议来实现。

跨域调用

跨域特指前端页面调用后端api,即前端页面在一个服务器,后端api在另外一个服务器,是浏览器安全保护行为,与后端没有关系。一般在前后端分离的项目中要解决跨域问题。解决跨域一般有以下几种方式:
(1)ajax+jsonp
(2)proxytable
(3)@CrossOrigin
(4)nginx代理
(5)response.setHeader(“Access-Control-Allow-Origin”, “*”);

远程调用

远程调用技术特指后端不同服务器之间的调用,例如在A服务的api中调用B服务的api。以下的技术都可以完成A服务调用B服务:
(1)dubbo+zookeeper
(2)springcloud中的eureka+feign
(3)httpclient/okhttp3
(4)spring中的RestTemplate
(5)webservice

搭建项目

image-20221109110910794

点击下一步

image-20221109111120857

修改后

image-20221109111304378

点击下一步

image-20221109111443127

点击下一步

image-20221109111509082

点击完成

image-20221109111537572

创建spring-provider、spring-consumer模块

image-20221109111744666

点击模块,选择Maven

image-20221109111923052

点击下一步,填写模块名称

image-20221109112110906

点击完成

image-20221109112146406

在spring-provider、spring-consumer模块中POM中引入WEB模块

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

增加配置文件application.yml

image-20221109112541147

spring-provider

application.yml

server:
  port: 8180

ProviderController

@RestController
public class ProviderController {

    @Value("${server.port}")
    private String port;

    @RequestMapping(value = "/provider/{id}")
    public String provider(@PathVariable String id){
        return "provider id = " + id + " port = " + port;
    }
}

运行结果

image-20221109153509257

spring-consumer

application.yml

server:
  port: 8280

ConsumerController

@RestController
public class ConsumerController {

    @RequestMapping(value = "/consumer/{id}")
    public String consumer(@PathVariable String id){
        return "consumer ";
    }
}

运行结果

image-20221109153435407

HttpClient和OkHttp3性能比

  • client连接为单例:
    单例模式下,HttpClient的响应速度要更快一些,单位为毫秒,性能差异相差不大
  • 非单例模式下,OkHttp的性能更好,HttpClient创建连接比较耗时,因为多数情况下这些资源都会写成单例模式。
  • HttpClient+okhttp+URLConnection

HttpClien

<dependency>
    <groupId>commons-httpclient</groupId>
    <artifactId>commons-httpclient</artifactId>
    <version>3.1</version>
</dependency>
    /**
     * @title consumerHttp
     *
     * @param: id
     * @updateTime 2022/11/9 15:09
     * @return: java.lang.String
     * @throws
     * @Description: HttpClient调用方式
     */
    @RequestMapping(value = "/consumerHttp/{id}")
    public String consumerHttp(@PathVariable String id){
        String consumer = null;
        String url = "http://localhost:8180/provider/" + id;

        HttpClient httpClient = new HttpClient();
        GetMethod getMethod = new GetMethod(url);
        try {
            httpClient.executeMethod(getMethod);
            byte[] body = getMethod.getResponseBody();
            consumer = new String(body, "UTF-8");
        } catch (IOException e) {
            return "HttpClient consumer exception";
        }
        return "HttpClient consumer " + consumer;
    }

运行结果:

image-20221109151746124

okhttp3

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.9.2</version>
</dependency>
    /**
     * @title consumerok
     *
     * @param: id
     * @updateTime 2022/11/9 15:25
     * @return: java.lang.String
     * @throws
     * @Description: OkHttpClient调用方式
     */
    @RequestMapping(value = "/consumerok/{id}")
    public String consumerok(@PathVariable String id){
        String consumer = null;
        String url = "http://localhost:8180/provider/" + id;

        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder().url(url).build();
        Response response = null;
        try {
            response = okHttpClient.newCall(request).execute();
            consumer = response.body().string();
        } catch (IOException e) {
            return "OkHttpClient consumer exception";
        }
        return "OkHttpClient consumer " + consumer;
    }

运行结果:

image-20221109152448929

Spring的RestTemplate

RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。RestTemplate 继承InterceptingHttpAccessor 并且实现了 RestOperations 接口,其中 RestOperations 接口定义了基本的 RESTful 操作,这些操作在 RestTemplate 中都得到了实现

常用方法:

HTTP Method常用方法描述
GETgetForObject发起 GET 请求响应对象
GETgetForEntity发起 GET 请求响应结果、包含响应对象、请求头、状态码等 HTTP 协议详细内容
POSTpostForObject发起 POST 请求响应对象
POSTpostForEntity发起 POST 请求响应结果、包含响应对象、请求头、状态码等 HTTP 协议详细内容
DELETEdelete发起 HTTP 的 DELETE 方法请求
PUTput发起 HTTP 的 PUT 方法请求

声明restTemplateBean方式一

@Bean
public RestTemplate getRestTemplate(){
    return new RestTemplate();
}

声明restTemplateBean方式二

@Bean
public RestTemplate getRestTemplate(RestTemplateBuilder builder){
    return builder.build();
}

restTemplate远程调用

    @Autowired
    private RestTemplate restTemplate;

    /**
     * @title consumerRest
     *
     * @param: id
     * @updateTime 2022/11/9 15:28
     * @return: java.lang.String
     * @throws
     * @Description: restTemplate调用方式
     */
    @RequestMapping(value = "/consumerRest/{id}")
    public String consumerRest(@PathVariable String id){
        String url = "http://localhost:8180/provider/" + id;
        String consumer = restTemplate.getForObject(url, String.class);
        return "restTemplate consumer " + consumer;
    }

运行结果:

image-20221109153025784

SpringCloud

微服务是一种架构方式,最终肯定需要技术架构去实施。

微服务的实现方式很多,目前Spring Cloud比较流行。为什么?

  • 后台硬:作为Spring家族的一员,有整个Spring全家桶靠山,背景十分强大。
  • 技术强:Spring作为Java领域的前辈,可以说是功力深厚,有强力的技术团队支撑。
  • 群众基础好:大多数程序员的成长都伴随着Spring框架,现在有几家公司开发不用Spring?SpringCloud与Spring的各个框架无缝整合,对大家来说一切都是熟悉的配方,熟悉的味道。
  • 使用方便:相信大家都体会到了SpringBoot给我们开发带来的便利,而SpringCloud完全支持SpringBoot的开发,用很少的配置就能完成微服务框架的搭建。

image-20221008093859011

简介

SpringCloud是Spring旗下的项目之一:

  • 官网地址:http://projects.spring.io/spring-cloud/
  • 中文地址:https://www.springcloud.cc/

Spring最擅长的就是集成,把世界上最好的框架拿过来,集成到自己的项目中。

SpringCloud也是一样,它将现在非常流行的一些技术整合到一起,实现了诸如:配置管理,服务发现,智能路由,负载均衡,熔断器,控制总线,集群状态等等功能。其主要涉及的组件包括:

  • Eureka:服务治理组件,包含服务注册中心,服务注册与发现机制的实现。(服务治理,服务注册/发现)
  • Zuul(gateway):网关组件,提供智能路由,访问过滤功能
  • Ribbon:客户端负载均衡的服务调用组件(客户端负载)
  • Feign(open feign):服务调用,给予Ribbon和Hystrix的声明式服务调用组件 (声明式服务调用)
  • Hystrix:容错管理组件,实现断路器模式,帮助服务依赖中出现的延迟和为故障提供强大的容错能力。(熔断、断路器,容错)

版本

因为Spring Cloud不同其他独立项目,它拥有很多子项目的大项目。所以它的版本是版本名+版本号 (如Angel.SR6)。

版本名:是伦敦的地铁名

版本号:SR(Service Releases)是固定的 ,大概意思是稳定版本。后面会有一个递增的数字。

所以 Edgware.SR3就是Edgware的第3个Release版本。

1528263985902

Eureka注册中心

原理图

  • Eureka:就是服务注册中心(可以是一个集群),对外暴露自己的地址
  • 提供者:启动后向Eureka注册自己信息(地址,提供什么服务)
  • 消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新
  • 心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态

image-20210322200104406

入门

搭建EurekaServer

接下来我们创建一个项目,启动一个EurekaServer:

依然使用spring提供的快速搭建工具:

选择依赖:EurekaServer-服务注册中心依赖,Eureka Discovery-服务提供方和服务消费方。因为,对于eureka来说:服务提供方和服务消费方都属于客户端

parent的pom.xml文件

<?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>
   <packaging>pom</packaging>
   <modules>
      <module>spring-provider</module>
      <module>spring-consumer</module>
        <module>eureka-server</module>
    </modules>
   <groupId>com.woniu</groupId>
   <artifactId>spring-cloud</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>spring-cloud</name>
   <description>Demo project for Spring Boot</description>
   <properties>
      <java.version>1.8</java.version>
      <spring-boot.version>2.3.11.RELEASE</spring-boot.version>
      <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
   </properties>
   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
      </dependency>

      <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <optional>true</optional>
      </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>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.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>
            <configuration>
               <excludes>
                  <exclude>
                     <groupId>org.projectlombok</groupId>
                     <artifactId>lombok</artifactId>
                  </exclude>
               </excludes>
            </configuration>
         </plugin>
      </plugins>
   </build>

</project>

eureka服务pom.xml文件

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud</artifactId>
        <groupId>com.woniu</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>eureka-server</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

</project>

application.yml配置:

server:
  port: 8081 # 端口
spring:
  application:
    name: eureka-server # 应用名称,会在Eureka中显示
eureka:
  client:
    service-url: # EurekaServer的地址,现在是自己的地址,如果是集群,需要加上其它Server的地址。
      defaultZone: http://127.0.0.1:${server.port}/eureka
    register-with-eureka: false  # 不把自己注册到eureka服务列表
    fetch-registry: false   # 拉取eureka服务信息
    
  instance:
    prefer-ip-address: true #客户端在注册时使用自己的IP而不是主机名
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  #实例id

修改引导类,在类上添加@EnableEurekaServer注解:

@SpringBootApplication
@EnableEurekaServer // 声明当前springboot应用是一个eureka服务中心
public class EurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

启动服务,并访问:http://127.0.0.1:8081

image-20221109160304630

服务方

注册服务,就是在服务上添加Eureka的客户端依赖,客户端代码会自动把服务注册到EurekaServer中。

spring-provider工程

1、在pom.xml中,添加springcloud eureka-client的相关依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2、在application.yml中,添加springcloud的相关依赖

# 应用服务 WEB 访问端口
server:
  port: 8180
# 应用名称
spring:
  application:
    name: spring-provider
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8081/eureka
  instance:
    prefer-ip-address: true #注册服务的时候使用服务的IP地址
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}

3、在引导类上开启Eureka客户端功能

添加**@EnableEurekaClient或者@EnableDiscoveryClient**来开启Eureka客户端功能

@SpringBootApplication
@EnableEurekaClient
public class SpringProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringProviderApplication.class, args);
    }
}

或者

@SpringBootApplication
@EnableDiscoveryClient
public class SpringProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringProviderApplication.class, args);
    }

}

@EnableEurekaClient和**@EnableDiscoveryClient**区别(了解)

@EnableEurekaClient

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface EnableEurekaClient {
}

@EnableDiscoveryClient

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({EnableDiscoveryClientImportSelector.class})
public @interface EnableDiscoveryClient {
    boolean autoRegister() default true;
}

在使用Spring Cloud feign使用中在使用服务发现的时候提到了两种注解:
一种为@EnableDiscoveryClient;
一种为@EnableEurekaClient,用法上基本一致。

spring cloud中discovery service有许多种实现(eureka、consul、zookeeper等等),
@EnableDiscoveryClient基于spring-cloud-commons;
@EnableEurekaClient基于spring-cloud-netflix。
其实用更简单的话来说,就是如果选用的注册中心是eureka,那么就推荐@EnableEurekaClient, 如果是其他的注册中心,那么推荐使用@EnableDiscoveryClient。

注解@EnableEurekaClient上有@EnableDiscoveryClient注解,可以说基本就是EnableEurekaClient有@EnableDiscoveryClient的功能,另外上面的注释中提到,其实@EnableEurekaClientz注解就是一种方便使用eureka的注解而已,可以说使用其他的注册中心后,都可以使用@EnableDiscoveryClient注解,但是使用@EnableEurekaClient的情景,就是在服务采用eureka作为注册中心的时候,使用场景较为单一。

重启项目,访问Eureka监控页面查看,发现spring-provider服务说明已经注册成功了

image-20221109170116891

消费方

1、引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  1. 修改配置
# 应用服务 WEB 访问端口
server:
  port: 8280
# 应用名称
spring:
  application:
    name: spring-consumer
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8081/eureka
  instance:
    prefer-ip-address: true #注册服务的时候使用服务的IP地址
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
  1. 在启动类开启Eureka客户端
@SpringBootApplication
@EnableDiscoveryClient // 开启Eureka客户端
public class SpringConsumerApplication {

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(SpringProviderApplication.class, args);
    }
}
  1. 修改UserController代码,用DiscoveryClient类的方法,根据服务名称,获取服务实例:
    @Autowired
    private DiscoveryClient discoveryClient; // eureka客户端,可以获取到eureka中服务的信息

    /**
     * @title consumerRestDiscovery
     *
     * @param: id
     * @updateTime 2022/11/9 15:28
     * @return: java.lang.String
     * @throws
     * @Description: 服务名称调用方式
     */
    @RequestMapping(value = "/consumerRestDiscovery/{id}")
    public String consumerRestDiscovery(@PathVariable String id){

        // 根据服务名称,获取服务实例。有可能是集群,所以是service实例集合
        List<ServiceInstance> instances = discoveryClient.getInstances("spring-provider");
        // 因为只有一个spring-provider。所以获取第一个实例
        ServiceInstance instance = instances.get(0);
        // 获取ip和端口信息,拼接成服务地址
        String baseUrl = "http://" + instance.getHost() + ":" + instance.getPort() + "/provider/" + id;
        String consumer = this.restTemplate.getForObject(baseUrl, String.class);
        return "restTemplate consumer " + consumer;
    }

重启程序

image-20221109175622812

运行结果:

image-20221109184804053

基础架构

Eureka架构中的三个核心角色:

  • 服务注册中心

    Eureka的服务端应用,提供服务注册和发现功能,就是刚刚我们建立的eureka-server。

  • 服务提供者

    提供服务的应用,可以是SpringBoot应用,也可以是其它任意技术实现,只要对外提供的是Rest风格服务即可。本例中就是我们实现的spring-provider。

  • 服务消费者

    消费应用从注册中心获取服务列表,从而得知每个服务方的信息,知道去哪里调用服务方。本例中就是我们实现的spring-consumer。

高可用的Eureka Server

Eureka Server即服务的注册中心,在刚才的案例中,我们只有一个EurekaServer,事实上EurekaServer也可以是一个集群,形成高可用的Eureka中心。

服务同步

多个Eureka Server之间也会互相注册为服务,当服务提供者注册到Eureka Server集群中的某个节点时,该节点会把服务的信息同步给集群中的每个节点,从而实现数据同步。因此,无论客户端访问到Eureka Server集群中的任意一个节点,都可以获取到完整的服务列表信息。

动手搭建高可用的EurekaServer

我们假设要运行两个EurekaServer的集群,端口分别为:8081和8082。只需要把eureka-server启动两次即可。

1、启动第一个eurekaServer,我们修改原来的EurekaServer配置:

server:
  port: 8081
spring:
  application:
    name: eureka-server
eureka:
  client:
    service-url: # EurekaServer的地址,现在是自己的地址,如果是集群,需要加上其它Server的地址。
      defaultZone: http://127.0.0.1:8082/eureka
  instance:
    prefer-ip-address: true #客户端在注册时使用自己的IP而不是主机名
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  #实例id

所谓的高可用注册中心,其实就是把EurekaServer自己也作为一个服务进行注册,这样多个EurekaServer之间就能互相发现对方,从而形成集群。因此我们做了以下修改:

  • 把service-url的值改成了另外一台EurekaServer的地址,而不是自己

启动报错,很正常。因为8082服务没有启动:

image-20221109191835708

2、启动第二个eurekaServer,再次修改eureka-server的配置:

server:
  port: 8082
spring:
  application:
    name: eureka-server
eureka:
  client:
    service-url: # EurekaServer的地址,现在是自己的地址,如果是集群,需要加上其它Server的地址。
      defaultZone: http://127.0.0.1:8081/eureka
  instance:
    prefer-ip-address: true #客户端在注册时使用自己的IP而不是主机名
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  #实例id

注意:idea中一个应用不能启动两次,我们需要重新配置一个启动器:复制运行的启动类即可

然后启动即可。

3、访问集群,测试:

8081服务

image-20221109192030585

8082服务

4、客户端注册服务到集群

因为EurekaServer不止一个,因此注册服务的时候,service-url参数需要变化:

eureka:
  client:
    service-url: # EurekaServer地址,多个地址以','隔开
      defaultZone: http://127.0.0.1:8081/eureka,http://127.0.0.1:8082/eureka

5、打开eureka-server监控页面

image-20221109192550343

image-20221109192641365

问题:IDEA无法同一个项目运行多次

解决方案:

  • 点击编辑配置

image-20221110094641088

  • 勾选以下等式,点击确认即可

  • 设置成功,如图:

image-20221110114931633

服务提供者

服务提供者要向EurekaServer注册服务,并且完成服务续约等工作。

服务注册

服务提供者在启动时,会检测配置属性中的:eureka.client.register-with-eureka=true参数,默认就是true。值为true,则会向EurekaServer发起一个Rest请求,并携带自己的元数据信息,Eureka Server会把这些信息保存到一个双层Map结构中。

  • 第一层Map的Key就是服务id,一般是配置中的spring.application.name属性
  • 第二层Map的key是服务的实例id。一般host+ serviceId + port,例如:locahost:spring-provider:8081
  • 值则是服务的实例对象,也就是说一个服务,可以同时启动多个不同实例,形成集群。

服务续约

在注册服务完成以后,服务提供者会维持一个心跳(定时向EurekaServer发起Rest请求),告诉EurekaServer:“我还活着”。这个我们称为服务的续约(renew);

有两个重要参数可以修改服务续约的行为:

eureka:
  instance:
    lease-expiration-duration-in-seconds: 90
    lease-renewal-interval-in-seconds: 30
  • lease-renewal-interval-in-seconds:服务续约(renew)的间隔,默认为30秒
  • lease-expiration-duration-in-seconds:服务失效时间,默认值90秒

默认情况下每个30秒服务会向注册中心发送一次心跳,证明自己还活着。超过90秒没有发送心跳,EurekaServer就会认为该服务宕机,会从服务列表中移除。

在开发时,这个值有点太长了,经常我们关掉一个服务,会发现Eureka依然认为服务在活着。所以我们在开发阶段可以适当调小。

eureka:
  instance:
    lease-expiration-duration-in-seconds: 10 # 10秒即过期
    lease-renewal-interval-in-seconds: 5 # 5秒一次心跳
    
    # 注意:从服务列表是否移除,还要看 eureka服务端的   eviction-interval-timer-in-ms:这个参数
    eviction-interval-timer-in-ms:6000  #这是6000毫秒 
    # 关闭自我保护机制  
    enable-self-preservation: false  

服务消费者

获取服务列表

当服务消费者启动时,会检测eureka.client.fetch-registry=true参数的值,如果为true,则会拉取Eureka Server服务的列表只读备份,然后缓存在本地。并且每隔30秒会重新获取并更新数据。我们可以通过下面的参数来修改:

eureka:
  client:
    registry-fetch-interval-seconds: 5

在开发环境下,能够快速得到服务的最新状态,我们可以将其设置小一点。

失效剔除和自我保护

服务下线

服务进行正常关闭操作,会触发一个服务下线的REST请求给Eureka Server,告诉服务注册中心:“我要下线了”。服务中心接受到请求之后,将该服务置为下线状态。

失效剔除

有些时候,我们的服务提供方并不一定会正常下线,可能因为内存溢出、网络故障等原因导致服务无法正常工作。Eureka Server需要将这样的服务剔除出服务列表。因此它会开启一个定时任务,每隔60秒对所有失效的服务(超过90秒未响应)进行剔除。

可以通过eureka.server.eviction-interval-timer-in-ms参数对其进行修改,单位是毫秒。

eureka:
  server:
    # 每隔多久(ms)触发一次服务剔除
    eviction-interval-timer-in-ms: 10000

原理图(了解)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2AkOwJla-1684317905505)(C:\Users\ThinkPad\AppData\Roaming\Typora\typora-user-images\image-20221110092516071.png)]

自我保护

我们关停一个服务,就会在Eureka面板看到一条警告:

1525618396076

这是触发了Eureka的自我保护机制。当一个服务未按时进行心跳续约时,Eureka会统计最近15分钟心跳失败的服务实例的比例是否超过了85%。在生产环境下,因为网络延迟等原因,心跳失败实例的比例很有可能超标,但是此时就把服务剔除列表并不妥当,因为服务可能没有宕机。Eureka就会把当前实例的注册信息保护起来,不予剔除。生产环境下这很有效,保证了大多数服务依然可用。

但是这给我们的开发带来了麻烦, 因此开发阶段我们都会关闭自我保护模式:(eureka-server)

eureka:
  server:
    enable-self-preservation: false # 如果为true,表示要保护实例,不被剔除,false关闭自我保护模式,剔除实例
    eviction-interval-timer-in-ms: 10000 # 扫描失效服务的间隔时间(缺省为60*1000ms)

如果保护实例不被剔除,而且配置了 eviction-interval-timer-in-ms: 10000,则eviction-interval-timer-in-ms参数为准,实例还是会被剔除

eureka:
  server:
    enable-self-preservation: true # 如果为true,表示要保护实例,不被剔除,false关闭自我保护模式,剔除实例
    #eviction-interval-timer-in-ms: 10000 # 扫描失效服务的间隔时间(缺省为60*1000ms)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

合合信息亮相CCIG2023:多位大咖共话智能文档未来,文档图像内容安全还面临哪些技术难题?

近日&#xff0c;中国图象图形大会&#xff08;CCIG 2023&#xff09;&#xff08;简称“大会”&#xff09;在苏州圆满落幕。本届大会以“图象图形向未来”为主题&#xff0c;由中国科学技术协会指导&#xff0c;中国图象图形学学会主办&#xff0c;苏州科技大学承办&#xff…

干货 | 利用SPSS进行高级统计第一期(更新)

Hello&#xff0c;大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是喵君姐姐~ 在之前的文章中&#xff0c;我们以此介绍了如何利用SPSS进行高级统计分析&#xff0c;内容包括&#xff1a; (1)描述性统计表格模板、卡方&T检验、相关&回归分析 (2)中介、多重中…

MD5_buuctf

概念 MD5信息摘要算法&#xff0c;一种被广泛使用的密码散列函数&#xff0c;可以产生出一个128位&#xff08;16字节&#xff09;的散列值&#xff08;hash value&#xff09;&#xff0c;用于确保信息传输完整一致。 MD5算法具有以下特点&#xff1a; 压缩性&#xff1a;任意…

一次失败的面试经历:我只想找个工作,你却看不起我?还用面试题羞辱我...

这段时间都说难找工作&#xff0c;没有面试机会。面对如此严峻的形式&#xff0c;很多软件测试人员都希望能拿一个满意的高薪offer&#xff0c;但是随着招聘职位的不断增多&#xff0c;面试的难度也随之加大&#xff0c;而面试官更是会择优录取 我最近为面试已经焦头烂额了&am…

循坏队列+OJ题之设计循环队列

生命不是要等待风暴过去&#xff0c;而是要学会在风暴中跳舞。 ——卡莉尔吉布朗目录 &#x1f33a;前言&#xff1a; &#x1f341;一.循环队列是什么&#xff1f; &#x1f34f;二.循环队列有什么作用&#xff1f; &#x1f340;三.OJ题之设计循环队列 1…

C++(3):字符串、向量和数组

命名空间的 using 声明 using namespace::name;1.每个名字都需要独立的 using 声明&#xff1b; 2.头文件不应包含 using 声明&#xff1a; 因为头文件的内容会拷贝到所有引用它的文件中去&#xff0c;如果头文件里有某个using声明&#xff0c;那么每个使用了该头文件的文件就…

Apache Kafka - 重识Kafka生产者

文章目录 概述Kafka 生产者Kafka 生产者工作原理如何使用 Kafka 生产者 生产者配置项&#xff08;核心&#xff09;导图总结 概述 Kafka 生产者是 Apache Kafka 中的一个重要组件&#xff0c;它负责将数据发送到 Kafka 集群中。在实时数据处理和流式处理应用程序中&#xff0c…

如何自建个人音乐播放器Navidrome

文章目录 1. 前言2. Navidrome网站搭建2.1 Navidrome下载和安装2.1.1 安装并添加ffmpeg2.1.2下载并配置Navidrome2.1.3 添加Navidrome到系统服务 2.2. Navidrome网页测试 3. 本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4. 公网访问测试5. 结语 转…

【总结】Nupmy1

Nupmy numpy的核心是名为ndarray的数据类型&#xff0c;它代表多维数组&#xff0c;封装了操作数据的运算和方法 1. 创建数组对象 1.1 方法1:array 通过array将list转换成数据对象 # 通过array将list转换成数据对象 array1np.array([1,2,3,4,5]) array1 # array([1, 2, 3,…

Nginx + fastCGI 实现动态网页部署

简介 本文章主要介绍下&#xff0c;如何通过Nginx fastCGI来部署动态网页。 CGI介绍 在介绍fastCGI之前先介绍下CGI是什么。CGI : Common Gateway Interface&#xff0c;公共网关接口。在物理层面上是一段程序&#xff0c;运行在服务器上&#xff0c;提供同客户端HTML页面的…

测试理论----Bug的严重程度(Severity)和优先级(Priority)的分类

【原文链接】测试理论----Bug的严重程度&#xff08;Severity&#xff09;和优先级&#xff08;Priority&#xff09;的分类 一、Bug的严重程度&#xff08;Severity&#xff09; Bug的Severity&#xff08;严重程度&#xff09;指的是一个Bug对软件系统功能影响的程度&#…

Java常用工具之Collections

目录 一、排序操作二、查找操作三、同步控制三、不可变集合四、其他五、CollectionUtils&#xff1a;Spring 和 Apache 都有提供的集合工具类六 、小结 Collections 是 JDK 提供的一个工具类&#xff0c;位于 java.util 包下&#xff0c;提供了一系列的静态方法&#xff0c;方便…

2023河海大学846软件工程学硕考研高分上岸经验分享

大家好&#xff0c;我是陪你考研每一天的大巴学长。 大巴学长为大家邀请到了2023年846软件工程学硕刚刚上岸的学长&#xff0c;为大家分享一下他的考研经验&#xff0c;经验里详细介绍了各科的复习方法&#xff0c;很有参考意义。 希望对大家有所借鉴和帮助&#xff0c;在此向…

栈实现队列(继续细起来啊)

生命不是要等待风暴过去&#xff0c;而是要学会在风暴中跳舞。 ——卡莉尔吉布朗目录 &#x1f341;一.栈实现队列 &#x1f340;二.使用两个栈实现队列的功能 &#x1f33c;1.在队列的结构体中创建两个栈 &#x1f681;2.创建一个队列的结构体指针 &#x1f309;3…

云计算中的大数据处理:尝试HDFS和MapReduce的应用

云计算中的大数据处理&#xff1a;尝试HDFS和MapReduce的应用 文章目录 云计算中的大数据处理&#xff1a;尝试HDFS和MapReduce的应用一、前言二、第一题1、命令方式2、java API方式 三、第二题1、创建CSV文件并将其上传到HDFS2、编写利用MapReduce框架的java代码3、打包java项…

【设计模式与范式:创建型】41 | 单例模式(上):为什么说支持懒加载的双重检测不比饿汉式更优?

从今天开始&#xff0c;我们正式进入到设计模式的学习。我们知道&#xff0c;经典的设计模式有 23 种。其中&#xff0c;常用的并不是很多。据我的工作经验来看&#xff0c;常用的可能都不到一半。如果随便抓一个程序员&#xff0c;让他说一说最熟悉的 3 种设计模式&#xff0c…

Kelvin和Rossby波 Part-2(浅水方程)

在前面博主有篇关于Kelvin和Rossby波的简要介绍&#xff0c;见下&#xff1a; Kelvin和Rossby波 Part-1&#xff08;简要介绍&#xff09; 开尔文波&#xff08;Kelvin Wave&#xff09;是发生在大气或海洋中的&#xff0c;迎向地形边界&#xff08;例如海岸线&#xff09;平衡…

回顾2023年计算机专业学生卑微求职 / 申博血泪史

0.前言 2023年是悲惨的一年&#xff0c;各个行业都在卷中卷。同时对于个人来说&#xff0c;2023年也是最忙碌的一年&#xff0c;不仅面临毕业&#xff0c;而且面临工作/读博&#xff0c;随便挑出一件&#xff0c;都是一件耗时耗力的事。相信大家也从网络上看到了很多的帖子或者…

文心一言 VS 讯飞星火 VS chatgpt (19)-- go语言的slice和rust语言的Vec的扩容流程是什么?

go语言的slice和rust语言的Vec的扩容流程是什么&#xff1f; 文心一言&#xff1a; 在Go语言中&#xff0c;slice&#xff08;切片&#xff09;和Rust语言中的Vec都是用于存储一组固定长度的元素的数据结构。它们的扩容流程略有不同&#xff0c;下面是它们的基本概述&#xf…

HNU数据结构与算法分析-作业3-树结构

1. (简答题) 5.1 定义满二叉树的每一个结点或者是一个分支结点&#xff0c;并恰好有两个非空子结点&#xff1b;或者是叶结点。 证明在有n个分支结点的所有二叉树中&#xff0c;满二叉树的叶结点的数目&#xff08;或者叶结点与全部结点数的比例&#xff09;是最高的。 5.6 …