第4章 微服务注册与发现

6 篇文章 0 订阅
1 篇文章 0 订阅

第四章 微服务注册与发现

服务发现概述

  • 服务发现组件是一个非常关键的组件。

  • 服务提供者服务消费者服务发现组件三者关系如下:

    • 各个微服务在启动时,将自己的网络地址等信息注册到服务发现组件中,服务发现组件会存储这些信息。
    • 服务消费者可从服务发现组件查询服务提供者的网络地址,并使用该地址调用服务提供者的接口。
    • 各个微服务与服务发现组件使用一定机制(如:心跳)通信。服务发现组件若长时间无法与某个微服务实例通信,就会注销该实例。
    • 微服务网络地址发生变更(如:实例增减或者IP端口发生变化等)时,会重新注册到服务发现组件。使用这种方式,服务消费者就无须人工修改提供者的网络地址了。

    在这里插入图片描述

服务发现组件具备的功能

  • 服务注册表:是服务发现组件的核心,它用来记录各个微服务的信息,如微服务的名称IP端口等。服务注册表提供查询API和管理API,查询API用于查询可用的微服务实例,管理API用于服务的注册和注销
  • 服务注册与服务发现:服务注册是指微服务在启动时,将自己的信息注册到服务发现组件上的过程。服务发现是指查询可用微服务列表及其网络地址的机制。
  • 服务检查:服务发现组件使用一定机制定时检测已注册的服务,如发现某实例长时间无法访问,就会从服务注册表中移除该实例。

Eureka简介

  • EurekaNetflix开源的服务发现组件,本身是一个基于REST的服务,它包含ServerClient两部分。Spring Cloud将其整合到了子项目Spring Cloud Netflix中,从而实现微服务的注册发现在这里插入图片描述

  • Application Service服务提供者。

  • Application Client服务消费者。

  • Make Remote Call可以理解成调用RESTful API的行为。

  • us-east-1c,us-east-1d,us-east-1e等都是zone,它们都属于us-east-1这个region

  • Eureka包含两个组件:Eureka ServerEureka Client,功能如下:

    • Eureka Server提供服务发现的能力,各个微服务启动时,会向Eureka Server注册自己的信息(如:IP端口微服务名称等),Eureka Server会存储这些信息。
    • Eureka Client是一个Java客户端,用于简化与Eureka Server的交互。
    • 微服务启动后,会周期性(默认30s)地向Eureka Server发送心跳以续约自己的“租期”。
    • 如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将注销该实例(默认90s)
    • 默认情况下,Eureka Server同时也是Eureka Client。多个Eureka Server实例互相之间通过复制的方式来实现服务注册表中数据的同步。
    • Eureka Client会缓存服务表中的信息。这种方式有一定的优势——首先,微服务无须每次请求都查询Eureka Server,从而降低了Eureka Server的压力;其次,即使Eureka Server所有节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者并完成调用。
  • Eureka通过心跳检查,客户端缓存等机制,提高了系统的灵活性,可伸缩性和可用性。

编写Eureka Server

  • 创建Maven工程如下

在这里插入图片描述

  • <?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>
        <groupId>com.ym.cloud</groupId>
        <artifactId>microservice-discovery-eureka</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <!-- 引入spring boot的依赖 -->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.9.RELEASE</version>
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.version>1.8</java.version>
        </properties>
    
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
        </dependencies>
    
        <!-- 引入spring cloud的依赖 -->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Edgware.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
        <!-- 添加spring-boot的maven插件 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
  • @SpringBootApplication
    @EnableEurekaServer
    public class EurekaApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaApplication.class,args);
        }
    }
    
  • server:
      port: 8761
    eureka:
      client:
        registerWithEureka: false
    #    是否将自己注册到Eureka Server,默认为false
        fetchRegistry: false
    #    是否从Eureka Server获取组测信息,默认为true
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
    #设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址,
    #默认为http://localhost:8761/eureka;多个地址之间可使用,分隔。
    
  • 启动项目并访问:http://localhost:8761

在这里插入图片描述

将微服务注册到Eureka Server上

  • 创建maven工程如下。

