protobuf rpc over http

1,299 views
Skip to first unread message

Romain François

unread,
Dec 9, 2009, 6:10:33 AM12/9/09
to Protocol Buffers
Hello,

Following Kenton's advice, I'm starting to look at implementing protobuf
rpc over http. I have started to work on a basic java server (based on
the com.sun.net.httpserver class). I will post this at some point when I
am happier with it (currently it can only serve one dummy service that
returns the input message as is)

A request looks like this :

-----------------------------------------------------
POST /{service full name}/{method name} HTTP/1.0
Connection: close
Content-Length: {length of the serialized message}

{raw bytes of the serialized message}
-----------------------------------------------------

And a successful response looks like this:

-----------------------------------------------------
HTTP/1.1 200 OK
Content-length: {length of the serialized response}

{raw bytes of the serialized response}
-----------------------------------------------------

Since this is very early in this, I wondered if others would have views
on this.

http is quite verbose for sending protobuf message around, but it is
likely to be implemented for a lot of languages.

Regards,

Romain

--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://tr.im/Gq7i : ohloh
|- http://tr.im/FtUu : new package : highlight
`- http://tr.im/EAD5 : LondonR slides

Kenton Varda

unread,
Dec 9, 2009, 3:12:41 PM12/9/09
to Romain François, Protocol Buffers
Coincidentally, last weekend I started working on an open source protobuf-based RPC system.  Currently I am defining a socket-level protocol, but I also intend to support an HTTP-level protocol with optional JSON encoding to allow calls from Javascript.  I stuck some totally undocumented code here:


But some coworkers pointed out that the name is confusingly similar to "pcap", so I'm planning to change it.

Currently this is not an official Google project; I'm working on it in my spare time.

2009/12/9 Romain François <francoi...@free.fr>

A request looks like this :

-----------------------------------------------------
POST /{service full name}/{method name} HTTP/1.0

I would recommend against putting the service type name in the URL.  This makes it impossible to export two services of the same type.  Instead, you should allow the application to register services under any name it chooses.

I'd also suggest making the method name be part of the query, like:

  POST /someservice?method={method name}

This may be a matter of taste, but I feel like a service object should be a single HTTP "resource", rather than have each method be a separate resource.
 
Connection: close

Why not allow pipelining?
 
Content-Length: {length of the serialized message}

{raw bytes of the serialized message}
-----------------------------------------------------

And a successful response looks like this:

-----------------------------------------------------
HTTP/1.1 200 OK
Content-length: {length of the serialized response}

{raw bytes of the serialized response}
-----------------------------------------------------

Since this is very early in this, I wondered if others would have views
on this.

http is quite verbose for sending protobuf message around, but it is
likely to be implemented for a lot of languages.

Regards,

Romain

--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://tr.im/Gq7i : ohloh
|- http://tr.im/FtUu : new package : highlight
`- http://tr.im/EAD5 : LondonR slides

--

You received this message because you are subscribed to the Google Groups "Protocol Buffers" group.
To post to this group, send email to prot...@googlegroups.com.
To unsubscribe from this group, send email to protobuf+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/protobuf?hl=en.



Romain François

unread,
Dec 10, 2009, 3:48:55 AM12/10/09
to Kenton Varda, Protocol Buffers
On 12/09/2009 09:12 PM, Kenton Varda wrote:
> Coincidentally, last weekend I started working on an open source
> protobuf-based RPC system. Currently I am defining a socket-level
> protocol, but I also intend to support an HTTP-level protocol with
> optional JSON encoding to allow calls from Javascript. I stuck some
> totally undocumented code here:

Thanks. My intention of having it over http is that it can communicate
with other languages. I'd be good if we can synchronize our protocols.

I need to make some changes based on what you said on another thread,
and then I'll make my java basic server code available.

> http://pbcap.googlecode.com
>
> But some coworkers pointed out that the name is confusingly similar to
> "pcap", so I'm planning to change it.
>
> Currently this is not an official Google project; I'm working on it in
> my spare time.
>
> 2009/12/9 Romain Fran�ois <francoi...@free.fr
> <mailto:francoi...@free.fr>>
>
> A request looks like this :
>
> -----------------------------------------------------
> POST /{service full name}/{method name} HTTP/1.0
>
>
> I would recommend against putting the service type name in the URL.
> This makes it impossible to export two services of the same type.
> Instead, you should allow the application to register services under
> any name it chooses.

Fair enough. Maybe adding some protobuf specific headers :

ProtobufService: {service full name}
ProtobufMethod: {method full name}

or encode it as parameters of the url as you said.

> I'd also suggest making the method name be part of the query, like:
>
> POST /someservice?method={method name}
>
> This may be a matter of taste, but I feel like a service object should
> be a single HTTP "resource", rather than have each method be a separate
> resource.
>
> Connection: close
>
>
> Why not allow pipelining?

this was simpler to do a one shot service call, but indeed why not.

Marc Gravell

unread,
Dec 10, 2009, 4:15:20 AM12/10/09
to Romain François, Kenton Varda, Protocol Buffers

The layout in the original post looks a lot like how protobuf-net does RPC over http. It uses {root}/service/method, but it would be trivial to tweak it to use any similar pattern. I'd be happy to make tweaks to protobuf-net to make it play the same game, and try a few cross-implementation scenarios.

Marc

2009/12/10 Romain François <francoi...@free.fr>
On 12/09/2009 09:12 PM, Kenton Varda wrote:
> Coincidentally, last weekend I started working on an open source
> protobuf-based RPC system.  Currently I am defining a socket-level
> protocol, but I also intend to support an HTTP-level protocol with
> optional JSON encoding to allow calls from Javascript.  I stuck some
> totally undocumented code here:

Thanks. My intention of having it over http is that it can communicate
with other languages. I'd be good if we can synchronize our protocols.

I need to make some changes based on what you said on another thread,
and then I'll make my java basic server code available.

> http://pbcap.googlecode.com
>
> But some coworkers pointed out that the name is confusingly similar to
> "pcap", so I'm planning to change it.
>
> Currently this is not an official Google project; I'm working on it in
> my spare time.
>
> 2009/12/9 Romain François <francoi...@free.fr
--

You received this message because you are subscribed to the Google Groups "Protocol Buffers" group.
To post to this group, send email to prot...@googlegroups.com.
To unsubscribe from this group, send email to protobuf+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/protobuf?hl=en.





--
Regards,

Marc

Kenton Varda

unread,
Dec 10, 2009, 4:15:54 AM12/10/09
to Romain François, Protocol Buffers


2009/12/10 Romain François <francoi...@free.fr>
On 12/09/2009 09:12 PM, Kenton Varda wrote:
Coincidentally, last weekend I started working on an open source
protobuf-based RPC system.  Currently I am defining a socket-level
protocol, but I also intend to support an HTTP-level protocol with
optional JSON encoding to allow calls from Javascript.  I stuck some
totally undocumented code here:

Thanks. My intention of having it over http is that it can communicate with other languages. I'd be good if we can synchronize our protocols.

I need to make some changes based on what you said on another thread, and then I'll make my java basic server code available.

http://pbcap.googlecode.com

But some coworkers pointed out that the name is confusingly similar to
"pcap", so I'm planning to change it.

Currently this is not an official Google project; I'm working on it in
my spare time.

2009/12/9 Romain François <francoi...@free.fr
<mailto:francoi...@free.fr>>


   A request looks like this :

   -----------------------------------------------------
   POST /{service full name}/{method name} HTTP/1.0


I would recommend against putting the service type name in the URL.
 This makes it impossible to export two services of the same type.
 Instead, you should allow the application to register services under
any name it chooses.

Fair enough. Maybe adding some protobuf specific headers :

ProtobufService: {service full name}

You don't need to send the service name at all.  The server should already know what kind of service it is exporting.
 
ProtobufMethod: {method full name}

You do need the method name, though.  Inventing new HTTP headers isn't usually a good idea as they may confuse proxies and such.

Romain François

unread,
Dec 10, 2009, 4:50:37 AM12/10/09
to Marc Gravell, Kenton Varda, Protocol Buffers
Cool. Do you have your layout documented somewhere in your project.

Embed service full name and method name in the http request as we do
allows the request to be self-contained. What kenton suggests needs the
client to know of the mapping between the service full name (in pb
speech) and the http service name, which might then need an independant
exchange before hand between the client and the server .

client: how do you call this service
server: foo
client: sending the http request using foo

Either way is fine. It would be good to all agree on what rpc over http
means.

On 12/10/2009 10:15 AM, Marc Gravell wrote:
>
> The layout in the original post looks a lot like how protobuf-net does
> RPC over http. It uses {root}/service/method, but it would be trivial to
> tweak it to use any similar pattern. I'd be happy to make tweaks to
> protobuf-net to make it play the same game, and try a few
> cross-implementation scenarios.
>
> Marc
>
> 2009/12/10 Romain Fran�ois <francoi...@free.fr
> <mailto:francoi...@free.fr>>
>
> On 12/09/2009 09:12 PM, Kenton Varda wrote:
> > Coincidentally, last weekend I started working on an open source
> > protobuf-based RPC system. Currently I am defining a socket-level
> > protocol, but I also intend to support an HTTP-level protocol with
> > optional JSON encoding to allow calls from Javascript. I stuck some
> > totally undocumented code here:
>
> Thanks. My intention of having it over http is that it can communicate
> with other languages. I'd be good if we can synchronize our protocols.
>
> I need to make some changes based on what you said on another thread,
> and then I'll make my java basic server code available.
>
> > http://pbcap.googlecode.com
> >
> > But some coworkers pointed out that the name is confusingly
> similar to
> > "pcap", so I'm planning to change it.
> >
> > Currently this is not an official Google project; I'm working on
> it in
> > my spare time.
> >
> > 2009/12/9 Romain Fran�ois <francoi...@free.fr
> <mailto:francoi...@free.fr>
> > <mailto:francoi...@free.fr <mailto:francoi...@free.fr>>>

Kenton Varda

unread,
Dec 10, 2009, 5:13:54 AM12/10/09
to Romain François, Marc Gravell, Protocol Buffers
2009/12/10 Romain François <francoi...@free.fr>

Cool. Do you have your layout documented somewhere in your project.

Embed service full name and method name in the http request as we do allows the request to be self-contained. What kenton suggests needs the client to know of the mapping between the service full name (in pb speech) and the http service name, which might then need an independant exchange before hand between the client and the server .

No, that's not what I'm suggesting.  The client doesn't start from "I want to use FooService.".  The client starts from "I want to talk to http://example.com/foo-service, which I already know is of type FooService.".  It doesn't make sense for the client to ask the server where to find a FooService, because the server might expose *multiple* FooServices.  The client has to know which one it wants to talk to.  The URL identifies that.
 

client: how do you call this service
server: foo
client: sending the http request using foo

Either way is fine. It would be good to all agree on what rpc over http means.


On 12/10/2009 10:15 AM, Marc Gravell wrote:

The layout in the original post looks a lot like how protobuf-net does
RPC over http. It uses {root}/service/method, but it would be trivial to
tweak it to use any similar pattern. I'd be happy to make tweaks to
protobuf-net to make it play the same game, and try a few
cross-implementation scenarios.

Marc

2009/12/10 Romain François <francoi...@free.fr
<mailto:francoi...@free.fr>>


   On 12/09/2009 09:12 PM, Kenton Varda wrote:
    > Coincidentally, last weekend I started working on an open source
    > protobuf-based RPC system.  Currently I am defining a socket-level
    > protocol, but I also intend to support an HTTP-level protocol with
    > optional JSON encoding to allow calls from Javascript.  I stuck some
    > totally undocumented code here:

   Thanks. My intention of having it over http is that it can communicate
   with other languages. I'd be good if we can synchronize our protocols.

   I need to make some changes based on what you said on another thread,
   and then I'll make my java basic server code available.

    > http://pbcap.googlecode.com
    >
    > But some coworkers pointed out that the name is confusingly
   similar to
    > "pcap", so I'm planning to change it.
    >
    > Currently this is not an official Google project; I'm working on
   it in
    > my spare time.
    >
    > 2009/12/9 Romain François <francoi...@free.fr
   <mailto:francoi...@free.fr>

