Publish-Subscribe Pattern 2/2

This post is the second in the series. The previous one described the Publish/Subscribe pattern and analysed MQTT, MQTT-SN and DDS specifications. This article will continue the analysis of other protocols including OPC-UA PubSub, according to the characteristics highlighted in previous post.

OPC-UA PubSub

The OPC-UA PubSub is an open specification 1. It is not to be confused with the classical connected OPC-UA Services.

The OPC-UA PubSub introduces lots of new concepts, somewhat similar to what can be seen in the DDS specification (DataWriter, etc.). Curiously, OPC-UA PubSub does not introduce a concept of a topic. The specification covers the definition of the concepts, of the services, and their encoding on the wire. Following the specification’s recommandation, most of the configuration process of the PubSub is done through an OPC-UA Server, which clearly limits its embeddability.

The OPC-UA PubSub is specific in that it has 3 layers: the Transport layer (transport protocol used to exchange messages), the Message layer (encoding of the OPC-UA PubSub headers), and the Data layer (actual encoding of the data). The OPC-UA PubSub provides several options for each layer, as seen in the following summary.

The OPC-UA PubSub is specific in that it defines a PublishingInterval (similar to the one of the OPC-UA Subscription Service). The data shall only be published at the rate defined by this interval. Its KeepAlive facilities and other aspects of the object life-cycles are organized around this concept.

The OPC-UA PubSub is specific in that it is possible to merge multiple published data-sets in the same Message, reducing the Message overhead.

Transport

Different options are available:

  • Raw Ethernet: broker-less, relies on Ethernet multicast.

  • UDP: broker-less, relies on multicast.

  • MQTT: broker-based, TCP/IP. Yes, OPC-UA PubSub may be transported by another Pub/Sub protocol. MQTT brokers can be reused without modifications. DataWriters are assigned to different topics, and payload can be either UADP Messages or JSON Messages.

  • AMQP: broker-based, TCP/IP. Similar to MQTT transport.

Message layer (OPC-UA PubSub specific)

The message layer bears the OPC-UA PubSub protocol headers. Sizes are given for the whole Message (not just the payload). Also comes in different flavors:

  • UADP Message: the binary encoding, available on all transports.

  • JSON Message: only available in MQTT and AMQP transports.

  • With Raw Ethernet: size is limited to MTU.

  • With UDP: size is limited to 64 Kib (datagram size).

  • With MQTT: message is put in the MQTT’s payload (as a blob), size is limited to 256 MiB

  • With AMQP: message is put in the AMQP’s payload (as a blob), size is limited to 4 GiB.

Payload (corresponds to the data layer, features depends on the underlying layers)

Depending on the chosen encoding, it may not be possible to decode data without configuration. The protocol may use promoted fields for filtering, it is not data-agnostic. There are three ways to encode data:

  • Variant encoding: the OPC-UA Variant type. This encoding is specified in Part 6 of the specification, §5.2.2.16. It is a super type that can encode any OPC-UA type. It can also encode unkown types as blobs and a TypeId. Hence, a Variant is always decodable.

  • DataValue encoding: the OPC-UA DataValue type (Part 6, § 5.2.2.17). This is a Variant plus a StatusCode (uint32), and two dates (each uint64 + uint16).

  • Raw encoding: the configuration specifies a list of DataTypes representing a structure. Each field of the structure is an OPC-UA type. Fields are encoded one after the other. It is not possible to decode the structure without the prior knowledge of the field types.

Security

Depends on the chosen layers. Security from the transport layer can be combined with the security from the message layer, as security of the transport layer does not protect the system from a malicious broker if any.

  • JSON Message: no message or payload security.

  • UADP Message: payload security with, for now, AES-128 or 256 in CBC mode signed with HMAC-SHA2-256. See Configuration for key exchanges. Which security policy is used is also part of the configuration. This may change signature size, hence message size.

  • With Raw Ethernet: no transport security.

  • With UDP: no transport security suggested (DTLS tunnel not standardized).

  • With MQTT: TLS transport security.

  • With AMQP: TLS transport security.

QoS

No requirements. MQTT’s QoS can be used. Otherwise, there are no acknowledgement or any means to check that a Message was successfully transmitted between agents, nor timing check capabilities.

Filtering

Topic-based (with MQTT and AMQP transports only) and content-based. However, the message must contain information that may be used for filtering. For instance, the WriterGroupId, the PublisherId, and the PromotedFields are all optional. PromotedFields are fields of the payload that stay unencrypted and are dedicated to filtering.

Queuing

Only if transported by broker-based transports (to be confirmed for AMQP).

Discovery

Messages exist for discovery. Subscribers can send a request for publishers to answer. On broker-less transports, this still requires the multicast address, and on broker-based transports, the used topic is not specified (or I missed it). A subscriber posts a request, and publishers responds (with various timing specifications to avoid denials of service). The following can be discovered:

  • Publisher Server Endpoints (Endpoints for the classical OPC-UA Server associated with publishers, if any).

  • DataSetMetaData and DataSetWriter configurations, used to encode/decode payloads.

Configuration

Configuration is mandatory. At least part of it (which version of each layer is used + layer-specific configuration (such as MQTT QoS levels), and the broker/multicast endpoint). The remaining configuration is mainly used to schedule publications (interval and what is published). The encoding of the payload is defined for each DataSet. This can be defined beforehand, acquired with PubSub discovery, or discovered in a classical OPC-UA Server which contains nodes describing the configuration. The latter implies that an OPC-UA Server is embedded within the Publisher and an OPC-UA Client is embedded within the Subscriber.

A note on Security Key Servers (SKS)

They can be seen as a part of the configuration. SKS are responsible for the authentication of agents and for the distribution of the security keys. They are classical OPC-UA Server using TCP/IP. Authentication to classical OPC-UA Server requires a PKI infrastructure. Key exchanges require the OPC-UA Method call service, which is outside the scope of the OPC-UA Nano Server profile. PubSub security keys are symmetric keys that encrypt/sign the exchange between Publishers and Subscribers. They are shared amongst a so-called “security group”. The security group also defines which security policy is chosen, which defines which cryptographic primitives will be used.

Other Pub/Sub protocols

Advanced Message Queueing Protocol (AMQP)

Open, [TLS/]TCP, broker or peer to peer, Microsoft Azure cloud services have AMQP bridges.

Streaming Text Oriented Messaging Protocol (STOMP)

Open, TCP (http-like), broker-based.

Pub/Sub of the Redis database system

Proprietary, TCP, broker-based.

Pub/Sub of ZeroMQ

Open-source, TCP, broker-less (publishers connect to their subscribers).

Pub/Sub of Apache Kafka

Open-source, TCP, broker-based (brokers are redundant clusters of servers).

Amazon SNS/SQS

Proprietary, TCP?, broker-based (cloud).

Pub/Sub of the eXtensible Messaging and Presence Protocol (XMPP)

Not finished, open-source, TCP?, multi-broker?

Note that the Java Message Service (JMS) defines API interfaces that a middleware should implement, but not how data are transported. An example implementation is Apache ActiveMQ, which supports multiple underlying Pub/Sub protocols, such as MQTT or AMQP. This is similar to the DDS specification.

Conclusions

Producing a synthesis on this subject is difficult, as the studied protocols are somewhat different, in that they don’t try to achieve the same goals:

  • MQTT provides an efficient, near zero configuration, and lightweight Pub/Sub protocol. The protocol is close to the wire. MQTT’s role is to associate a payload to a topic.

  • MQTT-SN is similar to MQTT, but targets unreliable data links and very lightweight implementations.

  • DDS specifies APIs for an application level Pub/Sub. It is highly configurable and customizable, and targets all transports, all environments, all working modes, all QoS, all OSes, etc. It is kind of meta, and it is not intended to specify wire protocols nor message formats.

  • OPC-UA PubSub specifies a highly customizable and configurable Pub/Sub protocol. There are multiple choices for the transport layer, the message encoding, and the payload encoding. Its message structure has lots of optional fields, aiming at less bandwidth overhead. It is built on the OPC-UA Information Model and targets compatibility with its concepts and types. It also targets repetitive updates.

