Showing posts with label Heroku. Show all posts
Showing posts with label Heroku. Show all posts

Friday, 30 November 2012

Herokuのスタックに独自のシェルコマンドを導入する

Herokuではgemでパックされていないシェルコマンドは使えないと思っていました。

が、最近buildpackでgit push でスタックを作成する時に


$ heroku create myapp --buildpack https://github.com/heroku/heroku-buildpack-ruby

としてカスタムのbuildpackを指定する事により、カスタムのシェルコマンドを導入する事ができます。あとはRubyの中で `command`です。buildpackについては下に記事があります。


シェルで使い慣れているあれやこれやのコマンドをHerokuにデプロイしたアプリケーションでもつかえるようになります。ただここまで来ると自分でクラウドアプリケーションサーバであるHerokuではなくVPSなど自分でサーバの環境から構築するのとどちらが良いのか微妙なラインになってきますね…。

Wednesday, 28 November 2012

Caching implementation on RoR

今作っているRuby on Railsでアプリケーションをキャシングをするのに、調べ物をあれこれと。

アプリケーションはHeroku上で動かすのですが、Herokuのドキュメント上にはアプリケーションが再起動する際にはコンパイル後に保存されたディスク上のデータは消えるので、ディスクキャッシュは使えないそうです。なのでHerokuのおすすめとしてはmemcachedを使う事。

ということで、今回はHerokuのプラグインであるMemcacheを使ってキャッシュしてみました。キャッシュの方法は下の3つ。

- ページキャッシュ --> アプリケーションのレイアウトを流用した404や500ページを使用したいのでカスタムでページを作ってページキャッシュ。データも大きくないし、消えてしまっても特に問題無いのでディスクキャッシュで。これは単純に

caches_page :action_name

と書くだけです。

- アクションキャッシュ --> sitemap.xmlをデータベースからデータを引っ張ってきて作成しているので、これをアクションキャッシュで保存。データベースが大きくなる予定なので、botが来る度にxmlを生成しているとパフォーアンスの低下に繋がる可能性が高いです。検索botたちが訪問する頻度はそんなに高くないだろうと思うので、3日で賞味期限が切れる様に設定。多分これで良いと思います…。これも同じくコントローラの最初で

caches_action :action_name, expires_in: 3.days

と記述するだけ。

- 外部API --> ショッピングモールが提供するAPIから商品の情報を引っ張ってきているのですが、このレスポンスがかなり時間がかかっている様です(20個ぐらいの商品情報を引っ張って来るのに2秒近く)。これは取りあえずAPIのデータのみをmemcachedに保存。まずは賞味期限8時間ぐらいで動かしてみます。コントローラ上でmemcacheを使用して幾つかのviewでもキャッシュしたデータを利用できる様にします。製品ごとに販売できる商品を製品のキャッシュデータをデータベースの中のidとupdated_atのタイムスタンプ、それに'buyable'の文字列を付与したインデックスで管理します。

@buyables = Rails.cache.fetch([@product, 'buyables'], expires_in: 8.hours) { @product.buyables }

Saturday, 10 November 2012

Google Calendarのイベントを拾ってFacebookページに投稿するアプリケーション

Google Calendarで管理しているイベントを前日に拾ってFacebookページに投稿するアプリケーションを作りました。コードはMITライセンスでGitHub上で公開しています。


ちょっとセッティングが面倒ですが使ってみてくださいね。セッティングにはある程度のRubyの開発環境とHerokuが使える事が前提です…。まだまだ開発者が使う事を前提としたアプリケーションですね…。

フィードバックもお待ちしてます。

Saturday, 6 October 2012

mongoid/MongHQ/Heroku設定

mongoid(3.1.0)/MongHQ/Heroku設定で少しはまりました。

Herokuのドキュメント上ではmongoid.ymlのファイルは下のように設定するのがおすすめと書かれていました。


production:
  sessions:
    default:
      uri: <%= ENV['MONGOHQ_URL'] %>
    options:
      skip_version_check: true
      safe: true


このまま設定しようとするとうまく動きません。調べてみるとこれはyamlファイルのインデントの問題でした。下記のようにインデントを直すとうまくDBが繋がりました。


production:
  sessions:
    default:
      uri: <%= ENV['MONGOHQ_URL'] %>
      options:
        skip_version_check: true
        safe: true

Heroku の上のドキュメントは多分多くの人が参照するので、MongoHQにドキュメントを修正するようにお願いして修正するという解答が来たのですが、今日の時点ではまだ修正されていない様ですね…。まあみんな忙しいですからね…。

Thursday, 27 September 2012

EC2 バックアップをRuby のAWS SDKとHerokuを用いて構築

EC2が運用ベースに乗ってきたので日ごとのバックアップ環境を構築しました。こんな方法もあるのだという参考にしてください。

バックアップスクリプトはAmazonが提供しているRubyのAWS SDKを用いて作成。これはgem が提供されているので、Gemfileに

gem 'aws-sdk'

の一行を書くだけで利用できます。

毎日一度バックアップスクリプトを動作させて、7日分のバックアップを取っておく内容です。バックアップスクリプトはローカルに置くと恒常的に実行できないのでHerokuを利用させてもらいました(こんな使い方はHerokuもあまりありがたくないでしょうけど、利用するリソールは限りなくゼロに近いので許してください)。Herokuのweb workerを0にして毎日1回実行するSchedulerを登録。Herokuの無料利用枠に収まると思います。

自動バックアップツールはAmazonが提供してくれていると便利なのですが、見つかりませんでした。他にバックアップスクリプトを書いている人はいるのですが、やはり自分の環境にカスタマイズするとなると結局手間なので、使い慣れたRubyとAWS SDKの組み合わせを利用しました。

質問がある方は気軽に連絡してもらえば歓迎です。

Thursday, 24 May 2012

SinatraとHerokuでフレキシブルな静的ファイルサーバ構築

SinatraとHerokuでフレキシブルな静的ファイルサーバ構築をしてみました。実際役に立つかどうか?というのは、用途によります。

SinatraもRailsもgemなどを使ってインストールさせ、サーバを起動すれば /public以下のフォルダをかってに拾ってくれるので、単純なhtmlのサイトであればお手軽に無料でサイトが作成できます。(無料でサイトを作成するという意味であればWordpressやFacebook, Google Pageなどいくらでも便利なつーるはあり、そちらの方が断然便利だと思います。)

Sinatraならではのフレキシブルな点としてはアプリケーションに

get "/folder_name/*"
  protect!
  File.read("/public/index.html")
end

などとすれば特定のフォルダを簡単にBasic認証で保護できます。

また、Amazon S3の上にファイルを置いて、下のようにすれば特定の(この場合は東北アジアのサーバに置いた)バスケットに見せたいファイルをアップロードすれば普通の静的ファイルサーバの様に見せてくれます。jpgでもhtmlでもpdfでも問題無いはずです。


require 'rubygems'
require 'sinatra'
require 'aws/s3'
include AWS::S3

helpers do
  def connect_aws_s3
    DEFAULT_HOST.replace "s3-ap-northeast-1.amazonaws.com"
    connection = Base.establish_connection!(
      :access_key_id     => 'YOUR-KEY-ID',
      :secret_access_key => 'YOUR-SECRET-ACCESS-KEY'
    )
    @bucket = Bucket.find('sinatra-aws-s3-test')
  end

  def protect!(user_name, passwd)
    unless authorized?(user_name, passwd)
      response['WWW-Authenticate'] = %(Basic realm="Restricted Area")
      throw(:halt, [401, "Not authorized\n"])
    end
  end

  def authorized?(user_name, passwd)
    @auth ||=  Rack::Auth::Basic::Request.new(request.env)
    username = user_name
    password = passwd
    @auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == [username, password]
  end
end

