来自:http://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels
The Quality of Service (QoS) level is an agreement between sender and receiver of a message regarding the guarantees of delivering a message. There are 3 QoS levels in MQTT:
When talking about QoS there are always two different parts of delivering a message: publishing client to broker and broker to subscribing client. We need to look at them separately since there are subtle differences. The QoS level for publishing client to broker is depending on the QoS level the client sets for the particular message. When the broker transfers a message to a subscribing client it uses the QoS of the subscription made by the client earlier. That means, QoS guarantees can get downgraded for a particular receiving client if subscribed with a lower QoS.
QoS is a major feature of MQTT, it makes communication in unreliable networks a lot easier because the protocol handles retransmission and guarantees the delivery of the message, regardless how unreliable the underlying transport is. Also it empowers a client to choose the QoS level depending on its network reliability and application logic.
So how is the quality of service implemented in the MQTT protocol ? We will look at each level one by one and explain the functionality.
The minimal level is zero and it guarantees a best effort delivery. A message won’t be acknowledged by the receiver or stored and redelivered by the sender. This is often called “fire and forget” and provides the same guarantee as the underlying TCP protocol.
When using QoS level 1, it is guaranteed that a message will be delivered at least once to the receiver. But the message can also be delivered more than once.
The sender will store the message until it gets an acknowledgement in form of a PUBACK command message from the receiver.
The association of PUBLISH and PUBACK is done by comparing the packet identifier in each packet. If the PUBACK isn’t received in a reasonable amount of time the sender will resend the PUBLISH message. If a receiver gets a message with QoS 1, it can process it immediately, for example sending it to all subscribing clients in case of a broker and then replying with the PUBACK.
The duplicate (DUP) flag, which is set in the case a PUBLISH is redelivered, is only for internal purposes and won’t be processed by broker or client in the case of QoS 1. The receiver will send a PUBACK regardless of the DUP flag.
The highest QoS is 2, it guarantees that each message is received only once by the counterpart. It is the safest and also the slowest quality of service level. The guarantee is provided by two flows there and back between sender and receiver.
If a receiver gets a QoS 2 PUBLISH it will process the publish message accordingly and acknowledge it to the sender with a PUBREC message.
The receiver will store a reference to the packet identifier until it has send the PUBCOMP. This is important for avoid processing the message a second time. When the sender receives the PUBREC it can safely discard the initial publish, because it knows that the counter part has successfully received the message. It will store the PUBREC and respond with a PUBREL.
After the receiver gets the PUBREL it can discard every stored state and answer with a PUBCOMP. The same is true when the sender receives the PUBCOMP.
When the flow is completed both parties can be sure that the message has been delivered and the sender also knows about it.
Whenever a packet gets lost on the way, the sender is responsible for resending the last message after a reasonable amount of time. This is true when the sender is a MQTT client and also when a MQTT broker sends a message. The receiver has the responsibility to respond to each command message accordingly.
There are a few things you should have in mind when using QoS. These are not obvious or clear on first sight.
As already said, the QoS flows between a publishing and subscribing client are two different things as well as the QoS can be different. That means the QoS level can be different from client A, who publishes a message, and client B, who receives the published message. Between the sender and the broker the QoS is defined by the sender. When the broker sends out the message to all subscribers, the QoS of the subscription from client B is used. If client B has subscribed to the broker with QoS 1 and client A sends a QoS 2 message, it will be received by client B with QoS 1. And of course it could be delivered more than once to client B, because QoS 1 only guarantees to deliver the message at least once.
Also important to know is that each packet identifier (used for QoS 1 and QoS 2) is unique between one client and a broker and not between all clients. If a flow is completed the same packet identifier can be reused anytime. That’s also the reason why the packet identifier doesn’t need to be bigger than 65535, because it is unrealistic that a client sends a such large number of message, without completing the flow.
We are often asked, when to choose which QoS level. The following should provide you some guidance if you are also confronted with this decision. Often this is heavily depending on your use case.
All messages sent with QoS 1 and 2 will also be queued for offline clients, until they are available again. But queuing is only happening, if the client has a persistent session.