服务器端
SessionManager: session管理者,创建session,保存了当前所有活动着的session
- 超时订时钟定时扫锚超时的session,将其停止掉
- session在每次请求时会更新一下lease time,超时时根据这个时间来判断,如果客户端长期不处于活跃状态就会被杀掉
Subscriber:订阅者 - 每个session会对应一个subscriber
- 内部实现了一个queue,有事件时产生时,Dispatcher会通知给Subscriber
- 客户过来拉数据时,会从这个queue里取出数据push给客户端。
Dispatcher:消息分发者,有新消息到来时,会分发给所有subscriber.
public class Session implements Protocol, ConfigDefs {
private Controller controller ;
private Subscriber subscriber ;
}
pushlet支持三种模式:
stream:采用长连接的方式,服务器会占用servelt线程不会释放,有数据时就会主动推给客户端。
poll:服务端轮询
pull:服务拉,感觉跟poll一样,都是用ajax定时器
下面是Dispatcher里的代码,在这里分别对三种不同的模式在服务器端进行了不同处理
public void fetchEvents (Command aCommand) throws PushletException {
Event[] events = null;
// 采用长连接方式,将事件推给客户端
// 采用while死循环方式
// 对于poll和pull在没有数据里会从循环中跳出来
// stream会被阻塞
long eventSeqNr = 1;
while (isActive()) {
// Indicate we are still alive
lastAlive = Sys.now();
// Update session time to live
session.kick();
//取下一个事件,stream模式没有数据将会阻赛,对拉模式将会直接返加回,返回代码在for之后
try {
// Put heartbeat in queue when starting to listen in stream mode
// This speeds up the return of *_LISTEN_ACK
if (mode .equals(MODE_STREAM) && eventSeqNr == 1) {
eventQueue.enQueue(new Event(E_HEARTBEAT));
}
events = eventQueue.deQueueAll(queueReadTimeoutMillis );
} catch (InterruptedException ie) {
warn( "interrupted");
bailout();
}
// Send heartbeat when no events received
.......................
......省略代码.........
.......................
for (int i = 0; i < events.length; i++) {
.......................
.........省略代码.......
.......................
// 将事件推到客户端
try {
// Set sequence number
events[i].setField( P_SEQ, eventSeqNr++);
// Push to client through client adapter
clientAdapter.push(events[i]);
} catch (Throwable t) {
bailout();
return;
}
}
// 拉模式和轮洵模式,数据推完了之后直接跳出,释放servlet线程,返回,这与stream模式不一样
if (mode .equals(MODE_PULL) || mode.equals( MODE_POLL)) {
sendRefresh(clientAdapter, refreshURL);
// Always leave loop in pull/poll mode
break;
}
}
}
客户端
客户端基本上采用两种方式:iframe和ajax
iframe方式:poll,pull采用timeout方式来保持与服务器的会话,stream是长连接所以iframe会一直处于取数据状态,有可能浏览器会一直转圈
ajax方式:同上,基本原理差不多,只是ajax的可以异步方式来取数据。对于stream方式需要浏览器支持readyState=3,IE不支持
缺陷
基本上pushlet只能适应小型应用,对于大型应用很容易出现性能问题,长连接保存方式采用hold线程方式,很容易把服务器的servelet线程全用完,导至不能接收新的请求,所以这里要采用nio的方式来做,异步化。而且在分发事件,mach的方式采用遍历的方式,性能上也有问题,可以采用消息订阅的方式来解决。