docker 正在更新Prometheus指标Http服务器:[48]地址已在使用错误

siotufzp  于 2022-11-03  发布在  Docker
关注(0)|答案(1)|浏览(121)

我正在处理一个Dockerized项目,并使用Prometheus_client package for python来监控系统状态。我有一个名为www.example.com的模块train.py,它在每次向容器发送请求时运行。在这个文件中,我使用下面的logger来收集模型的度量并公开它们

class PrometheusLogger(BaseLogger):
def __init__(self):
    self.registry = pc.CollectorRegistry() #pc is for prometheus_client
    self.training_state = pc.Enum('training_state','returns state of training',
                                states=['not started','running','done'], registry=self.registry)
    self.coverage =  pc.Gauge('dataset_coverage','shows the coverage of the datasets',
                            labelnames=['dataset'], registry=self.registry)
    self.diversity = pc.Gauge('model_diversity','shows the diversity parameter', registry=self.registry)
    self.personalization = pc.Gauge('model_personalization','shows the personalization parameter', registry=self.registry)
    self.scores = pc.Gauge('model_scores','shows the scores of the model',
                            labelnames=['name'], registry=self.registry)

def log_metrics(self, metrics):

    self.coverage.labels(dataset='catalog').set(float(metrics['catalog_coverage']))
    self.coverage.labels(dataset='user').set(float(metrics['user_coverage']))
    self.diversity.set(float(metrics['diversity']))
    self.personalization.set(float(metrics['personalization']))
    self.scores.labels(name='rmse').set(float(metrics['test_RMSE']))
    self.scores.labels(name='recall').set(float(metrics['test_recall']))
    self.scores.labels(name='f1').set(float(metrics['test_f1']))
    self.scores.labels(name='ndcg').set(float(metrics['test_nDCG_score']))
    self.scores.labels(name='precision').set(float(metrics['test_precision_k']))

def expose_metrics(self):
    pc.start_http_server(8003, registry=self.registry)

并且训练功能如下工作:

def train(model, logger=PrometheusLogger):
model.fit()
metrics = model.get_metrics()
logger.log_metrics(metrics)
logger.expose_metrics()

请注意,指标在Docker网络内的端口8003中公开。另一个容器到达此端口,并对本地主机生成API。

这段代码第一次运行得很好,但是当我第二次调用train函数时,我得到错误[48]:地址已被使用
我已经尝试了很多方法,比如get_pid()和用os.kill杀死它,但是它们都不起作用。我该怎么办?

8dtrkrch

8dtrkrch1#

发生这个问题的原因是start_http_server()命令没有在指定的端口上自动更新,这实际上是prometheus-client包的问题。我发现了一些东西,它不是一个真正的解决方案,但它适用于这种情况。
如果您不需要真实的应答,则可以使用此函数替换start_http_server来应答有限数量的请求,如果需要,则可以使用While True

import prometheus_client as pc
from wsgiref.simple_server import make_server

registry = pc.CollectorRegistry()

def expose_metrics(self):
    app = pc.make_wsgi_app(registry=registry)
    httpd = make_server('', 8003, app)
    for _ in range(5): #or While True
        httpd.handle_request()

相关问题