[Buffalo-pm] Plack/Comm::Express

Ben. B. bennymack at gmail.com
Fri Apr 29 07:05:45 PDT 2011


Here are the files from my Plack talk. Comm::Express is a Plack handler I
wrote to meet the needs of an application at $work.

Some questions that came up were (and my opinion/answer):

Q: What's the purpose of plack in relation to existing web frameworks.
A: Allow code written for those frameworks to seamlessly run on any number
of servers.

Q: Why write applications in Plack directly and not in
Catalyst/Dancer/Mojo/Web::Simple.
A: Not really the Right Thing, just how I roll. Made possible by the
existence of Plack::Middleware.

Q: Will Comm::Express be released to CPAN.
A: Not planning on it. If you have an application that you think could
benefit from it's particular qualities, let me know.

In addition to HTTPParser::MMAP::XS, I also wrote HTTPParser::XS (very
poorly named on both counts) that is just the HTTP streaming/http-parser
integration without the MMAP stuff which I find quite useful in my
day-to-day duties.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.pm.org/pipermail/buffalo-pm/attachments/20110429/55781641/attachment.html>
-------------- next part --------------
PSGI/Plack
----------
"PSGI is an interface between Perl web applications and web servers, and Plack
is a Perl module and toolkit  that contains PSGI middleware, helpers and adapters
to web servers." -plackperl.org

Applications
------------
All applications are a single code reference. Traditionally in a file with a
.psgi extension.

Environment
-----------
Input is in the form of an environment hash reference traditionally called $env.

Input
-----
If there is HTTP POST or PUT data, it will be available for reading from
$env->{'psgi.input'}.

Errors
------
There should be an error stream in $env->{'psgi.errors'}.

Response
--------
Output should either be a three element reference or a code reference for
delayed/streaming output.

Middleware
----------
Wrap entire applications with some additional functionality.

Use to use things like Catalyst plugins that were only available when you wrote
your application for Catalyst. Now you can target Plack middleware and take
functionality with you across frameworks.

Examples
--------
hello.psgi
file.psgi
dirs.psgi
middle.psgi (access_log, 304)

Servers
-------
HTTP::Server::Simple
Starman
Twiggy
Corona
Feersum
...

Comm::Express
-------------
Feature set
  Limited HTTP verbs. GET only. No POST, PUT, DELETE, file uploads etc.
  Subject to change. Under careful consideration.

  Keep-Alive is supported.

  sendfile(2) like zero-copy splicing of static files.

  Compile time optimization of command line switches.

Post-fork workers
  Can start with 0 workers or prefork up to MAX_WORKERS at startup.
  Fig 1.

Non-blocking
  Main server process should never do anything processor intensive.

IO::Epoll
  Efficiently handle large numbers of mostly idle sockets. Comes at the cost of
  increased code complexity (IMO) and additional bookkeeping syscalls.

  Superpoll?

HTTPParser::MMAP::XS
  Based on ry's http-parser (https://github.com/ry/http-parser) and
  HTTP::ParserXS. 

  Fig 2.

  Creates a per-connection parser object that all incoming data is streamed to.

  Handles all HTTP state associated with a given client.

  As data is streamed to it, the request is laid out in memory in a simple null
  byte separated format. 

  E.g. "GET\0/foo?bar=1#baz\0HTTP/1.0\0Connection\0Keep-Alive"

  It then determines if the request is valid. If so, a memcpy(3) copies the
  request into an mmap(2) region that is shared with a worker process.

  The worker is notified via a pipe that a serialized request is ready.

mmap(2) $env
  Shared memory used as a fast IPC mechanism to reduce overhead of farming out
  request handling to worker processes.

splice(2) response
  Efficient syscall for server process to pass response string from worker to
  client without examining it at all.

  Fig 3.

4MB SO_SNDBUF
  When a worker process writes a response to the server to be spliced to the
  client, it could conceivably fill the client's send buffer, causing the
  worker process to become an expensive way to buffer output to the client. To
  avoid this, set a moderately large send buffer on the client in the hopes that
  all responses can fit in it without delay.

