Loading ...
Sorry, an error occurred while loading the content.

Forking HTTP::Daemon

Expand Messages
  • Thom Eden
    Folks, Pardon my ignorance, I m a newbie at this... I am building a web service at a customer site using SOAP::Lite. Given that volumes will initally be in the
    Message 1 of 4 , Jul 11, 2003
    • 0 Attachment
      Folks,

      Pardon my ignorance, I'm a newbie at this...

      I am building a web service at a customer site using SOAP::Lite. Given that volumes will initally be in the 100,000/day, growing to twice that in a year, we want to ensure the service has the oomph necessary to handle the volume. When writing a simple server which uses SOAP::Transport::HTTP::Daemon, I notice that the handler gets bogged down while performing the dispatch_to work. I took the example Echo.pm and put in a 10 second sleep, and noticed that I routinely get just over 10 second response times, as expected. However, when I initiate 2 or more clients, response time becomes n (number of clients) * 10.?. This is clearly not a good thing.

      I found an example of a forking server, which spawns a specified number of children. I adapted it to my use, and notice that performance degradation is only slightly worse when the number of children forks is greater than the number of clients, which is a good thing. However, when the number of clients expands beyond the number of child forks, performance again degrades beyond what is acceptable. This may turn out to be an acceptable solution, though, as my atomic transactions may only turn out to be about 3 seconds long; after all, how many real requests will come in over a 3 second span?

      However, the architect in me would like a solution where the server takes each request and forks a process to handle it, thus allowing the handler to return to its work; handling requests.

      In the SOAP::Lite examples, there are a couple of "semi-published" modules, namely SOAP::Transport::HTTP::Daemon::ForkAfterProcessing and SOAP::Transport::HTTP::Daemon::ForkOnAccept. I cannot get the latter to work, even with the sample server code, it returns "500 unexpected EOF before status line seen" and the server punches out

      getsockname() on closed socket Symbol::GEN0 at /opt/perl5.6/lib/5.6.0/sun4-solaris/IO/Socket.pm line 186.
      Use of uninitialized value in string eq at /opt/perl5.6/lib/site_perl/5.6.0/HTTP/Daemon.pm line 124.
      Use of uninitialized value in gethostbyaddr at /opt/perl5.6/lib/site_perl/5.6.0/HTTP/Daemon.pm line 129.
      Use of uninitialized value in subroutine entry at /opt/perl5.6/lib/site_perl/5.6.0/HTTP/Daemon.pm line 129.
      Bad arg length for Socket::inet_ntoa, length is 0, should be 4 at /opt/perl5.6/lib/site_perl/5.6.0/HTTP/Daemon.pm line 129.

      Hmmm. Not sure what is going on here. Any clues would be great.

      The former (ForkAfterProcessing) works as advertised; however, I notice the process stack on my Solaris server keeps getting new processes (for each fork) which never expire. After a few minutes of load testing, my machine is about dead. I stop testing and wait up to an hour, yet none of the forked processes dies. This is clearly a bad situation!

      I know I can't be the first guy to come along and want to create a SOAP service without using Apache, CGI or mod_perl... If anyone has any pointers, I would be greatly appreciative!

      Thom Eden
      the@...
    • Michael A Nachbaur
      I m a relative newbie at SOAP as well, but I have (I think) successfully created a soap daemon that does just this. My requirement was that it should be able
      Message 2 of 4 , Jul 11, 2003
      • 0 Attachment
        I'm a relative newbie at SOAP as well, but I have (I think) successfully
        created a soap daemon that does just this. My requirement was that it should
        be able to be hammered with tons of requests in a short span of time, but to
        be dormant for pretty much of the time. Another requirement was security,
        and while I wanted to use secure certificates and SSL, SOAP::Lite died every
        time I tried it.

        My hack solution was to use TCP Wrappers to limit whom I would talk to.
        Attached is my SOAP transport, and a trimmed-down soapd executable that uses
        the transport.

        If anyone has a better way of doing this, I would much appreciate it!

        On Friday 11 July 2003 06:34 am, Thom Eden wrote:
        > Folks,
        >
        > Pardon my ignorance, I'm a newbie at this...
        >
        > I am building a web service at a customer site using SOAP::Lite. Given that
        > volumes will initally be in the 100,000/day, growing to twice that in a
        > year, we want to ensure the service has the oomph necessary to handle the
        > volume. When writing a simple server which uses
        > SOAP::Transport::HTTP::Daemon, I notice that the handler gets bogged down
        > while performing the dispatch_to work. I took the example Echo.pm and put
        > in a 10 second sleep, and noticed that I routinely get just over 10 second
        > response times, as expected. However, when I initiate 2 or more clients,
        > response time becomes n (number of clients) * 10.?. This is clearly not a
        > good thing.
        >
        > I found an example of a forking server, which spawns a specified number of
        > children. I adapted it to my use, and notice that performance degradation
        > is only slightly worse when the number of children forks is greater than
        > the number of clients, which is a good thing. However, when the number of
        > clients expands beyond the number of child forks, performance again
        > degrades beyond what is acceptable. This may turn out to be an acceptable
        > solution, though, as my atomic transactions may only turn out to be about 3
        > seconds long; after all, how many real requests will come in over a 3
        > second span?
        >
        > However, the architect in me would like a solution where the server takes
        > each request and forks a process to handle it, thus allowing the handler to
        > return to its work; handling requests.
        >
        > In the SOAP::Lite examples, there are a couple of "semi-published" modules,
        > namely SOAP::Transport::HTTP::Daemon::ForkAfterProcessing and
        > SOAP::Transport::HTTP::Daemon::ForkOnAccept. I cannot get the latter to
        > work, even with the sample server code, it returns "500 unexpected EOF
        > before status line seen" and the server punches out
        >
        > getsockname() on closed socket Symbol::GEN0 at
        > /opt/perl5.6/lib/5.6.0/sun4-solaris/IO/Socket.pm line 186. Use of
        > uninitialized value in string eq at
        > /opt/perl5.6/lib/site_perl/5.6.0/HTTP/Daemon.pm line 124. Use of
        > uninitialized value in gethostbyaddr at
        > /opt/perl5.6/lib/site_perl/5.6.0/HTTP/Daemon.pm line 129. Use of
        > uninitialized value in subroutine entry at
        > /opt/perl5.6/lib/site_perl/5.6.0/HTTP/Daemon.pm line 129. Bad arg length
        > for Socket::inet_ntoa, length is 0, should be 4 at
        > /opt/perl5.6/lib/site_perl/5.6.0/HTTP/Daemon.pm line 129.
        >
        > Hmmm. Not sure what is going on here. Any clues would be great.
        >
        > The former (ForkAfterProcessing) works as advertised; however, I notice the
        > process stack on my Solaris server keeps getting new processes (for each
        > fork) which never expire. After a few minutes of load testing, my machine
        > is about dead. I stop testing and wait up to an hour, yet none of the
        > forked processes dies. This is clearly a bad situation!
        >
        > I know I can't be the first guy to come along and want to create a SOAP
        > service without using Apache, CGI or mod_perl... If anyone has any
        > pointers, I would be greatly appreciative!
        >
        > Thom Eden
        > the@...
        >
        >
        > To unsubscribe from this group, send an email to:
        > soaplite-unsubscribe@yahoogroups.com
        >
        >
        >
        > Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/

        --
        /* Michael A. Nachbaur <mike@...>
        * http://nachbaur.com/pgpkey.asc
        */

        "`The best way to get a drink out of a Vogon is to stick
        your finger down his throat...'"
      • Alasdair Allan
        ... use threads; use threads::shared; use strict; use vars qw(@ISA); # based on SOAP::Transport::HTTP::Daemon use SOAP::Transport::HTTP; @ISA =
        Message 3 of 4 , Jul 11, 2003
        • 0 Attachment
          > I am building a web service at a customer site using SOAP::Lite. Given
          > that volumes will initally be in the 100,000/day, growing to twice that
          > in a year, we want to ensure the service has the oomph necessary to
          > handle the volume. When writing a simple server which uses
          > SOAP::Transport::HTTP::Daemon...

          For this sort of volume I wouldn't use Daemon.pm, personally I don't think
          its up to handling those sorts of load levels, however...

          > I notice that the handler gets bogged down while performing the
          > dispatch_to work. I took the example Echo.pm and put in a 10 second
          > sleep, and noticed that I routinely get just over 10 second response
          > times, as expected. However, when I initiate 2 or more clients, response
          > time becomes n (number of clients) * 10.?. This is clearly not a good
          > thing.

          The daemon is unthreaded and and the socket is blocking, if your sleep was
          longer than the connection timeout your additional clients would timeout
          waiting for the first connection to finish.

          > I found an example of a forking server, which spawns a specified number
          > of children. I adapted it to my use, and notice that performance
          > degradation is only slightly worse when the number of children forks is
          > greater than the number of clients, which is a good thing. However, when
          > the number of clients expands beyond the number of child forks,
          > performance again degrades beyond what is acceptable.

          If you _really_ need to roll your own instead of going with something a
          bit more robust (and tested) like a service running under Apache the I'd
          recommend threading rather than forking your handler processes...

          I've attached a very quick a dirty ThreadOnAccept.pm module, but it should
          really be rewitten using Thread::Pool so that a denial of service attack
          isn't so easy.

          > This may turn out to be an acceptable solution, though, as my atomic
          > transactions may only turn out to be about 3 seconds long; after all,
          > how many real requests will come in over a 3 second span?

          Thats fairly poor design choice, if you're going to drop a server like
          this onto a publically accessible site where you can't control the number
          of people connecting to it, you shouldn't make assumptions. The only way
          an assumption like this is valid is if you are the only one going to be
          running a client process to connect to this server.

          > In the SOAP::Lite examples, there are a couple of "semi-published"
          > modules, namely SOAP::Transport::HTTP::Daemon::ForkAfterProcessing and
          > SOAP::Transport::HTTP::Daemon::ForkOnAccept. I cannot get the latter to
          > work, even with the sample server code, it returns "500 unexpected EOF
          > before status line seen" and the server punches out

          ForkOnAccept works fine for me, but again, I'd recommend using ithreads
          and Perl 5.8(.1)

          > I know I can't be the first guy to come along and want to create a SOAP
          > service without using Apache, CGI or mod_perl... If anyone has any
          > pointers, I would be greatly appreciative!

          No you're not, I've got plenty of stand alone SOAP services, but for a
          production service, where I can't control whats going to be hitting the
          server, or one where I'm expecting the sort of load you seem to be
          expecting, I'd go for Apache, CGI or mod_perl...

          Al.
          --
          Dr. A. Allan, School of Physics, University of Exeter
        • Thom Eden
          ... From: Alasdair Allan Date: Fri, 11 Jul 2003 18:14:21 +0100 (BST) ... It looks as though Perl was installed without threading support
          Message 4 of 4 , Jul 11, 2003
          • 0 Attachment
            ---------- Original Message ----------------------------------
            From: Alasdair Allan <aa@...>
            Date: Fri, 11 Jul 2003 18:14:21 +0100 (BST)

            >
            >> I am building a web service at a customer site using SOAP::Lite. Given
            >> that volumes will initally be in the 100,000/day, growing to twice that
            >> in a year, we want to ensure the service has the oomph necessary to
            >> handle the volume. When writing a simple server which uses
            >> SOAP::Transport::HTTP::Daemon...
            >
            >For this sort of volume I wouldn't use Daemon.pm, personally I don't think
            >its up to handling those sorts of load levels, however...
            >
            >> I notice that the handler gets bogged down while performing the
            >> dispatch_to work. I took the example Echo.pm and put in a 10 second
            >> sleep, and noticed that I routinely get just over 10 second response
            >> times, as expected. However, when I initiate 2 or more clients, response
            >> time becomes n (number of clients) * 10.?. This is clearly not a good
            >> thing.
            >
            >The daemon is unthreaded and and the socket is blocking, if your sleep was
            >longer than the connection timeout your additional clients would timeout
            >waiting for the first connection to finish.
            >
            >> I found an example of a forking server, which spawns a specified number
            >> of children. I adapted it to my use, and notice that performance
            >> degradation is only slightly worse when the number of children forks is
            >> greater than the number of clients, which is a good thing. However, when
            >> the number of clients expands beyond the number of child forks,
            >> performance again degrades beyond what is acceptable.
            >
            >If you _really_ need to roll your own instead of going with something a
            >bit more robust (and tested) like a service running under Apache the I'd
            >recommend threading rather than forking your handler processes...
            >
            >I've attached a very quick a dirty ThreadOnAccept.pm module, but it should
            >really be rewitten using Thread::Pool so that a denial of service attack
            >isn't so easy.
            >

            It looks as though Perl was installed without threading support here :(

            >> This may turn out to be an acceptable solution, though, as my atomic
            >> transactions may only turn out to be about 3 seconds long; after all,
            >> how many real requests will come in over a 3 second span?
            >
            >Thats fairly poor design choice, if you're going to drop a server like
            >this onto a publically accessible site where you can't control the number
            >of people connecting to it, you shouldn't make assumptions. The only way
            >an assumption like this is valid is if you are the only one going to be
            >running a client process to connect to this server.
            >

            The system is internal, and will not be advertised outside of the firewall. Your point in general is well taken, however. What I am seeing with the current implementation in an Open Server environment (don't ask, you don't want to know) is up to 5 simultaneous clients at a time, with transactions in the 2-3 second realm.

            >> In the SOAP::Lite examples, there are a couple of "semi-published"
            >> modules, namely SOAP::Transport::HTTP::Daemon::ForkAfterProcessing and
            >> SOAP::Transport::HTTP::Daemon::ForkOnAccept. I cannot get the latter to
            >> work, even with the sample server code, it returns "500 unexpected EOF
            >> before status line seen" and the server punches out
            >
            >ForkOnAccept works fine for me, but again, I'd recommend using ithreads
            >and Perl 5.8(.1)
            >
            >> I know I can't be the first guy to come along and want to create a SOAP
            >> service without using Apache, CGI or mod_perl... If anyone has any
            >> pointers, I would be greatly appreciative!
            >
            >No you're not, I've got plenty of stand alone SOAP services, but for a
            >production service, where I can't control whats going to be hitting the
            >server, or one where I'm expecting the sort of load you seem to be
            >expecting, I'd go for Apache, CGI or mod_perl...
            >

            Thanks, but I've already received direction concerning Apache etc. here. Perhaps I'll get a reasonably acceptable solution using forks and hide several servers on different boxes behind a load balancer :|

            >Al.
            >--
            >Dr. A. Allan, School of Physics, University of Exeter
            >
            >
          Your message has been successfully submitted and would be delivered to recipients shortly.