You are viewing a plain text version of this content. The canonical link for it is here.
Posted to serf-dev@apr.apache.org by Ian Holsman <ia...@apache.org> on 2001/10/02 07:13:16 UTC
API for the serf
has anyone got a list of things that they want the client to do?
we could use this as a 'STATUS/Wish' list.
Here's are some of the things I would find usefull:
* Simple 'GET/Post/Head' function just does it and returns
the contents in a bucket-brigade
* Async version of above.. (like LWP::Parallel) I just push
GET requests and it notifies me when there is an event for
one of them.
* filters used for 'serf' as similiar in syntax/use to HTTPD
* HTTP/1.1 Support
* SSL Support
* Connection Pooling per server (ie we keep a max of n open connections
to a server and we re-use these on different requests)
* send requests to a server from a list of servers/ports (via round-robin)
what do you guys think?
Re: API for the serf
Posted by Greg Stein <gs...@lyra.org>.
On Tue, Oct 02, 2001 at 02:13:29AM -0700, Roy T. Fielding wrote:
> > I added a docs/ directory, but am pending on checking in a roadmap.txt until
> > we get the apr-serf repository added into avail. I'll dig up Sander's email
> > and add those, too.
>
> apr-serf is now in avail.
Cool. Thanks!
--
Greg Stein, http://www.lyra.org/
Re: API for the serf
Posted by "Roy T. Fielding" <fi...@ebuilt.com>.
> I added a docs/ directory, but am pending on checking in a roadmap.txt until
> we get the apr-serf repository added into avail. I'll dig up Sander's email
> and add those, too.
apr-serf is now in avail.
....Roy
Re: API for the serf
Posted by Greg Stein <gs...@lyra.org>.
On Mon, Oct 01, 2001 at 10:13:16PM -0700, Ian Holsman wrote:
> has anyone got a list of things that they want the client to do?
Sander posted a short list in the initial proposal, which was a good
snapshot of a discussion between the two of us the other night.
> we could use this as a 'STATUS/Wish' list.
I added a docs/ directory, but am pending on checking in a roadmap.txt until
we get the apr-serf repository added into avail. I'll dig up Sander's email
and add those, too.
For now, it is just a random set of notes, but it can be refined as we reach
consensus here.
>...
> * Simple 'GET/Post/Head' function just does it and returns
> the contents in a bucket-brigade
Right.
I would suggest familiarizing yourself with the Neon API. In particular,
this point is similar to the functions in ne_basic.h
> * Async version of above.. (like LWP::Parallel) I just push
> GET requests and it notifies me when there is an event for
> one of them.
In the proposal, we discussed the notion that you can do a push/pull on each
side of the request/response sequence. In your scenario above, the API would
contain an API such as "serf_process(ctx)" which enters into a select/poll
loop to deliver any pending requests, and then to call back to the client
when responses arrive.
The API should be thread capable so that serf_process() and its callbacks
can execute on a thread (while, say, another thread is pushing requests).
Another approach to handling requests is the synchronous ("pull") fashion:
brigade = serf_get(connection, url, ...)
The above would synchronously push the request, then wait for the response
to arrive. Note that pipelining requests is still possible in the pull
model:
serf_send_request(connection, "GET", url1, ...)
serf_send_request(connection, "GET", url2, ...)
serf_send_request(connection, "GET", url3, ...)
bb1 = serf_get_response(connection, ...)
bb2 = serf_get_response(connection, ...)
bb3 = serf_get_response(connection, ...)
(I use ... because I'm not sure what all args might also be needed)
Requests can also be push/pull:
pull:
serf_note_request(connection, my_callback)
serf_process(ctx)
push:
serf_send_request(connection, ...)
serf_process(ctx)
> * filters used for 'serf' as similiar in syntax/use to HTTPD
They come in two directions: push and pull. Push is like the output stack in
httpd (data is pushed through the stack). Pull is like the input stack --
data is pulled up thru the stack.
I believe that we can architect all filters as push filters. If we want to
use them in a pull fashion, then we can do something like:
defined stack: network <-> F1 <-> F2 <-> app
serf_get_brigade()
{
/* network */
brigade = read_socket()
/* F1 and F2 chain */
temp_chain = F1
temp_chain->next = F2
temp_chain->next->next = gatherer
pass_brigade(temp_chain, brigade)
return gatherer->collected
}
We're essentially "pushing" the data up the stack and collecting the
resulting brigade in a "gatherer" filter. The collected brigade is then
returned from the get_brigade function.
Since all filters are written as a push filter, and they can be used in both
directions, then we don't have httpd's dual model for coding filters,
meaning that we don't have to have to implementations of a chunk or dechunk
filter.
> * HTTP/1.1 Support
IMO, we *only* deliver HTTP/1.1 requests. I don't believe there is any
reason for us to ever send a 1.0 request.
We must support HTTP/1.0 and HTTP/1.1 responses, though. It could be argued
that we need to support HTTP/0.9 responses, but I'd say "screw that"
[ an app can never know if a target server requires an HTTP/1.0 request; if
we presume that the app *does* know, and can call a function to set the
use of the HTTP/1.0 protocol, then it should just be coded to call a
different library. ]
> * SSL Support
Absolutely.
> * Connection Pooling per server (ie we keep a max of n open connections
> to a server and we re-use these on different requests)
Hmm. Possibly. I can certainly see the utility of this.
> * send requests to a server from a list of servers/ports (via round-robin)
This is just part of the pooling -- the connection pool can use a full list
of server/ports for its connections. Ideally, we could just use the linked
list of apr_sockaddr_t structures returned from apr_sockaddr_info_get().
Cheers,
-g
--
Greg Stein, http://www.lyra.org/
Re: API for the serf
Posted by Greg Stein <gs...@lyra.org>.
On Tue, Oct 02, 2001 at 09:15:09AM -0700, Ian Holsman wrote:
> On Tue, 02 Oct 2001 07:08:47 -0700, Aaron Bannert wrote:
> > On Tue, Oct 02, 2001 at 02:30:26AM -0700, Greg Stein wrote:
>...
> >> I generally agree that it is an advanced concept and possibly able to
> >> relegate to the app, but I also think that many apps will want multiple
> >> connections and multiple outstanding requests. Thus, a pool of
> >> connections.
> >
> > Something to be built upon our base library.
>
> true,
> the pool would allow you to perform low-latency requests to a application
> server, by creating the connection and re-using it over and over, instead
> of creating/tearing-down the connection for every request.
That is an aspect of persistent connections, and is unrelated to pools of
connections.
>...
> you could program the pool so that it has multiple servers it talks to
> for load balancing, where a client may issue multiple 'gets' to the same
> 'pool' and they may be served from multiple machines/ports, invisible to
> the calling program
Absolutely!
I think this is pretty much a given. See my post about this stuff.
Cheers,
-g
--
Greg Stein, http://www.lyra.org/
Re: API for the serf
Posted by Ian Holsman <ia...@apache.org>.
On Tue, 02 Oct 2001 07:08:47 -0700, Aaron Bannert wrote:
> On Tue, Oct 02, 2001 at 02:30:26AM -0700, Greg Stein wrote:
>> On Mon, Oct 01, 2001 at 11:54:44PM -0700, Justin Erenkrantz wrote:
>> > > * Connection Pooling per server (ie we keep a max of n open
>> > > connections
>> > > to a server and we re-use these on different requests)
>> >
>> > Eh, I'm not terribly sure about this though. I'm not sure how you
>> > would get the lifetimes right. Ideally, the connections should
>> > timeout themselves. I guess we could enforce the lifetimes with
>> > socket timeouts (but that'd only be on our side not the server side).
>> > I think that if you want connection-pooling, that *might* be outside
>> > of the scope of this library. But, I'm not really sure. Thoughts?
>>
>> All of this would be subject to various parameters and controls, TBD.
>>
>> I generally agree that it is an advanced concept and possibly able to
>> relegate to the app, but I also think that many apps will want multiple
>> connections and multiple outstanding requests. Thus, a pool of
>> connections.
>
> Something to be built upon our base library.
true,
the pool would allow you to perform low-latency requests to a application
server, by creating the connection and re-using it over and over, instead
of creating/tearing-down the connection for every request.
The lifetime of a connection would handled by the server in this case, as
keep-alives are currently done.
you could program the pool so that it has multiple servers it talks to
for load balancing, where a client may issue multiple 'gets' to the same
'pool' and they may be served from multiple machines/ports, invisible to
the calling program
..Ian
>
> [snip]
>
> -aaron
Re: API for the serf
Posted by Greg Stein <gs...@lyra.org>.
On Tue, Oct 16, 2001 at 08:51:38AM -0700, Aaron Bannert wrote:
>...
> Yes. These seem like some of the same issues that have come up lately on
> httpd. I think the problem in semantics here comes from the fact that all
> filters are being forced to define their data requirements in terms of
> bytes, when that isn't really what unit of data they deal with internally.
> A Dechunk filter only cares about chunks and chunk tags, for example.
A stream is only bytes. We can't really define the interfaces between the
filters in any other way.
> ...
> > > Also, since some filters may be provided
> > > by our library (chunk, ssl, basic auth, various header manipulations, etc)
> > > and some will be provided by the application (flood will have a content-length
> > > verification filter, a webservices thingy could render some xml, etc), and
> >
> > Yes, although auth isn't really a filter. There is a lot of high-level
> > processing related to auth (think about failing auth, asking the app for
> > auth data, then re-submitting the request; a filter can't do that).
>
> I don't follow you. If a filter detects that auth fails, it passes a poison
> pill down the filter chain. I don't know what you mean by asking the app
> for auth data, the app should have inserted a filter to do this, no?
When authentication fails, the application needs to resend the request with
new auth info. So... *something* needs to ask for auth data, and something
needs to resend.
My point was that those activities don't belong within the filter chain, but
at the app level. Thus, your listig of "basic auth" as a possible filter
doesn't make sense -- a filter can't generate a new request since it is
really only about processing a response for an existing request/response.
Yes, it could be possible to replace the response brigade with an "error"
brigade detailing the auth failure. In that sense, you could do a small bit
of auth handling as a filter, but really: it is just looking at a single
header.
> > > since it seems that most of the power of our library will be in the filters,
> > > I don't see why the application will care if it's push or pull.
> >
> > The app will have data pushed at it, or the app will pull data from the
> > library. Transparent to the app, some filters will execute in there.
>
> When I consider the app, I'm picturing it as a control mechanism for
> this filter chain, where it has already inserted strategic filters of
> its own into the chain and then triggered a push or pull on the chain.
> I don't see data spilling out the end of the chain, but I may not be
> seeing the whole picture yet.
If the network layer pushes data into the response chain, then the terminus
of that chain could perform all handling / consumption of the response.
If the application *pulls* the response, then data does "fall out" of the
chain.
For a push model, I would agree with you: the app just sets up the chains,
shoves requests down the request chain, and then spins up the network
processing loop (to wait for an process responses).
On a separate note: my comment above made me think that "request chain" and
"response chain" might be better than "input chain" or "output chain". They
describe what is going through them much better.
>...
> I have some thoughts about this in the design drifting on the flotsam in
> my head, but the details are not yet clear. I think the main things we
> have here are: 1) the app controls how filters are ordered in the chain,
> 2) we can create utilities that the app can use to order the chain (these
> utils can be complex enough so as to completely hide the ordering), 3)
> I completely agree that filters should know nothing about the filters
> before or after it in the chain.
Agreed.
Cheers,
-g
--
Greg Stein, http://www.lyra.org/
Re: API for the serf
Posted by Aaron Bannert <aa...@clove.org>.
[...]
> We may all be agreeing here. All that we can do at this point is just move
> forwards. If some particular change or line of development seems to be
> moving the library "too far" from its original charter, then we can discuss
> it then. *if* it even comes up :-)
Agreed.
> > I'll agree that we can mix sync/async here (will the distinction be fragile?),
>
> I'm not sure what you mean by "fragile" here. Do you mean in the sense that
> we can't mix the modes easily? Or that you must set it up "just so" do do
> one mode, yet "like this" for the other mode? And that it won't be obvious
> which, so you'd usually end up with a broken setup?
I'm not really sure. But those are good things to keep in mind when we start
designing these interfaces.
> Personally, I think we can have an API that easily flows and can handle the
> different modes.
>
> > but I'm not quire sure I understand how this will work internally to the
> > filters. I think one of the bigger hurdles in handling push vs. pull on
> > input filters is where the buffers come from. I'll have to think about this
> > some more though...
>
> See one of my other posts, where I talk about turning a push filter into a
> pull filter. Essentially, a person should always write their filter as a
> "push" filter (like the output filters in httpd). If we want to run the
> filter in a "pull" mode (something wants to pull data through a filter
> chain), then we have a way to "flip" the chain and push data through in a
> way that ends up as a "pull".
>
> Let's say that you want to operate the response stack in a pull mode (the
> app is saying "give me more of the response"). The app calls
> serf_get_response() to get a brigade with more of the response. Inside that
> function, the network code creates a brigade with some socket data. That
> data is then pushed through the response filters. Whatever pops out the
> other side is then returned from serf_get_response().
>
> We may have some issues with limiting the amount of data which is processed.
> For example, if the app requests 200 bytes, but after pushing data through
> the response stack, we end up with 300 bytes... we can easily save aside the
> extra 100 bytes. But what happens if that happens *internally* to the stack?
>
> A bit of thought needed there.
>
> [ in particular, if F1 generates more data than F2 needs/wants, then should
> F2 set it aside? what if F2 is tossed and F3 is brought in, and should
> have received that data? ]
Yes. These seem like some of the same issues that have come up lately on
httpd. I think the problem in semantics here comes from the fact that all
filters are being forced to define their data requirements in terms of
bytes, when that isn't really what unit of data they deal with internally.
A Dechunk filter only cares about chunks and chunk tags, for example.
...
> > Also, since some filters may be provided
> > by our library (chunk, ssl, basic auth, various header manipulations, etc)
> > and some will be provided by the application (flood will have a content-length
> > verification filter, a webservices thingy could render some xml, etc), and
>
> Yes, although auth isn't really a filter. There is a lot of high-level
> processing related to auth (think about failing auth, asking the app for
> auth data, then re-submitting the request; a filter can't do that).
I don't follow you. If a filter detects that auth fails, it passes a poison
pill down the filter chain. I don't know what you mean by asking the app
for auth data, the app should have inserted a filter to do this, no?
> > since it seems that most of the power of our library will be in the filters,
> > I don't see why the application will care if it's push or pull.
>
> The app will have data pushed at it, or the app will pull data from the
> library. Transparent to the app, some filters will execute in there.
When I consider the app, I'm picturing it as a control mechanism for
this filter chain, where it has already inserted strategic filters of
its own into the chain and then triggered a push or pull on the chain.
I don't see data spilling out the end of the chain, but I may not be
seeing the whole picture yet.
> >...
> > That brings up a good point. We have an opportunity to come up with a
> > scheme for the ordering of filters that could potentially be more flexible
> > than the one for HTTP. (I think they are under more constraints). Suggestions?
>
> Filters should operate independent of what comes before/after themselves.
> That means that a higher-level entity is responsible for ordering them
> properly since a filter can't examine its neighbors and place itself
> accordingly.
>
> That said: even though a filter can operate "anywhere", it can also describe
> itself to some extent to the library/app about where it "should" go. This is
> the model used by httpd (filter type). However, httpd has a lot of extra goo
> for adding/removing those things. I don't know how much of that is needed.
I have some thoughts about this in the design drifting on the flotsam in
my head, but the details are not yet clear. I think the main things we
have here are: 1) the app controls how filters are ordered in the chain,
2) we can create utilities that the app can use to order the chain (these
utils can be complex enough so as to completely hide the ordering), 3)
I completely agree that filters should know nothing about the filters
before or after it in the chain.
-aaron
Re: API for the serf
Posted by Greg Stein <gs...@lyra.org>.
On Tue, Oct 02, 2001 at 07:02:04AM -0700, Aaron Bannert wrote:
> On Tue, Oct 02, 2001 at 02:30:26AM -0700, Greg Stein wrote:
> > On Mon, Oct 01, 2001 at 11:54:44PM -0700, Justin Erenkrantz wrote:
> > > Sure. I'd like to make it able to speak any protocol that
> > > has similar functionality to HTTP but isn't quite HTTP/1.1 - i.e.
> > > try to be as protocol-agnostic as we can make it.
> >
> > Euh... let's do HTTP/1.1 *today*. At some point in the future, we can look
> > back and see what kinds of tweaks/changes are necessary to meet other needs.
> > Just remember that our charter is based solely on an HTTP client library.
> > *Not* a general purpose "http-like" protocol library.
> >
> > Say "oh, but protocol X uses request/response, too... let's add that!" is
> > out of bounds for 1.0 :-)
>
> I'm going to have to sort-of agree with Justin on this one. Although I don't
> think we should go all out for a generic request/response meta-protocol API,
> it would be in our best interest to be as protocol-agnostic as possible, at
> least under the umbrella of HTTP.
We may all be agreeing here. All that we can do at this point is just move
forwards. If some particular change or line of development seems to be
moving the library "too far" from its original charter, then we can discuss
it then. *if* it even comes up :-)
>...
> > See my previous response to Ian, and my notes about the initial proposal. I
> > really think we can create an API that easily moves between the push/pull
> > and sync/async models.
>...
> I'll agree that we can mix sync/async here (will the distinction be fragile?),
I'm not sure what you mean by "fragile" here. Do you mean in the sense that
we can't mix the modes easily? Or that you must set it up "just so" do do
one mode, yet "like this" for the other mode? And that it won't be obvious
which, so you'd usually end up with a broken setup?
Personally, I think we can have an API that easily flows and can handle the
different modes.
> but I'm not quire sure I understand how this will work internally to the
> filters. I think one of the bigger hurdles in handling push vs. pull on
> input filters is where the buffers come from. I'll have to think about this
> some more though...
See one of my other posts, where I talk about turning a push filter into a
pull filter. Essentially, a person should always write their filter as a
"push" filter (like the output filters in httpd). If we want to run the
filter in a "pull" mode (something wants to pull data through a filter
chain), then we have a way to "flip" the chain and push data through in a
way that ends up as a "pull".
Let's say that you want to operate the response stack in a pull mode (the
app is saying "give me more of the response"). The app calls
serf_get_response() to get a brigade with more of the response. Inside that
function, the network code creates a brigade with some socket data. That
data is then pushed through the response filters. Whatever pops out the
other side is then returned from serf_get_response().
We may have some issues with limiting the amount of data which is processed.
For example, if the app requests 200 bytes, but after pushing data through
the response stack, we end up with 300 bytes... we can easily save aside the
extra 100 bytes. But what happens if that happens *internally* to the stack?
A bit of thought needed there.
[ in particular, if F1 generates more data than F2 needs/wants, then should
F2 set it aside? what if F2 is tossed and F3 is brought in, and should
have received that data? ]
>...
> I'm still trying to get a grip on this filters stuff, so correct me if I'm
> wrong here. To me it seems that filters blend the lines between the push
> vs. pull models.
Euh... no, I don't think they blend it. They are used in both models, but
they are pretty much used differently.
> A filter doesn't really care if the library or the app
> triggered the pass on the filter.
Correct. It should live in its own little world. It shouldn't know what is
before/after itself, it shouldn't know why it was invoked, it should have
all of the context it needs, etc.
> Also, since some filters may be provided
> by our library (chunk, ssl, basic auth, various header manipulations, etc)
> and some will be provided by the application (flood will have a content-length
> verification filter, a webservices thingy could render some xml, etc), and
Yes, although auth isn't really a filter. There is a lot of high-level
processing related to auth (think about failing auth, asking the app for
auth data, then re-submitting the request; a filter can't do that).
> since it seems that most of the power of our library will be in the filters,
> I don't see why the application will care if it's push or pull.
The app will have data pushed at it, or the app will pull data from the
library. Transparent to the app, some filters will execute in there.
>...
> That brings up a good point. We have an opportunity to come up with a
> scheme for the ordering of filters that could potentially be more flexible
> than the one for HTTP. (I think they are under more constraints). Suggestions?
Filters should operate independent of what comes before/after themselves.
That means that a higher-level entity is responsible for ordering them
properly since a filter can't examine its neighbors and place itself
accordingly.
That said: even though a filter can operate "anywhere", it can also describe
itself to some extent to the library/app about where it "should" go. This is
the model used by httpd (filter type). However, httpd has a lot of extra goo
for adding/removing those things. I don't know how much of that is needed.
>...
> > The serf will have both chunking and dechunking code. Since the request
> > could be "pushed" at the library, chunking is required. It is also possible
> > to give a brigade to the serf and it could compute the length and send a
> > request with a Content-Length header.
> >
> > On the response side, we'll definitely have dechunking.
>
> Stuff to add to the STATUS :)
Hmm? We have a lot of this in the feature/design roadmap. What exactly needs
to be added, where?
>...
> > I generally agree that it is an advanced concept and possibly able to
> > relegate to the app, but I also think that many apps will want multiple
> > connections and multiple outstanding requests. Thus, a pool of connections.
>
> Something to be built upon our base library.
We could have /core be the very base library. Then we could add the session
groups and things in /session or something. Not really sure. It would kind
of suck to have a single .c file per directory, so this might simply go into
/core. (i.e. it really depeneds on how much code is necessary for some of
the various feature groups)
Cheers,
-g
--
Greg Stein, http://www.lyra.org/
Re: API for the serf
Posted by Aaron Bannert <aa...@clove.org>.
On Tue, Oct 02, 2001 at 02:30:26AM -0700, Greg Stein wrote:
> On Mon, Oct 01, 2001 at 11:54:44PM -0700, Justin Erenkrantz wrote:
> > Sure. I'd like to make it able to speak any protocol that
> > has similar functionality to HTTP but isn't quite HTTP/1.1 - i.e.
> > try to be as protocol-agnostic as we can make it.
>
> Euh... let's do HTTP/1.1 *today*. At some point in the future, we can look
> back and see what kinds of tweaks/changes are necessary to meet other needs.
> Just remember that our charter is based solely on an HTTP client library.
> *Not* a general purpose "http-like" protocol library.
>
> Say "oh, but protocol X uses request/response, too... let's add that!" is
> out of bounds for 1.0 :-)
I'm going to have to sort-of agree with Justin on this one. Although I don't
think we should go all out for a generic request/response meta-protocol API,
it would be in our best interest to be as protocol-agnostic as possible, at
least under the umbrella of HTTP.
> > I'd like to see this client API be
> > able to handle that as well.
>
> In truth, I think the API is going to be very damned flexibile and *could*
> support other protocols. But let's *please* not go down that rathole until
> we have a 1.0 release? Please?
>
> Just having an HTTP client library is a *big* win in an of itself.
Agreed. To be clear on my point, as long as we support HTTP in current and
future versions "as well as possible" then I'm happy.
> > > * Async version of above.. (like LWP::Parallel) I just push
> > > GET requests and it notifies me when there is an event for
> > > one of them.
> >
> > I'm just not sure that we really want to make the API event-based.
> > I'm really not a fan of event-based or callback-based programming
> > (if you want event-based, use libwww in its various incarnations).
> > I think it makes things too confusing. I much prefer the
> > paralleism to be at the thread-level rather than select/poll-based.
>
> See my previous response to Ian, and my notes about the initial proposal. I
> really think we can create an API that easily moves between the push/pull
> and sync/async models.
>
> You can ask for a response's brigade (and the lib will fetch it off the
> wire), or the library will call you with the brigade. We're talking just a
> minor difference in how the app uses the library. Both models focus on the
> brigade, but the call sequence is something like:
>
> serf_send_request(session, req_brigade, NULL)
> :
> resp_brigade = serf_get_response(session)
> or
> serf_send_request(session, req_brigade, response_cb)
> :
> serf_process(ctx)
>
> apr_status_t response_cb(resp_brigade) { ... }
I'll agree that we can mix sync/async here (will the distinction be fragile?),
but I'm not quire sure I understand how this will work internally to the
filters. I think one of the bigger hurdles in handling push vs. pull on
input filters is where the buffers come from. I'll have to think about this
some more though...
> >...
> > also find that most web tasks don't need to be event-driven -
>
> In Subversion, we need to push request data at the network (yet,
> unfortunately, Neon wants to pull data). On the response side, we want the
> network to push data at Subversion (which Neon does).
>
> So for the response, I would say that serf needs to have a callback mode for
> delivering the response.
I'm still trying to get a grip on this filters stuff, so correct me if I'm
wrong here. To me it seems that filters blend the lines between the push
vs. pull models. A filter doesn't really care if the library or the app
triggered the pass on the filter. Also, since some filters may be provided
by our library (chunk, ssl, basic auth, various header manipulations, etc)
and some will be provided by the application (flood will have a content-length
verification filter, a webservices thingy could render some xml, etc), and
since it seems that most of the power of our library will be in the filters,
I don't see why the application will care if it's push or pull.
> > they are all essentially parallel tasks. I think you sacrifice
> > too much of the API to get callbacks and async.
>
> I don't buy this. I'm not seeing that a "sacrifice" is going to happen.
> Let's see what happens. I suspect the presence of callbacks is not going to
> bug you, as long as you have the sync mode.
Agreed.
> > > * filters used for 'serf' as similiar in syntax/use to HTTPD
> >
> > One thing I'd like to see is that we use filter framework as what
> > is already in httpd.
>
> No, on several accounts.
>
> The presence of f->r and f->c is severely whacked. The filter chain should
> operate independently of any global context. "Reaching out" is bad juju.
>
> I also don't believe the registration and naming of filters is useful for
> the serf. We're a library, not an application. The notion of names and
> simplified insertion is an application concept.
>
> [ that said: attaching a name to a filter could be useful for debugging,
> much like we have names for buckets ]
>
> Hmm. That is a good analogy: the filters are going to be referenced,
> inserted, etc, much more like buckets. We'd have some static structure
> defining the filter, and we simply call a function to insert the bugger in
> the filter chain.
That brings up a good point. We have an opportunity to come up with a
scheme for the ordering of filters that could potentially be more flexible
than the one for HTTP. (I think they are under more constraints). Suggestions?
> > This is good in two respects - we force
> > ourselves to clean up the filtering API in httpd (most of us are
> > active in httpd as well) and we can reuse the same code in both
> > places.
>
> Agreed on both accounts. However, I would suggest that it goes in the other
> direction. *We* define a Good filter stack and httpd moves towards it. We
> don't have the legacy stuff with the headers, nor the needs of f->r and f->c
> to get in our way of doing it Right.
I totally agree. ++1
> The serf will have both chunking and dechunking code. Since the request
> could be "pushed" at the library, chunking is required. It is also possible
> to give a brigade to the serf and it could compute the length and send a
> request with a Content-Length header.
>
> On the response side, we'll definitely have dechunking.
Stuff to add to the STATUS :)
> > > * SSL Support
> >
> > flood already does this with OpenSSL, so I think it should be
> > straightforward as most of the heavy lifting has already been
> > done.
>
> You betcha :-)
>
> IMO, I don't see that we need to use an SSL filter. I think the terminal
> filter (analog to CORE_IN / CORE_OUT) could simply handle SSL as necessary.
That's how flood does it.
> > Client certs might need to be added, but that's not too hard.
>
> Yes, they will be needed. (/me thinking of SVN)
Ah yes. Very useful indeed. Keep thinking of the client-side of webapps
("webservices") too.
> > > * Connection Pooling per server (ie we keep a max of n open connections
> > > to a server and we re-use these on different requests)
> >
> > Eh, I'm not terribly sure about this though. I'm not sure how you
> > would get the lifetimes right. Ideally, the connections should
> > timeout themselves. I guess we could enforce the lifetimes with
> > socket timeouts (but that'd only be on our side not the server
> > side). I think that if you want connection-pooling, that *might* be
> > outside of the scope of this library. But, I'm not really sure.
> > Thoughts?
>
> All of this would be subject to various parameters and controls, TBD.
>
> I generally agree that it is an advanced concept and possibly able to
> relegate to the app, but I also think that many apps will want multiple
> connections and multiple outstanding requests. Thus, a pool of connections.
Something to be built upon our base library.
[snip]
-aaron
Re: API for the serf
Posted by Greg Stein <gs...@lyra.org>.
On Tue, Oct 02, 2001 at 11:39:25AM +0200, Daniel Stenberg wrote:
> On Tue, 2 Oct 2001, Greg Stein wrote:
>
> > > Client certs might need to be added, but that's not too hard.
> >
> > Yes, they will be needed. (/me thinking of SVN)
>
> I might be able to assist with some already written libcurl code that does
> this.
>
> Further, SSL session ID caching should be considered for those SSL
> connections that don't get persistant.
Ah. Good point.
In my next post, I'm going to brain dump a discussion Sander and I just had
over AIM. There is a high-level data element where those IDs can be dropped.
Cheers,
-g
--
Greg Stein, http://www.lyra.org/
Re: API for the serf
Posted by Daniel Stenberg <da...@haxx.se>.
On Tue, 2 Oct 2001, Greg Stein wrote:
> > Client certs might need to be added, but that's not too hard.
>
> Yes, they will be needed. (/me thinking of SVN)
I might be able to assist with some already written libcurl code that does
this.
Further, SSL session ID caching should be considered for those SSL
connections that don't get persistant.
--
Daniel Stenberg - http://daniel.haxx.se - +46-705-44 31 77
ech`echo xiun|tr nu oc|sed 'sx\([sx]\)\([xoi]\)xo un\2\1 is xg'`ol
Re: API for the serf
Posted by Greg Stein <gs...@lyra.org>.
On Mon, Oct 01, 2001 at 11:54:44PM -0700, Justin Erenkrantz wrote:
> On Mon, Oct 01, 2001 at 10:13:16PM -0700, Ian Holsman wrote:
> > * Simple 'GET/Post/Head' function just does it and returns
> > the contents in a bucket-brigade
>
> Sure. I'd like to make it able to speak any protocol that
> has similar functionality to HTTP but isn't quite HTTP/1.1 - i.e.
> try to be as protocol-agnostic as we can make it.
Euh... let's do HTTP/1.1 *today*. At some point in the future, we can look
back and see what kinds of tweaks/changes are necessary to meet other needs.
Just remember that our charter is based solely on an HTTP client library.
*Not* a general purpose "http-like" protocol library.
Say "oh, but protocol X uses request/response, too... let's add that!" is
out of bounds for 1.0 :-)
>...
> I'd like to see this client API be
> able to handle that as well.
In truth, I think the API is going to be very damned flexibile and *could*
support other protocols. But let's *please* not go down that rathole until
we have a 1.0 release? Please?
Just having an HTTP client library is a *big* win in an of itself.
>...
> > * Async version of above.. (like LWP::Parallel) I just push
> > GET requests and it notifies me when there is an event for
> > one of them.
>
> I'm just not sure that we really want to make the API event-based.
> I'm really not a fan of event-based or callback-based programming
> (if you want event-based, use libwww in its various incarnations).
> I think it makes things too confusing. I much prefer the
> paralleism to be at the thread-level rather than select/poll-based.
See my previous response to Ian, and my notes about the initial proposal. I
really think we can create an API that easily moves between the push/pull
and sync/async models.
You can ask for a response's brigade (and the lib will fetch it off the
wire), or the library will call you with the brigade. We're talking just a
minor difference in how the app uses the library. Both models focus on the
brigade, but the call sequence is something like:
serf_send_request(session, req_brigade, NULL)
:
resp_brigade = serf_get_response(session)
or
serf_send_request(session, req_brigade, response_cb)
:
serf_process(ctx)
apr_status_t response_cb(resp_brigade) { ... }
>...
> also find that most web tasks don't need to be event-driven -
In Subversion, we need to push request data at the network (yet,
unfortunately, Neon wants to pull data). On the response side, we want the
network to push data at Subversion (which Neon does).
So for the response, I would say that serf needs to have a callback mode for
delivering the response.
> they are all essentially parallel tasks. I think you sacrifice
> too much of the API to get callbacks and async.
I don't buy this. I'm not seeing that a "sacrifice" is going to happen.
Let's see what happens. I suspect the presence of callbacks is not going to
bug you, as long as you have the sync mode.
> > * filters used for 'serf' as similiar in syntax/use to HTTPD
>
> One thing I'd like to see is that we use filter framework as what
> is already in httpd.
No, on several accounts.
The presence of f->r and f->c is severely whacked. The filter chain should
operate independently of any global context. "Reaching out" is bad juju.
I also don't believe the registration and naming of filters is useful for
the serf. We're a library, not an application. The notion of names and
simplified insertion is an application concept.
[ that said: attaching a name to a filter could be useful for debugging,
much like we have names for buckets ]
Hmm. That is a good analogy: the filters are going to be referenced,
inserted, etc, much more like buckets. We'd have some static structure
defining the filter, and we simply call a function to insert the bugger in
the filter chain.
To some extent, httpd is building those "static" structures from runtime
parameters to the registration functions (type, name, func, etc). No real
reason for that; I think we just kind of fell into it because we were more
focused on naming them so a config file could refer to them.
> This is good in two respects - we force
> ourselves to clean up the filtering API in httpd (most of us are
> active in httpd as well) and we can reuse the same code in both
> places.
Agreed on both accounts. However, I would suggest that it goes in the other
direction. *We* define a Good filter stack and httpd moves towards it. We
don't have the legacy stuff with the headers, nor the needs of f->r and f->c
to get in our way of doing it Right.
> This would mean that all of the filter code may need
> to get moved to a neutral repository. Not sure I know where
> it'd go or if this is even a good idea. But, most likely, any
> filters that we write will be implemented in both places - that
> seems a bit silly.
More than likely, serf just exports the filters for use by httpd. Recall
that one of our targets is for proxy to use the serf. Thus, the code will
already be "within" httpd.
> > * HTTP/1.1 Support
>
> As Greg said, we should only send out HTTP/1.1 requests. This is
> the way we did it with flood. The only thing we don't handle
> correctly as part of HTTP/1.1 is chunking. And, I've got a start
> on it in my tree, but I got sidetracked by the input filtering
> in httpd and now this.
The serf will have both chunking and dechunking code. Since the request
could be "pushed" at the library, chunking is required. It is also possible
to give a brigade to the serf and it could compute the length and send a
request with a Content-Length header.
On the response side, we'll definitely have dechunking.
> > * SSL Support
>
> flood already does this with OpenSSL, so I think it should be
> straightforward as most of the heavy lifting has already been
> done.
You betcha :-)
IMO, I don't see that we need to use an SSL filter. I think the terminal
filter (analog to CORE_IN / CORE_OUT) could simply handle SSL as necessary.
> Client certs might need to be added, but that's not too hard.
Yes, they will be needed. (/me thinking of SVN)
> > * Connection Pooling per server (ie we keep a max of n open connections
> > to a server and we re-use these on different requests)
>
> Eh, I'm not terribly sure about this though. I'm not sure how you
> would get the lifetimes right. Ideally, the connections should
> timeout themselves. I guess we could enforce the lifetimes with
> socket timeouts (but that'd only be on our side not the server
> side). I think that if you want connection-pooling, that *might* be
> outside of the scope of this library. But, I'm not really sure.
> Thoughts?
All of this would be subject to various parameters and controls, TBD.
I generally agree that it is an advanced concept and possibly able to
relegate to the app, but I also think that many apps will want multiple
connections and multiple outstanding requests. Thus, a pool of connections.
> FWIW, I think RFC 2616 8.1.4 says that you should only keep two
> connections per server open at any time for single-client machines.
> Proxy<->Proxy connections may be at 2*N (N == number of concurrent
> users) per server.
Huh. Neat. Hadn't seen that one.
> I don't expect that we should have knowledge
> of this within apr-serf - I just think this is something left to
> the program that uses apr-serf. My $.02.
Agreed. We provide the controls, the doc provides guidelines (including refs
to the RFC), and let the app do what it will.
Otherwise, I'm sure you'd be peeved if flood could only open a max of two
connections :-)
> > * send requests to a server from a list of servers/ports (via round-robin)
>
> Oh, Flood does this. =) -- justin
:-)
I think the above is simply an aspect of the connection grouping and
pooling. More on that in a bit.
Cheers,
-g
--
Greg Stein, http://www.lyra.org/
Re: API for the serf
Posted by Justin Erenkrantz <je...@ebuilt.com>.
On Mon, Oct 01, 2001 at 10:13:16PM -0700, Ian Holsman wrote:
> * Simple 'GET/Post/Head' function just does it and returns
> the contents in a bucket-brigade
Sure. I'd like to make it able to speak any protocol that
has similar functionality to HTTP but isn't quite HTTP/1.1 - i.e.
try to be as protocol-agnostic as we can make it. If HTTP 2.0 is
ever developed (rather when), I'd like to see this client API be
able to handle that as well. (This was one of the goals of flood
was to be able to rip out the protocol engine with the next
generation whenever we have a spec for it - most likely we should
be the first ones on the block with an implementation for it...)
> * Async version of above.. (like LWP::Parallel) I just push
> GET requests and it notifies me when there is an event for
> one of them.
I'm just not sure that we really want to make the API event-based.
I'm really not a fan of event-based or callback-based programming
(if you want event-based, use libwww in its various incarnations).
I think it makes things too confusing. I much prefer the
paralleism to be at the thread-level rather than select/poll-based.
I know that Dean has spoken at length on new-httpd about this
paradigm and for the most part httpd/apr is not event-driven. I
also find that most web tasks don't need to be event-driven -
they are all essentially parallel tasks. I think you sacrifice
too much of the API to get callbacks and async.
> * filters used for 'serf' as similiar in syntax/use to HTTPD
One thing I'd like to see is that we use filter framework as what
is already in httpd. This is good in two respects - we force
ourselves to clean up the filtering API in httpd (most of us are
active in httpd as well) and we can reuse the same code in both
places. This would mean that all of the filter code may need
to get moved to a neutral repository. Not sure I know where
it'd go or if this is even a good idea. But, most likely, any
filters that we write will be implemented in both places - that
seems a bit silly.
> * HTTP/1.1 Support
As Greg said, we should only send out HTTP/1.1 requests. This is
the way we did it with flood. The only thing we don't handle
correctly as part of HTTP/1.1 is chunking. And, I've got a start
on it in my tree, but I got sidetracked by the input filtering
in httpd and now this.
> * SSL Support
flood already does this with OpenSSL, so I think it should be
straightforward as most of the heavy lifting has already been
done. Client certs might need to be added, but that's not too
hard.
> * Connection Pooling per server (ie we keep a max of n open connections
> to a server and we re-use these on different requests)
Eh, I'm not terribly sure about this though. I'm not sure how you
would get the lifetimes right. Ideally, the connections should
timeout themselves. I guess we could enforce the lifetimes with
socket timeouts (but that'd only be on our side not the server
side). I think that if you want connection-pooling, that *might* be
outside of the scope of this library. But, I'm not really sure.
Thoughts?
FWIW, I think RFC 2616 8.1.4 says that you should only keep two
connections per server open at any time for single-client machines.
Proxy<->Proxy connections may be at 2*N (N == number of concurrent
users) per server. I don't expect that we should have knowledge
of this within apr-serf - I just think this is something left to
the program that uses apr-serf. My $.02.
> * send requests to a server from a list of servers/ports (via round-robin)
Oh, Flood does this. =) -- justin
RE: API for the serf
Posted by Sander Striker <st...@apache.org>.
> From: Ian Holsman [mailto:ianh@apache.org]
> Sent: 02 October 2001 07:13
> has anyone got a list of things that they want the client to do?
>
> we could use this as a 'STATUS/Wish' list.
>
> Here's are some of the things I would find usefull:
>
> * Simple 'GET/Post/Head' function just does it and returns
> the contents in a bucket-brigade
>
> * Async version of above.. (like LWP::Parallel) I just push
> GET requests and it notifies me when there is an event for
> one of them.
>
> * filters used for 'serf' as similiar in syntax/use to HTTPD
>
> * HTTP/1.1 Support
>
> * SSL Support
>
> * Connection Pooling per server (ie we keep a max of n open connections
> to a server and we re-use these on different requests)
>
> * send requests to a server from a list of servers/ports (via round-robin)
>
> what do you guys think?
I have some irc logs with a few things we wanted. I'll posta short
summary later. Unfortunately, I'll be out of the running all day today
(and possibly tomorrow).
Sander