在工作中,使用uwsgi部署项目,其中uwsgi设置为多进程,并且python中使用了kafka-python模块作为生产者不断产生数据,但上线不久后几乎所有的生产者消息都报:KafkaTimeoutError这个错误,并且在kafka服务器中并没有发现收到任何消息。

于是看了看kafka-python源码,发现在执行send方法后,消息并没有立即发送,而是放到本地的缓存中,在生成KafkaProducer实例时,有个选项buffer_memory设置了缓存的大小,默认为32M,然后如果这个buffer满了就会报KafkaTimeoutError,所以初步判断两个原因:

  1 生产者消息并没有发送出去,

  2 或者消息发送相对于消息生成来说过于缓慢导致

同时又因为看到kafka服务器中并没有接收到任何消息,遂排除第二个原因。也就是说生产者消息没有发送出去。于是采用同样的配置用写了一个脚本发现kafka服务器可以接收到消息,鉴定是我的生产者有问题,遂谷歌解决问题,找到该帖子:https://github.com/dpkp/kafka-python/issues/721。发布人情况和我差不多,作者回复到:

You cannot share producer instances across processes, only threads. I expect that is why the master process pattern is failing.

Second, producer.send() is async but is not guaranteed to deliver if you close the producer abruptly. In your final example I suspect that your producer instances are so short-lived that they are being reaped before flushing all pending messages. To guarantee delivery (or exception) call producer.send().get(timeout) or producer.flush() . otherwise you'll need to figure out how to get a producer instance per-uwsgi-thread and have it shared across requests (you would still want to flush before thread shutdown to guarantee no messages are dropped)

大体上说明了两点:

  1 多进程共享同一个生产者实例有问题

  2 send方法是异步的,当执行完send后立即关闭生产者实例的话可能会导致发送失败。

第二点错误我没有犯,沾沾自喜,继续看评论:

Aha, thanks! After looking more closely at uWSGI options I discovered the lazy-apps option, which causes each worker to load the entire app itself. This seems to have resolved my issue.

提问者说他解决了该问题,于是查一查uwsgi中的lazy-apps,发现改文章:https://uwsgi-docs-zh.readthedocs.io/zh_CN/latest/articles/TheArtOfGracefulReloading.html#preforking-vs-lazy-apps-vs-lazy,其中说到:

默认情况下,uWSGI在第一个进程中加载整个应用,然后在加载完应用之后,会多次 fork() 自己。

我看看了我自己的代码我确实是在app生成之前生成了生产者实例,这就导致该实例被父进程与其子进程共享。问题终于明白,开始解决:

  1 使用lazy-apps,这样就可以了。

  2 不使用lazy-apps,在代码层面解决问题: 

# producer.py文件
import json
from kafka import KafkaProducer class Single(object):
"""单例模式"""
def __new__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
cls._instance = super().__new__(cls)
if hasattr(cls, "initialize"):
cls._instance.initialize(*args, **kwargs)
return cls._instance class MsgQueue(Single):
"""
这个整成单例模式是因为:uwsgi配合kafka-python在多进程下会有问题,这里希望每个进程单独享有一个kafka producer实例,
也就是说当初始化app对象后,并不会生成producer实例,而是在运行时再生成,
具体参考:https://github.com/dpkp/kafka-python/issues/721
"""
app = None def initialize(self):
self.producer = KafkaProducer(bootstrap_servers=self.app.config["MQ_URI"],
api_version=self.app.config["KAFKA_API_VERSION"]) @classmethod
def init_app(cls, app):
cls.app = app def send(self, topic, data):
"""
:param topic:
:param data:
:return:
"""
data = json.dumps(data, ensure_ascii=True)
self.producer.send(topic, data.encode()) # app.py文件
from producer import MsgQueue
...
MsgQueue.init_app(app) # 业务逻辑中用到生产者的文件
from producer import MsgQueue
...
MsgQueue().send(msg)

