原文译文操作

mqttessentials_part5

Welcome to the fifth part of the MQTT Essentials, a blog series about the core features and concepts in the MQTT protocol. In this post we’ll focus on MQTT topics and best practices. As we have already mentioned, topics are used to decide on the MQTT broker which client receive which message. We will also discuss SYS-topics, which are special ones that reveal broker internal information. So let’s get started.

Topics

A topic is a UTF-8 string, which is used by the broker to filter messages for each connected client. A topic consists of one or more topic levels. Each topic level is separated by a forward slash (topic level separator).

mqttessentials_part5

欢迎来到MQTT Essentials的第五部分,这是一篇关于MQTT协议的核心特性和概念的系列博客。 在本文中,我们将重点介绍MQTT主题和最佳实践正如我们已经提到的,主题用于决定MQTT代理,由哪个客户端接收哪些消息。 我们还将讨论SYS-主题,特别是揭示代理内部信息的主题。 让我们开始吧。

主题

主题是一个UTF-8字符串,代理用它来过滤每个连接的客户端的消息。 主题由一个或多个主题级别组成。 每个主题级别之间由正斜杠(主题级别分隔符)分隔。

纠正翻译

topic_basics

In comparison to a message queue a topic is very lightweight. There is no need for a client to create the desired topic before publishing or subscribing to it, because a broker accepts each valid topic without any prior initialization.

Here are a few example topics:

myhome/groundfloor/livingroom/temperature
USA/California/San Francisco/Silicon Valley
5ff4a2ce-e485-40f4-826c-b1a5d81be9b6/status
Germany/Bavaria/car/2382340923453/latitude

Noticeable is that each topic must have at least 1 character to be valid and it can also contain spaces. Also a topic is case-sensitive, which makes myhome/temperature and MyHome/Temperature two individual topics. Additionally the forward slash alone is a valid topic, too.

topic_basics

与消息队列相比,主题非常轻量级。 客户端不需要在发布或订阅之前创建所需的主题,因为代理接受每个有效主题时不需要进行任何预初始化。
以下是几个示例主题:

myhome/groundfloor/livingroom/temperature
USA/California/San Francisco/Silicon Valley
5ff4a2ce-e485-40f4-826c-b1a5d81be9b6/status
Germany/Bavaria/car/2382340923453/latitude

值得注意的是,每个主题必须包含至少一个有效字符,并且它还可以包含空格。 另外,主题是区分大小写的,这使得myhome / temperature和MyHome / Temperature两个单独的主题。  除此之外,单独的正斜线也是有效的主题。

纠正翻译

Wildcards

When a client subscribes to a topic it can use the exact topic the message was published to or it can subscribe to more topics at once by using wildcards. A wildcard can only be used when subscribing to topics and is not permitted when publishing a message. In the following we will look at the two different kinds one by one: single level and multi level wildcards.

Single Level: +

As the name already suggests, a single level wildcard is a substitute for one topic level. The plus symbol represents a single level wildcard in the topic.

topic_wildcard_plus

Any topic matches to a topic including the single level wildcard if it contains an arbitrary string instead of the wildcard. For example a subscription to myhome/groundfloor/+/temperature would match or not match the following topics:

通配符

当客户端订阅主题时,它可以使用消息发布到的确切主题,或者可以使用通配符同时订阅更多的主题。 通配符只能在订阅主题时使用,并且在发布消息时不允许使用。 下面我们将逐一介绍两种不同的类型:单级和多级通配符。

单级: +

正如名称已经表明的,单个级别的通配符代替一个主题级别。 加号表示主题中的单个级别通配符。

topic_wildcard_plus

任何主题如果包含的是任意字符串而不是通配符,则该主题与包括单级通配符的主题匹配。 例如,对于myhome / groundfloor / + / temperature的订阅将匹配或不匹配以下主题:

纠正翻译

topic_wildcard_plus_example

Multi Level: #

While the single level wildcard only covers one topic level, the multi level wildcard covers an arbitrary number of topic levels. In order to determine the matching topics it is required that the multi level wildcard is always the last character in the topic and it is preceded by a forward slash.

topic_wildcard_hash

topic_wildcard_hash_example

