Проблемы с использованием контроллера в базе данных postgres на AWS RDS из приложения Heroku

Я настроил базу данных postgres для использования postgis для моего приложения Heroku, работающего на Ruby on Rails.

Мои шаги были:

  1. Создайте БД RDS, работающую на стр. 9.4.9.
  2. Включите rds.force_ssl в группе параметров RDS.
  3. Сделайте резервную копию и загрузите мою базу данных Heroku в новую базу данных postgres.
  4. Загрузите сертификат ЦС Amazon RDS и поместите его в папку config/amazon-rds-ca-cert.pem.
  5. Добавьте гем «activerecord-postgis-adapter» в мой файл гем.
  6. Обновите файл database.yml следующим образом:

:

default: &default
    adapter: postgis
    encoding: unicode
    pool: 5

production:
    <<: *default
    encoding: utf8
    database: <%= ENV['RDS_DB_NAME'] %>
    username: <%= ENV['RDS_USERNAME'] %>
    password: <%= ENV['RDS_PASSWORD'] %>
    host: <%= ENV['RDS_HOSTNAME'] %>
    port: <%= ENV['RDS_PORT'] %>
    postgis_extension: postgis
    schema_search_path: public,postgis
  1. Обновите параметр DATABASE_URL в Heroku на postgres://myuser:[email protected]/mydbname?sslmode=verify-full&sslrootcert=config/amazon-rds-ca-cert.pem.
  2. Дополнительные шаги в этом очень полезном вопросе: Включение поддержки Ruby PostGIS на Heroku
  3. Нажмите обновленный код и получите доступ к моему приложению.

Когда я пытаюсь получить доступ к базе данных, чтобы проверить подключение, все работает нормально:

nc -zv mydbinstance.xxxxxxxx.us-west-2.rds.amazonaws.com 5432
Connection to mydbinstance.xxxxxxxxx.us-west-2.rds.amazonaws.com 5432 port [tcp/postgresql] succeeded!

и когда я перемещаюсь по приложению, я могу видеть результаты запросов. Однако, когда я пытаюсь использовать модель, использующую postgis, мои соединения почему-то работают неправильно. Вот код моего контроллера, который хранит пары lat, lng с информацией об автобусной остановке и находит те, которые находятся рядом с точкой, указанной в параметрах:

class TransitStopsController < ApplicationController
    def create
    end

    def show
        @transit_stop = TransitStop.find(params[:id])
        @transit_routes = @transit_stop.transit_routes
    end

    def get_nearby_stops
        radius_in_meters = params[:radius_in_meters].nil? ? 3219 : params[:radius_in_meters]
        @nearby_stops = TransitStop.close_to(params[:lat], params[:lng], radius_in_meters)
    end
end

Моя модель:

class TransitStop < ActiveRecord::Base
  has_many :transit_stops_transit_routes, foreign_key: "onestop_id", class_name: "TransitStopsTransitRoute"
  has_many :transit_routes, through: :transit_stops_transit_routes, foreign_key: "route_onestop_id", class_name: "TransitRoute"
  validates_uniqueness_of :onestop_id

  #Get transit stops close to a given lat, lng pair. Default distance = 2 miles
  scope :close_to, -> (lat, lng, distance_in_meters = 3219) {
  where(%{
    ST_DWithin(
      ST_GeographyFromText(
          'SRID=4326;POINT(' || transit_stops.lng || ' ' || transit_stops.lat || ')'
        ),
        ST_GeographyFromText('SRID=4326;POINT(%f %f)'),
        %d
      )
    } % [lng, lat, distance_in_meters])
  }
end

и мой вид (get_nearby_stops.jbuilder):

json.nearby_stops @nearby_stops do |transit_stop|
  json.region_id transit_stop.region_id
  json.lat transit_stop.lat
  json.lng transit_stop.lng
  json.onestop_id transit_stop.onestop_id
  json.name transit_stop.name
  json.osm_way_id transit_stop.osm_way_id
  json.osm_way_id transit_stop.served_by_vehicle_types
  json.timezone transit_stop.timezone
  json.wheelchair_boarding transit_stop.wheelchair_boarding
  json.created_or_updated_in_changeset_id transit_stop.created_or_updated_in_changeset_id
  json.transit_routes transit_stop.transit_routes
end

Routes.rb добавил строку в метод доступа:

