Jupyter Notebook 跨域连接 Kernel 的方法

通常一个新的 Notebook 在打开的时候,会自动连接当前服务器,创建一个 Session 和一个 Kernel 进程。该 Session 绑定在该 nb(notebook 简称,下同) 的路径上,因此你要你的 server 不停,无论刷新 nb 还是打开该 nb 的一个新 tab,该 session 都是同一个 session,kernel 也是同一个 kernel。

以上是 Notebook 基本的前后端交互流程,本文关注的是当 nb 与 Kernel 不在同一个域下时,如何跨域连接的问题。即假设 nb 的地址是 a.com/xx.ipynb,但我们想连接 b.com 的一个 kernel。

修改后端地址

首先是创建 Session 的调用,该调用发生在 session.js 第 122 行

utils.ajax(this.session_service_url, {

这里需要修改为你想要连接的域名,比如 'http://b.com' + this.session_service_url

session 与 kernel 创建完成后,nb 与 kernel 的交互会使用 websocket 通道。ws 地址是类似 ws://localhost 这样的格式,定义在 notebook.html 模板中,在打开 nb 时由 server 进行渲染:

data-ws-url="{{ws_url | urlencode}}"

这两处修改为跨域地址后,你的 nb 就会自动向新服务器发请求,那么自然你的新服务器需要在响应中添加跨域头,这一点可以简单通过修改配置文件实现:

c.NotebookApp.allow_origin = '*'

该配置项会在 /base/handlers.py 中被访问:

[@property](https://my.oschina.net/property)
def allow_origin(self):
    """Normal Access-Control-Allow-Origin"""
    return self.settings.get('allow_origin', '')

处理认证

当然 server 不是对连接来者不拒的。在认证上仍有两处需要处理:

一是 xsrf token 认证,该认证可以在配置文件中关掉:

c.NotebookApp.disable_check_xsrf = True

二是用户登录认证。server 默认使用 token 的方式,该 token 会在渲染 nb 的时候写入 page.html 里:

data-jupyter-api-token="{{token | urlencode}}"

或者想直接绕过 auth 过程的话,修改 base/handlers.py 里的 get_current_user 方法即可。

完成以上修改后,跨域连接 kernel 的功能就可以实现了。

猜你喜欢

转载自my.oschina.net/lionets/blog/1631695