eureka-dns-cluster

栏目: Java · 发布时间: 7年前

内容简介:Spring Cloud Netflix Eureka集群配置方式主要用两种:Static servers list config和dns,本文主要介绍基于DNS的方式搭建Eureka集群。client启动后从config中获取region和zone以及serviceUrl,进行服务注册、发现,这种静态集群模式无法动态扩容,一旦新增节点,只能挨个修改server和client端的配置文件,大致配置如下:基于DNS的Eureka Cluster架构图如下:

Spring Cloud Netflix Eureka集群配置方式主要用两种:Static servers list config和dns,本文主要介绍基于DNS的方式搭建Eureka集群。

Static servers list config

client启动后从config中获取region和zone以及serviceUrl,进行服务注册、发现,这种静态集群模式无法动态扩容,一旦新增节点,只能挨个修改server和client端的配置文件,大致配置如下:

eureka:
server:
enable-self-preservation: false
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://10.25.102.174:8082/eureka/,http://10.25.102.174:8083/eureka/

DNS configuration

基于DNS的Eureka Cluster架构图如下:

eureka-dns-cluster

eureka-dns-cluster

简单来说就是使用DNS服务器管理Eureka Server的地址,弹性伸缩对客户端没有影响。

大致流程如下:

use-dns-for-fetching-service-urls: true
client.region
"http://" + ec2Url + ":" + clientConfig.getEurekaServerPort() + "/" + clientConfig.getEurekaServerURLContext() + "/";

只要解决DNS服务器配置就可以达到动态集群的效果,关于如何搭建DNS服务器集群,请移步另一篇文章: CentOS 搭建DNS主从服务器集群 ,文中详细介绍了如何在区域配置文件中配置TXT记录,本文不在赘述。

1.DNS 区域文件配置TXT记录

zts.local.zone区域配置文件中有关eureka的配置:

; eureka cluster配置
txt.shanghai IN TXT "defaultZone.zts.local"
txt.defaultZone IN TXT "10.29.181.56" "10.29.181.57" "10.29.181.58" "10.29.181.60"

;通过查看Eureka的源码,它的实现是通过寻找txt.beijing-a.zts.local(txt.region.eureka-server-d-n-s-name)获取"beijing-a.zts.local" "beijing-b.zts.local"的zone:beijing-a和beijing-b,
;然后再去获取txt.beijing-a.zts.local和txt.beijing-b.zts.local中对应的ServiceUrls的数据,也就是IP地址: "10.29.181.61" "10.29.181.62"
;这样服务间就可以获取到固定端口下的不同IP的机器的注册中心服务地址,并相互注册
txt.beijing IN TXT "beijing-a.zts.local" "beijing-b.zts.local"
txt.beijing-a IN TXT "10.29.181.61" "10.29.181.62"
txt.beijing-b IN TXT "10.29.181.63" "10.29.181.64"

2.Eureka Server/Client端配置

---
spring:
application:
name: eureka-server
server:
port: 8081
eureka:
server:
enable-self-preservation: false
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
    ## 是否将自己注册到eureka
register-with-eureka: true
    ## 是否获取注册信息到本地
fetch-registry: true
    ## 开启DNS方式获取serviceUrl,默认为false
use-dns-for-fetching-service-urls: true
    ## DNS域名,获取其他信息将以该域名为根域名
eureka-server-d-n-s-name: zts.local
    ## 当前应用所在区域,默认为us-east-1
region: beijing
    ## 配置中心的eureka目录
eureka-server-u-r-l-context: eureka
    ## 映射其他eurekaServer的端口,这里注意采用这种方式 server.port和这个端口最好一致
    ## 因为dns是控制地址的变化,端口不变,所以不像前面的哪些配置方式可以自己定义url和port。
    ## 所以每个IP都是用的相同的port进行注册中心服务的部署
eureka-server-port: 8081
    ## 获取serviceUrl时候是否优先获取相同zone的列表(如果获取为空则获取所在region第一个zone),如果为false则优先获取不在相同zone的列表
prefer-same-zone-eureka: true

3.测试

修改客户端DNS服务器配置为10.29.181.61,DNS服务器的域名为zts.local

依次启动4台Eureka Server服务器,查看启动日志(删减版的日志),:

2018-11-20 16:17:14.962  INFO 49750 --- [           main] c.n.d.s.r.aws.ConfigClusterResolver      : Resolving eureka endpoints via DNS: txt.beijing.zts.local (<------注意这里)
2018-11-20 16:17:15.012  INFO 49750 --- [           main] com.netflix.discovery.DiscoveryClient    : Disable delta property : false
2018-11-20 16:17:15.262  INFO 49750 --- [           main] com.netflix.discovery.DiscoveryClient    : Discovery Client initialized at timestamp 1542701835260 with initial instances count: 5
2018-11-20 16:17:15.326  INFO 49750 --- [           main] c.n.eureka.DefaultEurekaServerContext    : Initializing ...
2018-11-20 16:17:15.559  INFO 49750 --- [           main] c.n.eureka.cluster.PeerEurekaNodes       : Replica node URL:  http://10.29.181.62:8081/eureka/
2018-11-20 16:17:15.560  INFO 49750 --- [           main] c.n.eureka.cluster.PeerEurekaNodes       : Replica node URL:  http://10.29.181.64:8081/eureka/
2018-11-20 16:17:15.560  INFO 49750 --- [           main] c.n.eureka.cluster.PeerEurekaNodes       : Replica node URL:  http://10.29.181.61:8081/eureka/

2018-11-20 16:17:16.052  INFO 49750 --- [      Thread-14] o.s.c.n.e.server.EurekaServerBootstrap   : isAws returned false
2018-11-20 16:17:16.053  INFO 49750 --- [      Thread-14] o.s.c.n.e.server.EurekaServerBootstrap   : Initialized server context
2018-11-20 16:17:16.056  INFO 49750 --- [           main] c.z.e.server.EurekaServerApplication     : Started EurekaServerApplication in 7.112 seconds (JVM running for 7.625)
2018-11-20 16:17:16.060  INFO 49750 --- [      Thread-14] c.n.e.registry.AbstractInstanceRegistry  : Registered instance EUREKA-SERVER/10.29.181.61:eureka-server:8081 with status UP (replication=true)
2018-11-20 16:17:16.061  INFO 49750 --- [      Thread-14] c.n.e.registry.AbstractInstanceRegistry  : Registered instance EUREKA-SERVER/10.29.181.62:eureka-server:8081 with status UP (replication=true)
2018-11-20 16:17:16.061  INFO 49750 --- [      Thread-14] c.n.e.registry.AbstractInstanceRegistry  : Registered instance EUREKA-SERVER/10.29.181.64:eureka-server:8081 with status UP (replication=true)
2018-11-20 16:17:16.062  INFO 49750 --- [      Thread-14] c.n.e.registry.AbstractInstanceRegistry  : Registered instance EUREKA-SERVER/10.29.181.63:eureka-server:8081 with status UP (replication=true)
2018-11-20 16:17:16.062  INFO 49750 --- [      Thread-14] c.n.e.registry.AbstractInstanceRegistry  : Registered instance ACCOUNT-CENTER/10.25.102.174:account-center:8891 with status UP (replication=true)

2018-11-20 16:17:16.062  INFO 49750 --- [      Thread-14] c.n.e.r.PeerAwareInstanceRegistryImpl    : Got 5 instances from neighboring DS node
2018-11-20 16:17:16.062  INFO 49750 --- [      Thread-14] c.n.e.r.PeerAwareInstanceRegistryImpl    : Renew threshold is: 8
2018-11-20 16:17:16.062  INFO 49750 --- [      Thread-14] c.n.e.r.PeerAwareInstanceRegistryImpl    : Changing status to UP
2018-11-20 16:17:16.070  INFO 49750 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_EUREKA-SERVER/10.29.181.63:eureka-server:8081 - registration status: 204
2018-11-20 16:17:16.070  INFO 49750 --- [      Thread-14] e.s.EurekaServerInitializerConfiguration : Started Eureka Server
2018-11-20 16:17:16.310  INFO 49750 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2018-11-20 16:17:16.310  INFO 49750 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2018-11-20 16:17:16.327  INFO 49750 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 17 ms
2018-11-20 16:17:16.578  INFO 49750 --- [nio-8081-exec-1] c.n.e.registry.AbstractInstanceRegistry  : Registered instance EUREKA-SERVER/10.29.181.63:eureka-server:8081 with status UP (replication=true)
2018-11-20 16:17:17.457  INFO 49750 --- [nio-8081-exec-2] c.n.e.registry.AbstractInstanceRegistry  : Registered instance EUREKA-SERVER/10.29.181.63:eureka-server:8081 with status UP (replication=true)

Eureka Client端

Account服务配置

logging:
level:
    org.springframework.boot: info
    org.springframework.cloud: debug
spring:
application:
name: account-center
server:
port: 8891
eureka:
server:
enable-self-preservation: false
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
metadata-map:
configPath: ${server.servlet.context-path}
home-page-url-path: ${server.servlet.context-path}
    ## 服务过期时间配置,超过这个时间没有接收到心跳EurekaServer就会将这个实例剔除
lease-expiration-duration-in-seconds: 10
    ## 服务刷新时间配置,每隔这个时间会主动心跳一次
lease-renewal-interval-in-seconds: 5
client:
    ## 是否将自己注册到eureka
register-with-eureka: true
    ## 是否获取注册信息到本地
fetch-registry: true
    ## 开启DNS方式获取serviceUrl,默认为false
use-dns-for-fetching-service-urls: true
    ## DNS域名,获取其他信息将以该域名为根域名
eureka-server-d-n-s-name: zts.local
    ## 当前应用所在区域,默认为us-east-1
region: beijing
    ## 配置中心的eureka目录
eureka-server-u-r-l-context: eureka
    ## 映射其他eurekaServer的端口,这里注意采用这种方式 server.port和这个端口最好一致
    ## 因为dns是控制地址的变化,端口不变,所以不像前面的哪些配置方式可以自己定义url和port。
    ## 所以每个IP都是用的相同的port进行注册中心服务的部署
eureka-server-port: 8081
    ## 获取serviceUrl时候是否优先获取相同zone的列表(如果获取为空则获取所在region第一个zone),如果为false则优先获取不在相同zone的列表
prefer-same-zone-eureka: true

Account启动日志:

2018-11-20 16:11:05.373  INFO 5824 --- [ restartedMain] c.n.d.s.r.aws.ConfigClusterResolver      : Resolving eureka endpoints via DNS: txt.beijing.zts.local (<------看这里)
2018-11-20 16:11:05.529  INFO 5824 --- [ restartedMain] com.netflix.discovery.DiscoveryClient    : Disable delta property : false
2018-11-20 16:11:05.529  INFO 5824 --- [ restartedMain] com.netflix.discovery.DiscoveryClient    : Single vip registry refresh property : null
2018-11-20 16:11:05.529  INFO 5824 --- [ restartedMain] com.netflix.discovery.DiscoveryClient    : Force full registry fetch : false
2018-11-20 16:11:05.529  INFO 5824 --- [ restartedMain] com.netflix.discovery.DiscoveryClient    : Application is null : false
201

打开Eureka console,查看注册效果:

eureka-dns-cluster

参考资料

1.com.netflix.discovery.endpoint.EndpointUtils.getServiceUrlsFromDNS

版本:eureka-client:1.9.3