在这里插入图片描述

  • <?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">
    
        <groupId>com.ym.cloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
        <modelVersion>4.0.0</modelVersion>
        <artifactId>microservice-provider-user</artifactId>
        <packaging>jar</packaging>
    <!--    引入Spring boot依赖-->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.9.RELEASE</version>
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <jave.version>1.8</jave.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>com.h2database</groupId>
                <artifactId>h2</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
        </dependencies>
    
        <!-- 引入spring cloud的依赖 -->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Edgware.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <!-- 添加spring-boot的maven插件 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    
    </project>
    
  • server:
      port: 8000
    spring:
      application:
        name: microservice-provider-user
    #指定注册到Eureka Server上的应用名称
      jpa:
        generate-ddl: false
        show-sql: true
        hibernate:
          ddl-auto: none
      datasource:                         #指定数据源
        platform: h2;                     #指定数据库类型
        schema: classpath:schema.sql      #指定h2数据库的建表语句
        data: classpath:data.sql          #指定h2数据库的数据脚本
    logging:                              # 配置日志级别,让hibernate打印出执行的SQL
      level:
        root: INFO
        org.hibernate: INFO
        org.hibernate.type.descriptor.sql.BasicBinder: TRACE
        org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
    
    ## INFO
    info:
      app:
        name: @project.artifactId@
        encoding: @project.build.sourceEncoding@
        java:
          source: @java.version@
          target: @java.version@
    management:
      security:
        enabled: false
    
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/
      instance:
        prefer-ip-address: true
    #true表示将自己的ip注册到Eureka Server,若不配置该属性或将其设置为false,
    #则表示注册微服务所在操作系统的hostname到Eureka Server
    
  • @SpringBootApplication
    public class ProviderUserApplication {
        public static void main(String[] args) {
            SpringApplication.run(ProviderUserApplication.class,args);
        }
    }
    
  • 这样即可将用户微服务注册到Eureka Server上,同理将电影微服务也可以注册到Eureka Server上。

  • 访问http://localhost:8761/

在这里插入图片描述

  • 可以看到用户微服务,电影微服务已经被注册到Eureka Server上了。

提高

  • Spring Cloud Edgware之前,要想将微服务注册到Eureka Server或者其他服务发现组件上,必须在启动类上添加**@EnableEurekaClient@EnableDiscoveryClient**。
  • Spring Cloud Edgware以及更高版本中,只需添加相关依赖,即可自动注册。
  • 若不想将服务注册到Eureka Server,只需要设置spring.cloud.service-registry.auto-registration.enabled=false,或**@EnableDiscoveryClient(autoRegister = false)**即可。

Eureka Server的高可用

  • 单节点Eureka Server并不适合线上生产环境。Eureka Client会定时连接Eureka Server,获取服务注册表中的信息并缓存在本地。微服务在消费远程API时总是使用本地缓存中的数据。因此一般来说,即使Eureka Server发生宕机,也不会影响服务之间的调用。但如果Eureka Server宕机时,某些微服务也出现了不可用的情况,Eureka Client中的缓存若不被更新,就可能会影响微服务调用,甚至影响整个应用系统的高可用性。因此,在生产环境中,通常都会部署一个高可用的Eureka Server集群。

编写高可用Eureka Server

  • Eureka Server可以通过运行多个实例并相互组测的方式实现高可用部署,Eureka Server实例会彼此增量地同步信息,从而确保所有节点数据一致。
  • 创建Maven项目如下

