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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>anyi.space</groupId>
    <artifactId>distributedSystemLearn</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>member-service-provider_10000</module>
        <module>member-service-consumer</module>
        <module>common</module>
        <module>eureka-server_9001</module>
    </modules>
    <packaging>pom</packaging>

    <properties>
        <!--指定各种版本的依赖-->
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <spring.boot.version>2.7.17</spring.boot.version>
        <mysql.connector.version>8.3.0</mysql.connector.version>
        <log4j.version>1.2.17</log4j.version>
        <mybatis.plus.version>3.4.3.4</mybatis.plus.version>
        <druid.version>1.2.16</druid.version>
        <spring.colud.version>Hoxton.SR9</spring.colud.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!--springBoot父项目的依赖,以pom配置文件的形式导入-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--springCloud父项目的依赖,以pom配置文件的形式导入-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.colud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
                <version>${mysql.connector.version}</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis.plus.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

Eureka服务注册中心搭建

  1. Eureka依赖导入
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
  1. application.yaml配置文件的编写
    • 单机服务注册中心不需要向服务注册中注册自己,也不需要向服务注册中心拉取服务信息(集群部署时需要)
server:
  port: 9001
spring:
  application:
    name: eureka-server
eureka:
  instance:
#Eureka服务端的实例名称
    hostname: localhost
  client:
#配置不向服务中注册自己,默认是true
    register-with-eureka: false
#配置不向服务中抓取注册信息,因为自己就是服务端,默认是true
    fetch-registry: false
#配置服务注册中心的地址
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
  1. 主启动类EurekaServerApplication.java的编写
    • 使用"@EnableEurekaServer"注解标注该程序是Eureka的服务注册中心
package anyi.space.eurekaServer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * @ProjectName: distributedSystemLearn
 * @FileName: EurekaServerApplication
 * @Author: 杨逸
 * @Data:2025/4/14 19:11
 * @Description:
 */
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}
  1. 测试

    打开浏览器的页面

Eureka客户端搭建

服务提供客户端搭建

  1. 加入Erueka客户端依赖

     <!--引入eureka-client依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
  2. 编写application.yaml配置文件

    server:
      application:
        name: member-service-provider
      port: 10001
      servlet:
        context-path: /member-provider
    spring:
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        druid:
          url: jdbc:mysql://localhost:3306/spring_cloud?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
          username: root
          password: hsp
          driver-class-name: com.mysql.jdbc.Driver
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    eureka:
      client:
        #是否将自己注册到Eureka Server中
        register-with-eureka: true
        #是否从Eureka Server中获取注册信息,单节点不拉取也可以,集群部署时,需要拉取服务注册信息才能实现负载均衡
        fetch-registry: true
        #Eureka Server的地址
        service-url:
          defaultZone: http://localhost:9001/eureka/
    
    
  3. 编写主程序

    • 使用"@EnableEurekaClient"注解表示改程序是Eureka的客户端
    package anyi.space.memberServer;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    
    /**
     * @ProjectName: distributedSystemLearn
     * @FileName: MerberServiceApplication
     * @Author: 杨逸
     * @Data:2025/4/13 18:53
     * @Description:
     */
    @EnableEurekaClient
    @SpringBootApplication(scanBasePackages = {"anyi.sapce.common","anyi.space.memberServer"})
    public class MemberServiceApplication {
        public static void main(String[] args) {
            SpringApplication.run(MemberServiceApplication.class,args);
        }
    }
    
    
  4. 验证

服务调用客户端搭建

  1. 加入Eureka Client依赖

     <!--引入eureka-client依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
  2. 编写application.yaml配置文件

    server:
      port: 80
      servlet:
        context-path: /member-consumer
    spring:
      application:
        name: member-consumer
    eureka:
      instance:
        #配置注册到Eureka Server中的名称
        appname: member-consumer
      client:
        #是否将自己注册到Eureka Server中
        register-with-eureka: true
        #是否从Eureka Server中获取注册信息,单节点不拉取也可以,集群部署时,需要拉取服务注册信息才能实现负载均衡
        fetch-registry: true
        #Eureka Server的地址
        service-url:
          defaultZone: http://localhost:9001/eureka/
    
  3. 编写主启动类

    package anyi.space.memberConsumer;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    
    /**
     * @ProjectName: distributedSystemLearn
     * @FileName: MemberConsumerApplication
     * @Author: 杨逸
     * @Data:2025/4/13 20:05
     * @Description:
     */
    @EnableEurekaClient
    @SpringBootApplication(exclude= DataSourceAutoConfiguration.class)
    public class MemberConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(MemberConsumerApplication.class,args);
        }
    }
    
  4. 验证

Eureka自我保护机制

  • 在默认情况下,Eureka启动了自我保护模式
  • 默认情况下EurekaClient定时向EurekaServer端发送心跳包
  • 如果Eureka在server端在一定时间内(默认90秒)没有收到EurekaClient发送心跳包,便会直接从服务注册列表中剔除该服务
  • 如果Eureka开启了自我保护模式/机制,那么在短时间(90秒中)内丢失了大量的服务实例心跳,这时候EurekaServer会开启自我保护机制,不会剔除该服务(该现象可能出现在如果网络不通或者阻塞)因为客户端还能正常发送心跳,只是网络延迟问题,而保护机制是为了解决此问题而产生的
  • 自我保护是属于CAP里面的AP分支,保证高可用和分区容错性
  • 自我保护模式是—种应对网络异常的安全保护措施
  • 它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目注销任何健康的微服务。
  • 使用自我保护模式,可以让Eureka集群更加的健壮、稳定

禁用自我保护模式(生产环境一般不禁用)

  • 修改Eureka Server的application.yaml配置文件
  • 禁用自我保护机制
  • 修改心跳机制间隔超时时间
eureka:
  server:
    #关闭自我保护机制
    enable-self-preservation: false
    #心跳机制时间间隔(单位毫秒,默认是90*1000),心跳超时90秒后服务端会剔除超时的客户端
    eviction-interval-timer-in-ms: 2000
  • 修改Eureka Client的application.yaml
  • 修改发送心跳的间隔时间
  • 修改超时剔除服务的时间上限
eureka:
  instance:
    #心跳检测和续约的间隔时间
    #Eureka Client向Eureka Server发送心跳信息的间隔时间
    lease-renewal-interval-in-seconds: 30
    #Eureka Server在收到最后一次心跳后等待的时间上限,超时将剔除该服务实例,默认是90秒
    lease-expiration-duration-in-seconds: 90

搭建Eureka Server集群

  • 微服务RPC远程服务调用最核心的是实现高可用
  • 如果注册中心只有1个,它出故障,会导致整个服务环境不可用
  • 解决办法∶搭建Eureka注册中心集群,实现负载均衡+故障容错

在Erueka Server 9001模块的基础上,再搭建一个Eureka Server 9002模块,将两个服务注册相互注册实现服务注册中心集群的搭建

  1. 新模块,加入Srueka Server的依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    
  2. 配置Erueka Server 9002的application.yaml配置文件

    • 向Erueka Server 9001注册服务
    server:
      port: 9002
    spring:
      application:
        name: eureka-server
    eureka:
      instance:
    #Eureka服务端的实例名称
        hostname: localhost
      client:
    #配置向服务中注册自己,搭建集群
        register-with-eureka: true
    #配置向服务中抓取注册信息
        fetch-registry: true
    #配置服务注册中心的地址
        service-url:
          #向Eureka Server 9001相互注册
          defaultZone: http://localhost:9001/eureka
      server:
        #设置自我保护机制,默认开启
        enable-self-preservation: true
        #心跳机制时间间隔(单位毫秒,默认是30*1000)
        eviction-interval-timer-in-ms: 2000
    
    • 配置Eureka Server 9001向Eureka Server 9002注册
    server:
      port: 9001
    spring:
      application:
        name: eureka-server
    eureka:
      instance:
    #Eureka服务端的实例名称
        hostname: localhost
      client:
    #配置向服务中注册自己,搭建集群
        register-with-eureka: true
    #配置向服务中抓取注册信息
        fetch-registry: true
    #配置服务注册中心的地址
        service-url:
          #向Eureka Server 9002相互注册
          defaultZone: http://localhost:9002/eureka
      server:
        #设置自我保护机制,默认开启
        enable-self-preservation: true
        #心跳机制时间间隔(单位毫秒,默认是30*1000)
        eviction-interval-timer-in-ms: 2000
    
  3. 编写主程序

    package anyi.space.eurekaServer;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    /**
     * @ProjectName: distributedSystemLearn
     * @FileName: EurekaServer
     * @Author: 杨逸
     * @Data:2025/4/15 20:10
     * @Description:
     */
    @EnableEurekaServer
    @SpringBootApplication
    public class EurekaServerApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServerApplication.class, args);
        }
    }
    
    
  4. 启动两个Eureka Server,验证

    • 9001

    • 9002

搭建Eureka Client集群

搭建服务提供方集群

  • 因为member-service-provider-10001和member-service-provider-10002作为一个集群提供服务,因此需要将spring.application.name进行统一
  • 这样消费方可以通过统一的别名进行负载均衡调用
  1. 新模块member-service-provider_10002,引入Eureka Client依赖

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
  2. 配置application.yaml配置文件

    • 配置member-service-provider_10002模块向两个Eureka Server注册
    server:
      port: 10002
      servlet:
        context-path: /member-provider
    spring:
      application:
        name: member-service-provider
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        druid:
          url: jdbc:mysql://localhost:3306/spring_cloud?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
          username: root
          password: hsp
          driver-class-name: com.mysql.jdbc.Driver
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    eureka:
      instance:
        #配置注册到Eureka Server中的名称
        appname: member-service-provider
        #心跳检测和续约的间隔时间
        #Eureka Client向Eureka Server发送心跳信息的间隔时间
        lease-renewal-interval-in-seconds: 30
        #Eureka Server在收到最后一次心跳后等待的时间上限,超时将剔除该服务实例,默认是90秒
        lease-expiration-duration-in-seconds: 90
      client:
        #是否将自己注册到Eureka Server中
        register-with-eureka: true
        #是否从Eureka Server中获取注册信息,单节点不拉取也可以,集群部署时,需要拉取服务注册信息才能实现负载均衡
        fetch-registry: true
        #Eureka Server的地址
        service-url:
          #配置两个Eureka Server的地址,用逗号分割
          defaultZone: http://localhost:9001/eureka/,http://localhost:9002/eureka/
    
    
    • 配置member-service-provider_10001模块向两个Eureka Server注册
    server:
      port: 10001
      servlet:
        context-path: /member-provider
    spring:
      application:
        name: member-service-provider
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        druid:
          url: jdbc:mysql://localhost:3306/spring_cloud?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
          username: root
          password: hsp
          driver-class-name: com.mysql.jdbc.Driver
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    eureka:
      instance:
        #配置注册到Eureka Server中的名称
        appname: member-service-provider
        #心跳检测和续约的间隔时间
        #Eureka Client向Eureka Server发送心跳信息的间隔时间
        lease-renewal-interval-in-seconds: 30
        #Eureka Server在收到最后一次心跳后等待的时间上限,超时将剔除该服务实例,默认是90秒
        lease-expiration-duration-in-seconds: 90
      client:
        #是否将自己注册到Eureka Server中
        register-with-eureka: true
        #是否从Eureka Server中获取注册信息,单节点不拉取也可以,集群部署时,需要拉取服务注册信息才能实现负载均衡
        fetch-registry: true
        #Eureka Server的地址
        service-url:
          #配置两个Eureka Server的地址,用逗号分割
          defaultZone: http://localhost:9001/eureka/,http://localhost:9002/eureka/
    
    
  3. 编写主程序

    package anyi.space.memberServer;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    
    /**
     * @ProjectName: distributedSystemLearn
     * @FileName: MemberServiceApplication
     * @Author: 杨逸
     * @Data:2025/4/15 20:29
     * @Description:
     */
    @EnableEurekaClient
    @SpringBootApplication
    public class MemberServiceApplication {
        public static void main(String[] args) {
            SpringApplication.run(MemberServiceApplication.class, args);
        }
    }
    
    
  4. 启动两个member-service-provider,验证

配置服务消费方使用服务提供方集群

  1. 修改application.yaml配置文件,配置可以从两个服务注册中心拉取服务信息

    server:
      port: 80
      servlet:
        context-path: /member-consumer
    spring:
      application:
        name: member-consumer
    eureka:
      instance:
        #配置注册到Eureka Server中的名称
        appname: member-consumer
      client:
        #是否将自己注册到Eureka Server中
        register-with-eureka: true
        #是否从Eureka Server中获取注册信息,单节点不拉取也可以,集群部署时,需要拉取服务注册信息才能实现负载均衡
        fetch-registry: true
        #Eureka Server的地址
        service-url:
          #配置两个Eureka Server的地址,用逗号分割
          defaultZone: http://localhost:9001/eureka/,http://localhost:9002/eureka/
    
    
  2. 使用"@LoadBalanced"注解配置RestTemplate通过负载均衡的方式调用服务提供方的服务

    @Configuration
    public class RestTemplateConfig {
        @Bean
        @LoadBalanced
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
    }
    
  3. 使用RestTemplate通过服务别名的方式调用服务提供方的服务

    • 服务别名,注意使用小写的别名
        private static final String MEMBER_SERVICE_URL = "http://member-service-provider";
    
    • 调用服务
    package anyi.space.memberConsumer.service.impl;
    
    import anyi.sapce.common.entity.Member;
    import anyi.sapce.common.entity.ResponseResult;
    import anyi.space.memberConsumer.service.MemberService;
    import lombok.RequiredArgsConstructor;
    import org.springframework.http.HttpEntity;
    import org.springframework.http.ResponseEntity;
    import org.springframework.stereotype.Service;
    import org.springframework.web.client.RestTemplate;
    
    import java.util.Map;
    
    /**
     * @ProjectName: distributedSystemLearn
     * @FileName: MemberServiceIml
     * @Author: 杨逸
     * @Data:2025/4/13 20:10
     * @Description:
     */
    @RequiredArgsConstructor
    @Service
    public class MemberServiceIml implements MemberService {
        private final RestTemplate restTemplate;
        private static final String MEMBER_SERVICE_URL = "http://member-service-provider";
        @Override
        public Member getById(Long id) {
            /**
             * 通过RestTemplate调用远程服务
             */
            ResponseEntity<ResponseResult> resultResponseEntity = restTemplate.getForEntity(MEMBER_SERVICE_URL + "/member-provider/member?id="+id, ResponseResult.class);
            Object data = resultResponseEntity.getBody().getData();
            //映射请求结果
            Map map = (Map) data;
            Member member = new Member();
            id = Long.valueOf(map.get("id") + "");
            member.setId(id);
            member.setName((String) map.get("name"));
            member.setPwd((String) map.get("pwd"));
            member.setEmail((String) map.get("email"));
            member.setGender((int)map.get("gender"));
            return member;
        }
    
        @Override
        public boolean save(Member member) {
            //直接传递参数,是使用json的格式提交数据
            ResponseEntity<ResponseResult> responseResultResponseEntity = restTemplate.postForEntity(MEMBER_SERVICE_URL + "/member-provider/member", member, ResponseResult.class);
            //HttpEntity<String> stringHttpEntity = new HttpEntity<>();
            Object data = responseResultResponseEntity.getBody().getData();
            boolean flag = (boolean) data;
            return flag;
        }
    }
    
    