/**
    * Get the list of all eureka service urls for the eureka client to talk to.
    *
    * @param clientConfig the clientConfig to use
    * @param zone the zone in which the client resides
    * @param randomizer a randomizer to randomized returned urls, if loading from dns
    *
    * @return The list of all eureka service urls for the eureka client to talk to.
    */
   public static List<String> getDiscoveryServiceUrls(EurekaClientConfig clientConfig, String zone, ServiceUrlRandomizer randomizer) {
       boolean shouldUseDns = clientConfig.shouldUseDnsForFetchingServiceUrls();
       if (shouldUseDns) {
           return getServiceUrlsFromDNS(clientConfig, zone, clientConfig.shouldPreferSameZoneEureka(), randomizer);
       }
       return getServiceUrlsFromConfig(clientConfig, zone, clientConfig.shouldPreferSameZoneEureka());
   }

   /**
    * Get the list of all eureka service urls from DNS for the eureka client to
    * talk to. The client picks up the service url from its zone and then fails over to
    * other zones randomly. If there are multiple servers in the same zone, the client once
    * again picks one randomly. This way the traffic will be distributed in the case of failures.
    *
    * @param clientConfig the clientConfig to use
    * @param instanceZone The zone in which the client resides.
    * @param preferSameZone true if we have to prefer the same zone as the client, false otherwise.
    * @param randomizer a randomizer to randomized returned urls
    *
    * @return The list of all eureka service urls for the eureka client to talk to.
    */
   public static List<String> getServiceUrlsFromDNS(EurekaClientConfig clientConfig, String instanceZone, boolean preferSameZone, ServiceUrlRandomizer randomizer) {
       String region = getRegion(clientConfig);
       // Get zone-specific DNS names for the given region so that we can get a
       // list of available zones
       Map<String, List<String>> zoneDnsNamesMap = getZoneBasedDiscoveryUrlsFromRegion(clientConfig, region);
       Set<String> availableZones = zoneDnsNamesMap.keySet();
       List<String> zones = new ArrayList<String>(availableZones);
       if (zones.isEmpty()) {
           throw new RuntimeException("No available zones configured for the instanceZone " + instanceZone);
       }
       int zoneIndex = 0;
       boolean zoneFound = false;
       for (String zone : zones) {
           logger.debug("Checking if the instance zone {} is the same as the zone from DNS {}", instanceZone, zone);
           if (preferSameZone) {
               if (instanceZone.equalsIgnoreCase(zone)) {
                   zoneFound = true;
               }
           } else {
               if (!instanceZone.equalsIgnoreCase(zone)) {
                   zoneFound = true;
               }
           }
           if (zoneFound) {
               logger.debug("The zone index from the list {} that matches the instance zone {} is {}",
                       zones, instanceZone, zoneIndex);
               break;
           }
           zoneIndex++;
       }
       if (zoneIndex >= zones.size()) {
           if (logger.isWarnEnabled()) {
               logger.warn("No match for the zone {} in the list of available zones {}",
                       instanceZone, zones.toArray());
           }
       } else {
           // Rearrange the zones with the instance zone first
           for (int i = 0; i < zoneIndex; i++) {
               String zone = zones.remove(0);
               zones.add(zone);
           }
       }

       // Now get the eureka urls for all the zones in the order and return it
       List<String> serviceUrls = new ArrayList<String>();
       for (String zone : zones) {
           for (String zoneCname : zoneDnsNamesMap.get(zone)) {
               List<String> ec2Urls = new ArrayList<String>(getEC2DiscoveryUrlsFromZone(zoneCname, DiscoveryUrlType.CNAME));
               // Rearrange the list to distribute the load in case of multiple servers
               if (ec2Urls.size() > 1) {
                   randomizer.randomize(ec2Urls);
               }
               for (String ec2Url : ec2Urls) {
                   StringBuilder sb = new StringBuilder()
                           .append("http://")
                           .append(ec2Url)
                           .append(":")
                           .append(clientConfig.getEurekaServerPort());
                   if (clientConfig.getEurekaServerURLContext() != null) {
                       if (!clientConfig.getEurekaServerURLContext().startsWith("/")) {
                           sb.append("/");
                       }
                       sb.append(clientConfig.getEurekaServerURLContext());
                       if (!clientConfig.getEurekaServerURLContext().endsWith("/")) {
                           sb.append("/");
                       }
                   } else {
                       sb.append("/");
                   }
                   String serviceUrl = sb.toString();
                   logger.debug("The EC2 url is {}", serviceUrl);
                   serviceUrls.add(serviceUrl);
               }
           }
       }
       // Rearrange the fail over server list to distribute the load
       String primaryServiceUrl = serviceUrls.remove(0);
       randomizer.randomize(serviceUrls);
       serviceUrls.add(0, primaryServiceUrl);

       if (logger.isDebugEnabled()) {
           logger.debug("This client will talk to the following serviceUrls in order : {} ",
                   (Object) serviceUrls.toArray());
       }
       return serviceUrls;
   }

2. dns config配置参考文章


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Hacking

Hacking

Jon Erickson / No Starch Press / 2008-2-4 / USD 49.95

While other books merely show how to run existing exploits, Hacking: The Art of Exploitation broke ground as the first book to explain how hacking and software exploits work and how readers could deve......一起来看看 《Hacking》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具