storm Async loop died! & reconnect

探讨了Apache Storm中Supervisor重启导致的Topology错误及spout消费停滞现象。分析了异常堆栈,发现由于客户端关闭不再接收请求引发的问题,并给出了通过检查重复worker端口并删除冗余worker的解决方案。

storm 在有supervisor重启的时候,topology报错,导致所有spout不消费:

 

2015-07-15T09:48:26.470+0800 b.s.util [ERROR] Async loop died!
java.lang.RuntimeException: java.lang.RuntimeException: Client is being closed, and does not take requests any more
        at backtype.storm.utils.DisruptorQueue.consumeBatchToCursor(DisruptorQueue.java:128) ~[storm-core-0.9.3.jar:0.9.3]
        at backtype.storm.utils.DisruptorQueue.consumeBatchWhenAvailable(DisruptorQueue.java:99) ~[storm-core-0.9.3.jar:0.9.3]
        at backtype.storm.disruptor$consume_batch_when_available.invoke(disruptor.clj:80) ~[storm-core-0.9.3.jar:0.9.3]
        at backtype.storm.disruptor$consume_loop_STAR_$fn__1460.invoke(disruptor.clj:94) ~[storm-core-0.9.3.jar:0.9.3]
        at backtype.storm.util$async_loop$fn__464.invoke(util.clj:463) ~[storm-core-0.9.3.jar:0.9.3]
        at clojure.lang.AFn.run(AFn.java:24) [clojure-1.5.1.jar:na]
        at java.lang.Thread.run(Thread.java:745) [na:1.7.0_75]
Caused by: java.lang.RuntimeException: Client is being closed, and does not take requests any more
        at backtype.storm.messaging.netty.Client.send(Client.java:185) ~[storm-core-0.9.3.jar:0.9.3]
        at backtype.storm.utils.TransferDrainer.send(TransferDrainer.java:54) ~[storm-core-0.9.3.jar:0.9.3]
        at backtype.storm.daemon.worker$mk_transfer_tuples_handler$fn__3730$fn__3731.invoke(worker.clj:330) ~[storm-core-0.9.3.jar:0.9.3]
        at backtype.storm.daemon.worker$mk_transfer_tuples_handler$fn__3730.invoke(worker.clj:328) ~[storm-core-0.9.3.jar:0.9.3]
        at backtype.storm.disruptor$clojure_handler$reify__1447.onEvent(disruptor.clj:58) ~[storm-core-0.9.3.jar:0.9.3]
        at backtype.storm.utils.DisruptorQueue.consumeBatchToCursor(DisruptorQueue.java:125) ~[storm-core-0.9.3.jar:0.9.3]
        ... 6 common frames omitted
2015-07-15T09:48:26.507+0800 b.s.util [ERROR] Halting process: ("Async loop died!")
java.lang.RuntimeException: ("Async loop died!")
        at backtype.storm.util$exit_process_BANG_.doInvoke(util.clj:325) [storm-core-0.9.3.jar:0.9.3]
        at clojure.lang.RestFn.invoke(RestFn.java:423) [clojure-1.5.1.jar:na]
        at backtype.storm.disruptor$consume_loop_STAR_$fn__1458.invoke(disruptor.clj:92) [storm-core-0.9.3.jar:0.9.3]
        at backtype.storm.util$async_loop$fn__464.invoke(util.clj:473) [storm-core-0.9.3.jar:0.9.3]
        at clojure.lang.AFn.run(AFn.java:24) [clojure-1.5.1.jar:na]
        at java.lang.Thread.run(Thread.java:745) [na:1.7.0_75]

 在日志上边,大量reconnection

 Reconnect started for Netty-Client-hostxx/ip:6703... [91]
 Reconnect started for Netty-Client-hostxx/ip:6703... [92]
 Reconnect started for Netty-Client-hostxx/ip:6703... [93]
 Reconnect started for Netty-Client-hostxx/ip:6703... [94]
 Reconnect started for Netty-Client-hostxx/ip:6703... [95]
 Reconnect started for Netty-Client-hostxx/ip:6703... [96]
 Reconnect started for Netty-Client-hostxx/ip:6703... [97]
 Reconnect started for Netty-Client-hostxx/ip:6703... [98]
 Reconnect started for Netty-Client-hostxx/ip:6703... [99]

 登录到ip,发现6703端口有两个worker,导致一个work端口被占用(之前supervisor重启work没有关闭,bug,待解决)

解决:删除重复的端口的worker,让topology自动用其他work

 

 

 

