Long Polling长轮询实现进阶
简书 涤生。
转载请注明原创出处,谢谢!
如果读完觉得有收获的话,欢迎点赞加关注。
介绍
由于Long Polling长轮询详解 这篇文章中的code实现较为简单,尤其是服务端处理较为粗暴,有一些同学反馈希望服务端处理阻塞这块内容进行更深入讨论等等,所以这里专门补一篇实现进阶,让大家对长轮询有更加深刻的理解。
疑问
对上篇文章,同学反馈有两个疑问。
服务端实现使用的是同步servlet,性能比较差,能支撑的连接数比较少?
同步servlet来hold请求,确实会导致后续请求得不到及时处理,servlet3.0开始支持异步处理,可以更高效的处理请求。
服务端如何去hold住请求,sleep好吗?
同步servlet hold住请求的处理逻辑必须在servlet的doGet方法中,一般先fetch数据,准备好了,就返回,没准备好,就sleep片刻,再来重复。
异步servlet hold住请求比较简单,只要开启异步,执行完doGet方法后,不会自动返回此次请求,需要等到请求的context被complete,这样很巧妙的请求就自动hold住了。
实现
客户端实现
客户端实现基本和上篇差不多,没什么改变。
package com.andy.example.longpolling.client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.atomic.AtomicLong;
/**
* Created by andy on 17/7/8.
*/
public class AbstractBootstrap {
//同步URL
protected static final String URL = "http://localhost:8080/long-polling";
//异步URL
protected static final String ASYNC_URL = "http://localhost:8080/long-polling-async";
private final AtomicLong sequence = new AtomicLong();
protected void poll() {
//循环执行,保证每次longpolling结束,再次发起longpolling
while (!Thread.interrupted()) {
doPoll();
}
}
protected void doPoll() {
System.out.println("第" + (sequence.incrementAndGet()) + "次 longpolling");
long startMillis = System.currentTimeMillis();
HttpURLConnection connection = null;
try {
URL getUrl = new URL(URL);
connection = (HttpURLConnection) getUrl.openConnection();
//50s作为长轮询超时时间
connection.setReadTimeout(50000);
connection.setConnectTimeout(3000);
connection.setRequestMethod(