为了账号安全,请及时绑定邮箱和手机立即绑定

此示例 tcp 套接字编程事件序列安全吗?

此示例 tcp 套接字编程事件序列安全吗?

Go
蓝山帝景 2022-01-04 10:26:44
我计划提供两项服务。用 Ruby 编写的 HTTP REST 服务用 Go 编写的 JSON RPC 服务Ruby 服务将打开一个到 Go JSON RPC 服务的 TCP 套接字连接。它将为收到的每个传入 HTTP 请求执行此操作。它将通过套接字向 Go 服务发送一些数据,该服务随后将相应的数据发送回套接字。去代码Go 服务 go 看起来像这样(简化):srv := new(service.App) // this would expose a Process methodrpc.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。但是我想先与社区进行仔细检查,以防万一我遗漏了一些明显的东西。
查看完整描述

1 回答

?
HUX布斯

TA贡献1876条经验 获得超6个赞

是的,如果您每次都创建一个新连接,这是安全的。

也就是说,您的方法存在潜在问题:

  1. TCP 连接建立起来相当昂贵,因此您可能希望通过连接池重用连接

  2. 如果您同时发出太多请求,您将耗尽端口/打开文件描述符,这将导致您的程序崩溃

  3. 您没有任何超时,因此最终可能会出现永远无法完成的孤立 TCP 连接(由于 Go 方面的问题或网络问题)

我认为最好使用 HTTP(尽管有开销),因为已经编写了库来处理这些问题。HTTP 也更易于调试,因为您只需 curl 一个端点来测试它。

我个人可能会选择gRPC


查看完整回答
反对 回复 2022-01-04
  • 1 回答
  • 0 关注
  • 175 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号