IM系统开发、部署等过程中 遇到的问题记录

本文是对个人系统:xzll-im 的一篇记录文章,记录我搭建(搭建估计不会记录了现在已经过了这一阶段)、开发、部署im系统以及周边中间件过程中遇到的问题以及解决方式。遇到的问题太多了,时间充足就尽可能记录上,不充足或者问题比较小就在代码中注释记录一下。这文章只给我自己看。以便多年后 回首曾经走过的路😂。仅此而已😄。

  • 此文将不断更新(只要是此系统相关并且我有时间并且我个人觉得有必要)。
  • 由于之前的一些问题都在代码注释中记录了这里就不补充了。以后遇到的较大的、较费时的问题,尽量在这里记录 以便以后统一管理查看以及实现:不被同一块石头绊倒两次。
  • 本文始于:2024-06-25

1、RocketMq发消息报错:the broker's disk is full [CL: 0.95 CQ: 0.95 INDEX: 0.95] 解决

最近将im依赖的各个组件都迁移到了虚拟机的docker上去了,但是发MQ消息时却报错:

``` org.apache.rocketmq.client.exception.MQBrokerException: CODE: 14 DESC: service not available now. It may be caused by one of the following reasons: the broker's disk is full [CL: 0.95 CQ: 0.95 INDEX: 0.95], messages are put to the slave, message store has been shut down, etc. For more information, please visit the url, http://rocketmq.apache.org/docs/faq/ at org.apache.rocketmq.client.impl.MQClientAPIImpl.processSendResponse(MQClientAPIImpl.java:556) ~[rocketmq-client-4.5.0.jar:4.5.0] at org.apache.rocketmq.client.impl.MQClientAPIImpl.sendMessageSync(MQClientAPIImpl.java:358) ~[rocketmq-client-4.5.0.jar:4.5.0] at org.apache.rocketmq.client.impl.MQClientAPIImpl.sendMessage(MQClientAPIImpl.java:340) ~[rocketmq-client-4.5.0.jar:4.5.0] at org.apache.rocketmq.client.impl.MQClientAPIImpl.sendMessage(MQClientAPIImpl.java:294) ~[rocketmq-client-4.5.0.jar:4.5.0] at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.sendKernelImpl(DefaultMQProducerImpl.java:808) ~[rocketmq-client-4.5.0.jar:4.5.0] at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.sendSelectImpl(DefaultMQProducerImpl.java:1072) ~[rocketmq-client-4.5.0.jar:4.5.0] at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.send(DefaultMQProducerImpl.java:1044) ~[rocketmq-client-4.5.0.jar:4.5.0] at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.send(DefaultMQProducerImpl.java:1039) ~[rocketmq-client-4.5.0.jar:4.5.0] at org.apache.rocketmq.client.producer.DefaultMQProducer.send(DefaultMQProducer.java:458) ~[rocketmq-client-4.5.0.jar:4.5.0] at com.xzll.connect.cluster.mq.RocketMqProducerWrap.sendClusterEvent(RocketMqProducerWrap.java:80) ~[classes/:?] at com.xzll.connect.cluster.provider.C2CMsgProvider.offLineMsg(C2CMsgProvider.java:64) ~[classes/:?] at com.xzll.connect.strategy.impl.c2c.C2CMsgSendStrategyImpl.exchange(C2CMsgSendStrategyImpl.java:116) ~[classes/:?] at com.xzll.connect.dispatcher.HandlerDispatcher.dispatcher(HandlerDispatcher.java:43) ~[classes/:?] at com.xzll.connect.netty.handler.WebSocketServerHandler.lambda$handleWebSocketFrame$2(WebSocketServerHandler.java:211) ~[classes/:?] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[?:?] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[?:?] at java.lang.Thread.run(Thread.java:829) ~[?:?]

```

说明个前提:

我的rocketMQ是docker启动的,数据会挂载到宿主机中的目录,具体从启动命令可以看出: ```bash

启动 RocketMQ 的 NameServer

docker run -d \ --name rmqnamesrv \ -p 9876:9876 \ -v /usr/local/softhzz/docker/20240624/store:/root/store \ -v /usr/local/softhzz/docker/20240624/logs:/root/logs \ apache/rocketmq:4.8.0 \ sh mqnamesrv

启动 RocketMQ 的 Broker

docker run -d \ --name rmqbroker \ -p 10911:10911 \ -p 10909:10909 \ -v /usr/local/softhzz/docker/20240624/store:/root/store \ -v /usr/local/softhzz/docker/20240624/logs:/root/logs \ -v /usr/local/soft_hzz/docker/20240624/conf/broker.conf:/opt/rocketmq-4.8.0/conf/broker.conf \ apache/rocketmq:4.8.0 \ sh mqbroker -c /opt/rocketmq-4.8.0/conf/broker.conf

```