Romain François

unread,
Dec 10, 2009, 6:23:00 AM12/10/09
to Kenton Varda, Marc Gravell, Protocol Buffers
On 12/10/2009 11:13 AM, Kenton Varda wrote:
> 2009/12/10 Romain Fran�ois <francoi...@free.fr
> <mailto:francoi...@free.fr>>
>
> Cool. Do you have your layout documented somewhere in your project.
>
> Embed service full name and method name in the http request as we do
> allows the request to be self-contained. What kenton suggests needs
> the client to know of the mapping between the service full name (in
> pb speech) and the http service name, which might then need an
> independant exchange before hand between the client and the server .
>
>
> No, that's not what I'm suggesting. The client doesn't start from "I
> want to use FooService.". The client starts from "I want to talk to
> http://example.com/foo-service, which I already know is of type
> FooService.". It doesn't make sense for the client to ask the server
> where to find a FooService, because the server might expose *multiple*
> FooServices. The client has to know which one it wants to talk to. The
> URL identifies that.

Ah. I think I understand now.

For me the method full name uniquely identifies the method and the
server is generic, serving a service/method if it knows about it.


Anyway, for those interested my code is here:
$ svn checkout svn://svn.r-forge.r-project.org/svnroot/rprotobuf/java
$ ant
$ ./start.sh


Implementing a method involves subclassing the ProtobufMethodInvoker
class which is generic (on both input and output type). So for example
with this service:

service EchoService {
rpc Echo (Person) returns (Person);
}

I define the EchoInvoker class like this :

package org.rproject.rprotobuf ;

import com.example.tutorial.AddressBookProtos.Person ;
import com.google.protobuf.Message ;

@MethodImplementation("tutorial.EchoService.Echo")
public class EchoInvoker extends ProtobufMethodInvoker<Person,Person>{

public Person invoke(Person person){
return person ;
}

public Person getInputDefaultInstance(){
return
com.example.tutorial.AddressBookProtos.Person.getDefaultInstance() ;
}

}

The method invoker must be registered using the
ProtobufMethodPool.register method. For example :

register("tutorial.EchoService.Echo", new EchoInvoker() ) ;

I'm planning on adding some scanning based on the @MethodImplementation
annotation.

Romain

> client: how do you call this service
> server: foo
> client: sending the http request using foo
>
> Either way is fine. It would be good to all agree on what rpc over
> http means.
>
>
> On 12/10/2009 10:15 AM, Marc Gravell wrote:
>
>
> The layout in the original post looks a lot like how
> protobuf-net does
> RPC over http. It uses {root}/service/method, but it would be
> trivial to
> tweak it to use any similar pattern. I'd be happy to make tweaks to
> protobuf-net to make it play the same game, and try a few
> cross-implementation scenarios.
>
> Marc
>
> 2009/12/10 Romain Fran�ois <francoi...@free.fr
> > 2009/12/9 Romain Fran�ois <francoi...@free.fr

Romain François

unread,
Dec 10, 2009, 11:06:09 AM12/10/09
to Pavel Shramov, Protocol Buffers, Marc Gravell
On 12/10/2009 04:30 PM, Pavel Shramov wrote:
> On Wed, Dec 09, 2009 at 12:10:33PM +0100, Romain Fran�ois wrote:
>> Hello,
>>
>> Following Kenton's advice, I'm starting to look at implementing protobuf
>> rpc over http. I have started to work on a basic java server (based on
>> the com.sun.net.httpserver class). I will post this at some point when I
>> am happier with it (currently it can only serve one dummy service that
>> returns the input message as is)
>>
>> A request looks like this :
>>
>> -----------------------------------------------------
>> POST /{service full name}/{method name} HTTP/1.0
>> Connection: close
>> Content-Length: {length of the serialized message}
>>
>> {raw bytes of the serialized message}
>> -----------------------------------------------------
> I'm using method name encoded in query part of URL like /base/url?Service.Method

That seems odd. Why not /base/url?service=Service&method=Method instead ?

> Also it's seem useful to provide Content-Type to distinguish between different
> encodings of message (for example JSON).

Yep. Will add this.

>> And a successful response looks like this:
>>
>> -----------------------------------------------------
>> HTTP/1.1 200 OK
>> Content-length: {length of the serialized response}
>>
>> {raw bytes of the serialized response}
>> -----------------------------------------------------
> Also it may be useful to state that errors are transmitted as body of
> 500 Internal Server Error response.
>
>
> For my implementation You may see [1] and [2] for python and C++ HTTP client.

I will. So this makes 3 very similar http based protocols, but slightly
different. We should come to an agreement. :-)

> Pavel
>
> [1] http://grid.pp.ru/wiki/pbufrpc
> [2] http://grid.pp.ru/cgit/pbufrpc

Mikhail Opletayev

unread,
Dec 10, 2009, 11:13:54 AM12/10/09
to Protocol Buffers
It's great news that you working on a standard way to communicate
between Protocol Buffers implementations!

> You don't need to send the service name at all. The server should already
> know what kind of service it is exporting.

I think its handy to export several services from the same end point,
especially if you are running RPC over something else than HTTP. If
you were to run Protocol Buffers RPC over plain sockets you'd probably
want to publish a bunch of services on the same port.

In Dataflow implementation we use one field (method) but we require
the method name to be in "serviceName.methodName" format.

For the same reason we decided against using HTTP headers to transfer
the RPC metadata as it binds you to the transport protocol. That's why
send content length and header length as the first 2 values in the
coded stream, then the header message, then the actual data message:

http://www.dataflow-software.com/docs/pbuf-rpc.html

