Clojure REPL 连接远程会话

学习 Clojure 一般是用 lein repl 启动控制台, 每次启动 lein repl 都会发现它打开了一个端口, 例如

➜ ~ lein repl
nREPL server started on port 57212 on host 127.0.0.1 - nrepl://127.0.0.1:57212
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.8.0
...........

一直不清楚上面显示的 nrepl://127.0.0.1:57212 该作何用, 而且端口号是随机的, 这其中定有文章.

幸好有 Google 帮忙, 查一查, 然后才意识到何不运行  lein help repl 来看看 repl 中到底有何玄机, 原来是:

<none> -> :start     lein repl 默认的行为, 见下. 未指定 :host 或 :port , :host 默认为 127.0.0.1,  :port 为随机
:start [:host host] [:port port] 原来  lein repl 设计为为 CS 结构. :start 会启动一个 nREPL  server, 并且立即启动一个 client 连接上它. :host 默认为 127.0.0.1, :port 默认为随机的
:headless [:host host] [:port port]   只启动 nREPL server, 等待别人来连接它, 相同的默认 :host, :port 规则.  也就是它不会进到 Clojure 控制台
:connect [dest]   连接一个 nREPL server. 目标服务器的指定有三种方式: HTTPS(S) URL, host:port, 或 port

命令举例:

lein repl :start :port 1234    启动 nrepl://127.0.0.1:1234 Server, 并且立即开一个客户端连接上它. 比如进到控制台 user=>
lein repl :headless :host 0.0.0.0  启动 nrepl://0.0.0.0:7788, 并等待客户端连接. 它不接受输入
lein repl :connect 1234   启动一个客户端连接上本机的 1234 端口上的 nREPL server. 它可以进到控制台
lein repl :connect nrepl://192.168.0.1:57906  启动一个客户端连接  nREPL server nrepl://192.168.0.1:57906
lein repl :connect :host 192.168.0.1 :port 57906  用途同上

那么 lein repl 设计成 CS 结构有什么好处呢? 在使用 Scala 的 sbt 时, 我非常喜欢它有别于多数构建工具的交互界面, 只是它每一个会话是孤立的. 使用 lein repl 则不同, 如果不同的客户端连接到同一个 server 的话, 它们共享着相同的环境, 便于协作.

我们分别用命令

lein repl 启动 nREPL server 并连一个客户端, 这里端口号是 58687. 并在这个客户端中声明一个变量 v
lein repl :connect nrepl://127.0.0.1:58687 启动一个新客户端连接上面的服务端, 显示出前面定义的变量 v

lein-repl-server-client

这种架构下可以发挥的空间还是很大的. 比如预定义好项目用的函数, 那么无论何时连接上同一个 nREPL 就可以管理同一个项目.

看到了 lein repl 有这样的特性, 禁不住会想 java -jar clojure-1.8.0.jar 启动 Clojure 控制台的方式是否有类似的功能, 没有, 只有一行提示 "Clojure 1.8.0", 并没有什么端口之类的提示信息.

且住, 只是  java -jar clojure-1.8.0.jar 方式默认不启动 Clojure Socket Server, 要是加上系统属性 clojure.server.repl 就能达到类同的效果. 如下命令

java -Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}" -jar clojure-1.8.0.jar

虽然上面的命令得到的提示依然是那么的简洁, 然而我们已知它开了 5555 端口, 所以用  telnet 127.0.0.1 5555 连接, 立马就进到了相同的 Clojure 控制台. 如下图, 左窗格中定义的 my-name 变量, 右窗格口直接读出来, 右边定义的 foo 函数同样可在左边执行.

clojure-socket-server-new

 

这个特性也只是从 Clojure 1.8.0  开始支持的. 而且比 lein repl :connect ... 连接的远程会话更高明,  telnet 信手即可拈来, 用不着安装 lein 这个应用来当作客户端. 这样的话只要在 Server 上启动一个 Clojure Socket Server, 任何人都可以很轻松的体验一下  Clojure, 如果能为每一个会话分配唯一的 Namespace, 那么每个客户端可以做到一定程度的不相干性.

你可以尝试用 telnet 连接一下 lein repl 启动的 nREPL server 试下, 就一个普通的 Socket, 没什么卵用.

参考: 1. Clojure REPL and main entry points
        2. Socket Server REPL

 

本文链接 https://yanbin.blog/clojure-lein-repl-connect-session/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments