连接不会因主机错误而引发错误

时间:2015-06-30 14:08:57

标签: ruby ruby-on-rails-4 activerecord rails-activerecord

我正在处理的应用程序允许用户通过UI向其他数据库添加其他连接。我只是尝试创建一个确保可以建立连接的验证。 我创建了一个单独的类来测试数据库连接:

class StoredProcConnection < ActiveRecord::Base
  def self.abstract_class?
    true # So it gets its own connection
  end
end
然后我创建连接:

def connect
  adapter = sql_server? ? 'mssql' : 'mysql2'
  default_port = sql_server? ? '1443' : '3306'
  @connection_pool = StoredProcConnection.establish_connection(
    adapter: adapter,
    username: username, 
    password: password, 
    host: host, 
    database: database_name, 
    port: port || default_port,
    timeout: 300)
  end

def connection_pool
  connect unless @connection_pool
  @connection_pool
end

然后我用这种方法验证它:

def connection_test
  if connection_pool.connection
    #remove the connection from the StoredProcConnection pool
    connection_pool.remove(connection_pool.connection)
    return true
  else
    return false
  end
rescue Exception => error
  logger.info "unable to create connection with connection.id = #{id} - #{error}"
  return false
end

不幸的是,当它到达此行时,主机地址错误,例如127.0.0.abcdefg666.666.666.666

if connection_pool.connect

应用程序卡住,没有错误或任何错误。它只是冻结,我必须手动关闭服务器。

我有一个解决方法,但感觉很草率。我只是在那里插入自己的超时,但我觉得Active Record应该抛出某种错误。

def connection_test
  Timeout::timeout(3) {
    if connection_pool.connection
      #remove the connection from the StoredProcConnection pool
      connection_pool.remove(connection_pool.connection)
      return true
    else
      return false
    end
  }
rescue Exception => error
  logger.info "unable to create connection with connection.id = #{id} - #{error}"
  return false
end

有没有人看到任何可能导致冻结的事情?对我来说似乎很直接。我不确定为什么连接池甚至是在传入错误主机的情况下创建的。

1 个答案:

答案 0 :(得分:0)

  

它只是冻结......

赔率很高,它没有被冻结,只是等着看是否可以建立联系。 TCP / IP具有较长的超时值,这使得人们认为事物被冻结,实际上它是否有耐心。

很少有人真正理解互联网如何运作,以及它是如何真正建造稻草的房子,无论如何我们都试图继续运行。长IP超时是我们尝试使其自我修复的方法之一。软件并不关心事情需要多长时间,只有人关心。

由于您似乎关注格式错误的IP地址,为什么不对它们进行预先测试以确保它们至少采用有效格式?

使用Ruby的内置IPAddr类并尝试解析它们:

require 'ipaddr'

%w[
  127.0.0.abcdefg 
  666.666.666.666 
  127.0.0.1 
  192.168.0.1
  255.255.255.255
].each do |ip|
  begin
    IPAddr.new ip
    puts "Good: #{ ip }"
  rescue IPAddr::InvalidAddressError => e
    puts "#{ e }: #{ ip }"
  end
end
# >> invalid address: 127.0.0.abcdefg
# >> invalid address: 666.666.666.666
# >> Good: 127.0.0.1
# >> Good: 192.168.0.1
# >> Good: 255.255.255.255

有趣的阅读&#34;那里&#34; TCP Timeout and Retransmission&#34;和&#34; TCP Socket no connection timeout&#34;。