在这里插入图片描述

  • 修改电脑hosts文件添加配置如下:

    • 127.0.0.1 peer1 peer2
      
  • spring:
      application:
        name: microservice-discovery-eureka-ha
    ---
    # 连字符(---)将该application.yml文件分为三段,
    #第二,三段分别为spring.properties指定了一个值,
    #该值表示它所在的那段内容应用在哪个Profile里。
    #第一段由于未指定spring.profiles,因此这段内容会对所有Profile生效。
    spring:
      profiles: peer1
    #  指定profile=peer1
    server:
      port: 8761
    eureka:
      instance:
        hostname: peer1
    #    指定当profile=peer1时,主机名为peer1
      client:
        service-url:
          defaultZone: http://peer2:8762/eureka/
    #      将自己注册到peer2这个Eureka上面去
    ---
    spring:
      profiles: peer2
    server:
      port: 8762
    eureka:
      instance:
        hostname: peer2
      client:
        service-url:
          defaultZone: http://peer1:8761/eureka/
    
  • @SpringBootApplication
    @EnableEurekaServer
    public class EurekaApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaApplication.class,args);
        }
    }
    
  • <?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>
        <groupId>com.ym.cloud</groupId>
        <artifactId>microservice-discovery-eureka-ha</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <!-- 引入spring boot的依赖 -->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.9.RELEASE</version>
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.version>1.8</java.version>
        </properties>
    
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
        </dependencies>
    
        <!-- 引入spring cloud的依赖 -->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Edgware.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
        <!-- 添加spring-boot的maven插件 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
  • 上面配置了peer1peer2两个Profile。当应用以peer1这个Profile启动时,配置该Eureka Server的主机名为peer1,并将其注册到http://peer2:8762/eureka/;反之,当应用以profile=peer2时,Eureka Server会注册到peer1节点的Eureka Server

  • 接下来对项目进行打包,并运行如下命令:

    • java -jar microservice-discovery-eureka-ha-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1
      
    • java -jar microservice-discovery-eureka-ha-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2
      
  • 分别访问http://peer1:8761;http://peer2:8762

在这里插入图片描述

  • application.yml进行优化

    • spring:
        application:
          name: microservice-discovery-eureka-ha
      eureka:
        client:
          serviceUrl:
            defaultZone: http://peer2:8762/eureka/,http://peer1:8761/eureka/
      ---
      spring:
        profiles: peer1
      server:
        port: 8761
      eureka:
        instance:
          hostname: peer1
      ---
      spring:
        profiles: peer2
      server:
        port: 8762
      eureka:
        instance:
          hostname: peer2
      

将应用注册到Eureka Server集群上

  • 修改消费方的配置文件

    • eureka:
        client:
          service-url:
            defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/
      
  • 此外即使微服务只配置Eureka Server集群中的某个节点,也能正常注册到Eureka Server集群,因为多个Eureka Server之间的数据会相互同步。如下:

    • eureka:
        client:
          service-url:
            defaultZone: http://peer1:8761/eureka/
      
  • 正常情况下,这种配置方式与配置多个Server节点的效果是一样的,但是为了避免某些极端场景问题,还是建议配置多个Eureka Server节点。

用户认证

  • 在项目中可能希望必须经过用户认证才允许访问Eureka Server

为Eureka Server添加用户认证

  • 创建Maven项目如下

在这里插入图片描述

  • <?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>
        <groupId>com.ym.cloud</groupId>
        <artifactId>microservice-discovery-eureka-authenticating</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <!-- 引入spring boot的依赖 -->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.9.RELEASE</version>
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.version>1.8</java.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-security</artifactId>
            </dependency>
        </dependencies>
    
        <!-- 引入spring cloud的依赖 -->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Edgware.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
        <!-- 添加spring-boot的maven插件 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
  • @SpringBootApplication
    @EnableEurekaServer
    public class EurekaApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaApplication.class,args);
        }
    }
    
  • security:
      basic:
        enabled: true
    #    开启基于HTTP basic的认证
      user:
        name: user
        password: password123
    #    配置用户名密码
    #如果不设置这段内容,账号默认是user,密码是一个随机值,该值会在启动时打印出来。
    server:
      port: 8761
    eureka:
      client:
        registerWithEureka: false
    #    是否将自己注册到Eureka Server,默认为false
        fetchRegistry: false
    #    是否从Eureka Server获取组测信息,默认为true
        serviceUrl:
          defaultZone: http://user:password123@localhost:8761/eureka/
    #将eureka.client.serviceUrl.defaultZone修改为
    #http://user:password123@EUREKA_HOST:EUREKA_PORT/eureka/的形式
    
  • 启动项目,并访问http://localhost:8761/如下,需要身份验证。输入用户名,密码即可访问Eureka Server

在这里插入图片描述

将微服务注册到需认证的Eureka Server

  • 如何将微服务注册到需认证的Eureka Server上呢,只需要将服务消费方的eureka.client.serviceUrl.defaultZone配置为==http://user:password@EUREKA_HOST:EUREKA_PORT/eureka/==的形式,即可将微服务注册到Eureka Server