尝试解决:

github上也有类似问题的讨论:https://github.com/apache/rocketmq/issues/3750 ,其中有人提到权限不够,这确实也是一个可能引发此问题的点,为了打消这个目录读写权限方面的疑点,我接下来将rocketmq挂载的目录权限和容器内的目录的权限都放到最大,以确保docker容器用户可以写入,如下 bash sudo chown -R $(whoami):$(whoami) /你的rocketmq数据存储路径/store sudo chown -R $(whoami):$(whoami) /你的rocketmq日志文件存储路径/logs sudo chmod -R 777 /你的rocketmq数据存储路径/store sudo chmod -R 777 /你的rocketmq日志文件存储路径/logs

之后我们可以看到已经是最大权限了: image.png 赋完权限后,另一个问题就是磁盘不足,情况如下: 可以看到挂载根文件系统的 /dev/mapper/centos-root (是一个逻辑卷管理器(LVM)卷,用于挂载根文件系统(/)。它管理和存储系统的主要数据,包括操作系统、应用程序和配置文件)用了92% ! : image.png

ok那我就老老实实给虚拟机加磁盘吧,再不加的话虚拟机要罢工了。。。 image.png 在 VirtualBox 中添加新磁盘后,需要手动将新磁盘的空间分配给现有的分区(注意这一步必须有!),从而让系统可以使用这些新分配的空间,步骤如下:

  1. 首先看下在VirtualBox界面创建完磁盘后目前的情况 lsblk image.png

可以看到在界面创建完磁盘后,已经成功添加了一个新的 20GB 磁盘 (sdb)。接下来要做的是:将这个新的磁盘空间添加到现有的 LVM 卷组中,并扩展根分区 (/dev/centos/root)

  1. 创建一个新的物理卷bash sudo pvcreate /dev/sdb
  2. 将新的物理卷添加到现有的卷组 sudo vgextend centos /dev/sdb
  3. 扩展逻辑卷 sudo lvextend -l +100%FREE /dev/centos/root 以上 1、2、3 步截图如下: image.png 从提示上来看 逻辑卷已经扩展成功,接下来扩展文件系统。
  4. 扩展文件系统 sudo xfs_growfs / image.png
  5. 验证,观察是否应用到现有分区 df -h image.png

从上可以看到 现在dev/mapper/centos/root 已经变为37GB,使用率为 43% 成功扩容磁盘(后期不够再扩吧)。之后的话我将rocketmq重启。 image.png

测试一下:可以看到,可以发送消息并正常消费了 image.png image.png

2、使用redisTemplate 的execute执行lua脚本后,hash的key或value只要是string类型都被加上了 双引号 的解决记录

最近使用lua 将几个非原子命令搞成原子的,但是却发现 存进redis 的数据不管是key 还是value只要类型是string就会无缘无故多了个 双引号。如下(value没有是因为是int类型 如果是string也会加双引号): image.png 而我获取时 必须得这样获取才能获取到: image.png 而这不是我想要的,我存啥就给我放啥得了呗 别自作主张给我加,于是我一通排查,最开始我以为redisTemplate序列化有问题,但是最后发现其实并不是,如下是我的序列化配置, ```java @Bean("redisTemplate") @Primary public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory, ObjectMapper objectMapper) { RedisTemplate redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory);

//设置key 序列化的方式
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer);

//设置value 序列化的方式
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
serializer.setObjectMapper(objectMapper);

redisTemplate.setValueSerializer(serializer);

//设置 hash key value 序列化的方式
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());

// 禁用默认序列化器
redisTemplate.setEnableDefaultSerializer(false);
redisTemplate.setDefaultSerializer(null);

redisTemplate.afterPropertiesSet();
return redisTemplate;

} ``` 后来发现:redisTemplate的execute方法重载了好几个,其中有这么个重载方法: image.png 从参数就知道可以指定args和反参的序列化类型,嘿那不正好,来试试吧! image.png

启动项目以及客户端,发现redis中的数据不再带有 双引号了,如下所示: image.png 代码中也可以按期望 获取成功了。 image.png