验证负载均衡

  1. 修改服务提供方member-service-provider_10001和member-service-provider_10002的返回结果携带服务提供方的信息

    • 服务提供方member-service-provider_10001在响应结果添加额外信息
            responseResult.setMsg(responseResult.getMsg() + "服务提供方10001");
    
    • 服务提供方member-service-provider_10002在响应结果添加额外信息
            responseResult.setMsg(responseResult.getMsg() + "服务提供方10002");
    
  2. 使用服务消费方访问两次服务提供方,验证轮询的负载均衡

    • 使用日志打印两次调用的结果
    log.info("远程调用服务返回结果:{}",objectMapper.writeValueAsString(resultResponseEntity.getBody()));
    

获取注册到Eureka Server的服务信息

使用DiscoveryClient类获取注册到Eureka Server的服务信息

我们可以通过使用服务发现类DiscoveryClient获取需要的服务实例信息,然后动态拼接服务地址,再使用http协议进行调用

  1. 在服务消费方主程序使用"@EnableDiscoveryClient"注解启用服务发现功能,获取注册的服务信息

    package anyi.space.memberConsumer;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    
    /**
     * @ProjectName: distributedSystemLearn
     * @FileName: MemberConsumerApplication
     * @Author: 杨逸
     * @Data:2025/4/13 20:05
     * @Description:
     */
    @EnableDiscoveryClient
    @EnableEurekaClient
    @SpringBootApplication(exclude= DataSourceAutoConfiguration.class)
    public class MemberConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(MemberConsumerApplication.class,args);
        }
    }
    
    
  2. 在Controller注入一个DiscoveryClient类,用于获取注册的服务信息

  3. 使用DiscoveryClient获取服务信息

    package anyi.space.memberConsumer.controller;
    
    import anyi.sapce.common.entity.Member;
    import anyi.sapce.common.entity.ResponseResult;
    import anyi.space.memberConsumer.service.MemberService;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.discovery.DiscoveryClient;
    import org.springframework.util.DigestUtils;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.nio.charset.StandardCharsets;
    import java.util.List;
    
    /**
     * @ProjectName: distributedSystemLearn
     * @FileName: MemberConsumerController
     * @Author: 杨逸
     * @Data:2025/4/13 20:07
     * @Description:
     */
    @Slf4j
    @RequiredArgsConstructor
    @RestController
    @RequestMapping("/member")
    public class MemberConsumerController {
        private final MemberService memberService;
        private final DiscoveryClient discoveryClient;
        private final ObjectMapper objectMapper;
        @GetMapping
        public ResponseResult<Member> getMemberById(Long id){
            Member member = memberService.getById(id);
            return ResponseResult.okResult(member);
        }
        @PostMapping
        public ResponseResult addMember(Member member){
            String hex = DigestUtils.md5DigestAsHex(member.getPwd().getBytes(StandardCharsets.UTF_8));
            member.setPwd(hex);
            boolean save = memberService.save(member);
            return ResponseResult.okResult(save);
        }
        @GetMapping("/discovery")
        public ResponseResult discovery(){
            //获取所有注册的服务名称
            List<String> services = discoveryClient.getServices();
            for (int i = 0; i < services.size(); i++) {
                String service = services.get(i);
                log.info("服务名称:{}",service);
                //获取对应服务的实例信息列表
                List<ServiceInstance> instances = discoveryClient.getInstances(service);
                for (int j = 0; j < instances.size(); j++) {
                    //获取具体服务实例的信息,比如IP和端口等
                    ServiceInstance instance = instances.get(j);
                    try {
                        log.info("服务名称:{},服务实例信息:{}",service,objectMapper.writeValueAsString(instance));
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                        log.error("服务名称:{},服务实例信息:{}",service,e.getMessage());
                    }
                }
            }
            return ResponseResult.okResult(services);
        }
    }
    
    
  4. 验证结果