<think>我们正在讨论 mosquitto 库中的两个函数:`mosquitto_reconnect` 和 `mosquitto_reconnect_async`。 这两个函数都用于在连接断开后尝试重新连接,但它们在行为上有重要区别。 1. **mosquitto_reconnect**: - 这是一个同步函数,调用后会立即尝试重新连接。 - 在重新连接过程中,调用线程会被阻塞,直到连接成功或失败。 - 适用于需要立即处理重连结果的情况。 2. **mosquitto_reconnect_async**: - 这是一个异步函数,调用后会将重连请求放入队列,然后立即返回。 - 实际的重新连接操作将在后台线程中执行,不会阻塞当前线程。 - 适用于不希望阻塞主线程的场景,例如GUI应用程序或实时系统。 此外,需要注意的是,使用异步重连时,需要通过事件循环(例如调用`mosquitto_loop_start`)来处理网络流量。 下面是一个简单的代码示例来展示两者的使用: ```c // 同步重连 int rc = mosquitto_reconnect(mosq); if (rc != MOSQ_ERR_SUCCESS) { fprintf(stderr, "Reconnect failed: %s\n", mosquitto_strerror(rc)); } // 异步重连 rc = mosquitto_reconnect_async(mosq); if (rc != MOSQ_ERR_SUCCESS) { fprintf(stderr, "Failed to schedule reconnect: %s\n", mosquitto_strerror(rc)); } ``` 注意事项: - 在调用重连函数之前,确保已经设置了正确的连接参数(如服务器地址、端口等),因为重连会使用最初连接时的参数。 - 对于异步重连,需要确保已经启动了网络循环(通过`mosquitto_loop_start`或手动调用`mosquitto_loop`)。 如果连接断开,通常会在连接回调函数中收到通知,然后可以选择调用其中一个重连函数。 因此,选择哪个函数取决于应用程序的需求:是否需要等待重连结果,还是可以继续执行其他任务。 现在,根据要求,我们需要在最后提出3-5个相关问题,以“§§相关问题§§”开头。 </think>### `mosquitto_reconnect` 与 `mosquitto_reconnect_async` 区别解析 在 Eclipse Mosquitto 客户端库中,这两个函数都用于连接断开后的重连操作,但存在关键区别: #### 核心差异对比 | 特性 | `mosquitto_reconnect` | `mosquitto_reconnect_async` | |-----------------------|-----------------------------|----------------------------------| | **执行模式** | 同步阻塞模式 | 异步非阻塞模式 | | **线程行为** | 阻塞调用线程直到重连完成 | 立即返回,后台线程执行重连 | | **适用场景** | 简单命令行工具 | GUI应用/实时系统 | | **网络循环要求** | 需手动触发网络循环 | 依赖已启动的自动网络循环 | | **返回值处理** | 直接返回错误码 | 返回初始状态码,结果通过回调通知 | #### 底层机制说明 **1. 同步重连 (`mosquitto_reconnect`)** ```c // 同步重连示例(可能阻塞主线程) int rc = mosquitto_reconnect(mosq); if(rc != MOSQ_ERR_SUCCESS){ printf("重连失败: %s", mosquitto_strerror(rc)); } // 必须手动触发网络循环才能完成握手 mosquitto_loop(mosq, 1000, 1); ``` **2. 异步重连 (`mosquitto_reconnect_async`)** ```c // 前提:已启动自动网络循环 mosquitto_loop_start(mosq); // 异步重连(立即返回) int rc = mosquitto_reconnect_async(mosq); if(rc == MOSQ_ERR_SUCCESS){ // 通过回调函数获取实际结果 mosquitto_connect_v5_callback_set(mosq, [](...){ if(rc) printf("重连结果: %d", rc); }); } ``` #### 典型应用场景 ```mermaid graph LR A[连接断开] --> B{系统类型} B -->|命令行工具| C[使用mosquitto_reconnect] B -->|GUI/实时系统| D[使用mosquitto_reconnect_async] C --> E[阻塞等待结果] D --> F[后台重连不阻塞UI] ``` #### 注意事项 1. **线程安全** - `reconnect_async` 需确保网络循环在独立线程运行 (`mosquitto_loop_start`) - 同步版本在事件循环线程中调用会导致死锁 2. **错误代码差异** ```c // 异步调用可能返回 MOSQ_ERR_INVAL(未启动网络循环) // 同步调用可能返回 MOSQ_ERR_NO_CONN(TCP层错误) ``` 3. **重连策略** - 两者都继承初始连接的参数(服务器地址/端口/TLS设置) - 修改参数需先调用 `mosquitto_disconnect()` > 💡 **最佳实践**:在需要即时响应的系统中始终使用异步重连,并通过 `on_connect` 回调处理结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值