• Spring Cloud(Finchley版本)系列教程(一) 服务注册与发现(eureka)


    Spring Cloud(Finchley版本)系列教程(一) 服务注册与发现(eureka)

    为了更好的浏览体验,欢迎光顾勤奋的凯尔森同学个人博客http://www.huerpu.cc:7000

    如有错误恳请大家批评指正,与大家共同学习、一起成长,万分感谢。

    一、构建环境

    Spring Cloud构建工具可以使用MavenGradle,但Maven任然是主流。本文档所使用的开发环境如下:

    环境参数版本
    JDK8
    Maven3.9.4
    Spring CloudFinchley
    IDEidea2023.1.1 U
    OSWindows11专业版

    Spring Cloud相关模块

    模块说明
    Eureka服务注册中心,用于服务管理
    Ribbon基于客户端的负载均衡组件
    Hystrix容错框架,能够防止服务的雪崩效应
    FeignWeb服务客户端,能够简化HTTP接口的调用
    ZuulAPI网关,提供路由转发、请求过滤等功能
    Config分布式配置管理
    Sleuth服务跟踪
    Stream构建消息驱动的微服务应用程序的框架
    Bus消息代理的集群消息总线

    Spring Cloud主要有5大组件,分别为服务发现组件EurekaFeignRibbonZuulHystrix。但很多都弃用了,比如Ribbon等。

    注:SpringCloud版本说明

    英文中文boot大版本boot代表
    Angel安吉尔1.2.X1.2.8
    Brixton布里克斯顿1.3.X1.3.8
    Camden卡梅登1.4.X1.4.2
    Dalston达斯顿1.5.X1.5.0
    Edgware艾奇韦尔1.5.X1.5.19
    Finchley芬奇利2.0.X2.0.8
    Greenwich格林威治2.1.X2.1.2
    Hoxton霍克斯顿2.2.X2.2.6
    2020.0.6-aka Ilford埃福的2.5.72.5.7
    2021.0.6 Jubilee朱比利2.6.x2.6.1
    2022.0.0 Kilburn基尔伯恩3.0.x3.0.5

    二、微服务注册与发现

    Spring Cloud提供了很多服务发现组件,比如:EurekaConsulZooKeeper等。而EurekaNetflix开源的服务发现组件,它包含Server和Client两部分。Eureka Server提供服务发现的能力,每个微服务启动时,都会向Eureka Server注册自己的信息(IP、端口、微服务名称等),Eureka Server存储记录每个微服务的这些信息。Eureka Client是用于简化与Eureka Server交互的Java客户端。微服务启动后,会周期性地(默认30s)向Eureka Server发送心跳以续约自己的可用时间。如果Eureka Server在规定的时间内没有接收到微服务实例的心跳,Eureka Server则会将该实例注销(默认90s)。

    常见的注册中心

    组件名语言CAP一致性算法服务健康检查对外暴露接口
    EurekaJavaAP可配支持HTTP
    ConsulGoCPRaft支持HTTP/DNS
    ZookeeperJavaCPPaxos支持客户端
    NacosJavaAPRaft支持HTTP
    2.1 创建EurekaServer

    在idea中,创建一个名称为eurekaServerMaven工程。

    image-20230906120456178

    image-20230906121408500

    image-20230906131449947

    image-20230906121903248

    pom.xml文件增加Eureka依赖,修改SpringCloud版本为Finchley.SR2,修改SpringBoot版本为2.0.6.RELEASE

    
    <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.0modelVersion>
        <parent>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-parentartifactId>
            <version>2.0.6.RELEASEversion>
            <relativePath/> 
        parent>
        <groupId>cc.huerpugroupId>
        <artifactId>eurekaServerartifactId>
        <version>0.0.1-SNAPSHOTversion>
        <name>eurekaServername>
        <description>eurekaServerdescription>
        <properties>
            <java.version>1.8java.version>
            <spring-cloud.version>Finchley.SR2spring-cloud.version>
        properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
            dependency>
            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
            dependency>
        dependencies>
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloudgroupId>
                    <artifactId>spring-cloud-dependenciesartifactId>
                    <version>Finchley.SR2version>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
            dependencies>
        dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-maven-pluginartifactId>
                plugin>
            plugins>
        build>
    
    project>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    修改EurekaServerApplication启动类,增加@EnableEurekaServer注解。

    package cc.huerpu.eurekaserver;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaServerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(EurekaServerApplication.class, args);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    创建application.yml文件

    server:
      port: 8761 # 端口号
    
    spring:
      application:
        name: eurekaServer # Eureka名称
    
    eureka:
      instance:
        prefer-ip-address: false
        hostname: eurekaServer
      client:
        fetch-registry: false # 表示是否从EurekaServer获取注册信息,默认为true。因为本应用是一个单点的EurekaServer,不需要同步其他的EurekaServer节点的数据,因此设为false。
        register-with-eureka: false # 是否将自己注册到EurekaServer,默认为true。由于当前应用就是EurekaServer,因此设为false。
        service-url:
          defaultZone: http://eurekaServer:8761/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    修改系统的hostsWindows11hosts文件路径为:C:\Windows\System32\drivers\etc\hostsLinuxmacOS的文件路径为/etc/hosts。增加一行:127.0.0.1 eurekaServer

    启动项目,并测试访问

    点击idea的项目启动按钮,并访问http://eurekaserver:8761/查看Eureka首页。

    image-20230906134611417

    2.2 创建EurekaClient,并让它注册到EurekaServer上。

    复制eurekaServer项目,修改artifactIdEurekaClient。修改application.yml文件,端口号为8000,应用名称为eurekaClient

    server:
      port: 8000 # 端口号
    
    spring:
      application:
        name: eurekaClient # Eureka名称
    
    management:
      info:
        env:
          enabled: true
      endpoints:
        web:
          exposure:
            include: "*"
        enabled-by-default: true
    
    eureka:
      instance:
        prefer-ip-address: false
        hostname: eurekaClient
      client:
        healthcheck:
          enabled: true
        fetch-registry: true 
        register-with-eureka: true 
        service-url:
          defaultZone: http://eurekaServer:8761/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    修改启动类,增加@EnableDiscoveryClient注解。

    package cc.huerpu.eurekaclient;
    
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    @SpringBootApplication
    @EnableDiscoveryClient
    public class EurekaClientApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(EurekaClientApplication.class, args);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    编写一个测试接口,最简单的那种就好。

    @RestController
    public class UserController {
    
        @RequestMapping("/getUserById")
        public String getUserById(){
    
            return "{id:1,name:jason,age:23}";
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    修改pom.xml文件,把几处地方改为eurekaClient,另外增加了一个actuator包。

    
    <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.0modelVersion>
        <parent>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-parentartifactId>
            <version>2.0.6.RELEASEversion>
            <relativePath/> 
        parent>
        <groupId>cc.huerpugroupId>
        <artifactId>eurekaClientartifactId>
        <version>0.0.1-SNAPSHOTversion>
        <name>eurekaClientname>
        <description>eurekaClientdescription>
        <properties>
            <java.version>1.8java.version>
            <spring-cloud.version>Finchley.SR2spring-cloud.version>
        properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-actuatorartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
            dependency>
        dependencies>
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloudgroupId>
                    <artifactId>spring-cloud-dependenciesartifactId>
                    <version>Finchley.SR2version>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
            dependencies>
        dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-maven-pluginartifactId>
                plugin>
            plugins>
        build>
    
    project>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    启动项目,刷新http://eurekaClient:8761/会看到EurekaClient注册上来了。

    image-20230906140215041

    2.3 添加EurekaServer用户认证

    在实际应用中,资源的访问都是需要认证的,接下来我们把EurekaServer 改造为需要认证的服务。

    EurekaServer 添加security依赖:

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-securityartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    修改EurekaServerapplication.yml文件,增加security认证,增加spring.security.user.namespring.security.user.password。并修改defaultZonehttp://eurekaha:eurekapwd@eurekaServer:8761/eureka/

    server:
      port: 8761 # 端口号
    
    spring:
      security:
        user:
          name: eureka
          password: eurekapwd
      application:
        name: eurekaServer # Eureka名称
    
    eureka:
      instance:
        prefer-ip-address: false
        hostname: eurekaServer
      client:
        fetch-registry: true
        register-with-eureka: true
        service-url:
          defaultZone: http://eureka:eurekapwd@eurekaServer:8761/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    EurekaServercc.huerpu.eurekaserver.security包路径下创建WebSecurityConfig类,关闭csrf,并开启httpBasic认证。

    package cc.huerpu.eurekaserver.security;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable();
            http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    重新启动项目,访问时需要认证登录。

    image-20230906144643762

    输入配置文件里的账号/密码:eureka/eurekapwd进行登录。

    image-20230906144720577

    如果你的没有注册上来,耐心等一分钟就可以了。

    对于创建Eureka的注册中心集群,请参考文章:http://www.huerpu.cc:7000/?p=607。这里就不做过多的介绍了。

    三、创建一个eurekaClientConsumer调用eurekaClient服务

    复制eurekaClient项目,修改artifactIdeurekaClientConsumer。修改application.yml文件,端口号为8001,应用名称为eurekaClientConsumer(本机host中也增加这一个)。

    127.0.0.1   localhost
    127.0.0.1   eurekaServer
    127.0.0.1   eurekaClient
    127.0.0.1   eurekaclientconsumer
    
    • 1
    • 2
    • 3
    • 4
    
    <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.0modelVersion>
        <parent>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-parentartifactId>
            <version>2.0.6.RELEASEversion>
            <relativePath/> 
        parent>
        <groupId>cc.huerpugroupId>
        <artifactId>eurekaClientConsumerartifactId>
        <version>0.0.1-SNAPSHOTversion>
        <name>eurekaClientConsumername>
        <description>eurekaClientConsumerdescription>
        <properties>
            <java.version>1.8java.version>
            <spring-cloud.version>Finchley.SR2spring-cloud.version>
        properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-actuatorartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
            dependency>
        dependencies>
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloudgroupId>
                    <artifactId>spring-cloud-dependenciesartifactId>
                    <version>Finchley.SR2version>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
            dependencies>
        dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-maven-pluginartifactId>
                plugin>
            plugins>
        build>
    
    project>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    application.yml

    server:
      port: 8001 # 端口号
    
    spring:
      application:
        name: eurekaClientConsumer # Eureka名称
    
    
    management:
      info:
        env:
          enabled: true
      endpoints:
        web:
          exposure:
            include: "*"
        enabled-by-default: true
    
    eureka:
      instance:
        prefer-ip-address: false
        hostname: eurekaClientConsumer
      client:
        healthcheck:
          enabled: true
        fetch-registry: true
        register-with-eureka: true
        service-url:
          defaultZone: http://eureka:eurekapwd@eurekaServer:8761/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    修改启动类名称为EurekaClientConsumerApplication,并增加注入一个restTemplate

    package cc.huerpu.eurekaclient;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    @SpringBootApplication
    @EnableDiscoveryClient
    public class EurekaClientConsumerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(EurekaClientConsumerApplication.class, args);
        }
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    controller包下创建一个ConsumerController类,注入restTemplateeurekaClientdiscoveryClient

    package cc.huerpu.eurekaclient.controller;
    
    import com.netflix.appinfo.InstanceInfo;
    import com.netflix.discovery.EurekaClient;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.discovery.DiscoveryClient;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    import java.util.List;
    
    @RestController
    public class ConsumerController {
        @Autowired
        private RestTemplate  restTemplate;
        @Autowired
        private EurekaClient eurekaClient;
    
        @Autowired
        private DiscoveryClient discoveryClient;
    
        //获得eurekaClient的url
        @RequestMapping("/eurekaClientServiceUrl")
        private String eurekaClientServiceUrl() {
            InstanceInfo instance = eurekaClient.getNextServerFromEureka("eurekaClient", false);
            return instance.getHomePageUrl();
        }
    
        @RequestMapping("/consumerEurekaClient")
        public String consumerEurekaClient(){
            String eurekaClientURL = eurekaClientServiceUrl();
            String res = restTemplate.getForObject(eurekaClientURL + "/getUserById",String.class);
            return "consumerEurekaClient:" + res;
        }
    
        @RequestMapping("/eurekaClient-instance")
        public List<ServiceInstance> showInfo() {
            return this.discoveryClient.getInstances("eurekaClient");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    在没有服务注册中心的时候,eurekaClientConsumer服务调用eurekaClient服务,需要在eurekaClientConsumer服务代码里显式通过硬编码IP地址和端口号进行调用,也可以通过@Value注入配置的方式进行配置,但被调用方方的IP和端口号变化之后,调用方就必须进行修改,针对千千万万的接口来说,维护这些信息简直是场噩梦。

    @RestController
    public class ConsumerController {
    
        @RequestMapping("/consumerEurekaClient")
        public String consumerEurekaClient(){
            String res = restTemplate.getForObject("http://localhost:8000/getUserById", String.class);
            return "consumerEurekaClient:" + res;
        }
      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    @RestController
    public class ConsumerController {
    		//通过配置文件中的hep.eurekaclient.userservice.url值进行配置
        @Value("${hep.eurekaclient.userservice.url}")
        private String eurekaClient;
        @RequestMapping("/consumerEurekaClient")
        public String consumerEurekaClient(){
            String res = restTemplate.getForObject("http://localhost:8000/getUserById", String.class);
            return "consumerEurekaClient:" + res;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    但现在我们通过eureka就没有这个烦恼啦,只需要eurekaClient.getNextServerFromEureka("eurekaClient", false),就可以获得服务的调用地址,其中"eurekaClient"是由spring.application.name指定的,即使被调用方的IP和端口号变化,对我们来说都是无感的,调用方这边完全不用做任何修改,是不是很开心?

    访问http://eurekaclientconsumer:8001/consumerEurekaClient,就可以得到consumerEurekaClient:{id:1,name:jason,age:23},证明我们的消费方consumerEurekaClient调用被消费方eurekaClient成功了。

    image-20230420150333493

    四、Eureka 的元数据

    Eureka 的元数据有两种,标准元数据和自定义元数据。标准元数据有主机名、IP地址、端口号、状态页和健康检查等信息,这些信息都会被发布在服务注册表中,用于服务之间的调用。自定义元数据可以使用eureka.instance.metadata-map配置。

    可以通过http://eurekaserver:8761/eureka/apps来查看eureka中有哪些应用。

    <applications>
    	<versions__delta>1versions__delta>
    	<apps__hashcode>UP_3_apps__hashcode>
    	<application>
    		<name>EUREKASERVERname>
    		<instance>
    			<instanceId>localhost:eurekaServer:8761instanceId>
    			<hostName>eurekaServerhostName>
    			<app>EUREKASERVERapp>
    			<ipAddr>192.168.75.1ipAddr>
    			<status>UPstatus>
    			<overriddenstatus>UNKNOWNoverriddenstatus>
    			<port enabled="true">8761port>
    			<securePort enabled="false">443securePort>
    			<countryId>1countryId>
    			<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
    				<name>MyOwnname>
    			dataCenterInfo>
    			<leaseInfo>
    				<renewalIntervalInSecs>30renewalIntervalInSecs>
    				<durationInSecs>90durationInSecs>
    				<registrationTimestamp>1693982763311registrationTimestamp>
    				<lastRenewalTimestamp>1693984895889lastRenewalTimestamp>
    				<evictionTimestamp>0evictionTimestamp>
    				<serviceUpTimestamp>1693982734094serviceUpTimestamp>
    			leaseInfo>
    			<metadata>
    				<management.port>8761management.port>
    			metadata>
    			<homePageUrl>http://eurekaServer:8761/homePageUrl>
    			<statusPageUrl>http://eurekaServer:8761/actuator/infostatusPageUrl>
    			<healthCheckUrl>http://eurekaServer:8761/actuator/healthhealthCheckUrl>
    			<vipAddress>eurekaServervipAddress>
    			<secureVipAddress>eurekaServersecureVipAddress>
    			<isCoordinatingDiscoveryServer>trueisCoordinatingDiscoveryServer>
    			<lastUpdatedTimestamp>1693982763311lastUpdatedTimestamp>
    			<lastDirtyTimestamp>1693982733236lastDirtyTimestamp>
    			<actionType>ADDEDactionType>
    		instance>
    	application>
    	<application>
    		<name>EUREKACLIENTname>
    		<instance>
    			<instanceId>localhost:eurekaClient:8000instanceId>
    			<hostName>eurekaClienthostName>
    			<app>EUREKACLIENTapp>
    			<ipAddr>192.168.75.1ipAddr>
    			<status>UPstatus>
    			<overriddenstatus>UNKNOWNoverriddenstatus>
    			<port enabled="true">8000port>
    			<securePort enabled="false">443securePort>
    			<countryId>1countryId>
    			<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
    				<name>MyOwnname>
    			dataCenterInfo>
    			<leaseInfo>
    				<renewalIntervalInSecs>30renewalIntervalInSecs>
    				<durationInSecs>90durationInSecs>
    				<registrationTimestamp>1693982763312registrationTimestamp>
    				<lastRenewalTimestamp>1693984884241lastRenewalTimestamp>
    				<evictionTimestamp>0evictionTimestamp>
    				<serviceUpTimestamp>1693982751862serviceUpTimestamp>
    			leaseInfo>
    			<metadata>
    				<management.port>8000management.port>
    			metadata>
    			<homePageUrl>http://eurekaClient:8000/homePageUrl>
    			<statusPageUrl>http://eurekaClient:8000/actuator/infostatusPageUrl>
    			<healthCheckUrl>http://eurekaClient:8000/actuator/healthhealthCheckUrl>
    			<vipAddress>eurekaClientvipAddress>
    			<secureVipAddress>eurekaClientsecureVipAddress>
    			<isCoordinatingDiscoveryServer>falseisCoordinatingDiscoveryServer>
    			<lastUpdatedTimestamp>1693982763312lastUpdatedTimestamp>
    			<lastDirtyTimestamp>1693982751816lastDirtyTimestamp>
    			<actionType>ADDEDactionType>
    		instance>
    	application>
    	<application>
    		<name>EUREKACLIENTCONSUMERname>
    		<instance>
    			<instanceId>localhost:eurekaClientConsumer:8001instanceId>
    			<hostName>eurekaClientConsumerhostName>
    			<app>EUREKACLIENTCONSUMERapp>
    			<ipAddr>192.168.75.1ipAddr>
    			<status>UPstatus>
    			<overriddenstatus>UNKNOWNoverriddenstatus>
    			<port enabled="true">8001port>
    			<securePort enabled="false">443securePort>
    			<countryId>1countryId>
    			<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
    				<name>MyOwnname>
    			dataCenterInfo>
    			<leaseInfo>
    				<renewalIntervalInSecs>30renewalIntervalInSecs>
    				<durationInSecs>90durationInSecs>
    				<registrationTimestamp>1693984674119registrationTimestamp>
    				<lastRenewalTimestamp>1693984884145lastRenewalTimestamp>
    				<evictionTimestamp>0evictionTimestamp>
    				<serviceUpTimestamp>1693984674119serviceUpTimestamp>
    			leaseInfo>
    			<metadata>
    				<management.port>8001management.port>
    			metadata>
    			<homePageUrl>http://eurekaClientConsumer:8001/homePageUrl>
    			<statusPageUrl>http://eurekaClientConsumer:8001/actuator/infostatusPageUrl>
    			<healthCheckUrl>http://eurekaClientConsumer:8001/actuator/healthhealthCheckUrl>
    			<vipAddress>eurekaClientConsumervipAddress>
    			<secureVipAddress>eurekaClientConsumersecureVipAddress>
    			<isCoordinatingDiscoveryServer>falseisCoordinatingDiscoveryServer>
    			<lastUpdatedTimestamp>1693984674119lastUpdatedTimestamp>
    			<lastDirtyTimestamp>1693984674059lastDirtyTimestamp>
    			<actionType>ADDEDactionType>
    		instance>
    	application>
    applications>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115

    我们在上面也有写了一个接口,用来获得eurekaClient服务的相关实例。

    @Autowired
    private DiscoveryClient discoveryClient;
    
    @RequestMapping("/eurekaClient-instance")
    public List<ServiceInstance> showInfo() {
        return this.discoveryClient.getInstances("eurekaClient");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    <List>
    	<item>
    		<host>eurekaClienthost>
    		<port>8000port>
    		<metadata>
    			<management.port>8000management.port>
    		metadata>
    		<secure>falsesecure>
    		<uri>http://eurekaClient:8000uri>
    		<serviceId>EUREKACLIENTserviceId>
    		<instanceInfo>
    			<instanceId>localhost:eurekaClient:8000instanceId>
    			<app>EUREKACLIENTapp>
    			<appGroupName />
    			<ipAddr>192.168.75.1ipAddr>
    			<sid>nasid>
    			<homePageUrl>http://eurekaClient:8000/homePageUrl>
    			<statusPageUrl>http://eurekaClient:8000/actuator/infostatusPageUrl>
    			<healthCheckUrl>http://eurekaClient:8000/actuator/healthhealthCheckUrl>
    			<secureHealthCheckUrl />
    			<vipAddress>eurekaClientvipAddress>
    			<secureVipAddress>eurekaClientsecureVipAddress>
    			<countryId>1countryId>
    			<dataCenterInfo _class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
    				<name>MyOwnname>
    			dataCenterInfo>
    			<hostName>eurekaClienthostName>
    			<status>UPstatus>
    			<overriddenStatus>UNKNOWNoverriddenStatus>
    			<leaseInfo>
    				<renewalIntervalInSecs>30renewalIntervalInSecs>
    				<durationInSecs>90durationInSecs>
    				<registrationTimestamp>1693982763312registrationTimestamp>
    				<lastRenewalTimestamp>1693984674011lastRenewalTimestamp>
    				<evictionTimestamp>0evictionTimestamp>
    				<serviceUpTimestamp>1693982751862serviceUpTimestamp>
    			leaseInfo>
    			<isCoordinatingDiscoveryServer>falseisCoordinatingDiscoveryServer>
    			<metadata>
    				<management.port>8000management.port>
    			metadata>
    			<lastUpdatedTimestamp>1693982763312lastUpdatedTimestamp>
    			<lastDirtyTimestamp>1693982751816lastDirtyTimestamp>
    			<actionType>ADDEDactionType>
    			<asgName />
    		instanceInfo>
    		<scheme />
    	item>
    List>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    五、Eureka的健康检查

    在pom文件中引入Spring Boot Actuator,它提供了/health端点,该端点可展示应用程序的健康信息。

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-actuatorartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    引入Actuator后,在Eureka中开启健康检查。

    eureka:
      client:
        healthcheck:
          enabled: true 	 #开启健康检查(依赖spring-boot-actuator)
    
    • 1
    • 2
    • 3
    • 4

    访问http://localhost:8761/actuator/health可以查看Eureka的状态。

    若出现下面红色警告,其实是Eureka进入自我保护模式。如果最近一分钟实际接收到的心跳值Renews除以期望的心跳阈值 Renews threshold小于等于0.85,即 Renews/Renews threshold≤0.85

    EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE

    可以把renewal-percent-threshold调的小一些

    eureka:
      server:
        renewal-percent-threshold: 0.49
    
    • 1
    • 2
    • 3

    或者暴力一点关闭自我保护模式

    # 默认值是true
    eureka:
      server:
      	enable-self-preservation: false
    
    • 1
    • 2
    • 3
    • 4

    默认情况下,服务注册到Eureka Server的过程较慢。在开发或测试时,常常希望能够加速这一过程,从而提升工作效率。

    ##默认是30,单位秒。设成一个更小的值,该配置用于设置Eureka Client向Eureka Server发送心跳的时间间隔
    eureka:
      instance:
        lease-renewal-interval-in-seconds: 5
    
    • 1
    • 2
    • 3
    • 4

    本文参考SpringCloud官方文档:https://docs.spring.io/spring-cloud-netflix/docs/4.0.1/reference/html/

    六、部署eurekaserver到ubuntu22.04服务器

    每次都启动eureka的项目,太繁琐了,我们把eureka部署到Ubuntu,就可以愉快的玩耍了。最好部署到一台可以远程访问的服务器,这样在任何地方都可以注册服务和消费服务了。

    6.1 配置文件设置

    这里为了演示,我们准备好了一台 ubuntu22.04,IP地址为192.168.169.128

    eurekaserver项目,创建application-text.yml文件,内容如下

    server:
      port: 8761 # 端口号
    
    spring:
      security:
        user:
          name: eureka
          password: eurekapwd
      application:
        name: eurekaServer # Eureka名称
    
    eureka:
      server:
        enable-self-preservation: true
      instance:
        prefer-ip-address: ture
      client:
        fetch-registry: true
        register-with-eureka: true
        service-url:
          defaultZone: http://eureka:eurekapwd@192.168.169.128:8761/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    application.properties中增加让test生效配置。

    spring.profiles.active=test
    
    • 1
    6.2 生成eurekaserver的jar包

    生成eurekaserver的jar包:

    image-20230906154343842

    6.3 ubuntu安装jdk1.8
    sudo su -
    
    apt update
    
    apt upgrade -y
    
    apt install openjdk-8-jre-headless
    
    java -version
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    6.4 运行eurekaServer-0.0.1-SNAPSHOT.jar包

    我们把eurekaServer-0.0.1-SNAPSHOT.jar包 放在/usr/software目录下,根据个人喜好目录存放即可。使用MobaXterm等SSH工具上传即可。

    cd /usr
    #创建software文件夹,在此文件夹下有我们的eurekaServer-0.0.1-SNAPSHOT.jar包,可以通过上传工具上传过来
    mkdir software
    #赋予权限
    chmod -R 777 software
    #进入到software目录
    cd software
    
    #运行jar包
    nohup java -jar eurekaServer-0.0.1-SNAPSHOT.jar > log.txt &
    
    #开放8761端口
    ufw allow 8761
    ufw enable
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    6.5 验证eurekaserver服务

    打开http://192.168.169.128:8761/查看,Eureka已经启动了。

    image-20230906154948081

    eurekaClient项目修改defaultZonehttp://eureka:eurekapwd@192.168.169.128:8761/eureka/prefer-ip-address改为true

    defaultZone: http://eureka:eurekapwd@192.168.169.128:8761/eureka/
    prefer-ip-address: true
    
    • 1
    • 2

    重启eurekaClient项目,并刷新eurekaserver,查看服务是否注册上来。

    image-20230906160544912

    七、eureka相关说明

    7.1 EurekaServer REST API接口
    POST    /eureka/apps/{appId}                                            注册新的实例
    
    DELETE  /eureka/apps/{appId}/{instanceId}                               注销应用实例
    
    PUT     /eureka/apps/{appId}/{instanceId}                               应用实例发送心跳
    
    GET     /eureka/apps                                                    查询所有的实例
    
    GET     /eureka/apps/{appId}                                            查询指定appId的实例
    
    GET     /eureka/apps/{appId}/{instanceId}                               查询指定appId和instanceId的实例
    
    GET     /eureka/instances/{instanceId}                                  查询指定的instanceId的实例
    
    PUT     /eureka/apps/{appId}/{instanceId}/status?value=OUT_OF_SERVICE   暂停应用实例
    
    PUT     /eureka/apps/{appId}/{instanceId}/status?value=UP               恢复应用实例
    
    PUT     /eureka/apps/{appId}/{instanceId}/metadata?key=value            更新元数据信息
    
    GET     /eureka/vips/{vipAddress}                                       根据vip地址查询
    
    GET     /eureka/svips/{svipAddress}                                     根据svip地址查询
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    7.2 Client端参数
    eureka.client.register-with-eureka: true                     是否注册自己到Eureka Server上面
    eureka.client.fetch-registry: true                           是否从Eureka Server上面拉取服务信息
    eureka.client.enable: true                                   是否启用Eureka客户端,不启用则不注册到Eureka Server
    eureka.client.healthcheck.enable: true                       是否启用Eureka健康检查
    eureka.client.availability-zones: new HashMap<>()            告诉client有哪些可用的region和zone
    eureka.client.filter-only-up-instances: true                 是否过滤出InstanceStatus为UP的实例
    eureka.client.region: us-east-1                              指定该应用实例所在的region,AWS datacenters适用
    eureka.client.prefer-same-zone-eureka: true                  是否优先使用与该应用相同Zone的Eureka Server
    eureka.client.cache-refresh-executor-thread-pool-size: 2     缓存刷新线程池CacheRefreshThread的初始化线程数
    eureka.client.registry-fetch-interval-seconds: 30            Eureka client拉取服务注册信息间隔时间(s)
    eureka.client.instance-info-replication-interval-seconds: 30 复制实例变化信息到Eureka服务器所需要的时间间隔(s)
    eureka.client.eureka-service-url-poll-interval-seconds:  300 轮询Eureka服务端地址更改的间隔时间(s)
    eureka.client.eureka-server-read-timeout-seconds: 8          读取Eureka Server信息的超时时间(s)
    eureka.client.eureka-server-connect-timeout-seconds: 5       连接Eureka Server的超时时间(s)
    eureka.client.eureka-server-total-connections: 200           从Eureka客户端到所有Eureka服务端的连接总数
    eureka.client.eureka-server-total-connections-per-host: 50   从Eureka客户端到每个Eureka服务端主机的连接总数
    eureka.client.eureka-connection-idle-timeout-seconds: 30     Eureka服务端连接的空闲关闭时间(s)
    eureka.instance.metadata-map: new HashMap<>()                指定应用实例的元数据信息
    eureka.instance.prefer-ip-address: false                     是否优先使用ip地址来替代hostname作为实例hostname字段值 
    eureka.instance.lease-expiration-duration-in-seconds: 90     Eureka clent最后一次心跳后,Eureka Server剔除需要等待时间(s)
    eureka.instance.lease-renewal-interval-in-seconds: 30        客户端向Eureka Server发送心跳周期(s)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    7.3 Server端参数
    eureka.server.enable-self-preservation: true                 Eureka Server是否开启自我保护模式
    eureka.server.renewal-percent-threshold: 0.85                指定每分钟需要收到的续约次数的阙值,如果阈值比最小值大,则自我保护模式开启
    eureka.server.eviction-interval-timer-in-ms: 60*1000         指定EvictionTask定时任务的调度频率,用于剔除过期的实例
    eureka.server.wait-time-in-ms-when-sync-empty: 1000*60*5     在Eureka服务器获取不到集群里对等服务器上的实例时,需要等待的时间
    
    • 1
    • 2
    • 3
    • 4

    八、代码地址

    代码共享地址:http://www.huerpu.cc:2080/root/springcloud-finchley

  • 相关阅读:
    Linux权限
    spring循环依赖的解决方式以及成功失败案例分析
    一文搞懂容器运行时 Containerd
    odoo javascript参考(七)
    WSL2和ubuntu的安装过程
    任务流程----
    Redis入门 (店铺营业状态设置) --苍穹外卖day4
    为什么要选低代码开发平台
    Android ViewPager2 + TabLayout + BottomNavigationView
    word2vec中的skip-gram--学习笔记
  • 原文地址:https://blog.csdn.net/JingLisen/article/details/132717932