Spring Cloud 核心组件 Eureka

Spring Cloud 核心组件 Eureka

  • 作者:DecaMinCow
  • 博客:http://blog.csdn.net/m0_37567301
  • 邮箱:decamincow#gmail.com (#->@)

什么是 Eureka

注册中心,方便多实例弹性扩缩容

主流注册中心对比

  1. Zookeeper

Zookeeper它是一个分布式服务框架,是Apache Hadoop 的一个子项目,它主要是用来解决分布 式应 用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式 应用配置项的管理等。
简单来说zookeeper本质=存储+监听通知。 znode
Zookeeper 用来做服务注册中心,主要是因为它具有节点变更通知功能,只要客户端监听相关服 务节点,服务节点的所有变更,都能及时的通知到监听客户端,这样作为调用方只要使用 Zookeeper 的客户端就能实现服务节点的订阅和变更通知功能了,非常方便。另外,Zookeeper 可用性也可以,因为只要半数以上的选举节点存活,整个集群就是可用的。

  1. Eureka

由Netflix开源,并被Pivatal集成到SpringCloud体系中,它是基于 RestfulAPI ⻛格开发的服务注册 与发现组件。

  1. Consul

Consul是由HashiCorp基于Go语言开发的支持多数据中心分布式高可用的服务发布和注册服务软 件, 采用Raft算法保证服务的一致性,且支持健康检查。

  1. Nacos

Nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。简单来说 Nacos 就是 注册中心 + 配置中心的组合,帮助我们解决微服务开发必会涉及到的服务注册 与发现,服务 配置,服务管理等问题。Nacos 是 Spring Cloud Alibaba 核心组件之一,负责服务注册与发现, 还有配置。

组件名语言CAP对外暴露接口
EurekaJavaAPHTTP
ConsulGoCPHTTP/DNS
ZookeeperJavaCP客户端
NacosJava支持 AP/CP 切换HTTP

Eureka 客户端

provider:每隔30秒会向注册中心续约;租约在90秒没有响应则剔除

consumer:每隔30秒拉取服务列表,缓存到本地

Eureka 服务端

服务下线:当服务正常关闭操作时,会发送服务下线的REST请求给EurekaServer;服务中心接受到请求后,将该服务置为下线状态

失效剔除:一定时间内没有收到心跳,则会注销此实例

自我保护:服务端与客户端通信有问题,但是 provider 和 consumer 网络没有问题的情况,防止有误删除客户端机器的情形

自己练习的 DEMO 核心部分

先配置本地 host 解析

127.0.0.1 EurekaServerA

127.0.0.1 EurekaServerB

1. EurekaServer 部分

eureka server pom 依赖

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

eureka server1 启动类

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

eureka server1 配置文件

#Eureka server服务端口
server:
  port: 8761
spring:
  application:
    name: eureka-server # 应用名称,会在Eureka中作为服务的id标识(serviceId)
eureka:
  instance:
    hostname: EurekaServerA
  client:
    service-url: # 客户端与EurekaServer交互的地址,如果是集群,也需要写其它Server的地址
      defaultZone: http://EurekaServerB:8762/eureka/
    register-with-eureka: true
    fetch-registry: true #自己就是服务不需要从Eureka Server获取服务信息,默认为true,置为false

eureka server2 启动类

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

eureka server2 配置文件

#Eureka server服务端口
server:
  port: 8762
spring:
  application:
    name: eureka-server # 应用名称,会在Eureka中作为服务的id标识(serviceId)
eureka:
  instance:
    hostname: EurekaServerB
  client:
    service-url: # 客户端与EurekaServer交互的地址,如果是集群,也需要写其它Server的地址
      defaultZone: http://EurekaServerA:8761/eureka/
    register-with-eureka: true
    fetch-registry: true #自己就是服务不需要从Eureka Server获取服务信息,默认为true,置为false
2. EurekaClient 部分

provider 启动类

@SpringBootApplication
@EntityScan("com.decamincow.learning.springcloud.model")
@EnableDiscoveryClient // 开启注册中心客户端
public class ResumeApplication {

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

}

provider controller 类