On top of that, they all have different visions on how to realize the Pub/Sub:

  • MQTT does not help clients decode the payload. MQTT has QoS for reliability but not for timing, and does not provide timestamps. Security of MQTT is based on TLS, but applications can choose to also encode their payload. The user is free to choose his security level.

  • MQTT-SN intend to stay very close to MQTT. Actually, it relies on MQTT for its broker, and you need a gateway that translates MQTT-SN to an MQTT broker.

  • DDS is similar to JMS, which defines a programming interface rather than an implementation. DDS uses companion specs which help with interoperability and security (amongst others). I did not study the DDSI specification enough to outline its specificities. From the outside, I see 200 pages for the DDS + 200 pages for the DDSI + 280 pages for the DDS Security. I don’t known if this covers configuration discovery.

  • In the OPC-UA PubSub, all transports are specified, as well as the messages and the security features. It also specifies configuration means: the configuration is contained in an OPC-UA Server. This latter element is an heavy constraint on the system (however, this can be mitigated with pre-shared configurations without breaking the specification). The application interface is (hopefully) left to the developer. For the security features, only the payload is encrypted, but the whole message is signed. Only the binary encoding can be secured. However, security requires a stand-alone classical OPC-UA Server which handles the keys and the authentication of clients. Each agent of the Pub/Sub must connect to it as an OPC-UA Client to fetch the keys of a security group. Hence, security is difficult and definitely not lightweight; this may balance the benefits of OPC-UA PubSub. Data are typed and, with the correct configuration which may be discovered through the protocol (if implemented), it is possible to unmarshall them. OPC-UA PubSub is specific in that it targets repetitive updates, and it can group multiple data updates in a single message.

With its focus on repetitive updates, the OPC-UA PubSub it is very similar to the classical OPC-UA Subscription service, but extending it to many-to-many data exchanges.

Appendix A: DDS struggles

My personal feeling is that this protocol is very complex, does lots of things, and cannot be grasped in a one page overview 2. This makes it a perfect target for marketeers… It is filled with buzzwords, has few implementations (mostly in C++), open source implementations have commercial support, interoperability is put in the front (I think that it is weird to emphasize on interoperability of implementations of a protocol, as it should be natural that two implementations of the same specification should be interoperable 3), it is backed by big companies (Thales Group, and a US government contractor), it uses lots of acronyms (RTPS, OMG, DCPS, DLRL, CORBA, ORB, etc.), it is built on other standards defined by the same group, its specification has a paragraph §2.2.2.5.3.34, its specification introduces lots of new concepts (Listener, DataReader, DomainParticipant, etc.), it has a distributed object model, in most cases it saves up to 90% of the bandwidth, it is versatile and highly customizable, and nobody seems to know even how it is transported.

Some of the acronyms: Common Object Request Broker Architecture, Object Request Broker, Internet Inter-Orb Protocol, Remote Method Invocation.

I have found the OpenDDS explanations very useful to enter the subject.

The specification is 200 page-long, contains an overview, but it is not very accessible at first read, and the Object Management Group (OMG) wiki does not work very well (some pages are unreachable).

More on DDS

DDS mostly provides concepts on how Entities should interact inside a Domain. There are Publishers and Subscribers, and DataWriters are attached to publishers and DataReaders to subscribers. DataWriters produce named and typed Topics. DataReaders consume these Topics. The DDS standard states that data is published between compatible DataWriters’ topics and DataReaders’ topics. But it does not specify how data is transported. There is the DCPSInfoRepo which specifies how participants in a domain are made aware of each others.

A publisher may be linked to several DataWriters to publish data-objects of different types. Associating a publisher and a data-writer “expresses the intent of the application to publish the data described by the data-writer in the context provided by the publisher” 4. (similarly on the subscriber side)

There is a Listener attached to all these DomainParticipants. Let’s come back to Entities and DomainParticipants. The standard really works with the object model and provides mostly base classes for these concepts. The lowest base class is Entity. All the other concepts are Entities (DomainParticipant, Publisher, DataWriter, Topic, etc.). The DomainParticipant is the abstraction of the application. It is composed of other entities (except that it is not composed of other DomainParticipants). Entities all have: at most one Listener, some QoSPolicies, and at most one StatusCondition which defines its state. The Listener is the interface with the other Entities. Of course, Listeners are specialized for each of the Entity sub-types (e.g., DataWriterListener for DataWriters). The Listener interface specifies the callbacks, setters and getters of the functional interface between entities.

Footnotes

1

OPC-UA Specification v1.04 Part 14: PubSub (requires an account on the OPC Foundation website)

2

This bad publicity is probably due to the fact that the specification specifies how an application is structured rather than how data are encoded or how applications connect together. For me, this is very unusual.

3

Yes, ok, no, there is the DDSI

4

Object Management Group, Data Distribution Service Specification v1.4

Commentaires