eureka:
	client:
		serviceUrl:
			defaultZone: http://user:password123@localhost:8761/eureka/

Eureka的元数据

  • Eureka的元数据有两种,分别是标准元数据自定义元数据
    • 标准元数据指的是主机名IP地址端口号状态页健康检查等信息,这些信息都会被发布在服务注册表中,用于服务之间的调用。
    • 自定义元数据可以使用eureka.instance.metadata-map配置,这些元数据可以在远程客户端中访问,但一般不会改变客户端的行为。

改造用户微服务

  • 创建Maven项目

在这里插入图片描述

  • <?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">
    
        <groupId>com.ym.cloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
        <modelVersion>4.0.0</modelVersion>
        <artifactId>microservice-provider-user-my-metadata</artifactId>
        <packaging>jar</packaging>
    <!--    引入Spring boot依赖-->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.9.RELEASE</version>
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <jave.version>1.8</jave.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>com.h2database</groupId>
                <artifactId>h2</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
        </dependencies>
    
        <!-- 引入spring cloud的依赖 -->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Edgware.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <!-- 添加spring-boot的maven插件 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    
    </project>
    
  • @RestController
    public class UserController {
        @Autowired
        private UserRepository userRepository;
        @GetMapping("/{id}")
        public User findById(@PathVariable Long id) {
            User user = userRepository.findOne(id);
            return user;
        }
    }
    
  • @Entity
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
        @Column
        private String username;
        @Column
        private String name;
        @Column
        private Integer age;
        @Column
        private BigDecimal balance;
        
       //setter && getter
    }
    
  • @Repository
    public interface UserRepository extends JpaRepository<User,Long> {
    }
    
  • @SpringBootApplication
    public class ProviderUserApplication {
        public static void main(String[] args) {
            SpringApplication.run(ProviderUserApplication.class,args);
        }
    }
    
  • server:
      port: 8000
    spring:
      application:
        name: microservice-provider-user
    #指定注册到Eureka Server上的应用名称
      jpa:
        generate-ddl: false
        show-sql: true
        hibernate:
          ddl-auto: none
      datasource:                         #指定数据源
        platform: h2;                     #指定数据库类型
        schema: classpath:schema.sql      #指定h2数据库的建表语句
        data: classpath:data.sql          #指定h2数据库的数据脚本
    logging:                              # 配置日志级别,让hibernate打印出执行的SQL
      level:
        root: INFO
        org.hibernate: INFO
        org.hibernate.type.descriptor.sql.BasicBinder: TRACE
        org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
    
    ## INFO
    info:
      app:
        name: @project.artifactId@
        encoding: @project.build.sourceEncoding@
        java:
          source: @java.version@
          target: @java.version@
    management:
      security:
        enabled: false
    
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/
      instance:
        prefer-ip-address: true
    #true表示将自己的ip注册到Eureka Server,若不配置该属性或将其设置为false,
    #则表示注册微服务所在操作系统的hostname到Eureka Server
        metadata-map:
          my-metadata: 我自定义的元数据
    #自定义的元数据,key/value都可以随便写
    

改造电影微服务

  • 创建Maven项目

在这里插入图片描述

  • <?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>1.5.9.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.ym.cloud</groupId>
        <artifactId>microservice-consumer-movie-understanding-metadata</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
        </dependencies>
    
        <!-- 引入spring cloud的依赖 -->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Edgware.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
    <!--添加maven插件-->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
  • @SpringBootApplication
    public class ConsumerMovieApplication {
        @Bean
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
        public static void main(String[] args) {
            SpringApplication.run(ConsumerMovieApplication.class, args);
        }
    }
    
  • @RestController
    public class MovieController {
        @Autowired
        private RestTemplate restTemplate;
        @Autowired
        private DiscoveryClient discoveryClient;
        @GetMapping("/user/{id}")
        public User findByUser(@PathVariable Long id) {
            return restTemplate.getForObject("http://localhost:8000/"+id,User.class);
        }
    
        /**
         * 查询microservice-provider-user服务的信息并返回
         * @return microservice-provider-user服务的信息
         */
        @GetMapping("/user-instance")
        public List<ServiceInstance> showInfo() {
            return this.discoveryClient.getInstances("microservice-provider-user");
            //使用DiscoveryClient.getInstances(serviceId),可查询指定列表在Eureka上的实例列表
        }
    }
    
  • server:
      port: 8010
    spring:
      application:
        name: microservice-consumer-movie
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
      instance:
        prefer-ip-address: true
    

