每个线程或每个调用一个 ZeroMQ 套接字?

2023-12-07

众所周知,ZeroMQ套接字不得共享应用程序线程之间.
context_t但实例可以。

我有一个多线程应用程序,我想让每个线程不时与一个线程交换消息REQ/REP-socket 对方(事件、异常等),取决于他们正在做什么(他们正在做非 ZeroMQ 的事情)。

发送消息给我的REQ/REP-socket 我使用以下功能
(半C++半伪代码):

sendMessage:

bool sendMessage(std::string s)
{
    zmq::socket_t socket(globalContext(), ZMQ_REQ);
    socket.connect("ipc://http-concentrator");

    zmq::message_t message(s.size());
    memcpy(message.data(), s.data(), s.size());
    if (!socket.send(message))
        return false;

    // poll on socket for POLLIN with timeout

    socket.recv(&message);
    // do something with message

    return true;
}

当需要时,每个线程都会调用此函数。它创建本地套接字、连接、发送消息并接收响应。在退出时,套接字被断开连接并被删除(至少我假设它已关闭)。

这样,我就不需要费心在每个线程中维护一个套接字。这是以每次调用此函数时创建和连接为代价的。

我已经强调了这段代码,并且我没有看到重用一个套接字和此重新连接实现之间有多大区别。 (我有20kREP/REQ每秒事务数,包括用例两侧的 JSON 解码/编码)

Q:有更正确的 ZeroMQ 方法吗?


Nota Bene: this answer was posted before O/P was changed from 20k TPS to 140k TPS on ipc:// transport-class

Q: 有没有more正确的 ZeroMQ 做法this?

A:Not easy to say what is "this" and what are the parameters of the "correctness"-metric

鉴于,
以下几点将更加普遍
并适用于系统设计阶段推理:


避免资源利用开销

这一点是一把双刃剑。一些管理费用始终与基础设施元素的设置和处置(是的,甚至是关闭和拆除)相关。REQ- 访问点REQ/REP-pattern 和相关的基于套接字的传输类给两者带来了一些显着的开销REQ端主机以及REP-side.

您注意到,您在大约 20k TPS 的水平上对此进行了一些定量测试,并且没有观察到这种方法的任何不利影响,这是公平的。尚不清楚的是,是否还在同一 SUT(被测系统)上对任何其他场景进行了体内测试,以便为每个设计的比较提供一些基线(并允许确定开销的差异)本身)。

虽然设计良好的框架向用户维护的代码隐藏了这部分系统内部行为,但这并不意味着,这一切都是廉价的,更不是免费的处理。