Queue requests
  If MAX_WORKERS is reached, valid requests get pushed into a queue that are
  handled as soon as worker processes become available. Otherwise, if allowed to
  post-fork processes un-constrained, could use up all available RAM and start
  swapping.

Minimal IPC overhead
  A lot of emphasis is placed on not passing a lot of data between the server
  and worker processes as this causes slow downs. Server writes remote address
  and a flag to the worker, worker writes size of response to server. Usually 5
  bytes or less per message.

Embedded HTTP server
  Possible to embed an HTTP server inside of Comm::Express for the purpose of
  monitoring and managing.

Other Abuses
------------
Everything is an HTTP server
Embed them in your programs

Writing a Handler(Server)
-----------------
plackup
Plack::Loader
Plack::Runner
-------------- next part --------------
 Fig 1.
                                   .-,(  ),-.    
                                .-(          )-. 
                               (    internet    )
                                '-(          ).-'
                                    '-.( ).-'    
                                        |
                                        |
                                        v
                           .------------------------.
                           |         Server         |
                           |------------------------|
                           |                        |
                           |                        |
                           |                        |
                           '------------------------'
                            ^                      ^
                            |                      |
                            |                      |
                      .---------.              .---------.
                      | Worker1 |      ...     | WorkerN |
                      |---------|              |---------|
                      '---------'              '---------'


 Fig 2.
                      .---------.              .---------.
                      | Client1 |              | ClientN |
                      |---------|              |---------|
                      '---------'              '---------'
                            ^                       ^
             .--------------|-----------------------|--------------.
             |              |        Server         |              |
             |--------------|-----------------------|--------------|
             |           .-----------------------------.           |
             |           |         http-parser         |           |
             |           '-----------------------------'           |
             |              |                       |              |
             | .-------------------------------------------------. |
             | |                    epoll_fd                     | |
             | '-------------------------------------------------' |
             |                                                     |
             '-----------------------------------------------------'
-------------- next part --------------
 Fig 3.
         .--------.
         | Client |
         |--------|
         '--------'
              |
   .----------|--------------------------------.
   |          |       Server                   |
   |----------|--------------------------------|
   |          v                                |
   | .---------------------------------------. |
   | |         HTTPParser::MMAP::XS          | |
   | |---------------------------------------| |
   | |         .--------------------.        | |
   | |         | Private serialized |        | |
   | |         | request memory     |        | |
   | |         '--------------------'        | |
   | '---------------------------------------' |
   |                                           |
   '-------------------------------------------'
       ^           ^          |             |
       |           |          |             |
       |           |       peeraddr         |
       |           |       writer           v
       |           |          |     .------------------------.
       |        length        |     | Shared MMAP serialized |
       |        writer        |     | request memory         |
       |           |          |     '------------------------'
   response        |          |             ^
   writer          |          |             |
       |           |          |             |
       |           |          v             |
   .-------------------------------------------.
   |                  Worker                   |
   |-------------------------------------------|
   |                                           |
   |                                           |
   |                                           |
   |                                           |
   |                                           |
   |                                           |
   '-------------------------------------------'
-------------- next part --------------
A non-text attachment was scrubbed...
Name: hello.psgi
Type: application/octet-stream
Size: 139 bytes
Desc: not available
URL: <http://mail.pm.org/pipermail/buffalo-pm/attachments/20110429/55781641/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: file.psgi
Type: application/octet-stream
Size: 91 bytes
Desc: not available
URL: <http://mail.pm.org/pipermail/buffalo-pm/attachments/20110429/55781641/attachment-0001.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dirs.psgi
Type: application/octet-stream
Size: 101 bytes
Desc: not available
URL: <http://mail.pm.org/pipermail/buffalo-pm/attachments/20110429/55781641/attachment-0002.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: middle.psgi
Type: application/octet-stream
Size: 423 bytes
Desc: not available
URL: <http://mail.pm.org/pipermail/buffalo-pm/attachments/20110429/55781641/attachment-0003.obj>


More information about the Buffalo-pm mailing list