get 'transit_stops/get_nearby_stops' => 'transit_stops#get_nearby_stops'

Когда я пытаюсь получить к нему доступ через: https://myherokuapp.herokuapp.com/transit_stops/get_nearby_stops.json?lat=-122.49766&lng=37.71677

Все, что я получаю, это сообщение:

Ошибка приложения

В приложении произошла ошибка, и ваша страница не может быть обслужена. Если вы являетесь владельцем приложения, проверьте свои журналы для получения подробной информации.

Когда я смотрю на свои журналы heroku, все, что я вижу, это ошибка тайм-аута:

app[web.1]: Processing by TransitStopsController#get_nearby_stops as JSON
app[web.1]:   Parameters: {"lat"=>"-122.49766", "lng"=>"37.71677"}
heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/transit_stops/get_nearby_stops.json?lat=-122.49766&lng=37.71677" host=myherokuapp.herokuapp.com request_id=1e081fdf-d0ce-4000-a6b4-4e75c176b8a2 fwd="10.0.0.1" dyno=web.1 connect=0ms service=30001ms status=503 bytes=0

Журналы ошибок AWS ничего не показывают.

Для меня странно то, что я могу выполнить тот же запрос, подключившись к консоли рельсов Heroku:

irb(main):001:0> TransitStop.close_to(-122.49766,37.71677,5000)
=> #<ActiveRecord::Relation [#<TransitStop region_id: 1, lat: #<BigDecimal:7fe69f6c95c0,'-0.122504106E3',18(18)>...
...
etc

Итак, на данный момент я не понимаю, что вызывает сбой этого контроллера только тогда, когда я обращаюсь к нему через свое представление, а не через консоль? Должен ли URL-адрес базы данных отличаться, если я использую методы postgis?

Любая помощь будет высоко ценится.

РЕДАКТИРОВАТЬ: я протестировал метод show моего контроллера, и он работает нормально:

app<a class="jive-link-external" href="http://web.1">http://web.1</a>: Started GET "/transit_stops/s-9q8ys6puje-655johnmuirave.json" for 159.16.243.2 at 2016-11-12 19:55:16 +0000
app<a class="jive-link-external" href="http://web.1">http://web.1</a>: Processing by TransitStopsController#show as JSON
app<a class="jive-link-external" href="http://web.1">http://web.1</a>:   Parameters: {"id"=>"s-9q8ys6puje-655johnmuirave"}
heroku<a href="https://forums.aws.amazon.com/">router</a>: at=info method=GET path="/transit_stops/s-9q8ys6puje-655johnmuirave.json" host=myapp.herokuapp.com request_id=15814367-5235-484b-bff9-7727a2349dd0 fwd="10.0.0.1" dyno=web.1 connect=0ms service=329ms status=200 bytes=1385
app<a class="jive-link-external" href="http://web.1">http://web.1</a>:   Rendered transit_stops/show.json.jbuilder (107.3ms)
app<a class="jive-link-external" href="http://web.1">http://web.1</a>: Completed 200 OK in 217ms (Views: 6.7ms | ActiveRecord: 207.4ms)<br class="jive-newline" />

Что для меня означает, что, возможно, в базе данных есть какая-то проблема с выполнением запроса, который я делаю? Сам запрос должен быть быстрым, так как когда я тестирую его в консоли, я всегда получаю ответ почти сразу, но, возможно, нужно что-то изменить в конфигурации базы данных?


person Yael Herrera    schedule 11.11.2016    source источник


Ответы (1)


Просто для того, чтобы другие люди видели, моя проблема заключалась в том, что после запроса мое представление также производило несколько дополнительных запросов, потому что поле

transit_stop.transit_routes

является отношением к другой таблице. Таким образом, для каждой результирующей остановки база данных выполняла множество других запросов для каждого полученного мной результата. Поскольку мой запрос возвращал несколько сотен результатов, окончательное представление выполняло несколько сотен дополнительных запросов, что вызывало много накладных расходов для моей базы данных.

Чтобы обнаружить это, я обновил log_statement = all в моей группе параметров db, чтобы я мог видеть все действия, поступающие в базу данных. Я обновил свой запрос, чтобы сделать его более эффективным, уменьшив количество результатов только до n ближайших, максимум до 10, так как мне действительно не нужно получать так много результатов.

person Yael Herrera    schedule 08.12.2016