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…