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

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

新建一个模块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. Vue(1)Vue安装与使用

    前言 Vue(读音/vjuː/,类似于view) 是一套用于构建前后端分离的框架.刚开始是由国内优秀选手尤雨溪开发出来的,目前是全球"最"流行的前端框架.使用vue开发网页很简单, ...

  2. 一个排序引发的BUG

    你好呀,我是why. 前两天在 Git 上闲逛的时候又不知不觉逛到 Dubbo 那里去了. 看了一下最近一个月的数据,社区活跃度还是很高的: 然后看了一下最新的 issue,大家提问都很积极. 其中看 ...

  3. Docker笔记--镜像&基于GO项目创建Docker镜像

    Docker笔记--镜像&基于GO项目创建Docker镜像 核心概念 Doker镜像--包含一个基本的操作系统运行环境和应用程序,镜像是创建Docker容器的基础. Docker容器--如果把 ...

  4. 高性能的Redis之对象底层实现原理详解

    对象 在前面的数个章节里, 我们陆续介绍了 Redis 用到的所有主要数据结构, 比如简单动态字符串(SDS).双端链表.字典.压缩列表.整数集合, 等等. Redis 并没有直接使用这些数据结构来实 ...

  5. pip安装setuptools_rust报错

    公司项目中有主备CDN存在,由于阿里云以及腾讯云的预热功能不支持自动(一般是云函数),所以就根据云厂商给的脚本稍作更改,手动传入数据来进行预热. 由于之前部署在centos7.7系统python2.7 ...

  6. 我是怎么写 Git Commit message 的?

    目录 作用 用的什么规范? type scope subject body footer 参考文章 用的什么辅助工具? 作用 编写格式化的 commit message 能够大大提高代码的维护效率. ...

  7. 2.14、制作Centos模板及优化操作

    1.安装系统: (1)规范网卡为eth0的模式: (2)选择时区: (3)选择支持的语言包含中文: (4)选择软件包: 补充:桌面版包选择: (5)关闭down机内存日志: (6)分区: 1)分区说明 ...

  8. java设计模式(9):模板方法模式(TemplateMethod)

    一,定义:模板方法模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 二,类图: 三,通过小例子讲解: 这个模式一般用在 ...

  9. 南京大学计算机基础 X64函数调用和链接器原理和可重定位的文件.o

    一. 1.函数调用差别 X64的函数调用,和X86函数调用区别,在于参数的传递不一样了,X64的参数传递不在依靠栈来传,而是寄存器,不过还是具有局限性的 比如只能允许六个寄存器来传,分别是RDI,RS ...

  10. 小程序textarea设置maxlength后不是你想的那样简单

    可能很多小伙伴们.看见这个标题后; 觉得作者是一个标题党. textarea设置maxlength后, 限制用户输入的字符呗! 还能怎么样呢? 恭喜你,说对了一半. 之前我也一直是这样想的. 知道今天 ...