On Dec 10, 3:15 am, Kenton Varda <ken...@google.com> wrote:
> 2009/12/10 Romain François <francoisrom...@free.fr>
>
>
>
> > On 12/09/2009 09:12 PM, Kenton Varda wrote:
>
> >> Coincidentally, last weekend I started working on an open source
> >> protobuf-based RPC system.  Currently I am defining a socket-level
> >> protocol, but I also intend to support an HTTP-level protocol with
> >> optional JSON encoding to allow calls from Javascript.  I stuck some
> >> totally undocumented code here:
>
> > Thanks. My intention of having it over http is that it can communicate with
> > other languages. I'd be good if we can synchronize our protocols.
>
> > I need to make some changes based on what you said on another thread, and
> > then I'll make my java basic server code available.
>
> >  http://pbcap.googlecode.com
>
> >> But some coworkers pointed out that the name is confusingly similar to
> >> "pcap", so I'm planning to change it.
>
> >> Currently this is not an official Google project; I'm working on it in
> >> my spare time.
>
> >> 2009/12/9 Romain François <francoisrom...@free.fr
> >> <mailto:francoisrom...@free.fr>>

Marc Gravell

unread,
Dec 10, 2009, 11:30:25 AM12/10/09
to Protocol Buffers
For info only, protobuf-net currently uses:

        internal const string HTTP_RPC_VERSION_HEADER = "pb-net-rpc";
        internal const string HTTP_RPC_MIME_TYPE = "application/x-protobuf";

(version for my own internal purposes, in case I need to change the body layout)

Re the sockets point also raised; there's a lot of difference between raw sockets and http; it would be good to get some kind of "official" http transport working - people can always add raw later...? I'd rather not get bogged down in trying to predict every nuance of sockets, when people can always (for now) "do their own thing" using protocol buffers just for serialization.

Marc

2009/12/10 Romain François <francoi...@free.fr>
On 12/10/2009 04:30 PM, Pavel Shramov wrote:



--
Regards,

Marc

Romain François

unread,
Dec 10, 2009, 11:44:48 AM12/10/09
to Protocol Buffers
On 12/10/2009 05:30 PM, Marc Gravell wrote:
> For info only, protobuf-net currently uses:
>
> internal const string HTTP_RPC_VERSION_HEADER = "pb-net-rpc";
> internal const string HTTP_RPC_MIME_TYPE = "application/x-protobuf";
>
>
> (version for my own internal purposes, in case I need to change the body
> layout)
>
> Re the sockets point also raised; there's a lot of difference between
> raw sockets and http; it would be good to get some kind of "official"
> http transport working - people can always add raw later...?

Totally. From your posts and Pavels, what about :

request :

-----------------------------------------------------
POST /{root}/{service full name}/{method name} HTTP/1.0
Content-Length: {length of the serialized message}
Content-Type: application/x-protobuf

{raw bytes of the serialized message}
-----------------------------------------------------

(and some other headers)



successful response :

-----------------------------------------------------
HTTP/1.0 200 OK
Content-Length: {length of the serialized response}
Content-Type: application/x-protobuf

{raw bytes of the serialized response}
-----------------------------------------------------



error :

-----------------------------------------------------
HTTP/1.0 500 Internal Server Error
Content-Length: {length of error message}
Content-Type: text/html

{some error message}
-----------------------------------------------------


Romain


> I'd rather
> not get bogged down in trying to predict every nuance of sockets, when
> people can always (for now) "do their own thing" using protocol buffers
> just for serialization.
>
> Marc
>
> 2009/12/10 Romain Fran�ois <francoi...@free.fr
> <mailto:francoi...@free.fr>>
>
> On 12/10/2009 04:30 PM, Pavel Shramov wrote:
>

Pavel Shramov

unread,
Dec 10, 2009, 10:30:10 AM12/10/09
to Romain François, Protocol Buffers
On Wed, Dec 09, 2009 at 12:10:33PM +0100, Romain Fran�ois wrote:
> Hello,
>
> Following Kenton's advice, I'm starting to look at implementing protobuf
> rpc over http. I have started to work on a basic java server (based on
> the com.sun.net.httpserver class). I will post this at some point when I
> am happier with it (currently it can only serve one dummy service that
> returns the input message as is)
>
> A request looks like this :
>
> -----------------------------------------------------
> POST /{service full name}/{method name} HTTP/1.0
> Connection: close
> Content-Length: {length of the serialized message}
>
> {raw bytes of the serialized message}
> -----------------------------------------------------
I'm using method name encoded in query part of URL like /base/url?Service.Method
Also it's seem useful to provide Content-Type to distinguish between different
encodings of message (for example JSON).

> And a successful response looks like this:
>
> -----------------------------------------------------
> HTTP/1.1 200 OK
> Content-length: {length of the serialized response}
>
> {raw bytes of the serialized response}
> -----------------------------------------------------
Also it may be useful to state that errors are transmitted as body of
500 Internal Server Error response.


For my implementation You may see [1] and [2] for python and C++ HTTP client.

Pavel Shramov

unread,
Dec 10, 2009, 11:46:56 AM12/10/09
to Romain François, Pavel Shramov, Protocol Buffers, Marc Gravell
On Thu, Dec 10, 2009 at 05:06:09PM +0100, Romain Fran�ois wrote:
> > I'm using method name encoded in query part of URL like /base/url?Service.Method
>
> That seems odd. Why not /base/url?service=Service&method=Method instead ?
For simplicity (from my point of view). Query string is here only to identify method
to call and not to pass parameters to it. So why to bother?

> > Also it's seem useful to provide Content-Type to distinguish between different
> > encodings of message (for example JSON).
>
> Yep. Will add this.
I'm using application/x-protobuf here as protobuf-net does.

> I will. So this makes 3 very similar http based protocols, but slightly
> different. We should come to an agreement. :-)
Definitely we have :) But it seem impossible :)

Pavel

Romain François

unread,
Dec 10, 2009, 12:23:14 PM12/10/09
to Protocol Buffers
On 12/10/2009 05:46 PM, Pavel Shramov wrote:
> On Thu, Dec 10, 2009 at 05:06:09PM +0100, Romain Fran�ois wrote:
>>> I'm using method name encoded in query part of URL like /base/url?Service.Method
>>
>> That seems odd. Why not /base/url?service=Service&method=Method instead ?
> For simplicity (from my point of view). Query string is here only to identify method
> to call and not to pass parameters to it. So why to bother?

What about then if you want to control the kind of output that is
returned back (pb or json). I would then add &encoding=pb or
&encoding=json. How do you do this ?


I don't have any strong opinions. I think the best format is :

/base/url/{service}?method={method}

where "service" is the service full name, and "method" the method name
within the service.


>>> Also it's seem useful to provide Content-Type to distinguish between different
>>> encodings of message (for example JSON).
>>
>> Yep. Will add this.
> I'm using application/x-protobuf here as protobuf-net does.
>
>> I will. So this makes 3 very similar http based protocols, but slightly
>> different. We should come to an agreement. :-)
> Definitely we have :) But it seem impossible :)
>
> Pavel
>


Mikhail Opletayev

unread,
Dec 10, 2009, 12:41:15 PM12/10/09
to Protocol Buffers
> Re the sockets point also raised; there's a lot of difference between raw
> sockets and http; it would be good to get some kind of "official" http
> transport working - people can always add raw later...?

This is exactly the point I was trying to raise: if you bind Protocol
Buffer RPC to a transport protocol then you can't easily use different
transports as they might lack certain features. I mentioned TCP
sockets just as an example.

Here is my line of thought behind using a more generic (less HTTP-
dependent) approach:

1) Not all protobufs target applications have an HTTP stack available.
I know some applications that could use protobuf RPC but don't have
HTTP available;

2) PB is a very efficient binary format so tying it up to a less than
optimal text-based HTTP seems to be counterproductive;

3) It is a common practice to make RPC protocols self contained, and
having a message carry all the information needed for its delivery
(JSON RPC, SOAP, COBRA, Java RMI, etc.);

4) To achieve #3, no service or method name can be coded externally,
no custom transport protocol features can be used either (HTTP
headers);

5) Using protobuf to define header messages feels right as its easy to
parse with the existing tools and it allows for a greater
extensibility and "soft versioning" with optional fields;

6) Self contained RPC messages don't just enable using different
transports. You can do a whole lot more: safely and easily persist
messages, batch them which can greatly improve throughput;

7) It simplifies the RPC protocol specification. Header messages can
be declared as a .proto file, people can compile it for their own
platforms. It seems to be in line with the general protobuf
philosophy.

That's my 2c.

Regards,

