构建Multi Zone Eureka Server

    技术2022-07-12  74

    Zone与Region设计

    Region代表一个独立的地理区域, 每个Region之间是相互独立及隔离的, 默认情况下资源只在单个Region之间的AvailabilityZone进行复制.AvailabilityZone 可看作Region下面的一个个机房,各个机房相对独立,主要是为了Region 的高可用设计,当同一个Region下面的AvailabilityZone不可用时,还有其他AvailabilityZone可用。Eureka Server原生支持了Region及AvailabilityZone,由于资源在Region之间默认是不会复制的,因此Eureka Server的高可用主要就在于Region下面的AvailabilityZone。Eureka Client支持preferSameZone,也就是获取Eureka Server的serviceUrl优先拉取跟应用实例同处于一个AvailabilityZone的Eureka Server 地址列表。一个AvailabilityZone可以设置多个Eureka Server实例,它们之间构成peer节点,然后采用Peer to Peer的复制模式。Netflix的Ribbon组件针对多个AvailabilityZone 提供了ZoneAffinity 的支持,允许在客户端路由或网关路由时,优先选取与自身实例处于同一个AvailabilityZone的服务实例.

    demo

    重点关注yml中的eureka.instance.metadataMap.zone配置
    Eureka Server实例 // 依赖配置 <?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>org.example</groupId> <artifactId>eureka-server</artifactId> <version>1.0-SNAPSHOT</version> <name>eureka-server</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencyManagement> <dependencies> <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <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-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> // 启动类 import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; /** * Hello world! */ @SpringBootApplication @EnableEurekaServer public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); System.out.println("Hello World!"); } } // application-zone1a.yml server: port: 8761 spring: application: name: eureka-server eureka: instance: hostname: localhost preferIpAddress: true metadataMap.zone: zone1 client: register-with-eureka: true fetch-registry: true region: region-east serviceUrl: zone1: http://localhost:8761/eureka/,http://localhost:8762/eureka/ zone2: http://localhost:8763/eureka/,http://localhost:8764/eureka/ availability-zones: region-east: zone1,zone2 server: waitTimeInMsWhenSyncEmpty: 0 enableSelfPreservation: false // application-zone1b.yml server: port: 8762 spring: application: name: eureka-server eureka: instance: hostname: localhost preferIpAddress: true metadataMap.zone: zone1 client: register-with-eureka: true fetch-registry: true region: region-east serviceUrl: zone1: http://localhost:8761/eureka/,http://localhost:8762/eureka/ zone2: http://localhost:8763/eureka/,http://localhost:8764/eureka/ availability-zones: region-east: zone1,zone2 server: waitTimeInMsWhenSyncEmpty: 0 enableSelfPreservation: false // application-zone2a.yml server: port: 8763 spring: application: name: eureka-server eureka: instance: hostname: localhost preferIpAddress: true metadataMap.zone: zone2 client: register-with-eureka: true fetch-registry: true region: region-east serviceUrl: zone1: http://localhost:8761/eureka/,http://localhost:8762/eureka/ zone2: http://localhost:8763/eureka/,http://localhost:8764/eureka/ availability-zones: region-east: zone1,zone2 server: waitTimeInMsWhenSyncEmpty: 0 enableSelfPreservation: false // application-zone2b.yml server: port: 8763 spring: application: name: eureka-server eureka: instance: hostname: localhost preferIpAddress: true metadataMap.zone: zone2 client: register-with-eureka: true fetch-registry: true region: region-east serviceUrl: zone1: http://localhost:8761/eureka/,http://localhost:8762/eureka/ zone2: http://localhost:8763/eureka/,http://localhost:8764/eureka/ availability-zones: region-east: zone1,zone2 server: waitTimeInMsWhenSyncEmpty: 0 enableSelfPreservation: false eureka client实例 // 父依赖配置 <?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>cn.springcloud.book</groupId> <artifactId>ch3-2</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging> <name>ch3-2</name> <description>ch3-2</description> <modules> <module>ch3-2-zuul-gateway</module> <module>ch3-2-eureka-client</module> </modules> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <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>Finchley.RELEASE</spring-cloud.version> </properties> <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> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project> // eureka client依赖配置 <?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>cn.springcloud.book</groupId> <artifactId>ch3-2-eureka-client</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>ch3-2-eureka-client</name> <description>ch3-2-eureka-client</description> <parent> <groupId>cn.springcloud.book</groupId> <artifactId>ch3-2</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> // 启动类 @SpringBootApplication @EnableDiscoveryClient public class Ch32EurekaClientApplication { public static void main(String[] args) { SpringApplication.run(Ch32EurekaClientApplication.class, args); } } // application.yml management: endpoints: web: exposure: include: '*' // application-zone1.yml server: port: 8081 spring: application: name: client eureka: instance: metadataMap.zone: zone1 client: register-with-eureka: true fetch-registry: true region: region-east service-url: zone1: http://localhost:8761/eureka/,http://localhost:8762/eureka/ zone2: http://localhost:8763/eureka/,http://localhost:8764/eureka/ availability-zones: region-east: zone1,zone2 // application-zone2.yml server: port: 8082 spring: application: name: client eureka: instance: metadataMap.zone: zone2 client: register-with-eureka: true fetch-registry: true region: region-east service-url: zone1: http://localhost:8761/eureka/,http://localhost:8762/eureka/ zone2: http://localhost:8763/eureka/,http://localhost:8764/eureka/ availability-zones: region-east: zone1,zone2 zuul实例 // 依赖配置 <?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>cn.springcloud.book</groupId> <artifactId>ch3-2-zuul-gateway</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>ch3-2-zuul-gateway</name> <description>ch3-2-zuul-gateway</description> <parent> <groupId>cn.springcloud.book</groupId> <artifactId>ch3-2</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> // 启动类 import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @SpringBootApplication @EnableDiscoveryClient @EnableZuulProxy public class Ch322ZuulGatewayApplication { public static void main(String[] args) { SpringApplication.run(Ch322ZuulGatewayApplication.class, args); } } // application.yml spring: application: name: zuul-gateway management: endpoints: web: exposure: include: '*' // application-zone1.yml server: port: 10001 eureka: instance: metadataMap.zone: zone1 client: register-with-eureka: true fetch-registry: true region: region-east service-url: zone1: http://localhost:8761/eureka/,http://localhost:8762/eureka/ zone2: http://localhost:8763/eureka/,http://localhost:8764/eureka/ availability-zones: region-east: zone1,zone2 // application-zone2.yml server: port: 10002 eureka: instance: metadataMap.zone: zone2 client: register-with-eureka: true fetch-registry: true region: region-east service-url: zone1: http://localhost:8761/eureka/,http://localhost:8762/eureka/ zone2: http://localhost:8763/eureka/,http://localhost:8764/eureka/ availability-zones: region-east: zone1,zone2 测试结果 输入 http://localhost:10002/client/actuator/env, 只会路由到zone2上的eureka client实例
    Processed: 0.014, SQL: 9