测试

  • 依次启动服务端,用户微服务,电影微服务。
  • 访问http://:localhost:8761/eureka/apps,看查看Eurekametadata

在这里插入图片描述

  • 访问http://localhost:8010/user-instance,可以看到使用DiscoveryClientAPI获得了用户微服务的各种信息,其中包含了标准元数据和自定义元数据。同时,自定义的元数据my-metadata,也可以通过客户端查询到,但是并不会改变客户端的行为。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QEPc6lvi-1610621110913)(第四章 微服务注册与发现/user-instance.png)]

Eureka的自我保护模式

  • 自我保护机制模式的最直观的体现,就是Eureka Server首页输出的警告。如下

在这里插入图片描述

  • 默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将注销该实例(默认是90s)。但是当网络分区故障发生时,微服务与Eureka Server之间将无法正常通信,以上行为就可能变得非常危险-----因为微服务本身是健康的,此时不应该注销这个微服务。
  • Eureka通过”自我保护模式“来解决这个问题——当Eureka Server节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,Eureka Server就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server节点会自动退出自我保护模式。
  • 可以使用eureka.server.enable-self-preservation = false禁用自我保护模式。

Eureka的健康状况

在这里插入图片描述

  • Status一栏有个UP,表示应用程序状态正常。应用状态还有其他取值,如:DOWN,OUT_OF_SERVICE,UNKNOWN等。只有标记为”UP“的微服务会被请求。
  • Eureka ServerEureka Client之间使用心跳机制来确定Eureka Client的状态,默认情况下,服务器与客户端的心跳保持正常,应用程序就会始终保持”UP“状态。
  • 但是上面机制并不能完全反映应用程序的状态,如:微服务与Eureka Server之间的心跳正常,Eureka Server认为该微服务”UP“;然而,该微服务的数据源发生了问题(如:因为网络抖动,连不上数据源),根本无法正常工作。
  • 要解决这一点,只需启用Eureka的健康检查,应用程序就会将自己的健康状态传播到Eureka Server。在application.yml中配置如下。
eureka:
	client:
		healthcheck:
			enable: true
  • 某些场景下,希望更细粒度的控制健康检查,此时可实现com.netflix.appinfo.HealthCheckHandler接口。

    注:eureka.client.healthcheck.enable=true只能配置在application.yml中,如果配置在bootstrap.yml中,可能会导致一些不良的后果,如应用注册到Eureka Server上的状态是UNKNOWN。 当eureka.client.healthcheck.enable=true时,/pause端点(Spring Boot Actuator提供,用于暂停工作)无法正常工作。 当eureka.client.healthcheck.enable=true时,请求/pause端点无法将应用在Eureka Server上的状态标记为DOWN。(bug)

排除Jersey依赖

  • 默认情况下,Eureka Client使用Jersey 1.xEureka Server交互。

  • spring Cloud Edgware中,Jersey并非必选,可排除Jersey的相关依赖。此时,Spring Cloud将自动配置一个基于RestTemplateHTTP客户端。

  • 排除Jersey的操作方法如下。

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>com.sum.jersey</groupId>
                    <artifactId>jersey-client</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jersey</groupId>
                    <artifactId>jersey-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jersey.contribs</groupId>
                    <artifactId>jersey-apache-client4</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

中,Jersey并非必选,可排除Jersey的相关依赖。此时,Spring Cloud将自动配置一个基于RestTemplateHTTP**客户端。

  • 排除Jersey的操作方法如下。
<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>com.sum.jersey</groupId>
                    <artifactId>jersey-client</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jersey</groupId>
                    <artifactId>jersey-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jersey.contribs</groupId>
                    <artifactId>jersey-apache-client4</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
  • Jersey是一个流行的RESTful框架,目前,Jersey已经发行到2.x版本,2.x1.x不兼容,因此,当你想使用Jersey 2.x又希望将微服务注册到Eureka Server上时,就可以使用上面的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值