dongtuota3633 2016-04-09 17:19
浏览 44
已采纳

此示例tcp套接字编程事件顺序是否安全?

I plan on having two services.

  1. HTTP REST service written in Ruby
  2. JSON RPC service written in Go

The Ruby service will open a TCP socket connection to a Go JSON RPC service. It'll do this for each incoming HTTP request it receives. It will send some data over the socket to the Go service and that service will subsequently send back the corresponding data back down the socket.

Go code

The Go service go would look something like this (simplified):

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)
}

Notice we serve the incoming connection using a goroutine, so we can handle requests concurrently.

Ruby code

Below is a simple snippet of Ruby code that demonstrates (in theory) the way I would send data to the Go service:

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

My concern is: will this be a safe sequence of events?

I'm not asking if this will be 'thread safe', because i'm not worried about manipulating shared memory across the go routines. I'm more concerned around whether my Ruby HTTP service will get back the data it's expecting?

If I have two parallel requests coming into my HTTP Service (or maybe the Ruby app is hosted behind a load balancer and so different instances of the HTTP service is handling multiple requests), then I could have instance A send the message Foo to the Go service; while instance B sends the message Bar.

The business logic inside the Go service will return different responses depending on its input so I want to be sure that Ruby instance A gets back the correct response for Foo, and B gets back the correct response for Bar.

I assume a socket connection is more like a queue in that if instance A makes a request to the Go service first and then B does, but B is quicker responding for whatever reason, then the Go service will write the response for B to the socket and instance A of the Ruby app will end up reading in the wrong socket data (this is obviously just one possible scenario considering that I could get lucky and have instance B read the socket data before instance A does).

Solutions?

I'm not sure if there is simple solution to this problem. Unless I don't use a TCP socket or RPC and instead rely on standard HTTP in the Go service. But I wanted the performance and less overhead of TCP.

I'm worried the design could get more complicated by maybe having to implement an external queue as a way of synchronising the responses with the Ruby service.

It maybe because the nature of my Ruby service is fundamentally synchronous (HTTP response/request) that I have no option but to switch to HTTP for the Go service.

But wanted to double check with the community first just in case I'm missing something obvious.

  • 写回答

1条回答 默认 最新

  • duanlinma5885 2016-04-09 17:36
    关注

    Yes this is safe if you create a new connection every time.

    That said there are latent issues with your approach:

    1. TCP connections are rather expensive to establish, so you probably want to re-use connections with a connection pool
    2. If you make too many simultaneous requests you will exhaust ports/open file descriptors which will cause your program to crash
    3. You don't have any timeouts in place, so it's possible to end up with orphaned TCP connections which never complete (either because of something bad on the Go side, or network problems)

    I think you'd be better off using HTTP (despite the overhead) since libraries are already written to cope with these problems. HTTP is also much more debuggable since you can just curl an endpoint to test it.

    Personally I'd probably go with gRPC.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 高价求中通快递查询接口
  • ¥15 解决一个加好友限制问题 或者有好的方案
  • ¥15 关于#java#的问题,请各位专家解答!
  • ¥15 急matlab编程仿真二阶震荡系统
  • ¥20 TEC-9的数据通路实验
  • ¥15 ue5 .3之前好好的现在只要是激活关卡就会崩溃
  • ¥50 MATLAB实现圆柱体容器内球形颗粒堆积
  • ¥15 python如何将动态的多个子列表,拼接后进行集合的交集
  • ¥20 vitis-ai量化基于pytorch框架下的yolov5模型
  • ¥15 如何实现H5在QQ平台上的二次分享卡片效果?