lettuce 配置域名 dns 切换

大家好,我是烤鸭:
     如果你也有类似的困扰,运维告诉你,redis连接配置域名,这样出问题了,直接改dns地址就行,不需要重启服务。。。梦想是美好的,现实是残酷的。如果你使用的是 lettuce连接池,那么恭喜你,必须重启服务才能生效。

测试一下

环境:

    <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.2</version><relativePath/></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency></dependencies>        

配置:

application.properties

server.port=8115spring.redis.open=false
spring.redis.database=0
spring.redis.cluster.max-redirects=3
spring.redis.cluster.nodes=myredis1.test.com:6001,myredis1.test.com:6002,myredis2.test.com:6001,myredis2.test.com:6002,myredis3.test.com:6001,myredis3.test.com:6002
spring.redis.timeout=6000
spring.redis.pool.max-active=200
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=10
spring.redis.pool.min-idle=5
spring.redis.password=8efS6Snt

dns配置:

本地切换dns解析,可以通过 switchHosts 工具

https://pan.baidu.com/s/1eSgmYzS

修改完如图所示,右下角点 √ 生效

在这里插入图片描述

使用jmeter 每2秒发送一次请求,都是成功的
在这里插入图片描述

接着down掉现有的redis集群,服务开始报错:

切换本地hosts,发现报错依旧,spring-boot-starter-data-redis 是不支持 域名dns切换的。

2021-07-26 10:42:54.796 ERROR 3712 --- [nio-8115-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: CLUSTERDOWN The cluster is down] with root causeio.lettuce.core.RedisCommandExecutionException: CLUSTERDOWN The cluster is downat io.lettuce.core.internal.ExceptionFactory.createExecutionException(ExceptionFactory.java:137) ~[lettuce-core-6.1.3.RELEASE.jar:6.1.3.RELEASE]at io.lettuce.core.internal.ExceptionFactory.createExecutionException(ExceptionFactory.java:110) ~[lettuce-core-6.1.3.RELEASE.jar:6.1.3.RELEASE]at io.lettuce.core.protocol.AsyncCommand.completeResult(AsyncCommand.java:120) ~[lettuce-core-6.1.3.RELEASE.jar:6.1.3.RELEASE]at io.lettuce.core.protocol.AsyncCommand.complete(AsyncCommand.java:111) ~[lettuce-core-6.1.3.RELEASE.jar:6.1.3.RELEASE]at io.lettuce.core.protocol.CommandWrapper.complete(CommandWrapper.java:63) ~[lettuce-core-6.1.3.RELEASE.jar:6.1.3.RELEASE]at io.lettuce.core.cluster.ClusterCommand.complete(ClusterCommand.java:65) ~[lettuce-core-6.1.3.RELEASE.jar:6.1.3.RELEASE]at io.lettuce.core.protocol.CommandHandler.complete(CommandHandler.java:746) ~[lettuce-core-6.1.3.RELEASE.jar:6.1.3.RELEASE]at io.lettuce.core.protocol.CommandHandler.decode(CommandHandler.java:681) ~[lettuce-core-6.1.3.RELEASE.jar:6.1.3.RELEASE]at io.lettuce.core.protocol.CommandHandler.channelRead(CommandHandler.java:598) ~[lettuce-core-6.1.3.RELEASE.jar:6.1.3.RELEASE]at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]at java.lang.Thread.run(Thread.java:745) [na:1.8.0_45]

源码分析

PooledClusterConnectionProvider

根据操作类型获取不同的 connection

@Override
public CompletableFuture<StatefulRedisConnection<K, V>> getConnectionAsync(Intent intent, int slot) {if (debugEnabled) {logger.debug("getConnection(" + intent + ", " + slot + ")");}if (intent == Intent.READ && readFrom != null && readFrom != ReadFrom.UPSTREAM) {return getReadConnection(slot);}return getWriteConnection(slot).toCompletableFuture();
}

以set操作为例,会发现根据slot获取节点的时候,一直从 partitions 获取,而 partitions 初始化后,如果集群扩容之类的操作会更新 partitions ,其他是不变的