On Dec 10, 10:30 am, Marc Gravell <marc.grav...@gmail.com> wrote:
> For info only, protobuf-net currently uses:
>
>          internal const string HTTP_RPC_VERSION_HEADER = "pb-net-rpc";
>          internal const string HTTP_RPC_MIME_TYPE = "application/x-protobuf"
> ;
> (version for my own internal purposes, in case I need to change the body
> layout)
>
> Re the sockets point also raised; there's a lot of difference between raw
> sockets and http; it would be good to get some kind of "official" http
> transport working - people can always add raw later...? I'd rather not get
> bogged down in trying to predict every nuance of sockets, when people can
> always (for now) "do their own thing" using protocol buffers just for
> serialization.
>
> Marc
>
> 2009/12/10 Romain François <francoisrom...@free.fr>
> > |-http://tr.im/Gq7i: ohloh
> > |-http://tr.im/FtUu: new package : highlight
> > `-http://tr.im/EAD5: LondonR slides
>
> --
> Regards,
>
> Marc

--
Mikhail Opletayev
http://dataflow-software.com

Pavel Shramov

unread,
Dec 10, 2009, 12:24:22 PM12/10/09
to Romain François, Protocol Buffers
On Thu, Dec 10, 2009 at 05:44:48PM +0100, Romain Fran�ois wrote:
> -----------------------------------------------------
> POST /{root}/{service full name}/{method name} HTTP/1.0
> Content-Length: {length of the serialized message}
> Content-Type: application/x-protobuf
>
> {raw bytes of the serialized message}
> -----------------------------------------------------
I think that using query part for service and method is better than encoding
it in URL. Btw it's possible to define something like 'calling conventions' for
clients and tell client that it must use this or that.
Pavel

Pavel Shramov

unread,
Dec 10, 2009, 12:31:33 PM12/10/09
to Romain François, Protocol Buffers
On Thu, Dec 10, 2009 at 06:23:14PM +0100, Romain Fran�ois wrote:
> What about then if you want to control the kind of output that is
> returned back (pb or json). I would then add &encoding=pb or
> &encoding=json. How do you do this ?
Everything is invented before us [1] :)
To be fair in my implementation I send response encoded as request.
Request encoding is read from Content-Type header and defaults to PB.

> I don't have any strong opinions. I think the best format is :
>
> /base/url/{service}?method={method}
>
> where "service" is the service full name, and "method" the method name
> within the service.
So we have both URL and query encoding at once :)

Pavel
--
[1] http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3

Romain François

unread,
Dec 10, 2009, 1:56:49 PM12/10/09
to Protocol Buffers
On 12/10/2009 06:31 PM, Pavel Shramov wrote:
> On Thu, Dec 10, 2009 at 06:23:14PM +0100, Romain Fran�ois wrote:
>> What about then if you want to control the kind of output that is
>> returned back (pb or json). I would then add&encoding=pb or
>> &encoding=json. How do you do this ?
> Everything is invented before us [1] :)

Fair enough. I guess we could set Accept-encoding for that.

> To be fair in my implementation I send response encoded as request.
> Request encoding is read from Content-Type header and defaults to PB.
>
>> I don't have any strong opinions. I think the best format is :
>>
>> /base/url/{service}?method={method}
>>
>> where "service" is the service full name, and "method" the method name
>> within the service.
> So we have both URL and query encoding at once :)

The rationale is this: it seems about right for a service to be bound to
an url (whether the url uses the actual service full name or soime other
key as per kenton's emails) and the method smells more like a parameter.

It is easy enough for me to encode the request in your format if I
wanted to be able to interchange with your server, but is it not better
to all use the same ...

Pavel Shramov

unread,
Dec 10, 2009, 2:54:40 PM12/10/09
to Mikhail Opletayev, Protocol Buffers
Disclaimer: I'd be happy if once one of raw async RPC would be
'standart' but now maybe HTTP one will be. They just suppliment each other.

On Thu, Dec 10, 2009 at 09:41:15AM -0800, Mikhail Opletayev wrote:
> > Re the sockets point also raised; there's a lot of difference between raw
> > sockets and http; it would be good to get some kind of "official" http
> > transport working - people can always add raw later...?
>
> This is exactly the point I was trying to raise: if you bind Protocol
> Buffer RPC to a transport protocol then you can't easily use different
> transports as they might lack certain features. I mentioned TCP
> sockets just as an example.
>
> Here is my line of thought behind using a more generic (less HTTP-
> dependent) approach:
Nobody argues that non-HTTP RPC must exists. But raw transport needs some
kind of envelope (or header as in dataflow's pbuf-rpc) and thus a bit more
complicated (as protocol).

> 1) Not all protobufs target applications have an HTTP stack available.
> I know some applications that could use protobuf RPC but don't have
> HTTP available;
Then it's not place for RPC over HTTP :) But there is place for it.

> 2) PB is a very efficient binary format so tying it up to a less than
> optimal text-based HTTP seems to be counterproductive;
Sometimes You need slow non-efficient protocol for stateless calls or when
they are rare and must survive server restart.

> 3) It is a common practice to make RPC protocols self contained, and
> having a message carry all the information needed for its delivery
> (JSON RPC, SOAP, COBRA, Java RMI, etc.);
BTW have you seen/used non-HTTP SOAP transports? :) Not on slides but in
real life?

> 4) To achieve #3, no service or method name can be coded externally,
> no custom transport protocol features can be used either (HTTP
> headers);
>
> 5) Using protobuf to define header messages feels right as its easy to
> parse with the existing tools and it allows for a greater
> extensibility and "soft versioning" with optional fields;
>
> 6) Self contained RPC messages don't just enable using different
> transports. You can do a whole lot more: safely and easily persist
> messages, batch them which can greatly improve throughput;
>
> 7) It simplifies the RPC protocol specification. Header messages can
> be declared as a .proto file, people can compile it for their own
> platforms. It seems to be in line with the general protobuf
> philosophy.
Simpliest RPC implementation is one over HTTP since only part that needs
external specification is 'calling conventions' for mathod to URL
translation.

Pavel

P.S. Sorry for flaming :)

Pavel Shramov

unread,
Dec 10, 2009, 4:10:34 PM12/10/09
to Romain François, Protocol Buffers
On Thu, Dec 10, 2009 at 07:56:49PM +0100, Romain Fran�ois wrote:
> On 12/10/2009 06:31 PM, Pavel Shramov wrote:
> > On Thu, Dec 10, 2009 at 06:23:14PM +0100, Romain Fran�ois wrote:
> >> What about then if you want to control the kind of output that is
> >> returned back (pb or json). I would then add&encoding=pb or
> >> &encoding=json. How do you do this ?
> > Everything is invented before us [1] :)
>
> Fair enough. I guess we could set Accept-encoding for that.
>
> > To be fair in my implementation I send response encoded as request.
> > Request encoding is read from Content-Type header and defaults to PB.
> >
> >> I don't have any strong opinions. I think the best format is :
> >>
> >> /base/url/{service}?method={method}
> >>
> >> where "service" is the service full name, and "method" the method name
> >> within the service.
> > So we have both URL and query encoding at once :)
>
> The rationale is this: it seems about right for a service to be bound to
> an url (whether the url uses the actual service full name or soime other
> key as per kenton's emails) and the method smells more like a parameter.

My 'design' was affected by SOAP (Web-Services) concept of port types -- one
service may implement different 'ports'.

For example (not real life but like it) you have arigmetic service which
consists of two ports: one of sum/substract functions and another of
mul/div ones. It's one service with one endpoint but implementing two
different sets of functions.

In my opinion URL (path without query part) is more similar to host:port
combination in raw transport (or endpoint int Web-Services terminology).

So xxx?method=method&service=service is more close to me.

> It is easy enough for me to encode the request in your format if I
> wanted to be able to interchange with your server, but is it not better
> to all use the same ...
It is so we'll trying to find common point...

As last resort we may define set of calling conventions for clients.

Pavel

Marc Gravell

unread,
Dec 10, 2009, 4:48:29 PM12/10/09
to Pavel Shramov, Romain François, Protocol Buffers
Re the whole "what should an endpoint url look like" thing - I had a similar discussion with a user re protobuf-net; in the end it was quicker to just *default* to the former (since it doesn't need any extra specification), but *support* both - so the code detects key strings in the supplied url and works some magic.

i.e. if I give it the endpoint: "http://foo/foocorp"

but if I give it the endpoint "http://foo/foocorp?svc={service}&act={action}"

And so I can officially say "I don't care" about this discussion - either suits me without any code-changes ;-p

Marc
 
So xxx?method=method&service=service is more close to me.

> It is easy enough for me to encode the request in your format if I
> wanted to be able to interchange with your server, but is it not better
> to all use the same ...
It is so we'll trying to find common point...

As last resort we may define set of calling conventions for clients.

                       Pavel
--

You received this message because you are subscribed to the Google Groups "Protocol Buffers" group.
To post to this group, send email to prot...@googlegroups.com.
To unsubscribe from this group, send email to protobuf+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/protobuf?hl=en.





--
Regards,

Marc

Kenton Varda

unread,
Dec 10, 2009, 5:22:05 PM12/10/09
to Mikhail Opletayev, Protocol Buffers
On Thu, Dec 10, 2009 at 8:13 AM, Mikhail Opletayev <ople...@gmail.com> wrote:
It's great news that you working on a standard way to communicate
between Protocol Buffers implementations!

> You don't need to send the service name at all.  The server should already
> know what kind of service it is exporting.

I think its handy to export several services from the same end point,
especially if you are running RPC over something else than HTTP. If
you were to run Protocol Buffers RPC over plain sockets you'd probably
want to publish a bunch of services on the same port.

This is exactly my point.  If you use the service type name to identify the service, then you can only export one service of each type.  Instead, some other name -- having nothing to do with the type name -- should be used to identify the service.

Actually, the implementation I'm working on doesn't even identify services by names.  Instead, when you first connect on a port, you connect to the "default service" for that port.  However, the default service can send back pointers to other services in RPC responses.  So, the default service may have a method which looks up other services by name, but this is up to the application.
 

Kenton Varda

unread,
Dec 10, 2009, 5:27:07 PM12/10/09
to Pavel Shramov, Romain François, Protocol Buffers, Marc Gravell
2009/12/10 Pavel Shramov <shr...@mexmat.net>
On Thu, Dec 10, 2009 at 05:06:09PM +0100, Romain François wrote:
> > I'm using method name encoded in query part of URL like /base/url?Service.Method
>
> That seems odd. Why not /base/url?service=Service&method=Method instead ?
For simplicity (from my point of view). Query string is here only to identify method
to call and not to pass parameters to it. So why to bother?

Because it's a de-facto standard that the query is a set of name/value pairs.  Following this standard is likely to avoid problems integrating with other HTTP-based software.

Mikhail Opletayev

unread,
Dec 10, 2009, 5:37:34 PM12/10/09
to Protocol Buffers
Interesting. Essentially a discovery service for protobuf RPC.

I am not quite sure what you mean by "pointers to other services". Is
it going to reference them by name or a more complex structure
containing full endpoint information?

Also, is it going to be an extension to pbcap or something completely
new? The reason I am asking is because some patterns in pbcap (such as
wrapping up everything into a global Stream message) are rather
questionable and not without consequences.

Regards,

On Dec 10, 4:22 pm, Kenton Varda <ken...@google.com> wrote:
> > protobuf+u...@googlegroups.com<protobuf%2Bunsu...@googlegroups.com>
> > .
> > For more options, visit this group at
> >http://groups.google.com/group/protobuf?hl=en.

Kenton Varda

unread,
Dec 10, 2009, 5:42:26 PM12/10/09
to Mikhail Opletayev, Protocol Buffers
On Thu, Dec 10, 2009 at 2:37 PM, Mikhail Opletayev <ople...@gmail.com> wrote:
Interesting. Essentially a discovery service for protobuf RPC.

I am not quite sure what you mean by "pointers to other services". Is
it going to reference them by name or a more complex structure
containing full endpoint information?

Currently it references them by an ID number that is tied to the particular connection.  So, each time a new service object is returned on the connection, a new ID number is assigned to it.
 
Also, is it going to be an extension to pbcap or something completely
new?

Not an extension -- this *is* pbcap.  It supports this already.

(Note that I'm planning to change the name to "Captain Proto", aka capnproto, to avoid the confusion with pcap.)
 
The reason I am asking is because some patterns in pbcap (such as
wrapping up everything into a global Stream message) are rather
questionable and not without consequences.

What do you mean?  The global "Stream" message exists only to define the protocol.  It is not actually used at runtime -- individual messages are read from the stream one at a time.
 
To unsubscribe from this group, send email to protobuf+u...@googlegroups.com.

Kenton Varda

unread,
Dec 10, 2009, 5:43:35 PM12/10/09
to Mikhail Opletayev, Protocol Buffers
BTW, I haven't defined how pbcap/Captain Proto will work over HTTP yet.  So, I'm only talking about the raw-socket protocol.
Message has been deleted

Mikhail Opletayev

unread,
Dec 10, 2009, 6:02:04 PM12/10/09
to Protocol Buffers
Sorry for the double post :/

I understand that you are talking about raw raw-sockets. From my
perspective, it's a good thing as it doesn't tie the RPC protocol to
any specific transport protocol.

> Currently it references them by an ID number that is tied to the particular
> connection. So, each time a new service object is returned on the
> connection, a new ID number is assigned to it.

Will there be a way to directly connect to the service or a client
must go thru the discovery service each time a connection is open?

> What do you mean? The global "Stream" message exists only to define the
> protocol. It is not actually used at runtime -- individual messages are
> read from the stream one at a time.

From pbcap.proto it looked to me as all requests and responses must be
wrapped inside a Stream message. I guess I'll need to take a look at
the implementation before I ask more questions, I only had time to
take a quick peak earlier today.

P.S. I hope my questions don't derail this thread too much as the
original question was about HTTP RPC.

On Dec 10, 4:42 pm, Kenton Varda <ken...@google.com> wrote:
> > <protobuf%2Bunsu...@googlegroups.com<protobuf%252Buns...@googlegroups.com>

Kenton Varda

unread,
Dec 10, 2009, 6:33:39 PM12/10/09
to Mikhail Opletayev, Protocol Buffers
On Thu, Dec 10, 2009 at 3:02 PM, Mikhail Opletayev <ople...@gmail.com> wrote:
Will there be a way to directly connect to the service or a client
must go thru the discovery service each time a connection is open?

Why build this into the protocol when the discovery service is just as good?  Note that the protocol supports sending a request to the returned service before actually waiting for it to be returned.  In other words, a conversation might look like:

client:  "Open service Foo."
client:  "When request 1 is complete, call method Bar() on the result."
server:  "Foo opened successfully.  Here is a reference."
server:  "Bar completed.  Here is the response."

By keeping service naming out of the low-level protocol, we keep it nice and simple, which makes it easier to write a high-quality implementation.

I also intend to provide a standard "discovery service" interface, but it will be a layer that sits on top of the raw protocol implementation, rather than being built into it.  Applications will be able to use the raw protocol without using the standard discovery service if desired.
 
> What do you mean?  The global "Stream" message exists only to define the
> protocol.  It is not actually used at runtime -- individual messages are
> read from the stream one at a time.

From pbcap.proto it looked to me as all requests and responses must be
wrapped inside a Stream message. I guess I'll need to take a look at
the implementation before I ask more questions, I only had time to
take a quick peak earlier today.

Maybe what you don't like is the fact that the app-specific request message is embedded as "bytes" in pbcap.CallRequest?  Currently this requires a reduntant copy of all those bytes.  However, I was thinking of adding an optimization to the protobuf implementation to avoid this -- we could add a way to construct a new ByteString that is a substring of some other ByteString in constant time (with no copies).  Then, parsing "bytes" fields -- when the original input is a ByteString -- would not require a copy, making things efficient.
 
To unsubscribe from this group, send email to protobuf+u...@googlegroups.com.

Evan Jones

unread,
Dec 10, 2009, 7:07:35 PM12/10/09
to Kenton Varda, Mikhail Opletayev, Protocol Buffers
On Dec 10, 2009, at 18:33 , Kenton Varda wrote:
> client: "Open service Foo."
> client: "When request 1 is complete, call method Bar() on the
> result."

I'm curious: Why have the Open request at all? Why not just "cal
method Foo.Bar()"? Are you planning on supporting some concept of
"sessions"?

Evan

--
Evan Jones
http://evanjones.ca/

Kenton Varda

unread,
Dec 10, 2009, 7:22:40 PM12/10/09
to Evan Jones, Mikhail Opletayev, Protocol Buffers
On Thu, Dec 10, 2009 at 4:07 PM, Evan Jones <ev...@mit.edu> wrote:
On Dec 10, 2009, at 18:33 , Kenton Varda wrote:
client:  "Open service Foo."
client:  "When request 1 is complete, call method Bar() on the result."

I'm curious: Why have the Open request at all? Why not just "cal method Foo.Bar()"? Are you planning on supporting some concept of "sessions"?

Sorry, but I think you missed the whole point of the conversation.  The idea is that when you make a connection (using my RPC system), you initially only get access to some "default" service.  Typically that default service implements a method called Open() which returns references to other services.  This way, the protocol itself does not need to have any concept of naming RPC services -- this can all be pushed to a higher layer.

Pavel Shramov

unread,
Dec 11, 2009, 3:01:20 AM12/11/09
to Marc Gravell, Pavel Shramov, Romain François, Protocol Buffers
On Thu, Dec 10, 2009 at 09:48:29PM +0000, Marc Gravell wrote:
> Re the whole "what should an endpoint url look like" thing - I had a similar
> discussion with a user re protobuf-net; in the end it was quicker to just
> *default* to the former (since it doesn't need any extra specification), but
> *support* both - so the code detects key strings in the supplied url and
> works some magic.
Ok. But defaults may vary :)

> i.e. if I give it the endpoint: "http://foo/foocorp"
> then it uses "http://foo/foocorp/myservice/somemethod"
>
> but if I give it the endpoint "http://foo/foocorp?svc={service}&act={action}
> "
> it uses "http://foo/foocorp?svc=myservice&action=somemethod"
>
> And so I can officially say "I don't care" about this discussion - either
> suits me without any code-changes ;-p
I've added support for user defined URLs too (in python %(xxx)s format).

So at least we may have clients compatible to different servers...

As I understand other aspects (error encoding, content type) are common in
all HTTP implementations? May be we'll run some compatibility tests?

I've set one at http://psha.org.ru/pbuftest/?{service}.{action}

Pavel

Pavel Shramov

unread,
Dec 11, 2009, 3:11:07 AM12/11/09
to Pavel Shramov, Marc Gravell, Romain François, Protocol Buffers
On Fri, Dec 11, 2009 at 11:01:20AM +0300, Pavel Shramov wrote:
> I've set one at http://psha.org.ru/pbuftest/?{service}.{action}
Forgot to mention that it is standart Test service with Echo call
and Math service [1].
Pavel

--
[1] http://grid.pp.ru/cgit/psha/pbufrpc/tree/examples/test.proto

Marc Gravell

unread,
Dec 11, 2009, 3:44:57 AM12/11/09
to Pavel Shramov, Romain François, Protocol Buffers
I'll definitely try that later ;-p

2009/12/11 Pavel Shramov <shr...@mexmat.net>



--
Regards,

Marc

Mr Moose

unread,
Dec 11, 2009, 5:49:59 AM12/11/09
to Protocol Buffers
Hi Romain,

On 9 Dez., 12:10, Romain François <francoisrom...@free.fr> wrote:
> http is quite verbose for sending protobuf message around, but it is
> likely to be implemented for a lot of languages.

we did just this here. We wrote an RPC implementation complete with
HTTP transport and protobuf as serialization. So far with great
success and stability. The good thing is, that HTTP comes in many
different flavours and implementations, so we were able to integrate
those backends in pion based c++ servers as well as Java Servlets. All
communicating transparently and cross platform. Currently the only
really pressing issue seems to be large data sets.

Apparently at least in Java our current opinion here is, that it's
really not very performant or even feasable to assemble structures
larger than a few megs. We have structures containing large blobs for
data coming straight out of files (can be >1GB) and in order to put
the data in the protobuf these data would have to live in mem 3 times
while copying into the protobuf classes. Something like a stream
serialization would be in order and we do not know how to do that in
protobuf yet.

Apart from this it's a great way to go for small messages.

Cheers,
Stephan

Kenton Varda

unread,
Dec 12, 2009, 9:59:23 PM12/12/09
to Mikhail Opletayev, Protocol Buffers
If you're interested I have added explanatory comments to the socket-level protocol definition for Captain Proto (formerly pbcap):


I still have no conventions for HTTP transport.
Reply all
Reply to author
Forward
0 new messages