uwsgi多进程配合kafka-python消息无法发送的更多相关文章

  1. 【Kafka 源码解读】之 【代码没报错但是消息却发送失败!】

    聊聊最近,2020年,在2019年的年尾时,大家可谓对这年充满新希望,特别是有20200202这一天.可是澳洲长达几个月的大火,新型冠状病毒nCoV的发现,科比的去世等等事情,让大家感到相当的无奈,生 ...

  2. RabbitMQ,RocketMQ,Kafka 事务性,消息丢失和消息重复发送的处理策略

    消息队列常见问题处理 分布式事务 什么是分布式事务 常见的分布式事务解决方案 基于 MQ 实现的分布式事务 本地消息表-最终一致性 MQ事务-最终一致性 RocketMQ中如何处理事务 Kafka中如 ...

  3. Kafka消息重新发送

    Kafka消息重新发送   1.  使用kafka消息队列做消息的发布.订阅,如果consumer端消费出问题,导致数据并没有消费,此时不需要担心,数据并不会立刻丢失,kafka会把数据在服务器的磁盘 ...

  4. python 实现微信发送消息

    背景:利用Python来登入你个人的手机微信,之后向朋友发送消息,发送的消息可以来源于网页.下面的例子就是取得当前日元的汇率,之后发送自己的某一个朋友的手机上 环境:Python3,JetBrains ...

  5. 03 . Go开发一个日志平台之Elasticsearch使用及kafka消费消息发送到Elasticsearch

    Elasticsearch使用 详细使用请看我写的Go操作Elasticsearch专篇 https://www.cnblogs.com/you-men/p/13391265.html example ...

  6. 多进程IPC与Python支持

    多进程IPC与Python支持 linux下进程间通信的几种主要手段简介: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因 ...

  7. Python消息队列工具 Python-rq 中文教程

    原创文章,作者:Damon付,如若转载,请注明出处:<Python消息队列工具 Python-rq 中文教程>http://www.tiangr.com/python-xiao-xi-du ...

  8. Apache Kafka 企业级消息队列

    1.大纲 了解 Apache Kafka是什么 掌握Apache Kafka的基本架构 搭建Kafka集群 掌握操作集群的两种方式 了解Apache Kafka高级部分的内容 2.消息系统的作用是什么 ...

  9. kafka生产消息的速度跟什么有关?

    kafka的吞吐量很大,在保证带宽的情况下,网上的一些测试表明3台broker,没有replication,6个partition的情况下,一般的写入速度可以达到300MB/s.参考:kakfa测试 ...

随机推荐

  1. 《Linux内核分析》第七周笔记 可执行程序的装载

    20135132陈雨鑫 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000  ...

  2. linux及安全第五周总结

    给MenuOS增加time和time-asm命令 中间过程已省略了,我们所做的只是将menu更新 具体命令如下 rm menu -rf 强制删除 git clone http://github.com ...

  3. 2017-2018-2 1723《程序设计与数据结构》第八周作业 & 实验二 & 第一周结对编程 总结

    作业地址 第八周作业:https://edu.cnblogs.com/campus/besti/CS-IMIS-1723/homework/1847 (作业界面已评分,可随时查看,如果对自己的评分有意 ...

  4. SE Springer小组之《Spring音乐播放器》需求分析说明书一

    软件需求说明书 软件需求说明书的编制是为了使用户和软件开发者双方对该软件的初始规定有一个共同的理解, 使之成为整个开发工作的基础. 1 引言 1.1编写目的 使用户对该软件的初始规定有一个理解,也使软 ...

  5. 10-Python3从入门到实战—基础之函数

    Python从入门到实战系列--目录 函数的定义 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数的语法 def 函数名(参数列表): 函数体 函数代码块以 def 关键词开头 ...

  6. #Leetcode# 977. Squares of a Sorted Array

    https://leetcode.com/problems/squares-of-a-sorted-array/ Given an array of integers A sorted in non- ...

  7. BMC 安装操作系统以及 驱动的处理

    1. 在一个郊区的机房有两台机器需要重装系统. 2. 服务器配置了BMC 还不错... 能够节约很多时间. 3. BMC的配置不算复杂, 就是management 网口插上网线,然后配置一下可以使用的 ...

  8. vue原理探索--响应式系统

    Vue.js 是一款 MVVM 框架,数据模型仅仅是普通的 JavaScript 对象,但是对这些对象进行操作时,却能影响对应视图,它的核心实现就是「响应式系统」. 首先看一下 Object.defi ...

  9. 请求与响应编码及jsp基本原理

    1.请求转发和请求包含 (1)请求转发: this.getServletContext().getRequestDispatcher("").forward(request,res ...

  10. C# 8小特性

    对于C# 8,有吸引了大多数注意力的重大特性,如默认接口方法和可空引用,也有许多小特性被考虑在内.本文将介绍几例可能加入C#未来版本的小特性. 新的赋值运算符:&&=和||= 从第一个 ...