private CompletableFuture<StatefulRedisConnection<K, V>> getWriteConnection(int slot) {CompletableFuture<StatefulRedisConnection<K, V>> writer;// avoid races when reconfiguring partitions.synchronized (stateLock) {writer = writers[slot];}if (writer == null) {RedisClusterNode partition = partitions.getPartitionBySlot(slot);if (partition == null) {clusterEventListener.onUncoveredSlot(slot);return Futures.failed(new PartitionSelectorException("Cannot determine a partition for slot " + slot + ".",partitions.clone()));}// Use always host and port for slot-oriented operations. We don't want to get reconnected on a different// host because the nodeId can be handled by a different host.RedisURI uri = partition.getUri();ConnectionKey key = new ConnectionKey(Intent.WRITE, uri.getHost(), uri.getPort());ConnectionFuture<StatefulRedisConnection<K, V>> future = getConnectionAsync(key);return future.thenApply(connection -> {synchronized (stateLock) {if (writers[slot] == null) {writers[slot] = CompletableFuture.completedFuture(connection);}}return connection;}).toCompletableFuture();}return writer;
}

再看下初始化连接的方法,连接初始化之后内部的实例对象不会再更新了

/*** Create a clustered pub/sub connection with command distributor.** @param codec Use this codec to encode/decode keys and values, must not be {@code null}* @param <K> Key type* @param <V> Value type* @return a new connection*/
private <K, V> CompletableFuture<StatefulRedisClusterConnection<K, V>> connectClusterAsync(RedisCodec<K, V> codec) {if (partitions == null) {return Futures.failed(new IllegalStateException("Partitions not initialized. Initialize via RedisClusterClient.getPartitions()."));}topologyRefreshScheduler.activateTopologyRefreshIfNeeded();logger.debug("connectCluster(" + initialUris + ")");DefaultEndpoint endpoint = new DefaultEndpoint(getClusterClientOptions(), getResources());RedisChannelWriter writer = endpoint;if (CommandExpiryWriter.isSupported(getClusterClientOptions())) {writer = new CommandExpiryWriter(writer, getClusterClientOptions(), getResources());}if (CommandListenerWriter.isSupported(getCommandListeners())) {writer = new CommandListenerWriter(writer, getCommandListeners());}ClusterDistributionChannelWriter clusterWriter = new ClusterDistributionChannelWriter(getClusterClientOptions(), writer,topologyRefreshScheduler);PooledClusterConnectionProvider<K, V> pooledClusterConnectionProvider = new PooledClusterConnectionProvider<>(this,clusterWriter, codec, topologyRefreshScheduler);clusterWriter.setClusterConnectionProvider(pooledClusterConnectionProvider);StatefulRedisClusterConnectionImpl<K, V> connection = newStatefulRedisClusterConnection(clusterWriter,pooledClusterConnectionProvider, codec, getDefaultTimeout());connection.setReadFrom(ReadFrom.UPSTREAM);connection.setPartitions(partitions);Supplier<CommandHandler> commandHandlerSupplier = () -> new CommandHandler(getClusterClientOptions(), getResources(),endpoint);Mono<SocketAddress> socketAddressSupplier = getSocketAddressSupplier(connection::getPartitions,TopologyComparators::sortByClientCount);Mono<StatefulRedisClusterConnectionImpl<K, V>> connectionMono = Mono.defer(() -> connect(socketAddressSupplier, endpoint, connection, commandHandlerSupplier));for (int i = 1; i < getConnectionAttempts(); i++) {connectionMono = connectionMono.onErrorResume(t -> connect(socketAddressSupplier, endpoint, connection, commandHandlerSupplier));}return connectionMono.doOnNext(c -> connection.registerCloseables(closeableResources, clusterWriter, pooledClusterConnectionProvider)).map(it -> (StatefulRedisClusterConnection<K, V>) it).toFuture();
}

在这里插入图片描述

解决方案

别闹了,年初就有人提过。

