Alexander Rojas created MESOS-3705:
--------------------------------------

             Summary: HTTP Pipelining doesn't keep order of requests
                 Key: MESOS-3705
                 URL: https://issues.apache.org/jira/browse/MESOS-3705
             Project: Mesos
          Issue Type: Bug
          Components: libprocess
    Affects Versions: 0.24.0
            Reporter: Alexander Rojas
            Assignee: Alexander Rojas


[HTTP 1.1 Pipelining|https://en.wikipedia.org/wiki/HTTP_pipelining] describes a 
mechanism by which multiple HTTP request can be performed over a single socket. 
The requirement here is that responses should be send in the same order as 
requests are being made.

Libprocess has some mechanisms built in to deal with pipelining when multiple 
HTTP requests are made, it is still, however, possible to create a situation in 
which responses are scrambled respected to the requests arrival.

Consider the situation in which there are two libprocess processes, 
{{processA}} and {{processB}}, each running in a different thread, {{thread2}} 
and {{thread3}} respectively. The 
[{{ProcessManager}}|https://github.com/apache/mesos/blob/1d68eed9089659b06a1e710f707818dbcafeec52/3rdparty/libprocess/src/process.cpp#L374]
 runs in {{thread1}}.

{{processA}} is of type {{ProcessA}} which looks roughly as follows:

{code}
class ProcessA : public ProcessBase<ProcessA>
{
public:
  ProcessA() {}

  Future<http::Response> foo(const http::Request&) {
    // … Do something …
   return http::Ok();
  }

protected:
  virtual void initialize() {
    route("/foo", None(), &ProcessA::foo);
  }
}
{code}

{{processB}} is from type {{ProcessB}} which is just like {{ProcessA}} but 
routes {{"bar"}} instead of {{"foo"}}.

The situation in which the bug arises is the following:

# Two requests, one for {{"http://server_uri/(1)/foo"}} and one for 
{{"http://server_uri/(2)//bar"}} are made over the same socket.
# The first request arrives to 
[{{ProcessManager::handle}}|https://github.com/apache/mesos/blob/1d68eed9089659b06a1e710f707818dbcafeec52/3rdparty/libprocess/src/process.cpp#L2202]
 which is still running in {{thread1}}. This one creates an {{HttpEvent}} and 
delivers to the handler, in this case {{processA}}.
# 
[{{ProcessManager::deliver}}|https://github.com/apache/mesos/blob/1d68eed9089659b06a1e710f707818dbcafeec52/3rdparty/libprocess/src/process.cpp#L2361]
 enqueues the HTTP event in to the {{processA}} queue. This happens in 
{{thread1}}.
# The second request arrives to 
[{{ProcessManager::handle}}|https://github.com/apache/mesos/blob/1d68eed9089659b06a1e710f707818dbcafeec52/3rdparty/libprocess/src/process.cpp#L2202]
 which is still running in {{thread1}}. Another {{HttpEvent}} is created and 
delivered to the handler, in this case {{processB}}.
# 
[{{ProcessManager::deliver}}|https://github.com/apache/mesos/blob/1d68eed9089659b06a1e710f707818dbcafeec52/3rdparty/libprocess/src/process.cpp#L2361]
 enqueues the HTTP event in to the {{processB}} queue. This happens in 
{{thread1}}.
# {{Thread2}} is blocked, so {{processA}} cannot handle the first request, it 
is stuck in the queue.
# {{Thread3}} is idle, so it picks up the request to {{processB}} immediately.
# 
[{{ProcessBase::visit(HttpEvent)}}|https://github.com/apache/mesos/blob/1d68eed9089659b06a1e710f707818dbcafeec52/3rdparty/libprocess/src/process.cpp#L3073]
 is called in {{thread3}}, this one in turn 
[dispatches|https://github.com/apache/mesos/blob/1d68eed9089659b06a1e710f707818dbcafeec52/3rdparty/libprocess/src/process.cpp#L3106]
 the response's future to the {{HttpProxy}} associated with the socket where 
the request came.

At the last point, the bug is evident, the request to {{processB}} will be send 
before the request to {{processA}} even if the handler takes a long time and 
the {{processA::bar()}} actually finishes before. The responses are not send in 
the order the requests are done.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to