Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
f6205591
Commit
f6205591
authored
Dec 12, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Doc tweaks.
parent
b06ff395
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
73 additions
and
48 deletions
+73
-48
2013-12-12-capnproto-0.4-time-travel.md
doc/_posts/2013-12-12-capnproto-0.4-time-travel.md
+17
-10
cxxrpc.md
doc/cxxrpc.md
+11
-4
faq.md
doc/faq.md
+11
-7
rpc.md
doc/rpc.md
+33
-26
stylesheet.css
doc/stylesheets/stylesheet.css
+1
-1
No files found.
doc/_posts/2013-12-12-capnproto-0.4-time-travel.md
View file @
f6205591
...
...
@@ -4,8 +4,8 @@ title: "Cap'n Proto v0.4: Time Traveling RPC"
author
:
kentonv
---
Well,
Hofstadter kicked in and this release took way too long. But, after three long months, I'm
happy to announce...
Well,
[
Hofstadter
](
http://en.wikipedia.org/wiki/Hofstadter's_law
)
kicked in and this release took
way too long. But, after three long months, I'm happy to announce:
### Time-Traveling RPC
...
...
@@ -13,7 +13,7 @@ happy to announce...
v0.4 finally introduces the long-promised
[
RPC system
](
{{
site.baseurl }}rpc.html). Traditionally,
RPC is plagued by the fact that networks have latency, and pretending that latency doesn't exist by
hiding
hiding
it behind what looks like a normal function call only makes the problem worse.
hiding it behind what looks like a normal function call only makes the problem worse.
Cap'n Proto has a simple solution to this problem: send call results _back in time_, so they
arrive at the client at the point in time when the call was originally made!
...
...
@@ -22,7 +22,7 @@ Curious how Cap'n Proto bypasses the laws of physics?
### Promises in C++
If you do a
ny
Javascript programming, you've probably heard of
If you do a
lot of serious
Javascript programming, you've probably heard of
[
Promises/A+
](
http://promisesaplus.com/
)
and similar proposals. Cap'n Proto RPC introduces a
similar construct in C++. In fact, the API is nearly identical, and its semantics are nearly
identical. Compare with
...
...
@@ -48,19 +48,26 @@ getTweetsFor("domenic") // returns a promise
);
{% endhighlight %}
This is C++, but it is no more lines than the equivalent Javascript. We're doing several I/O
operations, we're doing them asynchronously, and we don't have a huge unreadable mess of callback
functions. Promises are based on event loop concurrency, which means you can perform concurrent
operations with shared state without worrying about mutex locking -- i.e., the Javascript model.
(Of course, if you really want threads, you can run multiple event loops in multiple threads.)
This is C++, but it is no more lines -- nor otherwise more complex -- than the equivalent
Javascript. We're doing several I/O operations, we're doing them asynchronously, and we don't
have a huge unreadable mess of callback functions. Promises are based on event loop concurrency,
which means you can perform concurrent operations with shared state without worrying about mutex
locking -- i.e., the Javascript model. (Of course, if you really want threads, you can run
multiple event loops in multiple threads and make inter-thread RPC calls between them.)
[
More on C++ promises.
](
{{
site.baseurl }}cxxrpc.html#kj_concurrency_framework)
### Python too
[
Jason
](
https://github.com/jparyani
)
has been diligently keeping his
[
Python bindings
](
http://jparyani.github.io/pycapnp/
)
up to date, so you can already use RPC there
as well. The Python interactive interpreter makes a great debugging tool for calling C++ servers.
### Up Next
Cap'n Proto is far from done, but working on it in a bubble will not produce ideal results.
Starting after the holidays, I will be refocusing some of my time into an adjacent project which
will be a heavy user of Cap'n Proto. I hope this experience will help me
experience
first hand
will be a heavy user of Cap'n Proto. I hope this experience will help me
discover
first hand
the pain points in the current interface and keep development going in the right direction.
This does, however, mean that core Cap'n Proto development will slow somewhat (unless contributors
...
...
doc/cxxrpc.md
View file @
f6205591
...
...
@@ -39,7 +39,8 @@ KJ's event loop model bears a lot of similarity to the Javascript concurrency mo
Javascript hackers -- especially node.js hackers -- will feel right at home.
_As of version 0.4, the only supported way to communicate between threads is over pipes or
socketpairs. This will be improved in future versions._
socketpairs. This will be improved in future versions. For now, just set up an RPC connection
over that socketpair. :)_
### Promises
...
...
@@ -50,6 +51,8 @@ of operations that have not yet completed. When the operation completes, we say
exception occurred.
{% highlight c++ %}
// Example promise-based interfaces.
kj::Promise
<kj::String>
fetchHttp(kj::StringPtr url);
// Asynchronously fetches an HTTP document and returns
// the content as a string.
...
...
@@ -57,7 +60,8 @@ kj::Promise<kj::String> fetchHttp(kj::StringPtr url);
kj::Promise
<void>
sendEmail(kj::StringPtr address,
kj::StringPtr title, kj::StringPtr body);
// Sends an e-mail to the given address with the given title
// and body.
// and body. The returned promise resolves (to nothing) when
// the message has been successfully sent.
{% endhighlight %}
As you will see, KJ promises are very similar to the evolving Javascript promise standard, and
...
...
@@ -68,7 +72,7 @@ applied to KJ promises.
If you want to do something with the result of a promise, you must first wait for it to complete.
This is normally done by registering a callback to execute on completion. Luckily, C++11 just
introduced lambdas which makes this far more pleasant than it would have been a few years ago!
introduced lambdas
,
which makes this far more pleasant than it would have been a few years ago!
{% highlight c++ %}
kj::Promise
<kj::String>
contentPromise =
...
...
@@ -326,6 +330,7 @@ A client should typically look like this:
{% highlight c++ %}
#include <capnp/ez-rpc.h>
#include "my-interface.capnp.h"
#include <iostream>
int main(int argc, const char
*
argv
[]
) {
// We expect one argument specifying the server address.
...
...
@@ -370,6 +375,7 @@ A server might look something like this:
{% highlight c++ %}
#include <capnp/ez-rpc.h>
#include "my-interface-impl.h"
#include <iostream>
int main(int argc, const char
*
argv
[]
) {
// We expect one argument specifying the address to which
...
...
@@ -407,4 +413,5 @@ For a more complete example, see the
If you've written a server and you want to connect to it to issue some calls for debugging, perhaps
interactively, the easiest way to do it is to use
[
pycapnp
](
http://jparyani.github.io/pycapnp/
)
.
The
`capnp`
tool probably will never add RPC functionality because pycapnp is better.
We have decided not to add RPC functionality to the
`capnp`
command-line tool because pycapnp is
better than anything we might provide.
doc/faq.md
View file @
f6205591
...
...
@@ -35,12 +35,15 @@ That said, Cap'n Proto RPC takes a very different approach. Cap'n Proto's model
stateful servers interacting in complex, object-oriented ways. The model is better suited to
tasks involving applications with many heterogeneous components and interactions between
mutually-distrusting parties. Requests and responses can go in any direction. Objects have
state and
two calls to the same object had best be implemented on the same machine. Fault
tolerance is pushed up the stack, because without a large pool of homogeneous work there's just
no way to make it
transparent at a low level.
state and
so two calls to the same object had best go to the same machine. Load balancing and
fault tolerance is pushed up the stack, because without a large pool of homogeneous work there's
just no way to make them
transparent at a low level.
Put concretely, you might build a search engine on ZeroMQ, but an online interactive spreadsheet
editor would be better built on Cap'n Proto RPC.
Put concretely, you might build a search engine indexing pipeline on ZeroMQ, but an online
interactive spreadsheet editor would be better built on Cap'n Proto RPC.
(Actually, a distributed programming framework providing similar features to ZeroMQ could itself be
built on top of Cap'n Proto RPC.)
### Aren't messages that contain pointers a huge security problem?
...
...
@@ -55,8 +58,9 @@ Proto message is negligible.
### I think I heard somewhere that capability-based security doesn't work?
This was a popular myth in security circles way back in the 80's and 90's, based on an incomplete
understanding of how to use capabilities effectively. Read
[
Capability Myths Demolished
](
http://srl.cs.jhu.edu/pubs/SRL2003-02.pdf
)
.
understanding of what capabilities are and how to use them effectively. Read
[
Capability Myths Demolished
](
http://srl.cs.jhu.edu/pubs/SRL2003-02.pdf
)
. (No really, read it;
it's awesome.)
## Usage
...
...
doc/rpc.md
View file @
f6205591
...
...
@@ -12,7 +12,7 @@ title: RPC Protocol
<img
src=
'images/time-travel.png'
style=
'max-width:639px'
>
Cap'n Proto RPC employs TIME TRAVEL! The results of an RPC call are returned to the client
instantly, before the server even receives the
request to start working on i
t!
instantly, before the server even receives the
initial reques
t!
There is, of course, a catch: The results can only be used as part of a new request sent to the
same server. If you want to use the results for anything else, you must wait.
...
...
@@ -31,7 +31,8 @@ to wait for the first call to actually return.
To make programming to this model easy, in your code, each call returns a "promise". Promises
work much like Javascript promises or promises/futures in other languages: the promise is returned
immediately, but you must later call
`wait()`
or register a completion callback to handle.
immediately, but you must later call
`wait()`
on it, or call
`then()`
to register an asynchronous
callback.
However, Cap'n Proto promises support an additional feature:
[
pipelining
](
http://en.wikipedia.org/wiki/Futures_and_promises#Promise_pipelining
)
. The promise
...
...
@@ -43,7 +44,7 @@ pipelined promise can be used in the parameters to another call without waiting.
OK, fair enough. In a traditional RPC system, we might solve our problem by introducing a new
method
`foobar()`
which combines
`foo()`
and
`bar()`
. Now we've eliminated the round trip, without
inventing a
new
protocol.
inventing a
whole new RPC
protocol.
The problem is, this kind of arbitrary combining of orthogonal features quickly turns elegant
object-oriented protocols into ad-hoc messes.
...
...
@@ -53,14 +54,9 @@ For example, consider the following interface:
{% highlight capnp %}
# A happy, object-oriented interface!
struct Node {
union {
file :File;
directory :Directory;
}
}
interface Node {}
interface Directory {
interface Directory
extends Node
{
list @0 () -> (list: List(Entry));
struct Entry {
name @0 :Text;
...
...
@@ -73,7 +69,7 @@ interface Directory {
link @4 (name :Text, node :Node);
}
interface File {
interface File
extends Node
{
size @0 () -> (size: UInt64);
read @1 (startAt :UInt64, amount :UInt64) -> (data: Data);
write @2 (startAt :UInt64, data :Data);
...
...
@@ -87,10 +83,10 @@ file `foo` in directory `bar` takes four round trips!
{% highlight python %}
# pseudocode
foo = root.open("foo")
.node.directory;
# 1
bar = foo.open("bar")
.node.file;
# 2
size = bar.size();
# 3
data = bar.read(0, size);
# 4
foo = root.open("foo")
;
# 1
bar = foo.open("bar")
;
# 2
size = bar.size(); # 3
data = bar.read(0, size); # 4
{% endhighlight %}
In such a high-latency scenario, making your interface elegant is simply not worth 4x the latency.
...
...
@@ -112,7 +108,7 @@ interface Filesystem {
fileSize @4 (path :Text) -> (size: UInt64);
read @5 (path :Text, startAt :UInt64, amount :UInt64)
-> (data
:
Data);
-> (data
:
Data);
readAll @6 (path :Text) -> (data: Data);
write @7 (path :Text, startAt :UInt64, data :Data);
truncate @8 (path :Text, size :UInt64);
...
...
@@ -126,10 +122,10 @@ We've now solved our latency problem... but at what cost?
be complicated and error-prone.
*
We can no longer give someone a specific
`File`
or a
`Directory`
-- we have to give them a
`Filesystem`
and a path.
*
But what if they are buggy and have hard-coded some path other than the one we specified?
*
Or what if we don't trust them, and we really want them to access only one particular
`File`
or
`Directory`
and not have permission to anything else. Now we have to implement authentication
and authorization systems! Arrgghh!
*
But what if they are buggy and have hard-coded some path other than the one we specified?
*
Or what if we don't trust them, and we really want them to access only one particular
`File`
or
`Directory`
and not have permission to anything else. Now we have to implement authentication
and authorization systems! Arrgghh!
Essentially, in our quest to avoid latency, we've resorted to using a singleton-ish design, and
[
singletons are evil
](
http://www.object-oriented-security.org/lets-argue/singletons
)
.
...
...
@@ -145,12 +141,13 @@ performs as well as we can possibly hope for.
As you've noticed by now, Cap'n Proto RPC is a distributed object protocol. Interface references --
or, as we more commonly call them, capabilities -- are a first-class type. You can pass a
capability as a parameter or embed it in a struct or list. This is a huge difference from many
modern RPC-over-HTTP protocols that only let you address global URLs, or other RPC systems like
Protocol Buffers and Thrift that only let you address singleton objects exported at startup. The
ability to dynamically introduce new objects and pass around references to them allows you to use
the same design patterns over the network that you use locally in object-oriented programming
languages. Many kinds of interactions become vastly easier to express given the richer vocabulary.
capability as a parameter to a method or embed it in a struct or list. This is a huge difference
from many modern RPC-over-HTTP protocols that only let you address global URLs, or other RPC
systems like Protocol Buffers and Thrift that only let you address singleton objects exported at
startup. The ability to dynamically introduce new objects and pass around references to them
allows you to use the same design patterns over the network that you use locally in object-oriented
programming languages. Many kinds of interactions become vastly easier to express given the
richer vocabulary.
**_Didn't CORBA prove this doesn't work?_**
...
...
@@ -181,6 +178,11 @@ ACL-based security, making it easy to keep security tight and avoid confused-dep
minimizing pain for legitimate users. That said, you can of course implement ACLs or any other
pattern on top of capabilities.
For an extended discussion of what capabilities are and why they are often easier and more powerful
than ACLs, see Mark Miller's
[
"An Ode to the Granovetter Diagram"
](
http://www.erights.org/elib/capability/ode/index.html
)
and
[
Capability Myths Demolished
](
http://srl.cs.jhu.edu/pubs/SRL2003-02.pdf
)
.
## Protocol Features
Cap'n Proto's RPC protocol has the following notable features. Since the protocol is complicated,
...
...
@@ -206,6 +208,11 @@ features they have covered by advertising a level number.
two verify that two or more other parties agree on something (imagine a digital escrow agent).
See
[
E's page on equality
](
http://erights.org/elib/equality/index.html
)
.
## Encryption
At this time, Cap'n Proto does not specify an encryption scheme, but as it is a simple byte
stream protocol, it can easily be layered on top of SSL/TLS or other such protocols.
## Specification
The Cap'n Proto RPC protocol is defined in terms of Cap'n Proto serialization schemas. The
...
...
doc/stylesheets/stylesheet.css
View file @
f6205591
...
...
@@ -387,7 +387,7 @@ body.normal #main_content.inner {
top
:
100px
;
z-index
:
100
;
border
:
2px
solid
black
;
background-color
:
rgba
(
196
,
196
,
196
,
0.
8
);
background-color
:
rgba
(
196
,
196
,
196
,
0.
9
);
text-align
:
center
;
color
:
black
;
padding
:
30px
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment