COMET: –
COMET: –
. .
COMET – OS
(Twisted, node.js, …)
Continuations (Jetty, GlassFish…)
(Erlang, Stackless Python…)
COMET- Java, Javascript, Python, Erlang.
, , , .
, , , :
, .
.
– .
, , (), , .
, , 20 , : , 5 30, .
, , ..
pre-fork, , – .
FastCGI: PHP/FastCGI, Perl/FastCGI, Ruby/FastCGI . WSGI(Python), .
– , . – , , , .
, .
– – : . .
, ( , ..) , .
, , , ..
– , . .
, – , .
, , (, – ), , .
, , PHP .
– , , . : , , , .
, . , – .
– . , .
:
// include MyFramework; MyFramework::init(); // while , while(request = FastCGI::accept()) MyFramework::process(request);
MyFramework::process(request) , .
request , . – .
? ! , , , Perl/FastCGI, Ruby/FastCGI.
, , . , .
– .
, , .
, , .
– , print counter . , – , counter++print counter. – .
– : , , ..
: counter :
process , – , . counter .
, , , .. , , .
, . , ..
– , , . , .
– – (Java): Tomcat, Resin . Servlet API 2.5. .
COMET- , .
( )
,
( )
, . – , – .
100 100 ( ), . , , .
1000, 10.000 , , : , -, .
COMET-, .
, , – , .
javascript:
xhr.send() , . XmlHttpRequest, onreadystatechange- processResult.
. COMET-, Twisted ( Python).
COMET- long-poll. :/publish/subscribe.
/subscribe , . – .
/publish message , .
class ClientManager: clients = [] def registerClient(self, client): self.clients.append(client) def broadcastMessage(self, message): for client in self.clients: client.write(message) client.finish() self.clients = [] clientManager = ClientManager() class CometServer(resource.Resource): isLeaf = False def __init__(self): resource.Resource.__init__(self) self.registerChildren() def registerChildren(self): self.putChild(subscribe, Subscribe() ) self.putChild(publish, Publish() ) def getChild( self, path, req ): if path == : return self else: return resource.Resource.getChild( self, path, req ) class Subscribe(resource.Resource): isLeaf = True def render_GET(self, req): clientManager.registerClient(req) return server.NOT_DONE_YET class Publish(resource.Resource): isLeaf = True def render_POST(self, req): clientManager.broadcastMessage(req.args[message][0]) return ok application = service.Application(App) service = internet.TCPServer(8001, server.Site(CometServer())) service.setServiceParent(application)
:
ClientManager -, clients.
registerClient broadcastMessage.
CometServer -, . Twisted.web Subscribe()Publish(), .
Subscribe . /subscribe, ( ) . server.NOT_DONE_YET, , Twisted .
, clientManager.
Publish POST-, message .
Publish . .
/.
.
, , clientManager.clients, .
, . , ..
, .
, – , .
, , API . .
, , . , , .
– .
– , Twisted (adbapi ) , :
, , deferToThread:
deferred Deferred , addCallback, .
– , .
, .. , , , , .
. , .
– . Python, , Global Interpreter Lock, .
, ( thread-safe) .
– , . .
– , , .. : , , .
Node.JS Javascript V8 Javascript- libev . . /.
COMET- Node.JS:
sys = require(sys), http = require(http); url = require(url) clientManager = new function() var clients = [] this.registerClient = function(client) clients.push(client) this.broadcastMessage = function(message) for(var i=0; iclients.length; i++) var client = clients[i] client.writeHeader(200, Content-Type: text/plain;charset=utf-8) client.write(message.toString(), utf-8) client.close() clients = [] http.createServer(function (req, res) var urlParsed = url.parse(req.url, true) if (urlParsed.pathname == /publish) ssage) res.writeHeader(200, Content-Type: text/plain;charset=utf-8) res.write(ok, utf-8) res.close() if (urlParsed.pathname == /subscribe) clientManager.registerClient(res) ).listen(8000);
, Node.JS Twisted . clientManager. .
Node.JS Twisted, , .
– Jetty, Java.
, Continuation, .
, , continuation.resume(), , continuation .
public class SubscribeServlet extends HttpServlet protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException Continuation continuation = ContinuationSupport.getContinuation(req); if (continuation.isInitial()) continuation.suspend(); ClientManager.getInstance().registerClient(continuation); else String message = (String)continuation.getAttribute(message); resp.setContentType(text/plain;charset=utf-8); resp.getWriter().print(message);
continuation.suspend(); ClientManager.getInstance().registerClient(continuation);
,
, – .
.
/publish. PublishServlet:
public class PublishServlet extends HttpServlet protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException ClientManager.getInstance().broadcastMessage(req.getParameter(message)); resp.setContentType(text/plain;charset=utf-8); resp.getWriter().print(ok);
ClientManagerbroadcastMessage, :
public class ClientManager ArrayListContinuation continuations = new ArrayListContinuation(); public synchronized void registerClient(Continuation continuation) continuations.add(continuation); public synchronized void broadcastMessage(String message) for(Continuation continuation: continuations) continuation.setAttribute(message, message); continuation.resume(); continuations.clear(); // private static ClientManager ourInstance = new ClientManager(); public static ClientManager getInstance() return ourInstance; private ClientManager()
, .
, Continuation, continuations. ArrayList, thread-safe.
broadcastMessage continuations ( ) continuation.resume().
, continuation, . continuation.isInitial() false, .. .
SubscribeServlet :
continuation.suspend(), .
, clientManager , .. synchronized. , .
Continuations , .
, continuation.resume()broadcastMessage , continuation.
, , :
continuation.resume(); – , , , – .
, ..
, : .
GlassFish Servlet API 3.0.
ThreadPool. , , , .
ontinuation . .
/CPU.
( continuations) .
.
– . , , , 100, 1000, 10.000 .
OS . .
, , Erlang.
, , , .
COMET- MochiWeb.
room(Users) – receive From, subscribe – From ! subscribed, room([From Users]); From, post, Message – From ! posted, lists:foreach(fun(User) – % broadcast the message User ! Message end, Users), room([]); _Any – room(Users) end. get_the_room() – % does the room exists? Pid = whereis(theroom), if is_pid(Pid) – % yup Pid; true – % create it NewPid = spawn(fun() – room([]) end), register(theroom, NewPid), NewPid end. loop(Req, DocRoot) – / ++ Path = Req:get(path), case Req:get(method) of Method when Method =:= GET; Method =:= HEAD – case Path of subscribe – Room = get_the_room(), Room ! self(), subscribe, receive subscribed – % subscription is ok % now wait for a message receive Message – ok after ?TIMEOUT – % we waited too long Message = timeout end after 50000 – % subscription failed on time Message = timeout end, % send back the JSON message Req:ok(text/plain;charset=utf-8, Message); end; POST – case Path of publish – Data = Req:parse_post(), Room = get_the_room(), % post Room ! self(), post, list_to_binary(proplists:get_value(message, Data)), receive posted – % posted ok after 50000 – % something went wrong notok end, % send back the message Req:ok(text/plain, ok); _ – Req:not_found() end; _ – Req:respond(501, [], []) end.
, – .
. . .
. . .
Erlang , .
, .
theroom. clientManager, .
get_the_room Pid theroom, , spawn.
get_the_room() – % does the room exists? Pid = whereis(theroom), if is_pid(Pid) – % yup Pid; true – % create it NewPid = spawn(fun() – room([]) end), register(theroom, NewPid), NewPid end.
– theroom. room.
room- . spawn .
room(Users) – *!*receive*/!* From, subscribe – From ! subscribed, room([From Users]); From, post, Message – From ! posted, lists:foreach(fun(User) – % broadcast the message User ! Message end, Users), room([]); _Any – room(Users) end.
receive , .
subscribe From, subscribed:
, .. , room([From Users])- , , From( ).
receive . , – .
From, post, Message post .
, .
, , , , – .
, , (-, subscribe) , (-, post, -)- , – _Any.
room([]) , .
. , subscribepublish.
% Room = get_the_room(), % subscribe () Room ! self(), subscribe, % receive subscribed – % , receive Message – ok % after ?TIMEOUT – % Message = timeout end after 50000 – % Message = timeout end, % Req:ok(text/plain;charset=utf-8, Message);
publish , .
, 100, 1000 100.000 Erlang/OTP.
Continuations.
(hibernate), , .
, , .
, .. hibernate, , , .
, , ( ), Erlang , .
.
Linux nf:
General gigabit tuning: net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 net.ipv4.tcp_rmem = 4096 87380 16777216 net.ipv4.tcp_wmem = 4096 65536 16777216 net.ipv4.tcp_syncookies = 1 this gives the kernel more memory for tcp which you need with many (100k+) open socket connections net.ipv4.tcp_mem = 50576 64768 98152 net.core.netdev_max_backlog = 2500 net.ipv4.tcp_keepalive_time = 300 net.core.somaxconn = 4096
– . , root: (/etc/security/limits.conf)
, , .
, COMET, javascript- : polling / streaming / long-poll.
:
Java – Continuations, Python/Ruby/Javascript – , Erlang- hibernate.
, Java- – CPU, Python/Ruby/Javascript – , Erlang , .
, .
, . – …
Rutwit . (, ) ?
, Node.js (, , Plurk ).
, .
P.S. , .
P.P.S. , Java Comet- Atmosphere (
COMET- . , – .
, ( ) . .
, – () COMET, . , – .
Java?
framework`.
. orbited pooling, long-pooling, Callback-Polling, Iframe Streaming, HTML5 WebSocket ( ? ?
APE long pooling, 100k .
comet ?
, , . , ..
, long polling … , – .
PHP COMET-? – [PHP] , .
phpDaemon .
. COMET Node.js, . subscribe publish, subscribe. subscribe- . , .
, , . : . ok, foo. publish, . .. . , – , publish…
( ).
, , , . . , Chrome , subscribe , publish.
, links.
– . , node.js ( , , ). , , . , .
Ajax – .
COMET: –
, COMET
XMLHTTPRequest, interactive
. 2.
Javascript
: , , Boolean
. .
javascript- 7
Ajax – .
. 2.
Yahoo:
Javascript-.
Javascript/CSS
a href=javascript:… –
– Selenium + PHP.
Google Closure Library
. DOM Storage .
DIV
. ?
DevTools – ?
checkbox .checked