Hello Eric,
on 12/01/2009 05:27 PM Eric Day said the following:
>>> That seems to be what dormando was suggesting, only pass a subset
>>> of request information to the worker, only what is required to make
>>> any decisions and respond with the result you need. Passing a few
>>> hundred bytes of form data to the worker is cheap, and can easily fit
>>> in the same TCP packets as the other protocol request information,
>>> so no extra overhead there if you are using Gearman.
>> I am afraid the point you are still missing is that often the Web script
>> only knows what information needs to be passed to the worker only after
>> it retrieves database records to know the state of the stored data. Only
>> after that it can decide what to do next.
>
> Actually, I'm fully aware of what is going on here. :) My point is
> that this is not a black box, you have some idea of what is happen,
> some context. We're also dealing with a finite amount of data, probably
> just a handful of fields from a web form. I'm not suggesting shipping
> the entire HTTP request over (although that would probably be fine
> too), but just the fields that you know you need. I understand the
> desire to keep things really generic, but like many things they all
> have trade-offs. I would focus more on reducing RTTs than total data
> sent with a single RTT.
Right, my point is that each Web script deals with several different use
cases. It needs to use different sets of information from the Web
request to determine what to do next. So, it is not a trivial job to
guess all the data that needs to be passed without checking what is in
the database.
Furthermore, there is another reason for wanting to just move the
database access layer to the workers. It is that we have already
separated that layer to individual model classes in our current
implementation.
Moving the model data access to the worker, is just a matter of
replacing in the client the current model classes by proxy classes that
provide the same API but make calls to workers. This is the easiest path
when upgrading from a single server approach (not based in Gearman) to a
distributed approach based in Gearman.
Meaning, it will dramatically cut the development cost of implementing
Gearman based distribution on existing code.
>>> Yes, most of us quite familiar with basic web scaling topics. :)
>>>
>>> What dormando was saying though is rather than using Gearman to manage
>>> your database connections, either use a direct database connections to
>>> other servers or use a database-specific load balancer/proxy. Gearman
>> I already explained that. If you keep doing database access directly
>> from your Web scripts, the scripts end up tying more memory, thus
>> reducing the ability of the Web server to handle more simultaneous requests.
>
> The same issue will come up in the workers, and like Apache, you just
> need to set a max # of requests per process to ensure the memory
> is given back into the kernel. I think Clint also mentined this in
> another email in this thread.
Right, but since workers will be distributed, if I need to handle more
requests, I just need to add more servers for the workers.
What happens is that if your sites are mostly for content serving, and
most of us develop such sites, 90% of the requests serve cached data. So
no worker access is needed. Single cache access, eventually to
memcached, will do.
However, if I keep doing database access on the Apache processes to
handle those 10% or less of the requests that needed, they will
increment significantly the usage of RAM on the Web server machines.
Thus reducing the ability to handle more Web server requests per server.
>>> was not designed to have transactional context within it. Once a job
>> That is what my proposal is aimed to improve.
>
> Understood, and I think there is some room for improvement in Gearman
> for further client->worker communication. I think the main thing
> people are questioning is this particular use case, since many of us
> have done something similar with Gearman, just without needing the
> extra communication.
Well I do not thing is such a particular case. I am sure a lot of us
have done plenty of content sites, on which most data comes from a
database and is cached somewhere to avoid further database access. Other
than that, if you need to change content, you need to do it
consistently, usually encapsulating it in a database transaction.
All those types of requests that require database access, even though
they represent 10% or less of the Web requests, those are the ones that
make the RAM usage of Web server processes, eventually double, depending
on what you are doing.
>> What I am saying is that after a worker executes a job that is part of
>> multi-request process, if the client disconnected for some reason, the
>> job server just needs to send a new message to the worker telling that,
>> so the worker can do what it needs to do, eventually rolling back an
>> ongoing database transaction. This is the same with databases.
>
> So, right now the job server does not have any means in the protocol
> to notify workers of client activity (ie, the attached client on the
> other end is gone). This is because many Gearman use cases expect
> clients to be transient. They can attach/detach and have the jobs
> coalesced by unique key without the worker even knowing what's going
> on. If the functionality you propose were to be added, what happens
> if two clients are connected and just one disconnects? Do you only
> notify workers when all disconnect? Do you notify when more than one
> connect? This also assumes the worker pauses to check for new status
> from the job server during execution of the jobs. Unfortunately it's
> not just a matter of adding in a new protocol command, it changes
> the semantics of the job server in a way that may not be able to be
> backwards compatible with how Gearman works today.
No, that is not my proposal. Here is a draft of some pseudo-code:
1. Client connects and sends the first job request of a multi-request
access. It also tells what (rollback) job the worker should execute, in
case the transaction fails because the client disconnected before the
final request.
2. Job server assigns an ID to that multi-request access, assigns and
reserves a worker to that multi-request access, send the first job
request to the worker.
3. Worker gets the request, executes the job, sends response to the job
server, waits for the next request.
4. job server gets response from worker passing it back to the client
along with the multi-request ID assigned in step 2.
5. client gets the multi-request id and the first job response, does
whatever he wants.
6. client sends a new multi-request job request along with the ID
returned by the server, and some information telling the server whether
it is the final request.
7. server gets the client request, looks up for the worker that was
reserved for the the given multi-request ID, forwards the request to
that worker.
8. Repeat from 3 if it was not a final request. Otherwise, after getting
the response from the work and passing it to the client, just free the
ID assigned for this multi-request access.
Exception: if after getting the response from the worker, the client
disconnected, just send a new job to the worker defined in step one
precisely for the case when the client disconnects.
I am not sure if I covered all the cases. Anyway, the protocol to
communicate with the worker does not change because it is never aware
that is a part of multi-request access.
As for the protocol to communicate with the client, it seems to need to
support new types of message to accomodate the additional information
related with multi-request accesses (ID, and additional rollback job
defined in step 1);
So, to the question whether the protocol needs to be changed, the answer
seems to be yes, but I do not think it will change the existing types of
messages exchanged, only new ones to add.
>>> In another thread you ask about contributing to Gearman. Check out
>>> all the various projects on the
gearman.org download page. Adding
>>> some features is easy if it's just client or server behavior. New
>>> protocol changes are not trivial because to be useful within the
>>> community it needs to be generally accepted and implemented by a
>>> handful of project maintainers. Sending out any such proposals to
>>> the mailing list for community feedback is a good way to start.
>> I still need to study the protocol, in order to determine if it needs to
>> be extended. Maybe not. I will post more on this once I figure out.
>
> The protocol is fairly simple, but there are some behaviors that
> come from it that will make it hard to extend Gearman in the way you
> want. I could possibly see adding a command that allows a client to
> send more data to a connected worker, but the trick here is having
> workers receive this data while avoiding blocking conditions. It also
> ends up being more data to track and manage in the job server should
> the worker die and it needs to be executed again on another worker.
I don't know if the pseudo-code above was clear enough, but when the
client disconnects, the server does not need to communicate with the
worker until the worker ends what it is doing. Only when the worker is
done, the server sends the (rollback) job request defined in step 1.
As for when the worker dies, you just need to return to the client
whatever error condition that is returned for simple request accesses.