https://github.com/lettuce-io/lettuce-core/issues/1572

想更新dns,需要重建 channel。作者也说了,没什么好办法,除非用反射,但是反射也不是很好。

刚开始出现这个问题,我还以为是 netty的问题,劲劲的给提issue了,不知道是是我表达不清楚,还是什么其他原因,他们还真给源码改了…(其实是lettuce的问题)

https://github.com/netty/netty/issues/11519

所以用域名,即便是dns切换了,也得重启服务才能生效。

对了,不止 lettuce,jedis 也是一样的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/412537.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

zuul 1.x 和gateway性能对比

大家好&#xff0c;我是烤鸭&#xff1a; 今天分享下 zuul和gateway 网关压测。 环境&#xff1a; windows 10 jdk 8 压测工具&#xff1a; wrk jmeter 数据对比 场景是仅单独转发&#xff0c;接口 Thread.sleep(50) jmeter 12 线程&#xff0c;30s zuul&#xf…

redisson 大量ping操作,导致 tps过高

大家好&#xff0c;我是烤鸭&#xff1a; 这个问题有点奇怪&#xff0c;新服务上线&#xff0c;redis tps居高不下&#xff0c;还都是ping命令。 环境&#xff1a; 服务 &#xff1a; 280台&#xff0c;redis集群&#xff1a;12主24从 问题 由于服务刚上线&#xff0c;还没…

PMP 学习总结

大家好&#xff0c;我是烤鸭&#xff1a; PMP终于考过了。成绩出了一个月了&#xff0c;一直想写一篇总结但没下笔&#xff0c;主要原因最近有点忙(太懒了)。考试的内容是基于第6版的。 晒个证书 证书上没写等级&#xff0c;一般都宣称5A过(其实我是 4A1T过的)。 学习过程…

处理器映射器(HandlerMapping)及处理器适配器(HandlerAdapter)详解(一)

非注解 处理器映射器 和 处理器适配器 处理器映射器&#xff1a; 第一种: BeanNameUrlHandlerMapping <!-- 配置Handler --> <bean id"userController1" name"/queryUsers.action" class"com.bjxb.ssm.controller.UserController" />…

Gateway Sentinel 做网关降级/流控,转发header和cookie

大家好&#xff0c;我是烤鸭&#xff1a; Springcloud Gateway 使用 Sentinel 流量控制。 环境 springcloud-gateway的网关应用&#xff0c;springboot的服务&#xff0c;nacos作为注册中心 sentinel-dashboard-1.8.2 最新版下载地址&#xff1a; https://github.com/aliba…

django后台数据管理admin设置代码

新建admin用户 createsuperuser 设定好用户名&#xff0c;邮箱&#xff0c;密码 设置setting LANGUAGE_CODE zh-hansTIME_ZONE Asia/ShanghaiUSE_I18N TrueUSE_L10N TrueUSE_TZ False 在写好的users的app下修改admin.py # -*- coding: utf-8 -*- from __future__ import u…

rocketmq 初探(一)

大家好&#xff0c;我是烤鸭&#xff1a; 今天看下rocketmq。这篇主要是简单介绍下 rocketmq以及idea 本地调试 rocketmq。 项目架构 感兴趣的可以下载源码看下。 https://github.com/apache/rocketmq 项目结构图。 rocketmq-acl: acl 秘钥方式的鉴权&#xff0c;用在bro…

客户将数据库迁移上云的常用办法

下载网站:www.SyncNavigator.CN 客服QQ1793040---------------------------------------------------------- 关于HKROnline SyncNavigator 注册机价格的问题 HKROnline SyncNavigator 8.4.1 非破解版 注册机 授权激活教程 最近一直在研究数据库同步的问题&#xff0c;在网上…

基于nchan打造百万用户的聊天室

大家好&#xff0c;我是烤鸭&#xff1a; 这次介绍下nchan&#xff0c;nginx的一个module。 nchan 源码: https://github.com/slact/nchan 官网: https://nchan.io/ nginx 配置说明文档: https://nchan.io/documents/nginxconf2016-slides.pdf 测试环境搭建 4 台linux cent…

