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数据结构是可行的。 YAMLmsgpack 和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 若要使用备用序列化方法,请使用下列选项之一。

  1. 按生产者设置序列化选项:

    >>> producer = Producer(channel,
    ...                     exchange=exchange,
    ...                     serializer='yaml')
    
  2. 设置每条消息的序列化选项:

    >>> 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_typecontent_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',
)