Eureka

第一章 eureka简介

Eureka 一个用于服务注册和发现的组件

Eureka

Eureka server 为服务注册中心

Eureka client Eureka客户端

 

Eureka架构中三种角色:

Register Service 服务注册中心,Eureka server 提供服务注册和发现的功能

Provider Service 服务提供者Eureka client 提供服务

Consumer Service 服务消费者Eureka client 消费服务

 

 

第二章 Eureka server

 

2.1. maven模块

 

maven模块为项目父节点模块,pom.xml配置

 

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
    </parent>
    <groupId>com.kai.springcloud</groupId>
    <artifactId>cloud-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <description>a micro service cloud demo</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8
        </project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR6</spring-cloud.version>
        <mapper.starter.version>2.1.5</mapper.starter.version>
        <mysql.version>8.0.20</mysql.version>
    </properties>



    <dependencyManagement>
        <dependencies>
            <!-- spring cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- 通用mapper启动器 -->
            <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>${mapper.starter.version}</version>
            </dependency>
            <!-- mysql驱动 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <!-- 修改后立即生效,热部署 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
            <version>1.2.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <classifier>exec</classifier>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <modules>
        <module>common</module>
        <module>consumer-80</module>
        <module>provider-9001</module>
        <module>eureka-server-7001</module>
        <module>eureka-server-7002</module>
        <module>eureka-server-7003</module>
    </modules>
</project>

 

2.2. Eureka server端配置

 

2.2.1. 起步依赖

 

<!-- eureka 服务端依赖 -->

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>

</dependency>

2.2.2. Application.yml配置

 

server:
  port: 7001
  
eureka:
  instance:
    hostname: localhost
    appname: eureka-server-7001  #eureka服务端的实例名称
  client:
    registerWithEureka: false    #向注册中心注册(eureka server本身不需要向自己注册),默认true
    fetchRegistry: false       #此客户端是否获取eureka服务器注册表上的注册信息(自己不需要获取自己),默认true
    serviceUrl:
      defaultZone: 
        #http://${eureka.instance.hostname}:${server.port}/eureka/
        http://eureka-server-7001:7001/eureka/

 

2.2.3. 启动类

启动类中需要加上@EnableEurekaServer来开启 eureka server功能

 

@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
    
    public static void main(String[] args) throws Exception {
        SpringApplication.run(EurekaServerApplication.class, args);
    }

 

2.3. Eureka client

 

2.3.1. 起步依赖

 

<!-- eureka 客户端 -->

 

<dependency>

 

<groupId>org.springframework.cloud</groupId>

 

<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>

 

</dependency>

2.3.2. Application.yml配置

 

server:
  port: 9001
spring:
  application:
    name: provider-9001
eureka:
  client:
    registerWithEureka: true
    fetchRegistry: true 
    serviceUrl:
      defaultZone: 
        http://eureka-server-7001:7001/eureka/
  instance:
    instance-id: provider-9001
prefer-ip-address: true

 

2.3.3. 启动类

@EnableEurekaClient 
@SpringBootApplication
@MapperScan("com.kai.cloud.mapper") 
public class Provider_StartSpringCloudApp

2.4. 界面

 

 

第三章 Eureka特性

 

3.1. 概念术语

 

 

3.1.1. Reguster 服务注册

Eureka clientEureka server注册时,提供自身元数据(ip地址,端口,运行状况,主页地址等)

Eureka client 在配置文件中没有配置ServiceId,则服务名为${spring.application.name}

源码:

配置文件

 

com.netflix.discovery.DefaultEurekaClientConfig

 

com.netflix.discovery.PropertyBasedClientConfigConstants

Client端

com.netflix.discovery.DiscoveryClient(实现了EurekaClient接口)

boolean register() throws Throwable {
        logger.info(PREFIX + "{}: registering service...", appPathIdentifier);
        EurekaHttpResponse<Void> httpResponse;
        try {
            httpResponse = eurekaTransport.registrationClient.register(instanceInfo);
        } catch (Exception e) {
            logger.warn(PREFIX + "{} - registration failed {}", appPathIdentifier, e.getMessage(), e);
            throw e;
        }
        if (logger.isInfoEnabled()) {
            logger.info(PREFIX + "{} - registration status: {}", appPathIdentifier, httpResponse.getStatusCode());
        }
        return httpResponse.getStatusCode() == Status.NO_CONTENT.getStatusCode();
}

com.netflix.discovery.InstanceInfoReplicator

run()

com.netflix.discovery.DiscoveryClient

initScheduledTasks()

Server端:

 

com.netflix.eureka.EurekaBootStrap

initEurekaServerContext()

registry = new PeerAwareInstanceRegistryImpl(
                    eurekaServerConfig,
                    eurekaClient.getEurekaClientConfig(),
                    serverCodecs,
                    eurekaClient
            );

com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl

public void register(final InstanceInfo info, final boolean isReplication) {
        int leaseDuration = Lease.DEFAULT_DURATION_IN_SECS;
        if (info.getLeaseInfo() != null && info.getLeaseInfo().getDurationInSecs() > 0) {
            leaseDuration = info.getLeaseInfo().getDurationInSecs();
        }
        super.register(info, leaseDuration, isReplication);
        replicateToPeers(Action.Register, info.getAppName(), info.getId(), info, null, isReplication);
    }

com.netflix.eureka.resources.ApplicationResource

addInstance

3.1.2. Renew 服务续约

 

Eureka client默认情况下每隔30秒发送一次心跳来进行服务续约,来通知Eureka serverclient服务仍然可用。

正常情况下,Eureka server90秒内没有收到client端的心跳,Eureka server会将该client实例从注册列表中删除。

 

源码:

com.netflix.discovery.DiscoveryClient

boolean renew() {
        EurekaHttpResponse<InstanceInfo> httpResponse;
        try {
            httpResponse = eurekaTransport.registrationClient.sendHeartBeat(instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo, null);
            logger.debug(PREFIX + "{} - Heartbeat status: {}", appPathIdentifier, httpResponse.getStatusCode());
            if (httpResponse.getStatusCode() == Status.NOT_FOUND.getStatusCode()) {
                REREGISTER_COUNTER.increment();
                logger.info(PREFIX + "{} - Re-registering apps/{}", appPathIdentifier, instanceInfo.getAppName());
                long timestamp = instanceInfo.setIsDirtyWithTime();
                boolean success = register();
                if (success) {
                    instanceInfo.unsetIsDirty(timestamp);
                }
                return success;
            }
            return httpResponse.getStatusCode() == Status.OK.getStatusCode();
        } catch (Throwable e) {
            logger.error(PREFIX + "{} - was unable to send heartbeat!", appPathIdentifier, e);
            return false;
        }
    }

3.1.3. Fatch Registries 获取服务注册列表信息

 

Eureka clientEureka server 获取服务注册列表信息,并将其缓存在本地,该信息列表信息每30秒更新一次

 

3.1.4. Cancel 服务下线

 

Eureka client程序关闭时可以向Eureka server 发送下线请求,发送请求后,client实例信息将从Eureka server的服务注册列表中删除。

 

该下线请求不会自动完成,需要在程序关闭时调用代码:

 

DisconveryManager.getInstance().shutdownComponent();

3.1.5. Eviction 服务剔除

默认情况下,当client90秒内没有想Eureka server发送服务续约,Eureka server会将该服务实例从服务注册列表中删除。

 

3.1.6. Eureka client注册延迟

 

Client启动后,不是立即向Eureka server注册,而是有一个延迟时间,默认延迟时间为40

 

com.netflix.discovery.DefaultEurekaClientConfig

 

com.netflix.discovery.PropertyBasedClientConfigConstants

public int getInitialInstanceInfoReplicationIntervalSeconds() {
        return configInstance.getIntProperty(
                namespace + INITIAL_REGISTRATION_REPLICATION_DELAY_KEY, 40).get();
}

 

3.1.7. Eureka server响应缓存

 

Eureka Server 维护每 30 更新一次响应缓存,可通过更改配置eureka.server.responseCacheUpdateIntervalMs来修改。所以即使是刚刚注册的实例,也不会立即出现在服务注册列表中。

 

3.1.8. Eureka client缓存

 

Eureka client保留注册表信息的缓存,每30秒更新一次。

 

3.1.9. LoadBalance缓存

 

Ribbon缓存,从本地的Eureka client获取服务注册列表信息,每30刷新一次,可通过配置修改:ribbom.ServerListRefreshInterval

 

3.2. Eureka的自我保护模式

 

如果Eureka server接收到的服务续约低于阈值的百分比(默认为15分钟内低于85%),则服务器开启自我保护模式,不再剔除注册列表信息。

 

这样主要是因为如果Eureka server自身网络出现问题而导致Eureka client无法续约,注册列表信息不再删除,Eureka client还可以别其他服务消费。

 

关闭自我保护模式:

Eureka:
  Server:
    Enable-self-preservation: false

第四章 Eureka server 集群

 

4.1. 集群中yml文件配置

 

Server1

 

server:
  port: 7001
  
eureka:
  instance:
    hostname: localhost
    appname: eureka-server-7001  #eureka服务端的实例名称
  client:
    registerWithEureka: false    #向注册中心注册(eureka server本身不需要向自己注册),默认true
    fetchRegistry: false         #此客户端是否获取eureka服务器注册表上的注册信息(自己不需要获取自己),默认true
    serviceUrl:
      defaultZone: 
        #http://${eureka.instance.hostname}:${server.port}/eureka/
        #http://eureka-server-7001:7001/eureka/
        http://eureka-server-7002:7002/eureka/,http://eureka-server-7003:7003/eureka/

 

Server2:

server:
  port: 7002
  
eureka:
  instance:
    hostname: localhost
    appname: eureka-server-7002 #eureka服务端的实例名称
  client:
    registerWithEureka: false #向注册中心注册(eureka server本身不需要向自己注册),默认true
    fetchRegistry: false #此客户端是否获取eureka服务器注册表上的注册信息(自己不需要获取自己),默认true
    serviceUrl:
      defaultZone: 
        #http://${eureka.instance.hostname}:${server.port}/eureka/  
        http://eureka-server-7001:7001/eureka/,http://eureka-server-7003:7003/eureka/

Server3:

server:
  port: 7003
  
eureka:
  instance:
    hostname: localhost
    appname: eureka-server-7003 #eureka服务端的实例名称
  client:
    registerWithEureka: false #向注册中心注册(eureka server本身不需要向自己注册),默认true
    fetchRegistry: false #此客户端是否获取eureka服务器注册表上的注册信息(自己不需要获取自己),默认true
    serviceUrl:
      defaultZone: 
        #http://${eureka.instance.hostname}:${server.port}/eureka/  
        http://eureka-server-7001:7001/eureka/,http://eureka-server-7002:7002/eureka/

4.2. 界面

 

 

 

4.3. 本地host文件修改

 

Window

C:\Windows\System32\drivers\etc\hosts

#for eureka

127.0.0.1  eureka-server-7001

127.0.0.1  eureka-server-7002

127.0.0.1  eureka-server-7003

 

127.0.0.1  provider-9001

 

汇总:

posted @ 2021-02-23 23:01  無_茗  阅读(70)  评论(0)    收藏  举报