Every effort must be made to deliver a client's request to a service. The client-service interaction style may be Request/Response or Request/Acknowledge.
How can a client ensure that requests are delivered to a web service despite temporary network or server failures?
Networks are inherently unreliable. Connections will occasionally time out or be dropped. Servers will be overloaded from time to time, and as a result, they may not be able to receive or process all requests. Problems will arise for innumerable reasons. A client could, for example, successfully connect to a service and send a request only to see the connection drop while waiting for a response. If the client naively resends the request, the service might, for example, create two orders when the client only wanted one. The client might not be able to establish a connection with a service in the first place due to network or server problems. One option to mitigate this problem is to send web service requests through intermediaries (e.g., broker services, ESBs, etc.). However, using an intermediary to solve the basic problem of service connectivity may be an overly elaborate strategy. And while queues can be used to help mitigate some service connectivity problems, they are best reserved for use within a secured network, far behind the corporate firewall. If a client can't connect to a service or loses a connection, or if the server reports that it is busy, sometimes the best solution is to simply try again.
Design the client such that common connectivity exceptions are caught. When a connection error occurs, reconnect to the service and resend the request. Limit the number of times such attempts are made. Include a unique identifier in each request so that the service can identify duplicate requests. Alternatively, send the request to a unique URI designated for the specific request.
The Idempotent Retry pattern seems quite simple. Whenever a client calls a service, it must be prepared to catch several connectivity-related errors. If an error occurs, the client should try to reconnect to the service and resubmit the request as long as it does not exceed a maximum retry threshold. The client must abort further attempts once this limit has been passed. On closer analysis, we see that this pattern entails much more than this summary implies. For more information, see the book.