Spring Cloud分区发布实践(3) 网关和负载均衡
注意: 因为涉及到配置测试切换, 中间环节需按此文章操作体验, 代码仓库里面的只有最后一步的代码
准备好了微服务, 那我们就来看看网关+负载均衡如何一起工作
新建一个模块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) 网关和负载均衡的更多相关文章
- Spring Cloud分区发布实践(1) 环境准备
最近研究了一下Spring Cloud里面的灰度发布, 看到各种各样的使用方式, 真是纷繁复杂, 眼花缭乱, 不同的场景需要不同的解决思路. 那我们也来实践一下最简单的场景: 区域划分: 服务分为be ...
- Spring Cloud分区发布实践(6)--灰度服务-根据Header选择实例区域
此文是一个完整的例子, 包含可运行起来的源码. 此例子包含以下部分: 网关层实现自定义LoadBalancer, 根据Header选取实例 服务中的Feign使用拦截器, 读取Header Feign ...
- Spring Cloud分区发布实践(4) FeignClient
上面看到直接通过网关访问微服务是可以实现按区域调用的, 那么微服务之间调用是否也能按区域划分哪? 下面我们使用FeignClient来调用微服务, 就可以配合LoadBalancer实现按区域调用. ...
- Spring Cloud分区发布实践(5)--定制ServiceInstanceListSupplier
现在我们简单地来定制二个 ServiceInstanceListSupplier, 都是zone-preference的变种. 为了方便, 我重新调整了一下项目的结构, 把一些公用的类移动到hello ...
- Spring Cloud分区发布实践(2) 微服务
我们准备一下用于查询姓名的微服务. 首先定义一下服务的接口, 新建一个空的Maven模块hello-remotename-core, 里面新建一个类: public interface RemoteN ...
- Spring Cloud微服务开发笔记5——Ribbon负载均衡策略规则定制
上一篇文章单独介绍了Ribbon框架的使用,及其如何实现客户端对服务访问的负载均衡,但只是单独从Ribbon框架实现,没有涉及spring cloud.本文着力介绍Ribbon的负载均衡机制,下一篇文 ...
- Spring cloud gateway 如何在路由时进行负载均衡
本文为博主原创,转载请注明出处: 1.spring cloud gateway 配置路由 在网关模块的配置文件中配置路由: spring: cloud: gateway: routes: - id: ...
- spring boot 2.0.3+spring cloud (Finchley)2、搭建负载均衡Ribbon (Eureka+Ribbon+RestTemplate)
Ribbon是Netflix公司开源的一个负载均衡组件,将负载均衡逻辑封装在客户端中,运行在客户端的进程里. 本例子是在搭建好eureka的基础上进行的,可参考spring boot 2.0.3+sp ...
- spring cloud学习(三)使用Ribbon实现客户端负载均衡
使用Ribbon实现客户端的负载均衡 * 个人博客空间 : https://zggdczfr.cn/ * Ribbon Spring Cloud Netflix Ribbon 是一个客户端负载均衡的组 ...
随机推荐
- Pytorch项目基本结构
梳理一下Pytorch项目的基本结构(其实TF的也差不多是这样,这种思路可以迁移到别的深度学习框架中) 结构树 -------checkpoints #存放训练完成的模型文件 ----xxx.pk ...
- JavaScript 沙盒模式
微前端已经成为前端领域比较火爆的话题,在技术方面,微前端有一个始终绕不过去的话题就是前端沙箱 什么是沙箱 Sandboxie(又叫沙箱.沙盘)即是一个虚拟系统程序,允许你在沙盘环境中运行浏览器或其他程 ...
- spring boot @Async异步注解上下文透传
上一篇文章说到,之前使用了@Async注解,子线程无法获取到上下文信息,导致流量无法打到灰度,然后改成 线程池的方式,每次调用异步调用的时候都手动透传 上下文(硬编码)解决了问题. 后面查阅了资料,找 ...
- 【Spring Cloud & Alibaba 实战 | 总结篇】Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现微服务统一认证授权和鉴权
一. 前言 hi,大家好~ 好久没更文了,期间主要致力于项目的功能升级和问题修复中,经过一年时间的打磨,[有来]终于迎来v2.0版本,相较于v1.x版本主要完善了OAuth2认证授权.鉴权的逻辑,结合 ...
- 解决Git操作报错
情况一: 当我拉取的代码是最新的时候,git pull是可以正常的拉取的,但是却不可以提交,报错如下图: 情况二: 如果我目前不是最新的版本,需要git pull,此时拉取就会失败,报错如下图: 出现 ...
- Dockerfile优化方式
如今GitHub 仓库中已经包含了成千上万的Dockerfile,但并不是所有的Dockerfile都是高效的.本文将从四个方面来介绍Dockerfile的最佳实践,以此来帮助大家编写更优雅的Dock ...
- (C++)戳西瓜
写在前面的话: 请不要吝啬你的点赞!!! 题目描述 有 n 个西瓜,编号为0 到 n-1,每个西瓜上都标有一个数字,这些数字存在数组 nums 中. 现在要求你戳破所有的西瓜.每当你戳破一个西瓜 i ...
- HDU 4438 Hunters 区域赛水题
本文转载于 http://blog.csdn.net/major_zhang/article/details/52197538 2012天津区域赛最水之题: 题意容易读懂,然后就是分情况求出A得分的数 ...
- 数据连接池JNDI
数据库连接有很多中方式,JDBC数据库的连接方式,前边我们已经介绍过了,而开发中我们经常使用的是DataBaseConnectionPool(数据库连接池,DBCP).数据库连接池到底是什么?它比jd ...
- Windows软件包管理工具:Scoop
前言 删库跑路后,Windows系统如何快速安装应用程序,部署环境呢? 以前想过这个问题,最近在安装Hugo时发现使用软件包管理工具可以解决这个问题. 阅读建议 首先需要测试下载速度,尝试从官网下载, ...