Ruby on rails 使用Mysql数据库从Heroku到远程服务器的SSH
我正在研究一个需要建立远程SSH会话SSH隧道的Rails应用程序?作为后台ActiveRecord会话的一部分,从Heroku到远程Mysql数据库。我们的目标是在不同的时间通过这个渠道将数据迁移到应用程序中。通过web连接到远程mysql数据库将不是一个选项 几个问题: 希罗库允许他们关掉Dyno吗? 有什么问题 这样做的缺点是什么? 我会担心宋承宪吗 会话持久性作业可能需要1小时? 最后,我如何配置Rails和Heroku以启用远程连接 database.yml mysql端点?Ruby on rails 使用Mysql数据库从Heroku到远程服务器的SSH,ruby-on-rails,ruby-on-rails-4,heroku,Ruby On Rails,Ruby On Rails 4,Heroku,我正在研究一个需要建立远程SSH会话SSH隧道的Rails应用程序?作为后台ActiveRecord会话的一部分,从Heroku到远程Mysql数据库。我们的目标是在不同的时间通过这个渠道将数据迁移到应用程序中。通过web连接到远程mysql数据库将不是一个选项 几个问题: 希罗库允许他们关掉Dyno吗? 有什么问题 这样做的缺点是什么? 我会担心宋承宪吗 会话持久性作业可能需要1小时? 最后,我如何配置Rails和Heroku以启用远程连接 database.yml mysql端点? 好吧,我
好吧,我现在可以回答我自己的问题了,经过几天的探索。简言之,是的
class LegacyAccount < ActiveRecord::Base
self.table_name = "account"
def self.test_connection
# net-ssh-gateway gem
gateway = Net::SSH::Gateway.new("ip_address","ssh_user_name",
password: "password",
port: "port if different from 22",
verbose: :debug
)
port = gateway.open('127.0.0.1', 3306, 3307)
establish_connection :legacy_production
result = LegacyAccount.first
puts "Record: #{result.to_yaml}"
gateway.close(port)
gateway.shutdown!
result
end
end
我尝试了@user1322092的方法,但当多个客户机试图访问数据库时遇到了麻烦,因为每个客户机都试图打开一个连接,但第一个客户机会出错 我创建了一个庞大的解决方案,包括在dyno上生成一个SSH进程,并将其用于所有通信。血淋淋的细节正在调查中。除了非常笨拙之外,无论您是否正在访问远程数据库,每次进程启动时都会导致延迟 使现代化 因此,这里有一种更好的方法似乎效果很好:只需捕获并忽略Errno::EADDRINUSE错误。代码如下:
require 'net/ssh/gateway'
class Mole
TUNNEL_HOST = <redacted>
TUNNEL_USER = <redacted>
AWS_HOST = <redacted>
TUNNEL_PORT_NUMBER = 3307
attr_reader :tunnel_gateway, :tunnel_port
# Call this to open an SSH tunnel from the current machine. If the
# the tunnel was already opened (e.g. by another process) , you'll
# get a warning message
def open_tunnel
@tunnel_gateway = Net::SSH::Gateway.new(TUNNEL_HOST, TUNNEL_USER)
begin
@tunnel_port = @tunnel_gateway.open(AWS_HOST, 3306, TUNNEL_PORT_NUMBER)
rescue Errno::EADDRINUSE => e
$stderr.puts("Warning: #{e.class}: #{e.message}")
end
end
# You won't normally call this, because the tunnel is a system wide
# resource; you don't know when other processes want to release it.
def close_tunnel
r = @tunnel_gateway.close(@tunnel_port) if @tunnel_gateway
@tunnel_gateway.shutdown!
r
end
end
只需补充一点,我愿意创建SSH隧道作为后台工作的一部分。不确定这是否会使迁移更容易。因为我正在迁移数据,所以过程是连续的;然而,我发现我的第一个SSH隧道连接是成功的,但是第二个会抛出“mysql连接已经消失”…grrrr。。所以我运行了heroku ps:restart,我想这会导致下一个连接成功。这就是你遇到的问题吗?@user1322092:我只是在本地机器上测试。我收到了一条不同的错误消息抱歉,我记不起确切的消息,但可能是相同的原因:试图重新打开一个已经打开的ssh隧道。我怀疑根本原因是隧道是每台机器的,如果您有单独的进程试图创建隧道,除了第一个进程之外,其他所有进程都会出错。也许有一种方法可以检测隧道是否已经在运行……我认为这种方法失败的地方是在网关中。打开调用-如果另一个进程已经打开了端口,您将得到一个错误,而且恐怕无法事先检测到。我开始认为正确的方法是在这种情况下简单地捕获并忽略EADDRINUSE异常。更多讨论请参见。@fearless_傻瓜,是的。。。这个解决方案测试并不是为了说明/支持多个流程,所以我添加了后台工作。在后台作业中,只有一个进程会打开网关。另外,在Heroku上测试成功,这是我最初的问题。我的应用程序也从后台任务访问远程数据库,区别在于我在不同的进程中有多个任务。我已经简单地测试了使用方法,它似乎很好地满足了我的需求。谢谢你帮我完成了80%的行程!
require 'net/ssh/gateway'
class Mole
TUNNEL_HOST = <redacted>
TUNNEL_USER = <redacted>
AWS_HOST = <redacted>
TUNNEL_PORT_NUMBER = 3307
attr_reader :tunnel_gateway, :tunnel_port
# Call this to open an SSH tunnel from the current machine. If the
# the tunnel was already opened (e.g. by another process) , you'll
# get a warning message
def open_tunnel
@tunnel_gateway = Net::SSH::Gateway.new(TUNNEL_HOST, TUNNEL_USER)
begin
@tunnel_port = @tunnel_gateway.open(AWS_HOST, 3306, TUNNEL_PORT_NUMBER)
rescue Errno::EADDRINUSE => e
$stderr.puts("Warning: #{e.class}: #{e.message}")
end
end
# You won't normally call this, because the tunnel is a system wide
# resource; you don't know when other processes want to release it.
def close_tunnel
r = @tunnel_gateway.close(@tunnel_port) if @tunnel_gateway
@tunnel_gateway.shutdown!
r
end
end