Here's my situation: I'm developing a web application using Dancer framework, and I would like to insert some data to the database on the server side from the browser side. The problem is, when the data is too large, the uploading takes so long that I'm considering displaying a progress bar describing the progress.
I implemented this by sending two requests: one for posting data, and the other polling the status. But it seems once the first requests is being handled, the other won't work until the first finishes. So the status returns nothing and suddenly 100%. To manage this, I create a thread when handling the first requests, so the main thread could return to handle the second polling requests. This works quite well until I have to kill some child progress spawned in the child thread (this is another question).
So my question is, is there any other ideas about dealing with the multiple requests simultaneously except for the multithread one? Normally how does the web programmers handle this situation?
You should have no problem handling multiple requests simultaneously.
How do you run your app? If you use built-in server (perl your_app.pl) then by default it is single threaded and will only process one request at a time.
You might want to use mutliprocess/multithread deployment options, for example Starman. It is described in https://metacpan.org/module/YANICK/Dancer-1.3113/lib/Dancer/Deployment.pod#Running-on-Perl-webservers-with-plackup
I'd start by gluing Dancer to AnyEvent and using Twiggy to host the app. A google search turns up this, which looks like a good starting point.
http://blogs.perl.org/users/mstplbg/2010/12/using-anyevent-and-dancer.html
http://blogs.perl.org/users/mstplbg/2010/12/anyevent-and-dancer-condvars.html
http://blogs.perl.org/users/mstplbg/2011/03/long-running-requests-with-progress-bar-in-dancer-anyevent.html
You can use Dancer with plackup and Starman, here is a example:
foo.psgi:
#!/usr/bin/perl
use strict;
use warnings;
use Dancer2;
$| = 1;
get '/foo' => sub {
`sleep 5`;
'ok';
};
to_app;
Run the program with plackup:
$ plackup -s Starman foo.pl
Resolved [*]:5000 to [0.0.0.0]:5000, IPv4
Binding to TCP port 5000 on host 0.0.0.0 with IPv4
Setting gid to "0 0 0"
Starman: Accepting connections at http://*:5000/
Then run the following for loop:
for i in $(seq 1 3)
> do
> time curl http://localhost:5000/foo &
> done
Output:
ok
real 0m5.077s
user 0m0.004s
sys 0m0.010s
ok
real 0m5.079s
user 0m0.001s
sys 0m0.012s
ok
real 0m5.097s
user 0m0.009s
sys 0m0.004s
You can see Dancer2 can accept multiple request now.
Related
I have 2 independent python 2 applications running in the same linux (ubuntu) computer.
I want to send messages from one to another (bidirectional) and receives these messages inside a callback function.
Is it possible? Do you have any example as reference?
Thanks
There are different options available for communicating between python apps.
A simple one would be to use an API based on HTTP. Each application will expose an specific port and communication takes place by exchanging HTTP requests.
There are several frameworks that allow you to build it in few steps. For example, using Bottle:
In app1:
from bottle import route, run, request
#route('/action_1', method='POST')
def action_1_handler():
data = request.json
print(str(data))
# Do something with data
return {'success': True, 'data': {'some_data': 1}}
run(host='localhost', port=8080)
In app2:
import requests
r = requests.post("http://localhost:8080/action_1", json={'v1': 123, 'v2': 'foo'})
print r.status_code
# 200
data = r.json()
# {u'data': {u'some_data': 1}, u'success': True}
Note that if the action executed at app1 after receiving the HTTP request takes lot of time, this could result in a timeout error. In such a case, consider to run the action in another thread or use an alternative communication protocol (e.g. sockets, ZeroMQ Messaging Library).
Some related reads:
Basic Python client socket example
Communication between two python scripts
https://www.digitalocean.com/community/tutorials/how-to-work-with-the-zeromq-messaging-library
How can a PSGI application be served with many concurrent connections? I have tried event-based and preforking webservers but the number of concurrent connections seems to be limited by the number of worker processes. I've heard that for instance Node.js scales to several thousand parallel connections, can you achieve similar in Perl?
Here is a sample application that keeps connection open infinitely. The point is not to have infinite connections but to keep connections open long enough to hit connection limits:
my $app = sub {
my $env = shift;
return sub {
my $responder = shift;
my $writer = $responder->(['200', ['Content-Type' => 'text/plain' ]]);
my $counter=0;
while (1);
$writer->write(++$counter."\n");
sleep 1; # or non-blocking sleep such as Coro::AnyEvent::sleep
}
$writer->close;
};
};
I don't think you're supposed to have infinite loops inside apps, I think you're supposed to only setup a recurring timer, and in that timer notify/message/write... See Plack::App::WebSocket - WebSocket server as a PSGI application and Re^4: real-time output from Mojolicious WebSockets?
While I have not yet tried it I came across this question whilst searching for a solution to a problem faced when using a socket server to report on progress etc of long-running jobs. Initially I was thinking of an approach along the lines of ParallelUserAgent except as a server and not a client.
Returning to the problem a few days later after realising that Net::WebSocket::Server blocked new connection requests if a long-running block of code within the new connection handler callback.
My next approach will be split out the long running functionality to a new spawned shell process and use a DB to track the progress which can then be accessed as required within the server without lengthy blocking.
Thought I'd throw up my approach in case it helps anyone walking a similar path.
I want a request to a Mojolicious application to be able to trigger a long running job. The client doesn't need to wait for that long job to finish, so I'd like the app to send back a quick response and start the job. Here's what I have in mind:
use Mojolicious::Lite;
get '/foo' => sub {
my $self = shift;
$self->render( text => 'Thanks for requesting /foo. I will get started on that.' );
# ... force Mojolicious to send response now ...
do_long_running_job();
};
But when I write the code like this, the client doesn't receive the response until after the long running job is finished (which may trigger inactivity timeouts, etc.). Is there any way to send the response more quickly? Is there another way to structure my code/app to achieve this?
Things from the docs that looked promising but didn't work:
$self->rendered(200);
$self->res->finish;
Randal Schwartz's Watching long processes through CGI should help:
The child goes on, but it must first close STDOUT, because otherwise Apache will think there might still be some output coming for the browser, and won't respond to the browser or release the connection until this is all resolved. Next, we have to launch a child process of the child to execute …
We'll do this with a pipe-open which includes an implicit fork, in line 37. The grandchild process merges STDERR to STDOUT, and then executes …
The child (that is, the parent of the traceroute) reads from the filehandle opened from the STDOUT (and STDERR) …
In short, the child process scurries off to execute the command. …
Given that you are only interested in kicking off a process rather than watching it, you should be able to prune most of the code.
In my Catalyst app I have a very important connection to a remote server using SOAP with WSDL.
Everything works fine, but when the remote server goes down due to any reason, ALL my app waits until the timeout expires. EVERYTHING. ALL the controllers and processes, ALL the clients!!
If I set a 15 secs timeout for the SOAP LITE transport error, everything waits for 15 secs.
Any page from any user or connection can't be displayed during the timeout wait.
I use Fast CGI and Ngnix for the Catalyst app. If I use multiple fcgi processes when one waits, others take care of the connections, but if all of them try to access the faulty SOAP service... they all wait and wait for an answer until they reach their timeouts. When all of them are waiting, no more connections are allowed.
Looking for answers I have read somewhere that SOAP::LITE is "single threaded".
Is it true? Does it means that ALL my app, with ALL the visitors can only use one SOAP connection? It is hard to believe.
This is my code for the call:
sub check_result {
my ($self, $code, $IP, $PORT) = #_;
my $soap = SOAP::Lite->new( proxy => "http://$IP:$PORT/REMOTE_SOAP
+");
$soap->autotype(0);
$soap->default_ns('http://REMOTENAMESPACE/namespace/default');
$soap->transport->timeout(15);
$soap-> on_fault(sub { my($soap, $res) = #_;
eval { die ref $res ? $res->faultstring : $soap->transport->st
+atus };
return ref $res ? $res : new SOAP::SOM;
});
my $som = $soap->call("remote_function",
SOAP::Data->name( 'Entry1' )->value( $code ),
);
return $som->paramsout;
}
I also tried this slightly different approach kindly suggested at perlmonks, but nothing got better
Please, can someone point me in the rigth direction?
Migue
This is not a problem with SOAP::Lite or Catalyst per se. Pretty much any resource you query will most likely wait for the return (i.e.: file read on disk, database access). If the resource blocks for a long time, there's a chance that you could "starve" other requests while waiting for this return.
There's not an easy answer to this problem, but you could create a "job queue" that a separate process executes, then instead of calling the other service you would add the entry to the queue and get a token. When the request is finished, the queue stores the result associated with that token, then your app, in a separate request checks if the token you want already has a result or not.
There are specialized "job queue" frameworks, such as RabbitMQ, ApacheMQ and even some solutions on top of Redis. If your web application uses rich Javascript, you could even have the "job queue" notification reach the javascript client using, for instance, WebSockets, but otherwise, just poll every second to see if there is a response or not.
I'm writing an internal service that needs to touch a mod_perl2 instance for a long-running-process. The job is fired from a HTTP POST, and them mod_perl handler picks it up and does the work. It could take a long time, and is ready to be handled asynchronously, so I was hoping I could terminate the HTTP connection while it is running.
PHP has a function ignore_user_abort(), that when combined with the right headers, can close the HTTP connection early, while leaving the process running (this technique is mentioned here on SO a few times).
Does Perl have an equivalent? I haven't been able to find one yet.
Ok, I figured it out.
Mod_perl has the 'opposite' problem of PHP here. By default, mod_perl processes are left open, even if the connection is aborted, where PHP by default closes the process.
The Practical mod_perl book says how to deal with aborted connections.
(BTW, for the purposes of this specific problem, a job queue was lower on the list than a 'disconnecting' http process)
#setup headers
$r->content_type('text/html');
$s = some_sub_returns_string();
$r->connection->keepalive(Apache2::Const::CONN_CLOSE);
$r->headers_out()->{'Content-Length'} = length($s);
$r->print($s);
$r->rflush();
#
# !!! at this point, the connection will close to the client
#
#do long running stuff
do_long_running_sub();
You may want to look at using a job queue for this. Here is one provided by Zend that will let you start background processing jobs. There should be a number of these to choose from for php and perl.
Here's another thread that talks about this problem and an article on some php options. I'm not perl monk, so I'll leave suggestions on those tools to others.