问题
I'll try to keep this as brief as possible and open the question to discussion.
I have a Rails app which is a static codebase and runs on 9 different servers all the same db schema but of course with different values.
I wrote some SQL to query some dollar totals and will be putting this into either a rake task or a sidekiq worker and have it fire once a week to generate the data. Initially I was thinking of just throwing the resulting data from each server into a mailer and mailing it to whoever needs the data. This is pretty straight forward.
But there's a kink in this, we need to see metrics over time in highcharts or some other charting engine.
So here's my thought.
- Create the sidekiq worker and fire it on a schedule
- Take the resulting data from each server and populate it on a target server via Postgres (not sure how to do this)
- The target server will have a very simple Rails app built that will have a model with metrics and an association for each server (ie server 1 server 2 etc), after populating the data via postgres (somehow) from the source servers, read the data in HighCharts and present the view
So that's my thought process so far. I'm not sure on how to get the data from the source servers via a live postgres call when the sidekiq worker fires. So that's problem #1. Problem #2 or more like question #2 is, would this be a better use case for creating some sort of consumable API on the target Rails server? If so, what's the best place to start.
If my question and thought process is unclear, please let me know so I can clarify and explain in better detail.
Cheers!
回答1:
There are plenty of tutorials on how to use multiple database connections in Rails as well as building an API in Rails. A few minutes of Googling will give you plenty of examples. But here are a couple barebones approaches:
For multiple database connections, you are right, you'll need to have the connection info for both databases defined in your database.yml
file. Example:
# Local Database
development:
adapter: mysql2
database: local_db
username: my_user
password: my_password
host: localhost
port: 3306
# Reporting Database
development_reporting_db:
adapter: postgresql
encoding: unicode
database: reporting
username: some_user
password: some_password
host: 1.2.3.4
port: 5432
Rails won't do anything with this extra block though unless you explicitly tell it to. The common practice is to define an abstract ActiveRecord model that will establish the second connection:
class ReportingRecord < ActiveRecord::Base
establish_connection( "#{Rails.env}_reporting_db".to_sym )
self.abstract_class = true
end
Then, create new models for tables that reside in your reporting database and inherit from ReportingRecord
instead of ActiveRecord::Base
:
class SomeModel < ReportingRecord
# this model sits on top of a table defined in database.yml --> development_reporting_db instead of database.yml --> development
end
For building an API, there are tons of different ways to do it. Regardless of your approach, I'd highly suggest you make sure it's only accessible via HTTPS. Here's a basic controller with one action that responds to json requests:
class ApiController < ApplicationController
before_filter :restrict_access # ensures the correct api token was passed (defined in config/secrets.yml)
skip_before_action :verify_authenticity_token # not needed since we're using token restriction
respond_to :json
def my_endpoint_action
render :json => {some_info: 'Hello World'}, :status => 200 # 200 = success
end
private
rescue_from StandardError do |e|
render :json => {:error => e.message}.to_json, :status => 400 # 400 = bad request
end
# ensures the correct api token was passed (defined in config/secrets.yml)
def restrict_access
authenticate_or_request_with_http_token do |token, options|
token == Rails.application.secrets[:my_access_token]
end
end
end
This example would require you to define an access token in your config/secrets.yml
file:
development:
secret_key_base: # normal Rails secret key base
my_api_access_token: # put a token here (you can generate one on the command like using rake secret)
Choosing between an API and a multiple DB solution depends mostly on how your application might expand in the future. The multiple DB approach is typically easier to implement and has higher performance. An API tends to scale horizontally better and databases that have a connection from only one application instead of 2 or more tend to be easier to maintain over time.
Hope this helps!
来源:https://stackoverflow.com/questions/31763634/getting-information-from-one-rails-server-to-another