我计划提供两项服务。
用 Ruby 编写的 HTTP REST 服务
用 Go 编写的 JSON RPC 服务
Ruby 服务将打开一个到 Go JSON RPC 服务的 TCP 套接字连接。它将为收到的每个传入 HTTP 请求执行此操作。它将通过套接字向 Go 服务发送一些数据,该服务随后将相应的数据发送回套接字。
Go 服务 go 看起来像这样(简化):
srv := new(service.App) // this would expose a Process method
rpc.Register(srv)
listener, err := net.Listen("tcp", ":8080")
if err != nil {
// handle error
}
for {
conn, err := listener.Accept()
if err != nil {
// handle error
}
go jsonrpc.ServeConn(conn)
}
请注意,我们使用 goroutine 为传入连接提供服务,因此我们可以并发处理请求。
红宝石代码
下面是一段简单的 Ruby 代码片段,它演示了(理论上)我将数据发送到 Go 服务的方式:
require "socket"
require "json"
socket = TCPSocket.new "localhost", "8080"
b = {
:method => "App.Process",
:params => [{ :Config => JSON.generate({ :foo => :bar }) }],
:id => "0"
}
socket.write(JSON.dump(b))
response = JSON.load socket.readline
我担心的是:这会是一个安全的事件序列吗?
我不是在问这是否是“线程安全的”,因为我不担心跨 go 例程操纵共享内存。我更关心我的 Ruby HTTP 服务是否会取回它期望的数据?
如果我有两个并行请求进入我的 HTTP 服务(或者 Ruby 应用程序托管在负载均衡器之后,因此HTTP 服务的不同实例正在处理多个请求),那么我可以让实例 A 将消息 Foo 发送到 Go服务; 而实例 B 发送消息 Bar。
Go 服务内部的业务逻辑将根据其输入返回不同的响应,因此我想确保 Ruby 实例 A 为 Foo 返回正确的响应,而 B 为 Bar 返回正确的响应。
我假设套接字连接更像是一个队列,因为如果实例 A 先向 Go 服务发出请求,然后B 这样做,但 B 无论出于何种原因响应更快,那么 Go 服务会将 B 的响应写入套接字并且 Ruby 应用程序的实例 A 最终将读取错误的套接字数据(这显然只是一种可能的情况,因为我可能很幸运并且让实例 B 在实例 A 之前读取了套接字数据)。
解决方案?
我不确定这个问题是否有简单的解决方案。除非我不使用 TCP 套接字或 RPC 而是依赖 Go 服务中的标准 HTTP。但我想要 TCP 的性能和更少的开销。
我担心设计可能会变得更加复杂,因为可能必须实现一个外部队列作为与 Ruby 服务同步响应的一种方式。
可能是因为我的 Ruby 服务本质上是同步的(HTTP 响应/请求),所以我别无选择,只能为 Go 服务切换到 HTTP。
但是我想先与社区进行仔细检查,以防万一我遗漏了一些明显的东西。
蓝山帝景
HUX布斯
随时随地看视频慕课网APP
相关分类