get %r{.+} do

  protect!("username", "password") if request.path.match(/^\/folder_name/)

  connect_aws_s3

  file_path = request.path
  file_path += "index.html" if file_path.match(/\/$/)
  file = @bucket[file_path.gsub(/^\//,"")] rescue throw(:halt, [404, "Page not found\n"])

  content_type file.content_type
  file.value
end

get %r{.+} do で全てのgetメソッドリクエストに対してアプリケーションが対応する様にしています。

ここで、確かに見せるだけは問題無いのですが、少し大きな動画などのファイルを見せると、S3 Bucketの読み込みに時間がかかるらしくレスポンスがかなり遅くなります。S3のBucketをアメリカのサーバに移しても同じでした。

なのでキャッシングを有効にするためにRack Middlewareを使います。http://rtomayko.github.com/rack-cache/
私の場合は 'rack-cache'と'dalli'のgem をインストールしてconfig.ruに

require 'rack/cache'
require 'dalli'


use Rack::Cache,
  :verbose     => true,
  :metastore   => Dalli::Client.new,
  :entitystore => 'file:tmp/cache/rack/body'


を加えると読み込みが断然改善されました。でもこうするとHerokuサーバ上に大きなキャッシュのファイルを置くことになるので、直接/publicの下にファイルを置くのと大差ありませんね。実験としては面白いと思いますが、実用的ではないかもしれませんね。

また、Herokuのアプリケーションを動かしているサーバからのレスポンスはサーバがアメリカにあるためこれ以上改善できなさそうです。この点はHerokuが日本のサーバでサーバを提供してくれるのを期待するしかなさそうです。

Wednesday, 2 May 2012

MongoDBをRailsで使ってみました

HerokuでPostgreSQLを使用してアプリケーションを開発していたのですが、その柔軟性が少ないことでこれからPostgresSQLを用いて開発していくことに疑問を持ち、最近もっとも頻繁に耳にするKVSであるMongoDBの導入をしようとしています。

@masatomon さんのブログ記事を参考にしてRailsでMongoDBを使ってみました。

mongo_mapperの代わりにmongoidを使用したので、Gemfileなど書き換えたのですが、とても簡単にRailsとMongoDBを使用してアプリケーションが構築できる環境が作れました。

MongoDBのローカルマシンへのインストールもソースをダウンロードしてきて適当な場所にフォルダを移しパスを通して、あとはdb用のフォルダ(デフォルトで/data/db)を作成すれば使える簡単な操作です。

MongoDBサーバの起動は

$ mongod

インタラクティブコンソールの起動は

$ mongo

です。

MongoDBでスケーリングやアプリケーションの柔軟性はできそうですが、クエリを構築したりトランザクションを管理するなどはまた学び直しなので、面倒ですね…。

最近はひたすらビジネスモデルの構築、設計や技術の調査などをしていますが、早くプロダクションに取りかかりたいです…。

Monday, 2 April 2012

Herokuデプロイ環境基礎勉強

HerokuでRailsアプリケーションを走らせる際の基本的な技術について調べて見ました。ざくっと言えばHerokuはサーバ管理などの知識が(ほぼ)無くても、ウェブアプリケーションを作ったから公開したいと思えば簡単にできるプラットフォームですよね。背景技術に詳しくなれば高度なカスタマイズも可能なのでしょう。

Stackのレベルから調べようと思い、HerokuのCeladon Cedarの項目を読み始めたのですが、出だしの文章が
Celedon Cedar is Heroku’s most recent runtime stack and is a flexible, polyglot environment with robust introspection and erosion-resistance capabilities. [cont.]
何のことやら…。Celadon Stackとか、データベースのプランがRoninとか、名前からサービスの内容が全然連想できないところも絶望的ですね…。気を取り直して地道に一語ずつ拾っていきます。

(Runtime) Stackはアプリケーションをアップロードすると、多くの言語を勝手に認識してデプロイに必要な環境(WEBRickやThinのようなHTTPリクエストをさばくdaemonとMRIのようなインタープリターを乗っけて動かす環境)を構築してくれる基礎のようです。私はMRI1.9.2を使用しているCeladon Cedar stackを作成し、ThinにHTTPリクエストをさばいてもらい、Railsアプリケーションを動かしています。

もう一つ分かりにくかったのがDynoという概念です。Process Modelという概念によりプロセス単位でスケーリングができる様に設計されているようで、その1プロセスを1 Dynoと呼んでいるようです。Web Dynoを増やせば同時にさばけるリクエストの量が増え、リクエストをさばくことにリソースが制限されるサイト(静的コンテンツをキャッシュに保存しておいて提供するサービスがメインのサイトなど)に関してはWeb Dynoの増減がスケーリングで考える重要な項目になってくるのでしょう。一方でWorker Dynoはcpuを消費する例えばオンラインシューティングゲームなどのサーバ運営でスケーリングを考える必要がある項目でしょう。いずれのDynoも自分の経験としてまだどれぐらいのアクセスで1プロセスを増やさなければいけないという感覚が掴めていないのは残念ですが…。ちなみにHerokuのプロセススケーリングを自動で管理してくれるHero Scalingという外部サービスもあるようです。

今回はHerokuデプロイ環境の本当に初歩の部分にしかたどり着きませんでしたが、今まであまり関与してこなかったインフラ系の知識もアプリケーションの開発や運営手法と共に車の両輪のように学んでいきたいと思います。ウェブマーケティングの知識を得る必要もありますし、課題は多いですね…。

Tuesday, 27 March 2012

Heroku でフリーのデータベースを利用

Herokuでアプリケーションをデプロイする際に魅力的なことの一つは、スケーリングが簡単ということです。小規模のアプリケーションであればデータベースを使用してもカスタムドメインを利用しても無料でデプロイできます。データの容量が大きくなってくればHerokuでスタンダードで用意されているオプションは割高なので、例えばAmazon S3のファイルサーバを利用したり、同じくAmzaonのデータベースサーバを利用する。まあリソースを拡大する前にアプリケーションのオプティマイゼーションをすることが前提ですが…。

私が今回作成しているアプリケーションはアジャイルでとにかく最低限のスペックのものをすぐに公開して必要なものを追加していくスタイルなので、データベースも無償のもので事足ります。

ただ少し困ったのは Heroku のドキュメンテーションを探しても全然 Basic の shared データベースを追加する方法が見つかりませんでした。簡単すぎることなので載せないのか、あまり無償のリソースの情報は載せたくないのか分からないですが…。結局 Herokuの addons のページで探し、Heroku Shared PostgreSQL のページでコマンド:

$ heroku addons:add heroku-shared-postgresql:basic

を見つけて解決しました。このコマンドを少し間違えて

$ heroku addons:add heroku:postgresql

として実行をしてしまうと、Herokuの一番最低価格の dedicated DB に契約してしまいます。最低限のプランはRoninで、最低といえども月に200 USDなので、ちょっとした間違いだと結構痛いです。

あとは

$ heroku pg:promote newdatabasename --app myapp

で新しく追加したデータベースがデフォルトで使用されるようになります。

これに結構時間を使ってしまいました。

TapsによるHeroku へのデータベースマイグレーション

Taps を使用し、Herokuにデータベースの内容を移動しようとしたときに少し困ったので書いておきます。

まずインストラクション通りに下のコマンド

$ heroku db:push sqlite://db/development.sqlite3 --app myapp

を実行して得られたのが下のようなエラーメッセージ。失敗です。

Taps Server Error: PGError: ERROR: time zone displacement out of range:

私が開発に使用している環境は rvm を使用してRubyのバージョンを管理し、このときは1.9.3を使っていました。http://bit.ly/GWnltC のポストにも書かれている通り、1.9.3はHerokuでは問題があるので1.9.2を導入してみました。

実はrvm 1.9.2の導入に際しても問題があり、Xcode 4.3とcommand line tools を導入してインストールされるgccを使用するとRuby 1.9.2がインストールできません。そのためhttps://github.com/kennethreitz/osx-gcc-installer からnon-LLVMのgccをダウンロードしてインストールし、

$ CC=/usr/bin/gcc-4.2 rvm install 1.9.2

で無事Ruby1.9.2のインストールができました。実はRuby 1.9.2でもHeroku で違う問題が出たので、rvm でRuby 1.8.7 を導入して heroku db:push を実行したところ、問題なくデータのexportができました。

Monday, 26 March 2012

Heroku でデプロイ時にgemのlibファイル読み込みエラー

Heroku でアプリケーションのデプロイ中に2回ほどはまってしまったのですが、そのうちの一つはgemのlibファイル読み込みエラーが発生するというものです。

最初のエラーは gem thin の読み込みエラーで、Herokuからのエラーメッセージは


2012-03-23T01:13:29+00:00 heroku[web.1]: Starting process with commandbundle exec thin start -R config.ru -e production -p 348962012-03-23T01:13:30+00:00 app[web.1]: /app/vendor/bundle/ruby/1.9.1/gems/thin-1.3.1/lib/thin.rb:41:in `require': cannot load such file -- /app/vendor/bundle/ruby/1.9.1/gems/thin-1.3.1/lib/thin_parser (LoadError)
I looked into /app/vendor/bundle/ruby/1.9.1/gems/thin-1.3.1/lib/ folder and indeed, could not find thin_parser.rb file. I have spent some time, but cannot solve this issue.
gem ファイルは正しくbundleされているはずだし、何がおかしいのか分からずしばらく時間を費やしました。ある時この記事に引っかかり問題が解決しました。--> http://bit.ly/GKNjjo
解決策はローカルで bundle install を実行する時に Gemfile に
group :development, :test do
gem 'sqlite3'
gem 'heroku'
gem 'taps'
end
group :production, :staging do gem 'pg' gem 'thin'end

などと記述して本番と開発環境で使用するgemを分け、さらに私はこれのステップで失敗したのですが、 bundle install をする際にオプションで意図的に本番環境の gem を /vendor/bundle/ に生成させないように
$ bundle install --without production
を指定する必要があります。すでに一度このオプションを指定しないで bundle install を実行してしまった場合はフォルダーを消せば問題ありません。
上の作業を実行すると Heroku の環境にネイティブな gem とライブラリがデプロイ時にインストールされ library ファイル読み込みのエラーメッセージが消えました。
今回はHerokuのインストラクションに従いスタンダードな形でアプリケーションをデプロイしました。問題は解決されたのですが、実際 Heroku でどのように thin が動いているのか、スタンダードRailsアプリケーションデプロイ時に指定する --stack cedar がどのように動いているのか、などなど残念ながら分からずにサービスを利用している部分が山積みです。時間を割いて理解したいです。

Saturday, 24 March 2012

fluxflex の私なりの使い方

知り合いから fluxflex というウェブアプリケーションデプロイのプラットフォームがあると聞き、利用してみました。価格的にはStandardで$1, Casualが$3というように、とてもリーズナブルです。



個人的にプロジェクトを管理するためにRedmineをインストールしてみたところ、Railsアプリケーションであるにも関わらず実に簡単にインストールして使用できています。フリーのプランではいろいろ制約あがあるのでフルにRedmineを活用というよりは現時点でお試しですが。他にもワンクリックでインストールできるアプリケーションはLAMP系がやはりお多く、その他PythonやPerlなど多くの共有サーバで使用できるCGI系ソフトが見られます。RailsのCMSもありました。

ソフトウェアのデプロイ環境として検討していたのですが、デプロイを試してみるとコマンドラインの環境がまだ整っていなくて、例えばGitでPushしている時やpushが終わりデプロイに入った段階でも進行状況がクリアでないなど、何が起きているのか分からないという問題がありました。アプリケーションがクラッシュした際もクラッシュした原因が詳しく探れないため、正直現時点でアプリケーションの開発には向いていないという印象を受けました。ワンクリックインストールしてソフトウェアが使用できる環境は確かに便利だと思います。

ほぼ丸一日fluxflexにRailsで開発したアプリケーションをデプロイする試行錯誤をしたのですが、結局あきらめてHerokuでデプロイすることにしました。ちょっと残念。私のfluxflex 環境に対する知識が足りなかったのかもしれません…。

HerokuはHerokuで独特のポップなエラーメッセージを出すために問題解決するためにエラーめセージを解読しなければならないなどの問題はありますが…。データベースが見つからないときは普通にdatabase not foundとかいうエラーメッセージを出してくれれば分かりやすいのに…。