3

我的服务器上运行了一个守护进程的 ruby​​ 脚本,如下所示:

@server = TCPServer.open(61101)                         
loop do                                                 
  @thr = Thread.new(@server.accept) do |sock|
    Thread.current[:myArrayOfHashes] = []   # hashes containing attributes of myObject
    SystemTimer.timeout_after(5) do
      Thread.current[:string] = sock.gets
      sock.close

      # parse the string and load the data into myArrayOfHashes

      Myobject.transaction do           # Update the myObjects Table
        Thread.current[:myArrayOfHashes].each do |h|
          Thread.current[:newMyObject] = Myobject.new
          # load up the new object with data
          Thread.current[:newMyObject].save
        end
      end

    end
  end
  @thr.join
end

该服务器接收和管理我在 Mac OS 10.6 上运行的 rails 应用程序的数据。客户端在 15 日每 15 分钟调用一次服务器,而我目前只有 16 个左右的客户端在 15 日每 15 分钟调用一次,我想知道以下几点:

  1. 如果两个客户端几乎同时调用,一个客户端的连接尝试会失败吗?
  2. 我如何才能确定我的服务器可以同时容纳多少个客户端连接?
  3. 如何监控我的服务器使用了多少内存?

另外,是否有一篇文章您可以指点我,讨论实现这种服务器的最佳方式?我的意思是我可以让多个服务器实例监听同一个端口吗?那会有帮助吗?

我正在使用 Bluepill 来监控我的服务器守护进程。

4

1 回答 1

2

1 和 2
答案是否定的,两个相互靠近的客户端连接不会导致连接失败(但是多个客户端连接可能会失败,见下文)。

原因是操作系统在所有服务器套接字中都有一个默认的所谓的侦听队列。因此,即使您accept在程序中调用的速度不够快,操作系统仍会继续为您缓冲传入的连接。只要监听队列没有被填满,它就会缓冲这些连接。

那么这个队列的大小是多少呢?

在大多数情况下,通常使用的默认大小是 5。大小是在您创建套接字并调用listen此套接字之后设置的(请参阅此处的监听手册页)。

因为 Ruby会TCPSocket自动为您调用listen,如果您查看 C 源代码,TCPSocket您会发现它确实将大小设置为 5:

https://github.com/ruby/ruby/blob/trunk/ext/socket/ipsocket.c#L108

SOMAXCONN在这里定义为 5:

https://github.com/ruby/ruby/blob/trunk/ext/socket/mkconstants.rb#L693

现在,如果您没有足够快地调用 accept 并且队列被填满,会发生什么?答案可在以下手册页中找到listen

backlog 参数定义了 sockfd 的挂起连接队列可以增长到的最大长度。如果队列已满时连接请求到达,客户端可能会收到带有 ECONNREFUSED 指示的错误,或者,如果底层协议支持重传,则可能会忽略该请求,以便稍后重新尝试连接成功。

但是,在您的代码中,如果超过 5 个客户端尝试同时连接,则可能会导致队列填满:您在@thr.join循环结束时调用。

当你这样做时,实际上发生的事情是你的服务器不会接受任何新的传入连接,直到你接受线程中的所有东西都完成执行。

因此,如果数据库内容和您在接受线程中执行的其他操作需要很长时间,则侦听队列可能会同时填满。这取决于您的处理需要多长时间,以及有多少客户端可能同时连接。

3
你没有说你在哪个平台上运行,但是在 linux/osx 上最简单的方法就是top在你的控制台中运行。对于更高级的内存监控选项,您可能需要查看这些:

ruby/ruby on rails 内存泄漏检测
跟踪 heroku 上的应用程序内存使用情况

于 2012-05-31T00:14:26.403 回答