3、宿主机连不上虚拟机中docker部署的服务(如nacos)

在家里,使用docker 桥接网络模式(默认的) 启动nacos 死活连不上,在虚拟机启动了rocketmq和mysql 在宿主机进行 telnet 192.168.1.103 9876 或者 telnet 192.168.1.103 3306 或者相互ping ip ,都没问题,说明宿主机和虚拟机直接网络没问题,那大概率就是docker0 这个网卡问题,在没找到原因之前,只能改成host模式启动docker 容器了,也即:让docker容器 使用虚拟机的端口。不进行虚拟机到docker0网卡的端口转发了。使用host模式的话只需要在启动时指定network即--network host,如下这个就是使用的host模式:

bash sudo docker run -d --name nacos-home-host --network host -e MODE=standalone -p 8848:8848 nacos/nacos-server:2.0.3

后续解决后补充:

我发现问题出在docker0网卡的设置上,即:之前一直宿主机连接不上虚拟机中docker内的服务(比如nacos) 可能是因为虚拟机和docker0的网段冲突,docker0网卡的网段也是192.168.1.xx,虚拟机是192.169.1.103, 我将/etc/docker/daemon.json 文件(就是你配镜像的那个文件)追加 :"bip": "172.17.0.1/24"(这个是docker0网卡默认的ip) 后 执行:

停止所有docker 容器 bash sudo systemctl stop docker 重启后 即自动创建docker0 网卡 bash sudo systemctl restart docker 然后再ifconfig 发现docker0网卡变为172.17.0.1, 之后再重启 docker restart nacos 就可以了,what fuck ! 倒腾很久,哎。。。

贴上启动nacos的命令: bash sudo docker run -d --name nacos -e MODE=standalone -p 8848:8848 nacos/nacos-server:2.0.3

能被这个问题拌住,说明对docker运行机制还不熟 尤其是他的几种网络模式。关于docker的几种模式这篇文章感觉讲的不错很清晰:https://www.cnblogs.com/liugp/p/16328904.html

4、dubbo指定网卡注册问题记录与多种方式解决

最近将本地mac上的服务,搞到了虚拟机中启动,但是在dubbo消费的时候,报了一个错: com.xzll.connect.rpcapi.RpcSendMsg2ClientApi from registry 172.30.128.65:2181 on the consumer 192.168.1.1 using the dubbo version 3.0.6. Please check if the providers have been started and registered