rocketmq 初探(二)

大家好&#xff0c;我是烤鸭&#xff1a; 上一篇简单介绍和rocketmq&#xff0c;这一篇看下源码之注册中心。 namesrv 先看两个初始化方法 NamesrvController.initialize() 和 NettyRemotingServer.start(); public boolean initialize() {// 加载配置文件this.kvConfigMana…

2 JVM 运行机制

转载于:https://www.cnblogs.com/likevin/p/10186591.html

WIN10远程连接时提示内部错误

微软官方的解决方案是重置远程连接设置&#xff0c;步骤如下&#xff1a; 1、以管理员身份运行命令提示符 2、输入以下命令&#xff1a; netsh winsoc reset 随后会提示重启电脑&#xff0c;遂解决。 3、重启后还不行的话&#xff0c;再试试删除掉远程连接保存的凭据&#xff0…

rocketmq 初探(四)

大家好&#xff0c;我是烤鸭&#xff1a; 上一篇简单介绍broker的初始化&#xff0c;这一篇介绍 NettyRequestProcessor 的实现(主要是broker里用到的)。 AdminBrokerProcessor、ClientManageProcessor、ConsumerManageProcessor、EndTransactionProcessor NettyRequestProce…

《自律100天,穿越人生盲点》读书笔记

大家好&#xff0c;我是烤鸭&#xff1a; 《自律100天&#xff0c;穿越人生盲点》&#xff0c;读书笔记。 第一章 “自律100天”的华丽开启 第一节 “自律100天”的底层逻辑 习惯没办法用金钱换&#xff0c;只能用时间。 训练延迟满足(增强自控、培养耐心、减少短期诱惑…

2021 年终总结

2021 年终总结 大家好&#xff0c;我是烤鸭&#xff0c;这是一篇无关技术的记录&#xff0c;总结一下这一年干了什么。 年初的目标 减肥 炒股回本 PMP拿证 多赚钱 多学习新技术 坚持写博客(一周一篇) 多看书 没达成的目标 减肥这个事&#xff0c;拖了好久&#xff0c…

记一次线上cpu飙升100%的排查过程

大家好&#xff0c;我是烤鸭&#xff1a; 最近没怎么写技术文章&#xff0c;还是得回归下初心&#xff0c;正好前几天出现个线上问题&#xff0c;记录下排查过程。 问题描述 某个时间点&#xff0c;接收到接口响应慢报警。 过一会收到服务器cpu可用率低(<10%)报警。 去c…

Node.js(爱前端) 一

一 Node.js 简介 1.1 官网 https://nodejs.org/en/ 官网介绍&#xff1a; Node.js是一个构建在 Chrome 浏览器V8引擎上的 JavaScript 运行环境。 Node.js 使用了事件驱动、非阻塞I/O模型&#xff0c;这些都使它轻量、好用。 Node.js 的包生态&#xff08;npm&#xff09;&#…

记一次线上服务假死排查过程

大家好&#xff0c;我是烤鸭&#xff1a; 最近线上问题有点多啊&#xff0c;分享一个服务假死的排查过程。 问题描述 9点10分&#xff0c;收到进程无响应报警(一共6台机器&#xff0c;有1台出现)&#xff0c;后来又有1台出现。 排查思路 首先确认是否误报或者网络抖动&…

vue小记

1.vue绑定属性&#xff0c;点击事件 1.<!-- 完整语法 --> <a v-bind:href"url">...</a><!-- 缩写 --> <a :href"url">...</a>2.<!-- 完整语法 --> <a v-on:click"doSomething">...</a>&l…

nacos注册中心自动上下负载

大家好&#xff0c;我是烤鸭&#xff1a; 还有2天就过年了&#xff0c;祝大家新年快乐。最近好久没写技术文章了&#xff0c;还是得回归下主业&#xff0c;今天分享下nacos注册中心自动上下负载的方式和组件。 组件版本 <properties><java.version>1.8</java.v…