A service likes to request information from a conversation partner.
How can a service request information from a provider if an immediate response is not available and it cannot accept unsolicited incoming messages?
- Many connection-oriented transport layers, such as TCP/IP, allow data transmission in both directions, independent of which party initiated the connection. However, network infrastructure such as firewalls restrict the ability to establish connections. For example, a PC can establish a connection to a Web site, but the website cannot establish a new connection to a regular PC that sits behind a firewall.
- A service may simply not be programmed to receive incoming connections as it is often easier to program actively making a connection as opposed to handling incoming connections.
- Even if the initiator is able to receive incoming messages or connections, its application program may not be interested in doing so. This can be the case if the initiating application can continue processing up to the point where it requires the data from another service. The natural programming model is to make a request, continue processing up to the point where a response is needed and then request the response from the external service. This way the flow of control stays within the application.
Have the requestor poll, i.e., inquire whether results are ready, multiple times if necessary.
The Polling conversation involves the following participants:
- The Requestor initiates the conversation with a Request and keeps sending Inquiry messages until the result becomes available. The Requestor expects a response to every Inquiry message, either a Nack (Negative Acknowledgment), meaning the result is not yet available, or the Result message.
- The Provider accepts the Request message and begins processing. While processing it can accept Inquiry messages, to which it either replies with a Nack or the processing results. The Provider has to keep the results until the Requestor picks them up.
Polling requires a Correlation Identifier to be agreed between Requestor and Provider. The identifier can either be selected by the Requestor and transmitted with the Request or the participants can use Quick Acknowledgment to transmit the identifier in the Acknowledgment message. The Requestor then includes the identifier in every Inquiry message.
The response to the last inquiry can immediately include the response message or indicate that the results are available (Ack), requiring the initiator of the conversation to make a separate request to retrieve the results.
Polling is significantly more "chatty" than Asynchronous Request-Response". It should only be used when either of the communicating parties cannot support a Asynchronous Request-Response" conversation. Excessive Polling can cause significant load on part of the Provider up to the point where it competes with resources with the actual operation.
Polling causes a delay in the overall conversation because the results are available before the Requestor can realize. The optimal Polling rate depends on the expected latency, the "cost" of a poll, and the time sensitivity of the request. More frequent Polling reduces the delay between the time the results are available and when they are picked up. Unnecessarily frequent polling introduces network and processing overhead. Adaptive polling intervals are conceivable, but run the risk of complicating the conversation. If the Requestor has a good approximation of the minimum processing time, it can delay the beginning of Polling and possibly use a higher Polling frequency without increasing the total overhead:
In reality, the Polling interval will depend on when the results can be meaningfully processed by the Requestor. For example, the Requestor may engage in other interactions whose results are needed for further processing. It makes sense to only poll for results once those steps are completed.
Polling requires the Provider to maintain state at the convenience of the Requestor, which should be considered a form of coupling. It can also limit the scalability of the service provider, for example if responses consume large amounts of memory and initiators are slow to pick up their results. Therefore, the service provider may use additional conversation patterns to terminate the conversation, such as a Lease", so it can relinquish the allocated result storage if the Requestor does not consume the results within a specified length of time. Correspondingly, the Requestor has to be prepared that an Inquiry results in a Not Available message, after which the Requestor should stop the conversation.
Reliable Messaging can often eliminate the need for Polling. The Requestor can consume results whenever it pleases, alleviating the Provider from having to keep results until the Requestor picks them up. Storing results in a message queue is generally more efficient than storing them inside the Provider as Messaging systems are designed to maintain state and use mechanisms such as Message Expiration to manage stale data.
The Requestor can also use a Poll Object [10] to implement polling internally, turning it into a Polling Consumer [2]. This allows the consumer application to control when the message is read while still using the preferred Asynchronous Request-Response conversation with the Provider.
In real life, participants often mix Asynchronous Request-Response and Polling: if a response does not arrive within a "reasonable" amount of time, the Requestor begins Polling. This can occasionally annoy the Provider.
Example: WS-Polling
http://www.w3.org/Submission/ws-polling/
Example: Project Manager
Some project managers who are wondering why a coding task takes so long keep asking for daily status updates.
Related patterns: Correlation Identifier, Lease, Message Expiration, Messaging, Quick Acknowledgment, Asynchronous Request-Response