zoukankan      html  css  js  c++  java
  • SpringCloud从入门到进阶(二)——注册中心Eureka的伪分布式部署

    内容

      服务发现是微服务架构中一个关键的原则,Eureka提供了服务注册和服务发现的功能,并且各注册中心之间会互相拷贝所注册的微服务的信息,这一机制增强了Eureka对网络分区的容错能力。本篇文章讲解了在一台主机上运行三个Eureka Server实例,实现Eureka的伪分布式部署。

    版本

      IDE:IDEA 2017.2.2 x64

      JDK:1.8.0_171

      manve:3.3.3

      SpringBoot:1.5.9.RELEASE

      SpringCloud:Dalston.SR1

    适合人群

      Java开发人员

    说明

      转载请说明出处:SpringCloud从入门到进阶(二)——注册中心Eureka的伪分布式部署

      GitHub仓库地址:https://github.com/leo-zz/SpringCloudDemo/tree/master/EurekaServer

    参考

           Linux入门实践笔记(二)--Jar包运行与关闭

    内容

    Eureka工作机制

    ​  Eureka就像开发公司的人事部,人事部维护了公司的通讯录,通过通讯录可以找到每一名员工的联系方式。正如人员在入职和离职时,人事部会更新公司的通讯录一样;当服务上线或者下线时,Eureka都会进行服务的注册和注销的操作。

      Eureka分为Server端和Client,包括Eureka Server在内(默认设置)的所有的微服务组件都属于Eureka Client。Eureka Client在服务启动时会注册到Eureka Server中,并在运行过程中定时向Eureka Server发送心跳以保持注册状态。Eureka Server把所有的注册信息都存储到内存中,并没有进行持久化存储。此外,每个Eureka Client都在内存中缓存一份Eureka Clients的注册信息,使的它在请求其他微服务时无需每次都从Eureka Server获取。本文主要讲解了Eureka Server的配置。
      默认情况下,Eureka Client使用主机名进行注册,这个主机名可以使用eureka.instance.hostname来规定。微服务之间也是通过主机名来调用的。如果DNS没有配置主机名跟IP的映射关系,那么使用主机名注册的方式就会导致微服务无法调用。可以修改eureka.instance.preferIpAddress为true,让Eureka Client注册时使用IP地址,本示例就是通过IP的方式注册微服务的。

    两种工作模式

      Eureka Server有两种工作模式,单机模式(Standalone Mode)和集群模式(Peer Awareness)。

    单机模式

      默认情况下每个Eureka Server都是一个Eureka Client,有着Eureka Client的行为,在启动时会向Eureka Server进行注册,因此需要配置“service-url”以定位其他Eureka Server。如果没有正确的配置该参数,Eureka Server虽然会正常工作,但是日志上会有许多“无法注册到其他Eureka Server”的干扰信息。
      如果想在单机模式下使用Eureka Server,需要修改配置eureka.client.registerWithEureka 和 eureka.client.fetchRegistry为false,以关闭其Eureka Client的行为,避免向Eureka Server注册。本示例搭建的是Eureka Server的集群模式,不讨论单机模式的情况。

    集群模式

      通过启动多个Eureka Server实例,并将它们互相注册以组建集群。集群模式有着更高的可用性。这也是Eureka Server默认的工作模式,在“service-url”上配置其他Eureka Server实例(peer)的地址。
      集群中的实例不要求必须能够两两互相访问,只要能够组建出一条连接链,集群之间就可以互相同步注册信息。比如三个实例A、B、C,A跟B可以互相访问,B跟C可以互相访问,但是A与C不能互相访问,那么A、B、C组建的集群仍然可以在所有实例之间互相同步注册信息。即使集群中的部分实例被物理分割,Eureka在原则上可以避免集群分区类型的故障(脑裂问题)。

    项目路径

    pom.xml

      配置maven的依赖文件pom.xml,引入SpringBoot,SpringCloud,Eureka的依赖,以及Spring Boot打包的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">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.leo.springcloud</groupId>
        <artifactId>eurekaserver</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <!-- 通过继承的方式引入spring boot  -->
        <!--parent标签用于指定父pom-->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.9.RELEASE</version>
        </parent>
    
        <!--properties标签用于声明一些常量,例如源码编码为UTF-8,输出代码也为UTF-8,Java版本为1.8-->
        <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>Dalston.SR1</spring-cloud.version>
        </properties>
    
        <dependencies>
            <!--eureka server-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka-server</artifactId>
            </dependency>
        </dependencies>
        <!--子Module不会继承该依赖,除非显示声明-->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <!-- Spring Boot的Maven插件,使用Maven插件的方式来启动Spring Boot工程
    如果不添加该插件在使用mvn命令打包的jar有问题,执行时会报错:xxx.jar中没有主清单属性-->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>
    yaml

      配置Eureka的yaml文件,此处按照集群模式配置Eureka,配置了三个profiles,以便在同一台机器上使用同一个jar包开启三个Eureka实例。

    spring:
      profiles: peer1
      application:
       name: application-eurekaserver
    server:
      port: 7001
    eureka:
      instance:
      #设置实例的hostname
        hostname: eureka7001.com
        instance-id: springcloud-eurekaserver-7001
        #作为Eureka Client,把实例的ip的信息注册到eureka server中。
        prefer-ip-address: true
      client:
        #不将eureka server 注册进来,会提示unavailable-replicas
        #默认情况下,Eureka Server会向自己注册,这时需要配置eureka.client.registerWithEureka 和 eureka.client.fetchRegistry为false,防止自己注册自己。
        register-with-eureka: true
        fetch-registry: true
        service-url:
        #defaultZone中填写的URL必须包括后缀/eureka,否则各eureka server之间不能通信
        #defaultZone为默认的Zone,来源于AWS的概念。区域(Region)和可用区(Availability Zone,AZ)是AWS的另外两个概念。区域是指服务器所在的区域,
        #比如北美洲、南美洲、欧洲和亚洲等,每个区域一般由多个可用区组成。 在本案例中defaultZone是指Eureka Server的注册地址。
         defaultZone: http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka #eureka集群的时候使用
          #http://${eureka.instance.hostname}:${server.port}/eureka/  #eureka单机模式的时候使用,指向自己。
    #  server:
    #     enable-self-preservation: false  #关闭自我保护机制
    #actuator
    management:
      port: 7101  #配置了Actuator对外暴露REST API接口的端口号,如果不指定,端口为应用程序的启动端口,这样做的目的是将程序端口和程序的监控端口分开。
      security:
       enabled: false #Actuator 采取非安全验证方式,l.5x 版本默认开启了 Actuator 的安全验证。​
    ---
    spring:
      profiles: peer2
      application:
       name: application-eurekaserver
    server:
      port: 7002
    eureka:
      instance:
       hostname: eureka7002.com
       instance-id: springcloud-eurekaserver-7002
       prefer-ip-address: true
      client:
       register-with-eureka: true
       fetch-registry: true
       service-url:
         defaultZone: http://eureka7001.com:7001/eureka,http://eureka7003.com:7003/eureka #eureka集群的时候使用
    #actuator
    management:
      port: 7102  #配置了Actuator对外暴露REST API接口的端口号,如果不指定,端口为应用程序的启动端口,这样做的目的是将程序端口和程序的监控端口分开。
      security:
       enabled: false #Actuator 采取非安全验证方式,l.5x 版本默认开启了 Actuator 的安全验证。
    ---
    spring:
      profiles: peer3
      application:
       name: application-eurekaserver
    server:
      port: 7003
    eureka:
      instance:
       hostname: eureka7003.com
       instance-id: springcloud-eurekaserver-7003
       prefer-ip-address: true
      client:
       register-with-eureka: true
       fetch-registry: true
       service-url:
         defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #eureka集群的时候使用
    #actuator
    management:
      port: 7103  #配置了Actuator对外暴露REST API接口的端口号,如果不指定,端口为应用程序的启动端口,这样做的目的是将程序端口和程序的监控端口分开。
      config:
       enabled: false #Actuator 采取非安全验证方式,l.5x 版本默认开启了 Actuator 的安全验证。
    SpringBootApplication

      配置SpringBoot的启动类,增加@EnableEurekaServer注解。

    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaServerDemo {
    
        public static void main(String[] args) {
            SpringApplication.run(EurekaServerDemo.class,args);
        }
    }
    项目打包

      在命令行工具中进入项目pom文件所在路径,然后执行mvn clean package打包。

    F:SpringCloud>cd eureka-server-7001-7002   #进入项目根目录
    F:SpringCloudeureka-server-7001-7002>mvn clean package    #执行maven打包语句
    ...
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 29.597 s
    [INFO] Finished at: 2018-10-23T09:14:11+08:00
    [INFO] Final Memory: 35M/293M
    ...
    拷贝

      由于当时注册发现服务没有开通公网,需要使用Bitvise SFTP或WinSCP等工具将jar包上传到有公网的服务器。然后再使用scp命令在局域网内从公网服务器拷贝到注册发现服务器。

    1540257784254

      然后使用scp命令将jar包拷贝到注册发现服务器普通用户的~/jars路径下。

    [ServerA@hostname jars]$ scp eureka-server-7001-7002-1.0-SNAPSHOT.jar  user@172.26.125.118:/home/user/jars
    ...
    eureka-server-7001-7002-1.0-SNAPSHOT.jar                                           100%   38MB  38.4MB/s   00:00
    修改hosts文件

      将内部域名eureka7001.com、eureka7002.com、eureka7003.com绑定到局域网IP 172.26.125.118。

      修改/etc/hosts,添加hostname对应的ip地址

    #IP     域名      别名
    [user@EurekaServer ~]$ sudo vi /etc/hosts
    127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
    127.0.0.1   eureka7001.com 
    127.0.0.1   eureka7002.com 
    127.0.0.1   eureka7003.com

      重启网卡

    [user@EurekaServer ~]$ sudo /etc/rc.d/init.d/network restart
    Restarting network (via systemctl):                       [  OK  ]

      进行ping测试

    [user@EurekaServer ~]$ ping eureka7001.com
    PING eureka7001.com (127.0.0.1) 56(84) bytes of data.
    64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.016 ms
    64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.024 ms
    [user@EurekaServer ~]$ ping eureka7002.com
    PING eureka7002.com (127.0.0.1) 56(84) bytes of data.
    64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.012 ms
    64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.024 ms
    [user@EurekaServer ~]$ ping eureka7003.com
    PING eureka7003.com (127.0.0.1) 56(84) bytes of data.
    64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.012 ms
    64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.024 ms
    启动与测试

      在启动时,通过JVM参数-Dspring.profiles.active选择项目启动的profiles。此处还设定了虚拟机堆空间的最小值为512mb,堆空间的最大值为1024mb。

    [ServerA@hostname jars]$ java  -Xms512m -Xmx1024m -Dspring.profiles.active=peer1 -jar eureka-server-7001-7002-1.0-SNAPSHOT.jar 
    [ServerA@hostname jars]$ java  -Xms512m -Xmx1024m -Dspring.profiles.active=peer2  -jar eureka-server-7001-7002-1.0-SNAPSHOT.jar  
    [ServerA@hostname jars]$ java  -Xms512m -Xmx1024m -Dspring.profiles.active=peer3  -jar eureka-server-7001-7002-1.0-SNAPSHOT.jar  

      确保本地能访问到eureka服务器,访问http://eureka7001:7001/

      访问http://eureka7002:7002/

     

      访问http://eureka7003:7003/

     

      关于运行和关闭java程序的操作请参考:Linux入门实践笔记(二)--Jar包运行与关闭

      通过Eureka的管理界面,可以看到所有Eureka的replicas的都是unavailable状态。下一节将在源码层级探究replicas为何是unavailable状态的原因,以及解决方法。

    补充:关于Eureka client注册ip信息和主机名这两种方式的说明  

      集群模式下的Eureka Server,同时也是Eureka Client,因此会向Eureka Server中注册自己的信息。Eureka Server的yaml配置的中prefer-ip-address属性为true,表示这个实例把IP地址注册到Eureka Server中,并不会要求或者限制其他Eureka Client的注册行为。笔者曾误以为Eureka Server的yaml配置的中prefer-ip-address属性为true,会要求所有向该Eureka Server注册的Client在注册时都提交IP信息。显然这是错误的。

      对于Eureka Server,不会限制Client以哪种信息注册,这个选择权在Client。比如ClientA把自己的ip信息注册到Eureka,而ClentB把自己的主机名注册到Eureka,那么ClientC在调用ClientA时会从Eureka中拿到它的ip信息进行调用;在调用ClientB时会从Eureka中拿到它的主机名信息进行调用,如果此时未配置主机名和ip的DNS信息,那么调用可能会出错。

  • 相关阅读:
    496. 下一个更大元素 I
    240. 搜索二维矩阵 II
    java反射之ObjectAnalyzer
    PHP导出excel文件的多种方式
    git获取公钥和私钥以及常用的命令
    PHP PSR-2 代码风格规范
    phpStrom安装PHP_CodeSniffer检查代码规范
    常见PHP安全网站漏洞及防范措施
    Oracle中创建主键并在Spring data JPA中使用
    JPA自定义查询中报错:缺失右括号
  • 原文地址:https://www.cnblogs.com/lonelyJay/p/9841905.html
Copyright © 2011-2022 走看看