org.apache.dubbo.rpc.RpcException: Failed to invoke the method responseClientAck2Client in the service com.xzll.connect.rpcapi.RpcSendMsg2ClientApi. No provider available for the service com.xzll.connect.rpcapi.RpcSendMsg2ClientApi from registry 172.30.128.65:2181 on the consumer 192.168.1.1 using the dubbo version 3.0.6. Please check if the providers have been started and registered. at org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker.checkInvokers(AbstractClusterInvoker.java:366) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker.doInvoke(FailoverClusterInvoker.java:59) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke(AbstractClusterInvoker.java:340) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.rpc.cluster.router.RouterSnapshotFilter.invoke(RouterSnapshotFilter.java:46) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:99) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter.invoke(FutureFilter.java:51) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.rpc.cluster.filter.support.ConsumerContextFilter.invoke(ConsumerContextFilter.java:108) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CallbackRegistrationInvoker.invoke(FilterChainBuilder.java:193) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster$ClusterFilterInvoker.invoke(AbstractCluster.java:92) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker.invoke(MockClusterInvoker.java:97) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.registry.client.migration.MigrationInvoker.invoke(MigrationInvoker.java:280) ~[dubbo-3.0.6.jar!/:3.0.6] at org.apache.dubbo.rpc.proxy.InvokerInvocationHandler.invoke(InvokerInvocationHandler.java:97) ~[dubbo-3.0.6.jar!/:3.0.6] at com.xzll.connect.rpcapi.RpcSendMsg2ClientApiDubboProxy0.responseClientAck2Client(RpcSendMsg2ClientApiDubboProxy0.java) ~[im-connect-api-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT] at jdk.internal.reflect.GeneratedMethodAccessor143.invoke(Unknown Source) ~[?:?] at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar!/:5.3.20] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-5.3.20.jar!/:5.3.20] at com.sun.proxy.$Proxy111.responseClientAck2Client(Unknown Source) ~[?:?] at com.xzll.business.handler.c2c.C2CClientReceivedAckMsgHandler.clientReceivedAckMsgDeal(C2CClientReceivedAckMsgHandler.java:64) ~[classes!/:0.0.1-SNAPSHOT] at com.xzll.business.handler.c2c.C2CClientReceivedAckMsgHandler$$FastClassBySpringCGLIB$$113371f.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar!/:5.3.20] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar!/:5.3.20] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar!/:5.3.20] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20] at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.20.jar!/:5.3.20] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.20.jar!/:5.3.20] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.20.jar!/:5.3.20] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar!/:5.3.20] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.20.jar!/:5.3.20] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.20.jar!/:5.3.20] at com.xzll.business.handler.c2c.C2CClientReceivedAckMsgHandler$$EnhancerBySpringCGLIB$$a22b9c6b.clientReceivedAckMsgDeal(<generated>) ~[classes!/:0.0.1-SNAPSHOT] at com.xzll.business.cluster.consumer.C2CMsgEventConsumer.handleEvent(C2CMsgEventConsumer.java:81) ~[classes!/:0.0.1-SNAPSHOT] at com.xzll.common.rocketmq.ClusterConsumerEventHandler.orderMessageHandle(ClusterConsumerEventHandler.java:78) ~[im-common-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT] at com.xzll.common.rocketmq.RocketMQOrderConsumerListener.consumeMessage(RocketMQOrderConsumerListener.java:37) ~[im-common-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT] at org.apache.rocketmq.client.impl.consumer.ConsumeMessageOrderlyService$ConsumeRequest.run(ConsumeMessageOrderlyService.java:471) ~[rocketmq-client-4.5.0.jar!/:4.5.0] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) ~[?:?] at java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[?:?] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[?:?] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[?:?] at java.lang.Thread.run(Thread.java:829) ~[?:?] ? 我的虚拟机ip是172.30.128.65呀 怎么注册到dubbo上的是192.168.1.1呢? 奇怪。注册情况如下: image.png

192.168.1.1这个ip正好是我的docker0网卡ip: image.png 而我 不希望 dubbo使用这个网卡的ip来注册到zk,而是希望 主网卡enp0s3 的ip注册到zk上去。怎么办呢?

一通排查搜索发现 这个和dubbo注册时的网卡选择策略有关,dubbo选网卡代码如下: ```java

类是:org.apache.dubbo.common.utils.NetUtils

private static InetAddress getLocalAddress0() { InetAddress localAddress = null;

try {
    NetworkInterface networkInterface = findNetworkInterface();
    Enumeration addresses = networkInterface.getInetAddresses();

    while(addresses.hasMoreElements()) {
        Optional<InetAddress> addressOp = toValidAddress((InetAddress)addresses.nextElement());
        if (addressOp.isPresent()) {
            try {
                if (((InetAddress)addressOp.get()).isReachable(100)) {
                    return (InetAddress)addressOp.get();
                }
            } catch (IOException var6) {
            }
        }
    }
} catch (Throwable var7) {
    logger.warn(var7);
}

try {
    localAddress = InetAddress.getLocalHost();
    Optional<InetAddress> addressOp = toValidAddress(localAddress);
    if (addressOp.isPresent()) {
        return (InetAddress)addressOp.get();
    }
} catch (Throwable var5) {
    logger.warn(var5);
}

return localAddress;

}

public static NetworkInterface findNetworkInterface() { List validNetworkInterfaces = Collections.emptyList();

try {
    //获取所有有效的网卡
    validNetworkInterfaces = getValidNetworkInterfaces();
} catch (Throwable var8) {
    logger.warn(var8);
}

NetworkInterface result = null;
Iterator var2 = validNetworkInterfaces.iterator();

NetworkInterface networkInterface;
while(var2.hasNext()) {
    networkInterface = (NetworkInterface)var2.next();
    //这一步会将 优先选择 配置了优先的网卡!
    if (isPreferredNetworkInterface(networkInterface)) {
        result = networkInterface;
        break;
    }
}

if (result == null) {
    var2 = validNetworkInterfaces.iterator();

    while(var2.hasNext()) {
        networkInterface = (NetworkInterface)var2.next();
        Enumeration addresses = networkInterface.getInetAddresses();

        while(addresses.hasMoreElements()) {
            Optional<InetAddress> addressOp = toValidAddress((InetAddress)addresses.nextElement());
            if (addressOp.isPresent()) {
                try {
                    if (((InetAddress)addressOp.get()).isReachable(100)) {
                        return networkInterface;
                    }
                } catch (IOException var7) {
                }
            }
        }
    }
}

if (result == null) {
    result = (NetworkInterface)CollectionUtils.first(validNetworkInterfaces);
}

return result;

}

private static List getValidNetworkInterfaces() throws SocketException { List validNetworkInterfaces = new LinkedList(); Enumeration interfaces = NetworkInterface.getNetworkInterfaces();

while(interfaces.hasMoreElements()) {
    NetworkInterface networkInterface = (NetworkInterface)interfaces.nextElement();
    //这一步会将 忽略的网卡 过滤掉!
    if (!ignoreNetworkInterface(networkInterface)) {
        validNetworkInterfaces.add(networkInterface);
    }
}

return validNetworkInterfaces;

} ``` 以上代码归纳总结一下大概就是这么几件事:

  1. 查找所有合适的网卡
  2. 如果没找到网卡,则设置ip为 127.0.0.1
  3. 找到了则校验网卡对应的ip是否有效(会在这一步 过滤掉dubbo.network.interface.ignored配置的网卡)
  4. 在查找的网卡里遍历一遍,看是否有优先设置的(对应 dubbo.network.interface.preferred配置)
  5. 如果没有配置优先的网卡,选择一个网速小于100毫秒响应的网卡
  6. 如果还没有,则返回第一个网卡
  7. 最终将胜出的网卡 对应的ip注册到zk中去