很明显,在幕后有一些工作在进行Context()-实例线程(...是的,这里使用复数是正确的,因为某些高性能代码可能会受益于每个线程使用多个 I/O 线程Context()实例并通过模式套接字与其各自的 I/O 线程处理程序之间显式定义的关联映射来积极影响工作负载分配(以便以某种方式平衡(如果无法确定性地调整)预期的 I/O 吞吐量,包括.所有相关的管理费用)。

如果仍然有疑问,人们应该永远记住,命令式编程风格的函数或面向对象的方法主要是外部调用者的受害者,外部调用者决定在哪一刻以及多久这样一次“被奴役的“代码执行单元被值班调用并被执行。该函数/方法没有任何自然手段来回溯(抑制)来自外部调用者的调用频率,并且健壮的设计根本无法保持仅依赖乐观的假设,即此类调用不会比 XYZ-k TPS 更频繁(上面引用的 20k 对于体外测试可能没问题,但实际部署可能会改变几个数量级的操作(无论是人为的 - 在测试期间)或不 - 在某些高峰时段或用户(系统)恐慌期间或由于某些技术错误或硬件故障(我们都多次听说过 NIC 卡淹没 L1/L2 流量超出所有可想象的限制等) - 我们只是不知道也不可能知道下次它会在何时何地再次发生)。

避免阻塞风险

其中提到的REQ/REP可扩展的正式通信模式因其陷入外部无法解决的分布式内部死锁的风险而闻名。这始终是需要避免的风险。缓解策略可能取决于实际用例的风险价值(需要认证医疗仪器、金融科技用例、控制循环用例、学术研究论文代码或私人爱好玩具)。

Ref.: REQ/REP死锁>>>https://stackoverflow.com/a/38163015/3666197

Fig.1:为什么使用 naive 是错误的REQ/REP
所有情况当[App1]in_WaitToRecvSTATE_W2R + [App2]in_WaitToRecvSTATE_W2R
主要是不可挽救的分布式相互死锁REQ-FSA/REP-FSA(两个有限状态自动机都等待“另一个”移动)并且永远不会到达“下一个”in_WaitToSendSTATE_W2S内部状态。

               XTRN_RISK_OF_FSA_DEADLOCKED ~ {  NETWORK_LoS
                                         :   || NETWORK_LoM
                                         :   || SIG_KILL( App2 )
                                         :   || ...
                                         :      }
                                         :
[App1]      ![ZeroMQ]                    :    [ZeroMQ]              ![App2] 
code-control! code-control               :    [code-control         ! code-control
+===========!=======================+    :    +=====================!===========+
|           ! ZMQ                   |    :    |              ZMQ    !           |
|           ! REQ-FSA               |    :    |              REP-FSA!           |
|           !+------+BUF> .connect()|    v    |.bind()  +BUF>------+!           |
|           !|W2S   |___|>tcp:>---------[*]-----(tcp:)--|___|W2R   |!           |
|     .send()>-o--->|___|           |         |         |___|-o---->.recv()     |
| ___/      !| ^  | |___|           |         |         |___| ^  | |!      \___ |
| REQ       !| |  v |___|           |         |         |___| |  v |!       REP |
| \___.recv()<----o-|___|           |         |         |___|<---o-<.send()___/ |
|           !|   W2R|___|           |         |         |___|   W2S|!           |
|           !+------<BUF+           |         |         <BUF+------+!           |
|           !                       |         |                     !           |
|           ! ZMQ                   |         |   ZMQ               !           |
|           ! REQ-FSA               |         |   REP-FSA           !           |
~~~~~~~~~~~~~ DEADLOCKED in W2R ~~~~~~~~ * ~~~~~~ DEADLOCKED in W2R ~~~~~~~~~~~~~
|           ! /\/\/\/\/\/\/\/\/\/\/\|         |/\/\/\/\/\/\/\/\/\/\/!           |
|           ! \/\/\/\/\/\/\/\/\/\/\/|         |\/\/\/\/\/\/\/\/\/\/\!           |
+===========!=======================+         +=====================!===========+

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

每个线程或每个调用一个 ZeroMQ 套接字? 的相关文章

  • 为什么 C# Array.BinarySearch 这么快?

    我已经实施了一个很简单用于在整数数组中查找整数的 C 中的 binarySearch 实现 二分查找 static int binarySearch int arr int i int low 0 high arr Length 1 mid
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • 按成员序列化

    我已经实现了template
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • asp.net core / kestrel中的线程管理

    我正在解决我们已迁移到 asp net core 2 0 的 asp net 应用程序的性能 可扩展性问题 我们的应用程序作为应用程序服务托管在 azure 上 并且在任何中等流量的情况下都很容易崩溃 让我困惑的一件事是如何处理多个并发请求
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • 无锁算法真的比全锁算法性能更好吗?

    陈雷蒙德 http blogs msdn com b oldnewthing 一直在做一个huge http blogs msdn com b oldnewthing archive 2011 04 15 10154245 aspx ser
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • Java列表的线程安全

    我有一个列表 它将在线程安全上下文或非线程安全上下文中使用 究竟会是哪一个 无法提前确定 在这种特殊情况下 每当列表进入非线程安全上下文时 我都会使用它来包装它 Collections synchronizedList 但如果不进入非线程安
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