3

我有 main() 函数,它产生两个单独的子进程。这两个子流程共享指标。如何共享两个流程的指标并保持更新?这是我的片段,以供更多理解。

from multiprocessing import Process
import prometheus_client as prom
from prometheus_client import Counter

# Metrics
c1 = prom.gauge('Counter1', 'Number of Request')
c2 = prom.gauge('Gauge1', 'Processing time in Seconds')

def process_abc():
  while True:
    #Some operations
    c1.set(some_value)
    c2.set(some_value)
    time.sleep(10)

def process_xyz():
   while True:
     #Some operations
     c1.set(some_value)
     c2.set(some_value)
     time.sleep(10)

def main():
  prom.start_http_server(8080)

  Process(target=process_abc).start()
  Process(target=process_xyz).start()

if __name__ == "__main__":
  main()

我能够在端点看到指标名称,但计数始终为零意味着它永远不会被子流程更新。

4

1 回答 1

1

文档prometheus_client解决了这种情况:

Prometheus 客户端库假定一个线程模型,其中指标在工作人员之间共享。这对于像 Python 这样的语言来说效果并不好,在这些语言中,通常有进程而不是线程来处理大型工作负载。

我不会在这里复制解释(针对 gunicorn)用例,但基本上,您需要:

  • 定义一个带有目录的环境变量来使用:因为你是Process自己使用的,你可以在代码中设置它
os.environ["PROMETHEUS_MULTIPROC_DIR"] = "/path/to/writeable/tmp/"
  • 每个进程都必须有自己的收集器,在启动时注册并在退出时取消注册:
from prometheus_client import multiprocess

def called_from_process():
    registry = CollectorRegistry()
    multiprocess.MultiProcessCollector(CollectorRegistry())

def process_exit(process):
    if process.pid is not None:
        multiprocess.mark_process_dead(process.pid)

p = Process(target=f)
# f calls called_from_process
p.start()
p.join()
process_exit(process)

请参阅有关如何处理仪表和任何其他怪癖的完整文档。

我希望PROMETHEUS_MULTIPROC_DIR应该在您的应用程序启动时清理它以处理应用程序先前运行无法这样做的奇怪情况。

于 2021-10-15T07:45:17.963 回答