A client subscribing to a topic with a multi level wildcard is receiving all messages, which start with the pattern before the wildcard character, no matter how long or deep the topics will get. If you only specify the multilevel wildcard as a topic (#), it means that you will get every message sent over the MQTT broker. If you expect high throughput this is an anti pattern, see the best practices below.

topic_wildcard_plus_example

多级: #

虽然单级通配符仅涵盖一个主题级别,但是多级通配符可以涵盖任意数量的主题级别。 为了确定匹配的主题,需要多级通配符总是主题中的最后一个字符,并且确保它前面是正斜杠。

topic_wildcard_hash

topic_wildcard_hash_example

订阅具有多级通配符的主题的客户端将接收所有的消息,这些消息以通配符之前的模式开始,无论多长或多深的主题将将被获取到。 如果仅将多级通配符指定为主题(#),则意味着您将获得的每条消息都是通过MQTT代理发送。 如果你期望这种反模式的高吞吐量,请参见下面的最佳实践。

纠正翻译

Topics beginning with $

In general you are totally free in naming your topics, but there is one exception. Each topic, which starts with a $-symbol will be treated specially and is for example not part of the subscription when subscribing to #These topics are reserved for internal statistics of the MQTT broker. Therefore it is not possible for clients to publish messages to these topics. At the moment there is no clear official standardization of topics that must be published by the broker. It is common practice to use $SYS/ for all these information and a lot of brokers implement these, but in different formats. One suggestion on $SYS-topics is in the MQTT GitHub wiki and here are some examples:

以$开始的主题

通常,对主题进行命名是完全自由的,但是也有一个例外。以$号开始的每个主题都会被特殊对待,比如,当订阅到#时,它们不作为订阅的组成部分。这些主题被保留作为MQTT代理服务器的内部特性。因此,客户端向这些主题发布消息是不可能的。目前还没有明确的有关代理必须发布的主题的官方标准。一般的做法是使用$SYS/ 表示所有的这些信息,但使用不同的格式。在MQTT GitHub wiki中可以找到有关$SYS主题的一个建议, 这里有一些例子:

纠正翻译

$SYS/broker/clients/connected
$SYS/broker/clients/disconnected
$SYS/broker/clients/total
$SYS/broker/messages/sent
$SYS/broker/uptime

Summary

So these were the basics about MQTT message topics. As you can see, MQTT topics are dynamically and give great flexibility to its creator. But when using these in real world applications there are some challenges you should be aware of. We collected our best practices, we learned the last year with excessively using MQTT in various projects. We are open to other suggestions or a discussion about these in the comments, so let us know your best practices or if you disagree with one of our best practices!

$SYS/broker/clients/connected
$SYS/broker/clients/disconnected
$SYS/broker/clients/total
$SYS/broker/messages/sent
$SYS/broker/uptime

概要

这些是关于MQTT消息主题的基础。正如你所看到的,MQTT主题是动态的,并且给开发者提供了很大的灵活性。但是当你应该注意的是当你把这些知识应用到真实的程序中还是有一些挑战的。我们收集了我们的最佳的实践,我们是从去年开始学习MQTT,并把它频繁的用在了很多项目中。我们欢迎大家在评论中提供建议或者讨论,如果你不认同我们最好的实践方法的话,请让我们知道您的最佳做法。

纠正翻译

Best practices

Don’t use a leading forward slash

It is allowed to use a leading forward slash in MQTT, for example /myhome/groundfloor/livingroom. But that introduces a unnecessary topic level with a zero character at the front. That should be avoided, because it doesn’t provide any benefit and often leads to confusion.

Don’t use spaces in a topic

A space is the natural enemy of each programmer, they often make it much harder to read and debug topics, when things are not going the way, they should be. So similar to the first one, only because something is allowed doesn’t mean it should be used. UTF-8 knows many different white space types, it’s pretty obvious that such uncommon characters should be avoided.

最佳实践

不要是使用正斜杠

在MQTT运行使用真斜杠,例如/myhome/groundfloor/livingroom. 它前面引入了一个不必要的空字符的级别,应该避免这样,因为没有任何作用,容易导致混乱.

不要在主题中使用空格

空格是每个程序员的天敌,当出现异常的时候,他们很难被阅读和调试,与第一点类似,允许的规则并不意味着它应该被使用。UTF-8包含很多不同的空格字符类型,很显然,应该避免使用这种不常见的字符。

纠正翻译

Keep the topic short and concise

Each topic will be included in every message it is used in, so you should think about making them short and concise. When it comes to small devices, each byte counts and makes really a difference.

Use only ASCII characters, avoid non printable characters

Using non-ASCII UTF-8 character makes it really hard to find typos or issues related to the character set, because often they can not be displayed correctly. Unless it is really necessary we recommend avoid using non ASCII character in a topic.

Embed a unique identifier or the ClientId into the topic

保持主题简短

每个主题将被包含在每个消息中,所以你应该考虑使它们简洁明了。 当涉及到小型设备时,每个字节都会计数,并且确实有所不同。

只使用ASCII字符,避免不可打印的字符

使用非ASCII UTF-8字符很难找到与字符集有关的拼写错误或问题,因为它们经常无法正确显示。 除非真的有必要,否则我们建议避免在主题中使用非ASCII字符。

将唯一标识符或ClientId包含到主题中

纠正翻译

In some cases it is very helpful, when the topic contains a unique identifier of the client the publish is coming from. This helps identifying, who send the message. Another advantage is the enforcement of authorization, so that only a client with the same ClientId as contained in the topic is allowed to publish to that topic. So a client with the idclient1 is allowed to publish to client1/status, but not permitted to publish to client2/status.

Don’t subscribe to #

Sometimes it is necessary to subscribe to all messages, which are transferred over the broker, for example when persisting all of them into a database. This should not be done by using a MQTT client and subscribing to the multi level wildcard. The reason is that often the subscribing client is not able to process the load of messages that is coming its way. Especially if you have a massive throughput. Our recommended solution is to implement an extension in the MQTT broker, for example the plugin system of HiveMQ allows you to hook into the behavior of HiveMQ and add a asynchronous routine to process each incoming message and persist it to a database.

在某些情况下,当主题包含发布来自的客户端的唯一标识符时,它非常有用。这有助于识别谁发送消息。另一个优点是强制执行,因此只允许具有与主题中包含的客户端ID相同的客户端发布到该主题。因此,允许具有idclient1的客户端发布到client1/status,但不允许发布到client2/status。

不订阅#

有时需要订阅通过代理传输的所有消息,例如将所有消息都保存到数据库中时。这不应该通过使用MQTT客户端并订阅多级通配符来完成。原因是订阅客户端通常无法处理即将发生的消息加载。特别是如果你有大量的吞吐量。我们推荐的解决方案是在MQTT代理中实现扩展,例如HiveMQ的插件系统允许您挂钩HiveMQ的行为并添加异步例程来处理每个传入消息并将其持久保存到数据库。

纠正翻译

Don’t forget extensibility

Topics are a flexible concept and there is no need to preallocate them in any kind of way, regardless both the publisher and subscriber need to be aware of the topic. So it is important to think about how they can be extended in case you are adding new features to your product. For example when your smart home solution is extended by some new sensors, it should be possible to add these to your topic tree without changing the whole topic hierarchy.

Use specific topics, instead of general ones

When naming topics it is important not to use them like a queue, for example using only one topic for all messages is a anti pattern. You should use as specific topics as possible. So if you have three sensors in your living room, you should use topics myhome/livingroom/temperaturemyhome/livingroom/brightness andmyhome/livingroom/humidity, instead of sending all values over myhome/livingroom. Also this enables you to use other MQTT features like retained messages, which we cover in one of the next posts.

不要忘记可扩展性

主题是一个灵活的概念,无论发布者和订阅者都需要了解该主题,都无需以任何方式预分配它们。因此,在为产品添加新功能的情况下,考虑如何扩展它们非常重要。例如,当您的智能家居解决方案被某些新传感器扩展时,应该可以将这些传感器添加到主题树中,而无需更改整个主题层次结构。

使用特定主题,而不是一般主题

在命名主题时,重要的是不要像队列那样使用它们,例如,对所有消息仅使用一个主题是反模式。您应该尽可能使用特定主题。因此,如果你的起居室里有三个传感器,你应该使用主题myhome/livingroom/temperature,myhome/livingroom/brightness和myhome/livingroom/humidity,而不是在myhome/livingroom上发送所有值。此外,这使您可以使用其他MQTT功能,如保留消息,我们将在下一篇文章中介绍。

纠正翻译

So that’s the end of part five in our MQTT Essentials series. We hope you enjoyed it. In the next post we cover the often mention Quality of Service (QoS) in MQTT. We’ll explain why this is an essential feature and how you can leverage it.

Have a great week and we’ll hope to see you on the next MQTT Monday!

If you still haven’t signed up for our newsletter in order to get each new post delivered directly to your inbox, you can do so below. If you prefer RSS, you can subscribe to our RSS feed here.

这就是我们的MQTT Essentials系列的第五部分结束。我们希望你喜欢它。在下一篇文章中,我们将介绍MQTT中经常提到的服务质量(QoS)。我们将解释为什么这是一个基本功能以及如何利用它。

祝您度过愉快的一周,我们希望在下周的MQTT上见到您!

如果您还没有注册我们的简报,以便将每个新帖子直接发送到您的收件箱,您可以在下面这样做。如果您更喜欢RSS,可以在此订阅我们的RSS源。

纠正翻译