而我现在是没有配置优先或者忽略的。想必dubbo这个工具类的逻辑大概如这样: 找到的网卡列表中 docker0是第一个元素 并且他也在100毫秒响应了,所以选择了这个docker0网卡对应的192.168.1.1 这个ip作为注册到zk上的ip

而我想设置enp0s3这个网卡的ip为注册ip (不卖关子直接给出答案) ,很简单在启动时设置系统参数,也就是说告诉dubbo你要优先哪个 过滤哪个。先看下dubbo中获取配置的代码: //获取忽略的网卡 String ignoredInterfaces = System.getProperty("dubbo.network.interface.ignored"); //获取优先的网卡 String ignoredInterfaces = System.getProperty("dubbo.network.interface.preferred"); 知道了dubbo怎么读的了,那么我们就在启动的时候指定,不就完事了? 所以接下来,直接在启动项目时 指定系统参数:由原来的

bash java -jar im-connect-service.jar --server.port=8087 java -jar im-business-service.jar --server.port=8097 改为: bash java -Ddubbo.network.interface.preferred=enp0s3 -Ddubbo.network.interface.ignored=docker0 -jar im-connect-service.jar --server.port=8087 java -Ddubbo.network.interface.preferred=enp0s3 -Ddubbo.network.interface.ignored=docker0 -jar im-business-service.jar --server.port=8097 ok 大功告成,实测是可行的。如下,成功将enp0s3的网卡的ip注册到zk: image.png

ok到此就可以了,但是如果你就是不想在启动时加这个参数,而是想要将其配到application.yaml配置中心的文件中去,那么该如何做呢?

步骤简述:

  • 首先在application.yaml中配置: image.png
  • 然后编写代码(我选择实现ApplicationContextInitializerinitialize方法 这个方法的执行时机 是spring容器还没被初始化之前 具体可以看我之前的一篇关于spring扩展点的文章,) image.png
    • (注意 一定要在dubbo读取之前,从application.ymal读取配置并设置进去系统环境中,否则不生效,说白了就是让):image.png这一步尽量提前。保证其在dubbo读取的前边执行。
    • 之后我们让image.png生效
  • 之后打包上传到虚拟机并启动: image.png
  • 然后看下zk里: image.png
  • 看下调用情况 image.png

ok到此问题就解决了。当然 还有多种方式指定dubbo选址的方式 比如:

  1. 可以配置 /etc/hosts 文件,将 hostname 对应的 IP 显式配置进去。
  2. 可以使用启动参数去显式指定注册的 IP: -DDUBBO_IP_TO_REGISTRY=1.2.3.4 也可以指定 Dubbo 服务绑定在哪块网卡上: -DDUBBO_IP_TO_BIND=1.2.3.4 或者指定dubbo的注册ip: image.png

推荐看一看,一篇dubbo官网上质量很高的文章:研究-dubbo-网卡地址注册时的一点思考

  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值