Aleph 将来自网络的数据作为 Manifold 流公开,可以轻松转换为java.io.InputStream
、 core.async 通道、 Clojure 序列或许多其他字节表示形式。它公开了 HTTP、TCP 和 UDP 的简单默认包装器,但允许访问底层 Netty 库的全部性能和灵活性。
莱宁根:
[aleph " 0.8.2 " ]
deps.edn:
aleph/aleph { :mvn/version " 0.8.2 " }
; ; alternatively
io.github.clj-commons/aleph { :git/sha " ... " }
Aleph 完全遵循 Ring 规范,并且可以直接替代任何现有的 Ring 兼容服务器。但是,它还允许处理程序函数返回延迟的 Manifold 以表示最终响应。此功能可能无法与修改响应的同步 Ring 中间件很好地配合,但可以通过使用 Manifold 的 let-flow 运算符重新实现中间件来轻松解决此问题。 aleph.http/wrap-ring-async-handler
帮助器可用于将异步 3 元环处理程序转换为符合 Aleph 的处理程序。
( require '[aleph.http :as http])
( defn handler [req]
{ :status 200
:headers { " content-type " " text/plain " }
:body " hello! " })
( http/start-server handler { :port 8080 }) ; HTTP/1-only
; ; To support HTTP/2, do the following:
; ; (def my-ssl-context ...)
( http/start-server handler { :port 443
:http-versions [ :http2 :http1 ]
:ssl-context my-ssl-context})
; ; See aleph.examples.http2 for more details
响应的主体也可以是一个 Manifold 流,其中来自流的每条消息都作为一个块发送,从而允许对服务器发送事件和其他目的的流式响应进行精确控制。
对于 HTTP 客户端请求,Aleph 在 clj-http 后对自身进行建模,不同之处在于每个请求立即返回代表响应的 Manifold deferred。
( require
'[aleph.http :as http]
'[manifold.deferred :as d]
'[clj-commons.byte-streams :as bs])
( -> @( http/get " https://google.com/ " )
:body
bs/to-string
prn)
( d/chain ( http/get " https://google.com " )
:body
bs/to-string
prn)
; ; To support HTTP/2, do the following:
( def conn-pool
( http/connection-pool { :connection-options { :http-versions [ :http2 :http1 ]}}))
@( http/get " https://google.com " { :pool conn-pool})
; ; See aleph.examples.http2 for more details
Aleph 尝试完全模仿 clj-http API 和功能。它支持多部分/表单数据请求、cookie 存储、代理服务器和请求检查,但有一些显着差异:
设置连接池时应为连接设置代理配置,不允许按请求设置代理
HTTP 代理功能通过隧道设置、可选 HTTP 标头和连接超时控制进行了扩展,请参阅所有配置键
:proxy-ignore-hosts
cookie 中间件和内置 cookie 存储都不支持自 RFC2965 以来已废弃的 cookie 参数:comment、comment URL、discard、version(请参阅 cookie 的完整结构)
当使用:debug
、 :save-request?
和:debug-body?
选项,相应的请求将存储在响应映射的:aleph/netty-request
、 :aleph/request
、 :aleph/request-body
键中
:response-interceptor
选项
Aleph 引入了:log-activity
连接池配置来打开连接状态更改以及请求/响应十六进制转储的日志记录
目前不支持:cache
和:cache-config
选项
Aleph 客户端还支持完全异步且高度可定制的 DNS 解析器。
要了解更多信息,请阅读示例代码。
从 0.7.0 开始,Aleph 在客户端和服务器上都支持 HTTP/2。
在大多数情况下,Aleph 的 HTTP/2 支持是 HTTP/1 的直接替代品。不过,为了向后兼容,Aleph 默认仅使用 HTTP/1。有关 HTTP/2 入门的详细概述,请参阅示例 HTTP/2 代码。
需要注意的事项:
pipeline-transform
来更改底层 Netty 管道,则需要检查它对 HTTP/2 的使用情况。在底层,新的 HTTP/2 代码使用 Netty 的多路复用管道设置,以及一个共享连接级管道,该管道将特定于流的帧提供给为 N 个单独流创建的 N 个管道。 (标准 HTTP 请求/响应对映射到单个 H2 流。)在任何具有正确Upgrade
标头的 HTTP 请求中,您可以调用(aleph.http/websocket-connection req)
,它返回一个 deferred ,它会产生一个双工流,它使用单个流来表示双向通信。可以通过take!
接收来自客户端的消息! ,并通过put!
发送给客户端。那么,一个 echo WebSocket 处理程序将只包含以下内容:
( require '[manifold.stream :as s])
( defn echo-handler [req]
( let [s @( http/websocket-connection req)]
( s/connect s s)))
这将从客户端获取所有消息,并将它们反馈到双工套接字中,然后将它们返回给客户端。 WebSocket 文本消息将以字符串形式发出,二进制消息以字节数组形式发出。
WebSocket 客户端可以通过(aleph.http/websocket-client url)
创建,它返回一个延迟,生成一个可以从服务器发送和接收消息的双工流。
要了解更多信息,请阅读示例代码。
TCP 服务器与 HTTP 服务器类似,不同之处在于,对于每个连接,处理程序采用两个参数:一个双工流和一个包含有关客户端信息的映射。该流将发出字节数组,可以使用字节流库将其强制转换为其他字节表示形式。该流将接受任何可以强制转换为二进制表示形式的消息。
echo TCP 服务器与上面的 WebSocket 示例非常相似:
( require '[aleph.tcp :as tcp])
( defn echo-handler [s info]
( s/connect s s))
( tcp/start-server echo-handler { :port 10001 })
TCP 客户端可以通过(aleph.tcp/client {:host "example.com", :port 10001})
创建,它返回一个延迟,从而产生一个双工流。
要了解更多信息,请阅读示例代码。
可以使用(aleph.udp/socket {:port 10001, :broadcast? false})
生成 UDP 套接字。如果指定了:port
,它将产生一个双工套接字,可用于发送和接收消息,消息的结构为具有以下数据的映射:
{ :host " example.com "
:port 10001
:message ...}
其中传入数据包将有一个:message
,它是一个字节数组,可以使用byte-streams
进行强制,而传出数据包可以是任何可以强制为二进制表示的数据。如果没有指定:port
,则套接字只能用于发送消息。
要了解更多信息,请阅读示例代码。
Aleph 使用 Leiningen 来管理依赖项、运行 REPL 和测试以及构建代码。
最小的tools.deps
支持以deps.edn
文件的形式提供,该文件是从project.clj
生成的。它提供的功能足以将 Aleph 用作 git 或:local/root
依赖项。当提交对project.clj
的更改时,运行deps/lein-to-deps
并提交生成的更改。
版权所有 © 2010-2024 扎卡里·泰尔曼
根据 MIT 许可证分发。
非常感谢 YourKit 对 Aleph 的支持。 YourKit 通过创新和智能的工具支持开源项目,用于监视和分析 Java 和 .NET 应用程序。
YourKit 是 YourKit Java Profiler、YourKit .NET Profiler 和 YourKit YouMonitor 的创建者。