On 01.11.10 23:51, Jeff Rogers wrote:
It looks like my previous answer was, at best, partially right. It looks lke [ns_conn channel] does in fact give you a read/write channel. The effect of the missing content-length header is to discard any data that was read past the headers. Attached is a patch (readahead.patch) to change that behavior. The patch does 2 things: one, if the request includes 'upgrade' in the connection header, it doesn't read past the header (and doesn't throw away what it has read). Two, when [ns_conn channel] is called, it will insert into the channel buffer any data that was already read (and not processed) on the socket. Combined, it means that on an upgrade connection you can get the entire body, even if there was no content-length header sent.
nice!
Importantly, this design of thread-per-connection is not scalable - your server will fall down and start crying once you start up a few dozen threads. (perhaps more; a really rough guess is that each tcl thread consumes 2M of memory before doing anything). What you really want to do is to transfer each new websocket to a single existing background thread, but I'm not sure how to send stuff into another thread's event loop using the aolserver thread tools. The standard tcl thread package is more powerful (with thread::send and thread::wait) but I don't know if those play nice inside AOLserver.
the bgdelivery-procs in the OpenACS CVS [1] do exactly this
(using tcl threads and native tcl streams)

We use bgdelivery in production since several years, with up to
a mio bgdeliveries per day, so i can assert, this runs stable and
scalable (in aolserver 4.0, 4.5 and naviserver). Often, we see
more than 100 concurrent  deliveries running, just occupying a
single thread.

Here is a significantly simplified example showing the guts:
- get channel
- transfer channel
- send thread a command to continue work using the open channel

   proc spool_jpeg {jpeg_file} {
if {[ns_headers 200 image/jpeg [file size $jpeg_file]]} {
           set chan [ns_conn channel]
           thread::transfer $::serverThreadId $chan
thread::send -async $::serverThreadId [list spoolfile -channel $chan -file $jpeg_file]
       }
   }

The bgdelivery-procs [1] do more than only delivering plain
files (FileSpool), so they do more than one needs for e.g.
websockets. The gb-delivery-procs handle as well
h264 pseudo streaming and  http spooling, and provide as
well a publish-subscriber handling for broadcasting info to
multiple subscribers in a comet-style (web clients keep a
connection open, therefore web-clients for e.g. a chat
work immediately without polling).

One important advantage of the tcl thread package is that it is sitting in an event loop, so it is easy to communicate to it from all other
threads in a sync or async fashion. The reason for using
tcl streams instead of ns_streams is that in some situations
one simply needs it since the existing interfaces require it (unless
reprogramming certain modules based on aolserver streams). One
such use case is the tcl command fcopy, which is used by bgdelivery.

One important disadvantage of using native tcl streams is that once you are working on the native tcl streams, ns_stream functionality is gone. So, if one connects via https, the native tcl stream can't
decode the content (this requires running a reverse proxy such
as nginx in such situations, which is for larger sites
anyhow a good idea). One can use https + bgdelivery via tcl's tls
package nicely for e.g. outgoing connections.

best regards
-gustaf neumann

[1] http://cvs.openacs.org/browse/OpenACS/openacs-4/packages/xotcl-core/tcl/bgdelivery-procs.tcl?r=HEAD


--
AOLserver - http://www.aolserver.com/

To Remove yourself from this list, simply send an email to 
<[email protected]> with the
body of "SIGNOFF AOLSERVER" in the email message. You can leave the Subject: 
field of your email blank.

Reply via email to