Usage scenarios
It is suitable for handling front-end polling to avoid server stress caused by frequent polling requests
Implementation effect
If a service is completed during the delay period, the service will be returned actively. If no specified service is completed during the delay period, the next long poll will be conducted after the specified delay time. (Apollo implementation principle)
The following illustrates the use of DeferredResult by simulating Apollo configuration changes in real time
implementation
@RestController
public class ApolloController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
// A key can hold multiple values
private Multimap<String, DeferredResult<String>> watchRequests = Multimaps.synchronizedSetMultimap(HashMultimap.create());
// Simulate long polling
@RequestMapping(value = "/watch/{namespace}", method = RequestMethod.GET, produces = "text/html")
public DeferredResult<String> watch(@PathVariable("namespace") String namespace) {
logger.info("Request received");
DeferredResult<String> deferredResult = new DeferredResult<>();
// When deferredResult completes (whether timed out, abnormal, or normal), remove the corresponding Watch key from watchRequests
deferredResult.onCompletion(new Runnable() {
@Override
public void run(a) {
System.out.println("remove key:"+ namespace); watchRequests.remove(namespace, deferredResult); }}); watchRequests.put(namespace, deferredResult); logger.info("Servlet thread released");
return deferredResult;
}
// Simulate publishing the namespace configuration
@RequestMapping(value = "/publish/{namespace}", method = RequestMethod.GET, produces = "text/html")
public Object publishConfig(@PathVariable("namespace") String namespace) {
if (watchRequests.containsKey(namespace)) {
Collection<DeferredResult<String>> deferredResults = watchRequests.get(namespace);
Long time = System.currentTimeMillis();
// Inform all watch of the configuration change result of namespace change
for (DeferredResult<String> deferredResult : deferredResults) {
deferredResult.setResult(namespace + " changed:"+ time); }}return "success"; }}Copy the code
conclusion
The advantage over regular polling is that it does not require multiple requests to consume server resources and does not consume the main thread, similar to WebSocket
reference
Github.com/ctripcorp/a…