This document is for Kombu's development version, which can be significantly different from previous releases. Get the stable docs here: 5.0.
序列化¶
串行化程序¶
默认情况下,每条消息都使用 JSON ,所以发送像字典和列表这样的Python数据结构是可行的。 YAML , msgpack 和Python的内置功能 pickle 模块也是受支持的,如果需要,您可以注册任何想要使用的自定义序列化方案。
默认情况下,Kombu将仅加载JSON消息,因此,如果您希望使用其他序列化格式,则必须在您的使用者中通过使用 accept
论据:
Consumer(conn, [queue], accept=['json', 'pickle', 'msgpack'])
Accept参数还可以包括MIME类型。
每种选择都有其优势和劣势。
- json --JSON在许多编程语言中都受支持,
这是Python的标准部分,并且解码速度相当快。
的主要缺点是 JSON 它将您限制为以下数据类型:字符串、Unicode、浮点数、布尔值、字典、列表、小数、DjangoPromise、DateTime、Date、Time、Bytes和UUID。
对于日期、日期时间、UUID和字节,序列化程序将生成一个字典,稍后将指示反序列化程序如何生成正确的类型。
此外,二进制数据将使用Base64编码传输,这将导致传输的数据比支持本机二进制类型的编码大约34%。只有在字节对象无法解码为UTF8时才会发生这种情况。
但是,如果您的数据符合上述约束,并且需要跨语言支持,则默认设置为 JSON 可能是你最好的选择。
如果需要对自定义类型的支持,可以编写序列化/反序列化函数并按如下方式注册它们:
from kombu.utils.json import register_type from django.db.models import Model from django.apps import apps # Allow serialization of django models: register_type( Model, "model", lambda o: [o._meta.label, o.pk], lambda o: apps.get_model(o[0]).objects.get(pk=o[1]), )
- pickle --如果您不想支持除
然后使用 pickle 编码将获得对所有内置Python数据类型(类实例除外)的支持、发送二进制文件时的较小消息以及略有加速 JSON 正在处理。
泡菜与安全
Pickle格式非常方便,因为它可以序列化和反序列化几乎任何对象,但这也是一个安全问题。
精心设计的PICLE有效负载几乎可以做常规Python程序能做的任何事情,因此,如果您让您的使用者自动解码PICKLE对象,您必须确保限制对代理的访问,这样不受信任的方就无法发送消息!
默认情况下,Kombu使用Pickle协议4,但可以使用
PICKLE_PROTOCOL
环境变量或通过更改全局kombu.serialization.pickle_protocol
旗帜。- yaml --YAML有许多相同的特征 json ,
只是它本身支持更多的数据类型(包括日期、递归引用等)。
然而,用于YAML的Python库比用于JSON的库慢得多。
如果您需要一组更具表现力的数据类型并需要维护跨语言兼容性,那么 YAML 可能比上面的更合适。
指示,指示 Kombu 若要使用备用序列化方法,请使用下列选项之一。
按生产者设置序列化选项:
>>> producer = Producer(channel, ... exchange=exchange, ... serializer='yaml')设置每条消息的序列化选项:
>>> producer.publish(message, routing_key=rkey, ... serializer='pickle')
请注意,一个 Consumer 不需要指定的序列化方法。当内容类型作为消息头发送时,它们可以自动检测序列化方法。
发送未序列化的原始数据¶
在某些情况下,您不需要序列化消息数据。如果将纯字符串或Unicode对象作为消息和自定义 content_type ,那么 Kombu 不会浪费序列化/反序列化数据的周期。
您可以选择性地指定一个 content_encoding 对于原始数据:
>>> with open('~/my_picture.jpg', 'rb') as fh:
... producer.publish(fh.read(),
content_type='image/jpeg',
content_encoding='binary',
routing_key=rkey)
这个 Message 方法返回的对象 Consumer 类将有一个 content_type 和 content_encoding 属性。
使用SetupTools入口点创建扩展¶
包还可以使用SetupTools入口点注册新的序列化程序。
入口点必须提供序列化程序的名称以及提供其余参数的元组的路径: encoder_function, decoder_function, content_type, content_encoding
。
例如,入口点可以是:
from setuptools import setup
setup(
entry_points={
'kombu.serializers': [
'my_serializer = my_module.serializer:register_args'
]
}
)
然后是模块 my_module.serializer
将如下所示:
register_args = (my_encoder, my_decoder, 'application/x-mimetype', 'utf-8')
安装此程序包后,Kombu将支持新的‘my_Serializer’序列化程序。
缓冲区对象
自定义序列化程序的解码器函数必须同时支持字符串和Python的旧式缓冲区对象。
Python Pickle和Json模块通常不会通过其 loads
函数,但您可以通过在 load
接受文件对象而不是字符串的函数。
下面是一个包装示例 pickle.loads()
以这样的方式:
import pickle
from io import BytesIO
from kombu import serialization
def loads(s):
return pickle.load(BytesIO(s))
serialization.register(
'my_pickle', pickle.dumps, loads,
content_type='application/x-pickle2',
content_encoding='binary',
)