@RestController
@RequestMapping("/resume")
public class ResumeController {
    @Autowired
    private ResumeService resumeService;
    // /resume/openstate/1545132
    @GetMapping("/openstate/{userId}")
    public Integer findDefaultResumeState(@PathVariable Long userId) {
        return resumeService.findDefaultResumeByUserId(userId).getIsOpenResume();
    }
}

provider 配置文件

server:
  port: 8080
spring:
  application:
    name: resume
  datasource:
    url: jdbc:mysql://localhost:3306/test?useUnicode=yes&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true&useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    database: MySQL
    show-sql: true
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl #避免将驼峰 命名转换为下划线命名

eureka:
  client:
    serviceUrl: # eureka server的路径
      defaultZone: http://EurekaServerA:8761/eureka/,http://EurekaServerB:8762/eureka/ #把 eureka 集群中的所有 url 都填写了进来,也可以只写一台,因为各个 eureka server 可以同步注册表
  instance:
    #使用ip注册,否则会使用主机名注册了(此处考虑到对老版本的兼容,新版本经过实验都是ip)
    prefer-ip-address: true #自定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早期版本是ipAddress
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
    metadata-map:
    # 自定义元数据(kv自定义)
      cluster: cl1
      region: rn1
    # 租约续约间隔时间,默认30秒
    lease-renewal-interval-in-seconds: 30
    # 租约到期,服务时效时间,默认值90秒,服务超过90秒没有发生心跳,EurekaServer会将服务从列表移除
    lease-expiration-duration-in-seconds: 90

consumer 启动类

@SpringBootApplication
@EnableDiscoveryClient
public class AutodeliverApplcation {
    public static void main(String[] args) {
        SpringApplication.run(AutodeliverApplcation.class, args);
    }

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

consumer controller 类

@RestController
@RequestMapping("/autodeliver")
public class AutodeliverController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    // /autodeliver/checkState/1545132
    @GetMapping("/checkState/{userId}")
    public Integer findResumeOpenState(@PathVariable Long userId) {

        // 1, 获取 Eureka 实例列表
        List<ServiceInstance> serviceInstances = discoveryClient.getInstances("resume");
        // 2, 选择一个实例,这是负载均衡的过程
        ServiceInstance serviceInstance = serviceInstances.get(0);
        // 3, 从元数据取 host port
        String host = serviceInstance.getHost();
        int port = serviceInstance.getPort();

        String url = "http://"+ host +":"+ port +"/resume/openstate/" + userId;
        Integer forObject = restTemplate.getForObject(url, Integer.class);
        System.out.println("======>>从 Eureka 获取的 url:" + url);
        return forObject;
    }

    @GetMapping("/instances")
    public List<ServiceInstance> showInfo() {
        return this.discoveryClient.getInstances("resume");
    }
}

consumer 配置文件

server:
  port: 8090
spring:
  application:
    name: autodeliver

eureka:
  client:
    serviceUrl: # eureka server的路径
      defaultZone: http://EurekaServerA:8761/eureka/,http://EurekaServerB:8762/eureka/ #把 eureka 集群中的所有 url 都填写了进来,也可以只写一台,因为各个 eureka server 可以同步注册表
    # 每隔多久拉取一次服务列表
    registry-fetch-interval-seconds: 30
  instance:
    #使用ip注册,否则会使用主机名注册了(此处考虑到对老版本的兼容,新版本经过实验都是ip)
    prefer-ip-address: true #自定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早期版本是ipAddress
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@

3. 父工程依赖文件

<?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>com.decamincow.learning.springcloud</groupId>
    <artifactId>parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>common</module>
        <module>resume</module>
        <module>autodeliver</module>
        <module>eureka-8761</module>
        <module>eureka-8762</module>
    </modules>

    <packaging>pom</packaging>

    <!--spring boot 父启动器依赖-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
    </parent>

    <dependencies>
        <!--web依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--日志依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>
        <!--测试依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--lombok工具-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>
        <!-- Actuator可以帮助你监控和管理Spring Boot应用-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

        <!--引入Jaxb,开始-->
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.2.11</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.2.11</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.2.10-b140310.1920</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!--引入Jaxb,结束-->


        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-commons</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <!--编译插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>
            <!--打包插件-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值