Skip to content

Commit 4094a5d

Browse files
committed
Document kernel message additions by Jupyter server
We also document things about kernel message buffering, rate limiting, etc. This migrates jupyter/notebook#3765 to the Jupyter Server repo, where the kernel message additions now happen.
1 parent b82d102 commit 4094a5d

File tree

1 file changed

+103
-7
lines changed

1 file changed

+103
-7
lines changed

docs/source/developers/websocket-protocols.rst

Lines changed: 103 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,108 @@
11
.. _websocket_protocols:
22

3-
WebSocket kernel wire protocols
4-
===============================
53

6-
The Jupyter Server needs to pass messages between kernels and the Jupyter web application. Kernels use ZeroMQ sockets, and the web application uses a WebSocket.
4+
Kernel Messages
5+
===============
6+
7+
When a kernel is created or connected to via the `REST API
8+
<https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/jupyter_server/master/jupyter_server/services/api/api.yaml>`__,
9+
the Jupyter server sets up a websocket to ZeroMQ bridge for communicating
10+
between the browser and the kernel. When the server connects to a kernel, the
11+
server sends a ``request_kernel_info`` messages to retrieve the kernel message
12+
spec version the kernel implements. The server automatically adapts messages
13+
from the kernel spec version the kernel implements to the kernel spec
14+
implemented by the current version of jupyter_client installed.
15+
16+
Restarting or shutting down a kernel should be done with a REST request to the
17+
server, not through a kernel message, so that the kernel manager can do the
18+
appropriate logic around kernel shutdown, like asking the kernel to shut down
19+
first through a kernel message, then forcefully shutting down the kernel if
20+
there is no response.
21+
22+
Kernel messages
23+
---------------
24+
25+
A websocket client connecting to a kernel through the Jupyter server websocket
26+
bridge will use messages according to the Jupyter kernel message spec, with the
27+
modifications noted below.
28+
29+
Kernel Message Specification Changes
30+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31+
32+
**Message Channels**
33+
34+
The notebook server multiplexes all kernel message channels into a single
35+
websocket channel and encodes the channel name in the websocket message wire
36+
format (see below).
37+
38+
**Kernel Status**
39+
40+
The Jupyter server sends several additional `kernel status <https://jupyter-client.readthedocs.io/en/stable/messaging.html#kernel-status>`__ messages in addition
41+
to the kernel status messages that are sent by the kernel itself:
42+
43+
1. When a kernel is restarted, an ``execution_state: 'restarting'`` kernel status message is sent.
44+
2. When a kernel dies, an ``execution_state: 'dead'`` kernel status message is sent.
45+
46+
These status messages will have a different message header ``session`` value
47+
than the message header session values in messages from the kernel.
48+
49+
.. note::
50+
51+
As an implementation detail, the message header session value of these
52+
messages matches the `session_id` in the kernel connection URL.
53+
54+
.. note::
55+
56+
In the classic notebook and JupyterLab client code, the websocket connection
57+
is closed when explicitly requesting a restart or shutdown, so the
58+
restarting and dead messages aren't received if it was requested by the
59+
user. In those cases, receiving a ``restarting`` or ``dead`` message from
60+
the notebook server means that the kernel had something happen to it, and
61+
the user should be explicitly notified.
62+
63+
**IOpub Message Rate Limits**
64+
65+
The notebook server inspects the messages coming from the kernel to the client
66+
to rate-limit iopub messages. These rate limits can be raised.
67+
68+
69+
Buffering
70+
~~~~~~~~~
71+
72+
If all websocket clients have disconnected from a kernel, the notebook server
73+
will temporarily buffer messages from the kernel to be delivered to the first
74+
websocket client that connects to the kernel.
75+
76+
77+
78+
.. note::
79+
80+
In the classic notebook client and JupyterLab, requesting a kernel restart
81+
immediately closes all websocket connections to the kernel, so kernel
82+
buffering starts. When a new websocket connection is created connecting to
83+
the kernel, the notebook server transmits all of the messages buffered from
84+
the kernel. For the IPython kernel, this means the new websocket connection
85+
will start with receiving status busy, shutdown_reply, and status idle
86+
messages on the iopub channel from before the restart.
87+
88+
.. note::
89+
90+
TODO
91+
92+
Document the session URL parameter used in kernel connections. Is that
93+
created every time we request a kernel with a post request? Is it tied to
94+
just creating new sessions with the session rest api?
95+
96+
97+
Wire protocol
98+
-------------
99+
100+
Jupyter Server translates messages between the ZeroMQ channels connected to a
101+
kernel and the websocket connection to the browser. The wire formats for these
102+
messages is as follows.
7103

8104
ZeroMQ wire protocol
9-
--------------------
105+
~~~~~~~~~~~~~~~~~~~~
10106

11107
The kernel wire protocol over ZeroMQ takes advantage of multipart messages,
12108
allowing to decompose a message into parts and to send and receive them
@@ -38,12 +134,12 @@ See also the `Jupyter Client documentation <https://jupyter-client.readthedocs.i
38134
Note that a set of ZeroMQ sockets, one for each channel (shell, iopub, etc.), are multiplexed into one WebSocket. Thus, the channel name must be encoded in WebSocket messages.
39135

40136
WebSocket protocol negotiation
41-
------------------------------
137+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
42138

43139
When opening a WebSocket, the Jupyter web application can optionally provide a list of subprotocols it supports (see e.g. the `MDN documentation <https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#subprotocols>`_). If nothing is provided (empty list), then the Jupyter Server assumes the default protocol will be used. Otherwise, the Jupyter Server must select one of the provided subprotocols, or none of them. If none of them is selected, the Jupyter Server must reply with an empty string, which means that the default protocol will be used.
44140

45141
Default WebSocket protocol
46-
--------------------------
142+
~~~~~~~~~~~~~~~~~~~~~~~~~~
47143

48144
The Jupyter Server must support the default protocol, in which a kernel message is serialized over WebSocket as follows:
49145

@@ -101,7 +197,7 @@ Then retrieving the channel name, and updating with the buffers, if any:
101197
}
102198
103199
``v1.kernel.websocket.jupyter.org`` protocol
104-
--------------------------------------------
200+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
105201

106202
The Jupyter Server can optionally support the ``v1.kernel.websocket.jupyter.org`` protocol, in which a kernel message is serialized over WebSocket as follows:
107203

0 commit comments

Comments
 (0)