注意: 因为涉及到配置测试切换, 中间环节需按此文章操作体验, 代码仓库里面的只有最后一步的代码

准备好了微服务, 那我们就来看看网关+负载均衡如何一起工作

新建一个模块hello-gateway, 开启gateway和loadbalancer, pom部分如下:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cnscud.betazone</groupId>
<artifactId>betazone-root</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent> <artifactId>hello-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hello-gateway</name>
<description>Demo project for Spring Boot</description> <dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency> </dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

HelloGatewayApplication 不修改, 使用默认的实现.

下面我们来实验几种配置, 看看LoadBalancer的表现

1. 默认配置, 不配置zone: application.yml (没有CustomLoadBalancerConfiguration标注)

server:
port: 8800 spring:
application:
name: betazone-hello-gateway
main:
allow-bean-definition-overriding: true
cloud:
gateway:
discovery:
locator:
lowerCaseServiceId: true
enabled: true
routes:
- id: remotename
uri: lb://betazone-hello-remotename
predicates:
- Path=/remoteapi/**
filters:
- StripPrefix=1
loadbalancer:
ribbon:
enabled: false eureka:
instance:
prefer-ip-address: true client:
register-with-eureka: true
fetch-registry: true
prefer-same-zone-eureka: true
service-url:
defaultZone: http://localhost:8001/eureka/ logging:
level:
org.springframework.cloud: debug

启动应用, 访问 http://localhost:8800/remoteapi/remote/id/2, 刷新几次浏览器, 可以看到内容在

"World [remotename: 127.0.0.1:9001]"
"World [remotename: 127.0.0.1:9002]"

两种情况下依次切换, 说明LoadBalancer在生效, 但是没有任何zone设置.

2. 实验: 设置应用的metadata的zone, 负载均衡会不会自动感知哪?

我们复制一份application-main.yml, 修改如下:

server:
port: 8801 spring:
application:
name: betazone-hello-gateway
main:
allow-bean-definition-overriding: true
cloud:
gateway:
discovery:
locator:
lowerCaseServiceId: true
enabled: true
routes:
- id: remotename
uri: lb://betazone-hello-remotename
predicates:
- Path=/remoteapi/**
filters:
- StripPrefix=1
loadbalancer:
ribbon:
enabled: false eureka:
instance:
prefer-ip-address: true
metadata-map:
zone: main
client:
register-with-eureka: true
fetch-registry: true
prefer-same-zone-eureka: true
service-url:
defaultZone: http://localhost:8001/eureka/ logging:
level:
org.springframework.cloud: debug

修改了eureka.instance.metadata-map.zone 为main, 端口改为8801, 按此配置启动应用, 访问 http://localhost:8801/remoteapi/remote/id/2

发现和第一种情况一样, zone没有生效, 说明默认的LoadBalancer没有考虑zone配置.

3. 开启LoadBalancer的zone感应 (main区域)

修改application-main.yml中loadbalancer部分如下:

spring:
cloud:
loadbalancer:
ribbon:
enabled: false
zone: main
configurations: zone-preference

重新运行, 访问 http://localhost:8801/remoteapi/remote/id/2

现在生效了, 服务总是返回 "World [remotename: 127.0.0.1:9001]" , 不再返回端口 9002的信息了, 说明 zone区域设置生效了.

设置关键点:

  • zone 设置loadbalancer要访问的服务的zone, 如果没设置, 则按需读取实例的eureka.instance.metadata-map.zone设置
  • configurations 具体描述看Spring文档, 此处zone-preference 则设置优先按区域选择服务实例.

4. 测试LoadBalancer的zone感应 (beta区域)

复制一份application-beta.yml, 修改端口为 8802, 相关的zone都改为beta区域,
修改application-main.yml中loadbalancer部分如下:

server:
port: 8802 spring:
cloud:
loadbalancer:
ribbon:
enabled: false
zone: beta
configurations: zone-preference

复制配置, 修改profile为beta, 启动实例, 访问 http://localhost:8802/remoteapi/remote/id/2, 则可以看到总是输出 "World [remotename: 127.0.0.1:9002]", 说明beta区域设置生效了.

此时我们可以看到如何使用内置的 "zone-preference"了, 那么我们如何自己定义个性化的策略哪, 我们可以看到Spring的这个配置指向 LoadBalancerClientConfiguration, 打开源码,
可以看到里面有好多的discoveryClientServiceInstanceListSupplier实现, 我们自己实现(抄袭)一个不就可以了吗?

5. 定制ServiceInstanceListSupplier

我们先直接抄袭一份出来, 作为我们自己的实现(个性化实现代码不同, 但是流程一样, 这里主要跑通流程)

/**
* 自定义 Instance List Supplier: 根据默认Zone划分.
* 也可以自己实现zone规则
*
*/
public class CustomLoadBalancerConfiguration { @Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withZonePreference()
.withCaching()
.build(context);
} }

这里直接就是从 zonePreferenceDiscoveryClientServiceInstanceListSupplier 抄袭过来的, 我们主要先演示一下流程, 后面我们会实现自己的ServiceInstanceListSupplier.

声明配置以便生效:

@Configuration(proxyBeanMethods = false)
@LoadBalancerClients(defaultConfiguration = CustomLoadBalancerConfiguration.class)
public class SamezoneAutoConfiguration {
}

注释掉yml里面的 configurations: zone-preference, 其他不修改, 重新启动8801, 8802端口, 重新测试.

效果和上面一样, 说明通过类的方式也同样效果, 只不过我们可以使用自己定制的ServiceInstanceListSupplier 了.

  • 注意:
    zone设置优先以 eureka.instance.metadata-map.zone 为首要设置, 没有特殊情况下不要设置spring.cloud.loadbalancer.zone, 这样loadbalancer就会读取实例的zone.

代码位置: https://github.com/cnscud/javaroom/tree/main/betazone2/hello-gateway 注意代码只是最后一步的情况

接下来我们实验一下连锁调用的情况下, zone配置会不会被继承传递哪? 什么情况下会失效哪? ......

Spring Cloud分区发布实践(3) 网关和负载均衡的更多相关文章

  1. Spring Cloud分区发布实践(1) 环境准备

    最近研究了一下Spring Cloud里面的灰度发布, 看到各种各样的使用方式, 真是纷繁复杂, 眼花缭乱, 不同的场景需要不同的解决思路. 那我们也来实践一下最简单的场景: 区域划分: 服务分为be ...

  2. Spring Cloud分区发布实践(6)--灰度服务-根据Header选择实例区域

    此文是一个完整的例子, 包含可运行起来的源码. 此例子包含以下部分: 网关层实现自定义LoadBalancer, 根据Header选取实例 服务中的Feign使用拦截器, 读取Header Feign ...

  3. Spring Cloud分区发布实践(4) FeignClient

    上面看到直接通过网关访问微服务是可以实现按区域调用的, 那么微服务之间调用是否也能按区域划分哪? 下面我们使用FeignClient来调用微服务, 就可以配合LoadBalancer实现按区域调用. ...

  4. Spring Cloud分区发布实践(5)--定制ServiceInstanceListSupplier

    现在我们简单地来定制二个 ServiceInstanceListSupplier, 都是zone-preference的变种. 为了方便, 我重新调整了一下项目的结构, 把一些公用的类移动到hello ...

  5. Spring Cloud分区发布实践(2) 微服务

    我们准备一下用于查询姓名的微服务. 首先定义一下服务的接口, 新建一个空的Maven模块hello-remotename-core, 里面新建一个类: public interface RemoteN ...

  6. Spring Cloud微服务开发笔记5——Ribbon负载均衡策略规则定制

    上一篇文章单独介绍了Ribbon框架的使用,及其如何实现客户端对服务访问的负载均衡,但只是单独从Ribbon框架实现,没有涉及spring cloud.本文着力介绍Ribbon的负载均衡机制,下一篇文 ...

  7. Spring cloud gateway 如何在路由时进行负载均衡

    本文为博主原创,转载请注明出处: 1.spring cloud gateway 配置路由 在网关模块的配置文件中配置路由: spring: cloud: gateway: routes: - id: ...

  8. spring boot 2.0.3+spring cloud (Finchley)2、搭建负载均衡Ribbon (Eureka+Ribbon+RestTemplate)

    Ribbon是Netflix公司开源的一个负载均衡组件,将负载均衡逻辑封装在客户端中,运行在客户端的进程里. 本例子是在搭建好eureka的基础上进行的,可参考spring boot 2.0.3+sp ...

  9. spring cloud学习(三)使用Ribbon实现客户端负载均衡

    使用Ribbon实现客户端的负载均衡 * 个人博客空间 : https://zggdczfr.cn/ * Ribbon Spring Cloud Netflix Ribbon 是一个客户端负载均衡的组 ...

随机推荐

  1. Golang学习(用代码来学习) - 第四篇

    /** 一个用来进行go routine的函数 */ func print_something(msg string){ for i:= 0;i < 5;i++{ time.Sleep(1 * ...

  2. CMake 两种变量原理

    目录 [TOC] 1.两种变量的定义参考 2.两种变量的作用域原理及使用 1.Normal Variables (1).包含 add_subdirectory().function().(本质是值拷贝 ...

  3. sql把一个字段中的特定字符替换成其他字符

    将'0654879'替换成'0754879' UPDATE dbo.SG_Functionality SET FunctionalityCode=REPLACE(FunctionalityCode,' ...

  4. 02 jumpserver系统设置

    2.系统设置: (1)基本设置: (2)邮件设置: 1)163邮箱设置: 2)在jumpserver上填写邮箱信息: 3)邮件测试信息如下: (3)邮件内容设置: (4)终端设置: (5)安全设置:

  5. 17、lnmp_php编译安装

    17.1.FastCGI介绍: 1.什么是CGI: CGI的全称为"通用网关接口",为http服务器与其他机器上的程序服务通信交流的一种工具,CGI程序 必须运行在网络服务器上:传 ...

  6. POJ 1696 Space Ant 点积计算夹角

    题意: 一只特别的蚂蚁,只能直走或者左转.在一个平面上,有很多株植物,这只蚂蚁每天需要进食一株,这只蚂蚁从起点为(0,miny)的点开始出发.求最多能活多少天 分析: 肯定是可以吃到所有植物的,以当前 ...

  7. promise的基本使用

    // 什么情况下适用promise? // 一般情况下是有异步请求操作时,使用promise对这个异步操作进行封装 // new ->构造函数(1.保存了一些状态信息 2.执行传入的函数) // ...

  8. MVC 与 三层架构

    https://www.bilibili.com/video/av29086718/?p=24 MVC: MVC与三层架构进行比较:

  9. Java实验项目二——打印某年某月日历

    Program:打印万年历(输入年份,月份,输出该月的日历,已知1900年1月1日是星期一), 要 求: (1)编写一个方法判断闰年: (2)编写一个方法判断某年某月有多少天: (3)编写一个方法计算 ...

  10. C# 8.0和.NET Core 3.0高级编程 分享笔记三:控制流程和转换类型

    控制流程和转换类型 本章的内容主要包括编写代码.对变量执行简单的操作.做出决策.重复执行语句块.将变量或表达式值从一种类型转换为另一种类型.处理异常以及在数值变量中检查溢出. 本章涵盖以下主题: 操作 ...