Linux 如何自动更新Docker实例之间共享的计数器 我有一个简单的C++服务(API端点),每次调用API时都会增加计数器。当调用者向计数器发送数据时,计数器必须递增1,并将计数器的值返回给调用者

Linux 如何自动更新Docker实例之间共享的计数器 我有一个简单的C++服务(API端点),每次调用API时都会增加计数器。当调用者向计数器发送数据时,计数器必须递增1,并将计数器的值返回给调用者,linux,performance,docker,shared-memory,Linux,Performance,Docker,Shared Memory,当服务被停靠时,事情变得更加复杂。当同一服务的两个实例运行时,必须以原子方式进行添加,即计数器值存储在数据库中,每个docker实例必须获取锁获取旧值,添加一个,返回调用方并解锁 当实例是同一台Linux机器上的进程时,我们使用共享内存来高效地锁定、读取、写入和解锁共享数据,性能得到了认可。然而,当我们使用dockers和数据库时,性能很低。结果正常,但性能较低 停靠属性实例之间执行上述操作的规范方式是什么?容器化进程是否有“共享内存”功能 您的案例数据库似乎需要开销。您只需要一些具有共享密钥锁

当服务被停靠时,事情变得更加复杂。当同一服务的两个实例运行时,必须以原子方式进行添加,即计数器值存储在数据库中,每个docker实例必须获取锁获取旧值,添加一个,返回调用方并解锁

当实例是同一台Linux机器上的进程时,我们使用共享内存来高效地锁定、读取、写入和解锁共享数据,性能得到了认可。然而,当我们使用dockers和数据库时,性能很低。结果正常,但性能较低


停靠属性实例之间执行上述操作的规范方式是什么?容器化进程是否有“共享内存”功能

您的案例数据库似乎需要开销。您只需要一些具有共享密钥锁支持的分布式轻量级密钥值存储。以下是一些候选人:

  • etcd()
  • 领事(尤其是)
  • redis()
启用容器之间的共享内存访问:

IPC设置(--IPC)
--ipc=”“
:设置容器的ipc模式

“容器:”
:重用另一个容器的IPC命名空间

“主机”
:在容器内使用主机的IPC命名空间

默认情况下,所有容器都启用了IPC命名空间

IPC(POSIX/SysV IPC)命名空间提供了命名共享 内存段、信号量和消息队列

共享内存段用于加速进程间通信 以内存速度通信,而不是通过管道或 网络堆栈。共享内存通常由数据库和应用程序使用 定制(通常为C/OpenMPI、C++/使用boost库)高 科学计算和金融的性能应用 服务业。如果将这些类型的应用程序分为 多个容器,您可能需要共享 容器


提供了一些关于其用法的演示。

我遇到了一个类似的问题,决定从头开始

唯一快速发展的是域套接字。所以我创建了一个小型c程序,它在一个域套接字上侦听,在一个共享卷/套接字上侦听

请参阅gitlab.com上的工作概念

counter.c
执行任务,监听sockets/count.sock并 在接收到数据报中的单个字符时:

  • “+”:它将增加计数并将计数作为u_int64_t返回
  • “0”:重置计数并将0值作为u\u int64\t返回
  • “=”:以u_int64_t的形式返回计数,不带增量
  • “-”:使用1递减计数,并将计数作为u_int64_t返回
对于概念测试:

  • 计数器--interval=1000000
    =>启动计数器
  • 测试\u计数器--重复=100000个应力
    =>向插座发送100k请求
  • 测试\计数器重置
    将计数器设置为0
  • test\u计数器——quiet——strip result
    返回不带
    的计数器\n
  • test\u counter[count]
    递增计数器并返回结果
构建了2个docker容器:
count
&
test

为了进行测试,我在gitlab runner中使用了docker-compose.yml:

my-test:
    image: dockregi.gioxa.com/dgoo2308/dockersocket:test
    links:
    - counter
    entrypoint:
    - /test_counter
    - --repeats=${REPEATS}
    - --timeout=200
    - stress
volumes:
- './sockets:/sockets'

counter:
    image: dockregi.gioxa.com/dgoo2308/dockersocket:count
    volumes:
    - './sockets:/sockets'
    entrypoint:
    - /counter
    - --start_delay=100
    - --interval=${TARGET}
要开始测试,请执行以下操作:

mkdir sockets
docker-compose pull --parallel
docker-compose up -d
docker-compose scale my-test=$SCALE
概念测试成功!!!看

空腔:

对于客户端实现,客户端套接字不能绑定为自动,但需要指定一个名称,请参阅测试中的“我们使用主机名”,映射到同一/sockets卷中。
此外,它们对于每个客户端都需要不同。

concur.io取决于进程和KV存储之间的http通信。这将引入延迟,不是吗?通常来说,与共享内存和单个主机相比,是的,但实际上,延迟远低于使用数据库。与@Vyacheslav的想法相关,您可以使用容器来存储数据。建立一个docker网络,将每个容器放在同一个网络上,以便于访问和服务发现。是的,忘了它,但它也相对轻量级。添加到答案中。您是否需要始终准确计算请求数?让每个容器跟踪本地,然后让另一个进程偶尔聚合它们(例如,作为Prometheus或Grafana度量)可能更容易。任何时候都要精确计数,即我不能依赖“本地”数据。让我们假设这个计数器是一个银行帐户的更新,即我不能定期更新钱。你在这里问的可能是一个简化的情况。它在规模上应该如何表现?@ovanes,实际上这就是问题所在。多个进程必须共享一个公共源,并且还应根据源的值进行同步。为了扩展,共享值的最佳/规范方法是什么?然后可以使用x86指令fetch和add来增加计数器。这是否意味着docker映像位于同一主机(同一内核)上?。如果docker容器位于不同的机器上,它是否工作?共享内存仅适用于同一机器上的容器。如果必须同步在不同计算机上运行的容器,则无法避免网络访问。这是否要求docker映像位于同一主机上?域套接字意味着我们在同一个“kermel”是的,它需要在同一个主机上这在正常情况下是不可能的。生产中的容器将位于不同的主机中。