何でも屋エンジニアのブログ

Rails中級者向け勉強会Step-to-Rails-Expert.rbや出席した勉強会に関するメモが多い

レポート: 【ランチセッション】クラウド時代のソフトウェアアーキテクチャ

登壇者

西谷 圭介様(アマゾン ウェブ サービス ジャパン株式会社 技術本部 ソリューションアーキテクト)

The Twelve-Factor App

12factor.net

codebase

  • バージョン管理は当たり前、1つのコードベースから複数のアプリができるのは良くない

依存関係

  • 環境に依存しないこと
  • 依存関係を明示的に分離

設定

並行性

  • スケールするときはプロセスごと増やす

マイクロサービス

hexagonal architecture

  • 特定ポートに届いたイベントをアダプターがアプリに渡す
  • アダプターがメッセージのやり取りをする

ヘキサゴナルアーキテクチャ日本語翻訳ページ http://blog.tai2.net/hexagonal_architexture.html

マイクロサービスのポイント

  • 各サービスは独立、単一でデプロイと実行が可能
  • 分割単位はビジネスの境界やビジネスの遂行能力で分割する(技術的なものではない)
  • プロトコルはhttpでRESTfulのケースが多い
  • 各サービスごとにスケーリングできる

Polyglot Persistence

  • 各サービスごとに最適な言語とDBを組み合わせる
    • 検索: elasticsearch
    • ソーシャルデータ: Neo4J(グラフDB)
    • ユーザーセッション: Redis

Amazonの例

  • Amazonも昔はモノリシックなサービスだった
  • チームの体制がTwo Pizza Team理論に即した体制に変化
  • それによりチームの体制がマイクロサービスの文脈へ
  • 開発チームは小さく、それぞれのチームが開発した単位でリリースできる

www.lifehacker.jp

アプリケーションの実装パターン

Graceful Degradation

  • 500エラーは返さない
  • 一部にエラーがあっても全体の停止を起こさずその他の機能は有効に動くようにする
  • 例えば、ECサイトのリコメンド機能がダメな場合でも、トップページにアクセスしてもページが表示されるようにする。おすすめ品が表示されなくても、全部表示されないよりマシ。

Fail Silently

  • 外部向けには、エラーコードを返さない。
  • 内部できちんとロギング、監視すること。

retry

  • 失敗は一時的なものが多く、リトライすることで成功することが多いため、リトライする処理を入れる。
  • 間隔の調整はフィボナッチ数列、exponetial back offを利用する。

curcuit breaker

  • リトライの閾値を設定し、超えたときにフォールバックプランを実行する。
  • サイト全体のアベイラビリティの方が大事。

Smooth internal traffic

マイクロサービスの考慮点

トランザクション

  • 複数DBでデータが同期されている必要性
  • 結果整合性の導入
  • 状態変化に合わせてイベントを発行する
  • イベントをsubscribeし、イベントドリブンに処理を行う
  • 一時的なconsistencyの妥協

イベントソーシング

  • 状態でなくイベントを追加するという考え方
  • イベントのリプライにより現在の状態を導出できる
  • スケールしやすい(キャッシュが楽)
  • イベントドリブンでは、状態を変更しイベントを追加するが、これはイベント追加のワンアクションで済む

CQRS

  • DDDの文脈で登場
  • 更新処理と参照処理の分離
    • 更新処理は正規化、クエリは非正規化の方がいいなど差異が大きいため

RESTfulAPI

ステートレスは他の店員になっても問題無し→スケーラビリティが高い

AWSでどうマイクロサービスを実現するか

  • 満たすべき要件は自動化と自動化のためのAPI
  • インフラは何でも良い

感想

アプリケーションの実装パターンやイベントソーシングという考え方など、知らないことが多く非常に勉強になりました。
昨日からAWS Summitに参加しマイクロサービスのセッションを拝聴していて、マイクロサービスの難しい点として「分散したコンポーネントを扱う難しさ」が共通して上がっていました。また、本セッションで挙げられたトランザクションやデータ同期も確かに悩ましい問題で、西谷さんが個人的には「プロダクトが小さい場合はマイクロサービスのデメリットの方が目立つ」とおっしゃっていた理由もよくわかる気がします。ビズリーチさんのマイクロサービスに関するインタビューでも竹添さんが同じようなことをおっしゃっていました。

開発のときのオーバヘッドや、インフラコストで見ると、短期的にはデメリットのほうが大きいと思っています。どこかで損益分岐点はあると思うんですが。とりあえずスモール仕立てでやってみようとか、成功するかまったくわから状況なら、モノリシックで作って、後から大きくなったタイミングでマイクロサービスにしてもいいのではないでしょうか。

非常にためになるお話をありがとうございました!

参考

html5experts.jp 12factor.net ヘキサゴナルアーキテクチャ(Hexagonal architecture翻訳) AWS Summit Tokyo 2016 Developers Conference(DevCon) - アプリ開発・IoT の最新トレンドが集う2日間 - 2016年6月2~3日 グランドプリンスホテル新高輪 飛天会場にて開催

米AmazonのCEOジェフ・ベゾスが提唱する「2枚のピザ理論」 | ライフハッカー[日本版]

レポート:【パネルディスカッション】Slack, Qiita, GitHub 利用者 & 提供者の視点で見る、クラウドとツールの使いどころ

はじめに

AWSSummit 2016の「【パネルディスカッション】Slack, Qiita, GitHub 利用者 & 提供者の視点で見る、クラウドとツールの使いどころ」の内容をまとめたレポートです。セッション動画が公開されると思いますが、さしあたり参考になれば嬉しいです。

注:ですます/である調が混在しているのでご了承下さい。大きく聞き逃したところもあり、その点は記載してあります。 内容に誤りがある場合は指摘して頂けると嬉しいです。

本編

登壇者紹介

パネリスト
【Slack 利用者】岩瀬 義昌様(エヌ・ティ・ティ・コミュニケーションズ株式会社 技術開発部 エンジニア
【Qiita 提供者】髙橋 侑久様(Increments 株式会社 CTO)
GitHub 提供者】藤田 純様 (ギットハブ・ジャパン合同会社 カントリーマネージャー)

モデレータ
吉羽 龍太郎様(Ryuzee.com)

なぜこれらのツールやクラウドが受け入れられたのか

岩: チャットは昔からよく使われていた。irc hipchatなどあるが、slackは開発者の相性が良い。integrationが豊富でapiが公開されていることが重要。

吉: apiの影響が大きいとうことでしたがその辺どうでしょう。
髙: qiitaチーム、slack、githubは連携ができるというのが大きい。親和性が重要。

藤: api連携をしており、ユーザーがどんな問題を解決したいかが明快で、特定のドメインの問題を解決するに集中できる。 ほかの分野は連携するという感覚で、これがスピード感に繋がり受け入れられたのでは。

岩: 議論がslackで盛り上がった場合、slackはフローの情報でqiitaはstockの情報だが、フローの情報の共有はどうしているか。

髙: slackでというよりは、オフラインの会話をオンラインに持っていくというのが大事だと思っていて、良い方法を模索中。

藤:半分がリモートなのでリモート前提。オフラインの情報は、オンラインに残すように習慣づけるようにすべき。

受け入れられた背景、ビジネス的側面

藤: スピードだと思う。PCDAがあるが、Pの部分がすごく重いので動きが遅くなってしまったり、また、Pが一度決まるとそれを100%守らなければいけなくなってしまう。どうせやってみなければわからないんだから、早くトライして速く失敗して学ぶことが重要で、それを許容する心が組織には必要。

岩: 研究職は早く失敗するというのを求められている。本来やるべきことに集中するためにツールが大事になってくる。

ツールとクラウドの親和性

藤: 本業に集中するという観点から、繰り返しの同じ作業に関してはツールに任せることが大事で、CIなども同じ考え方だが、スピードを上げるために本業に集中し、組織としても強みを発揮する。ツールとクラウドの親和性はスピード、本業への集中。

(筆者:この間の話は聞き逃してしまいました。)

髙: オンプレミスが必要な理由は、結局社内の事情で、スピード感がなくなる。

吉: 逆にクラウドだからこその辛みはあるか。

藤: どこに情報を置くかというのが企業によっては問題になるので辛い。

吉: セキュリティとかポリシーとかですかね。そのような障壁がある場合、どうやってクラウドを導入していけばよいのでしょうか。

岩: エンプラなので導入ハードル高い。社内に通す時、偉い人よりミドルマネジメント層で技術のわかる人を巻き込んで行動した方がいい。slackの時は導入して使えることがわかると偉い人も使い出した。

吉: ラインの偉い人はそれで通るかもしれないが、例えば専任のセキュリティ担当と折衝するケースではどうだったか。

岩: お客様情報など重要な情報に関してはオンプレミス。qiita:teamなどは漏れてもokな情報しか書かない。 お客様の名前など出ていないか最初はチェックしていた。

髙: 導入に関して、ミドルマネジメント層のわかる人を巻き込んでやった方がいいが、いない場合もある。 導入して勝手にそのツールが広まることはないので、率先して使い広める人が必要。

吉: 社内エバンジェリストのような人が必要かな。でも一人だけだと辛い。

岩: 折れてからが勝負!

藤: 導入に関しては、社内のスターを巻き込んで使ってもらう。基本的に組織を管理する人たちにとって、みんなんが幸せに仕事してもらえれば嬉しい。ある例だが、現場からgithubムーブメントが起こり社内に広まった。導入された後に、スターたちが偉い人にお礼のメールをしたら「あ、こういうのが嬉しいんだ」と偉い人が理解したというケースがある。コミュニケーション大事。

岩: 社外コンサルに頼るという手もある

藤: とりあえず試すことが大事。

吉: 評価する前にとりあえず使うことが大事なんですね。

髙: あるツールを使うというよりは、既存の導入しているツールと連携させるイメージで使うような感覚で使うと定着する。

岩: kpiを求められた場合は?

吉: 人件費が一番高いので、今あるリソースを本業にどれだけ避けるようになるかを説得する。

藤: 数字だけでは理解できないものがあるので、その部分をアピールすることが重要。

吉: 合宿みたいに集まって、偉い人も集めて、作っているところを見せて理解を得たことがある。

吉: 言い残したことは?

岩: 内製頑張りましょう!採用にも繋がるので、ブランディングが大事。

髙: 他のツールを敵視(ライバル視)していない。それよも、情報共有の重要性が浸透していない問題に対し一緒に解決を試みる仲間と思っている。 情報共有の重要性に関する世論を形成したい。

藤: 経営資源は遜色ないけど、なぜこんなに外国と差がつくのかという話を聞くことがあるが、失敗を許容するマインドがないというのが大きな違いではないかと考えている。髙橋さんが「ムーブメント」と言っていたが、失敗してもいいムーブメントを起こしたい。不確実性の中、一寸先は闇なので、失敗することは悪ではない。

最後に

登壇者の皆様、非常に興味深いお話ありがとうございました!

参考

プロフィールは以下の詳細ページから取得しました。
http://www.awssummit.tokyo/devcon/index.html

JAWS-UG CLI専門支部 #38に参加してきた。

JAWS-UG CLI専門支部 #38 - 初級者歓迎 復習編: S3 + 静的Webホスティングに参加してきました。

JAWS-UG CLIの勉強会に参加しました。 jawsug-cli.doorkeeper.jp

JAWS-UG CLI専門支部とは

JAWS-UG CLI専門支部とは、AWS CLIの勉強会で、AWSのサービスをマネジメントコンソールからではなくCLIを使用して扱うことに特化した勉強会やイベントを開催している組織です。これまで3度ほど参加させて頂いていたのですが、「初級者歓迎」の回に参加するのは初めてでした。

流れ

  • CLI専門支部についての説明
  • 基本的なAWS CLIに関しての説明
  • S3に関しての説明
  • ハンズオン
  • 自己紹介&はまりどころ
  • 懇親会

メモ

  • CLI専門支部についての説明

    • 主催者の波田野さんがAWS SummitでCLIの専門支部を立ち上げる話をしたら引っ込みがつかなっくなったそうです笑
    • 当時はCLIを使用している人がかなり少なかったそうです。
  • Query(--query)

    • 出力結果から特定のノードを取り出すことができる
    • jqの代替 JAMES-Path表記
    • describe系のサブコマンドのfilterオプションで絞り込みをして、その結果からqueryオプションでノードを取り出す
  • 補完は以下で行えるようになる(bashの場合)

    • complete -C aws_completer
  • jsonlint

    • ヒアドキュメントでjson作るので壊れていないかチェックするために必要
  • CLIのupdate

    • 1.10.0にて(2016 1/21)acm(無料でssl証明書を作るサービス)追加
  • S3の説明

    • S3 はサービス名の頭文字がs3つだから
      • EC2の後がS3で、この後は「何4」がでてくるのかと期待していたそうです笑
    • オブジェクトストレージ(not ブロックストレージ)
    • 動的コンテンツがなければS3のみで完結できる
    • 動的コンテンツはcognitoとの併用で対応可
    • URLをつけないとファイル置き場、つけると外部から見える
    • URL自体をバケット名になるので、S3全体でバケット名はユニークである必要がある
    • オブジェクトは最小単位、内部的にフラットだが、名前で擬似的に階層構造を表現できる
  • cli s3コマンドの説明

    • ハイレベルS3コマンドはデフォルト出力がテキスト形式なので注意
  • その他メモ

    • cognitoと組み合わせて動的サイトも作成可能(cognitoでjsが動く)
    • webサイトホスティングでは、最初にあげたファイルにのみアクセス許可が与えられている(ファイルごとに許可与える)ので、バケット自体に権限を与える処理が必要。ポリシーを自分で与える必要がある( 以下の2.*で設定http://qiita.com/tcsh/items/dd99e9f7ced6406f8818
    • コマンドの成功or失敗に関しては画面に何も出力がないことを確認するかecho $?をする必要がある。基本的に何も出力されなければ成功と思って良い。
    • webサイトホスティングの際に、例えばindexページなどを認識させるためには以下のコマンドを実行する(参考の[JAWS-UG CLI] S3:#2 ハイレベルS3コマンドで静的Webホスティングより抜粋) aws s3 website "s3://${S3_BUCKET_NAME}" \ --index-document index.html \ --error-document error.html
    • バージョンによる挙動の違い
      • S3のバケット名は大文字使用が非推奨ですが、CLIのバージョンによって(もしくはPythonのバージョンなど他の環境によって)バケット名に大文字を使用した際の挙動が異なっていました。サポートして頂いた方や私は大文字バケット名指定によりエラーが出ませんでしたが、隣の方はエラーが出ていたそうです。

感想

今回は初級者向けということで、ゆっくりと進めて頂いたため余裕を持って進めることができました。他の回ではかなり急いでいた記憶があるので対照的でした笑。 初級者歓迎を冠していない回だとCLIを触ったことのない方は敷居が高いかもしれませんが、主催者の方も懇親会でおっしゃっていたように「出席して実行した結果を持ち帰ってもらえば後で復習できる」ので、出席してとにかく手を動かしてみるのが良いと思います。資料もかなり充実しています。 勉強会&懇親会ともに非常に楽しかったです。主催者の方、参加者の方々ありがとうございました。

参考

JAWS-UG CLI専門支部 #38 - 初級者歓迎 復習編: S3 + 静的Webホスティング - JAWS-UG CLI専門支部 | Doorkeeper

[JAWS-UG CLI] S3:#1 ハイレベルS3コマンドを使ってみる (バケットの作成から静的Webホスティング、削除まで) - Qiita

[JAWS-UG CLI] S3:#2 ハイレベルS3コマンドで静的Webホスティング - Qiita

[JAWS-UG CLI] S3:#4 静的Webホスティングのバケットポリシー設定 - Qiita

モデルと画像のリレーションが多対多のケースで画像をcarrierwave + fogでAWS S3に登録する

carrierwave + fogでAWS S3に画像を保存する方法に関して、画像と当該モデルのリレーションを多対多で設定したいことがあると思います。例えばある写真を他のブログ記事に使いたいという場合がそのケースにあたります。 画像と当該モデルのリレーションを多対多に設定して画像アップロード機能を実装する際に少しハマったので記事に残しておきます。

ハマった内容

恥ずかしいのですが、画像登録機能実装時にaccepts_nested_attributes_forやbuildを使用せずに登録しようとしていたところ、 以下の内容でハマりました。

hmu29.hatenablog.com

実際、本来なら画像データに関して

"name"=>#<ActionDispatch::Http::UploadedFile:0x007fa32c0726d8 @tempfile=#<Tempfile:hogehoge.jpg>, @original_filename="hogehoge.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"hogehoge\"; filename=\"hogehoge.jpg\"\r\nContent-Type: image/jpeg\r\n”>

のようなリクエストを送るのが正しい動作なのですが、

Parameters: {~略~, "image"=>{"name"=>"hogehoge.jpg"}, "commit"=>"登録"}

となってしまい画像のデータがリクエスト時に送れないという事態に陥りました。

今回考えるケース

  • ブログ記事に画像をアップロードする。
  • 但し、ブログ記事(entryテーブル)と画像(imageテーブル)は多対多の関係とする。
  • 登録機能のみ例示する

前提

  • 基本的なcarrierwave, fogの設定は終了しているものとする。
  • 必要最低限しか記載していないので、必要に応じて処理を追加してください。

実装

migrationファイル

  • 説明・注意点
    • add_foreign_keyにnameオプションを渡すことで、いちいち制約名が変わらなくなるので便利
    • 中間テーブルにて記事IDと画像IDにユニーク制約を付与すること

entryテーブル

class CreateEntries < ActiveRecord::Migration
  def change
    create_table :entries do |t|
      t.string :title, null: false
      t.text :content, null: false
      t.timestamps, null: false
    end
end

imageテーブル

class CreateImages < ActiveRecord::Migration
  def change
    create_table :images do |t|
      t.string :name, null: false
      t.timestamps null: false
    end
  end
end

中間テーブル

class CreateEntryImages < ActiveRecord::Migration
  def change
    create_table :entry_images do |t|
      t.references :entry, null: false
      t.references :image, null: false
      t.timestamps null: false
    end
    add_index :entry_images, [:entry_id, :image_id], unique: true
    add_foreign_key :entry_images, :entries, name: 'fk_rails_from_entry_images_to_entries', option: 'ON UPDATE CASCADE ON DELETE CASCADE'
    add_foreign_key :entry_images, :images, name: 'fk_rails_from_entry_images_to_images', option: 'ON UPDATE CASCADE ON DELETE CASCADE'
  end
end

modelの作成(バリデーションなどは省略)

  • 説明・注意点
    • entry.rbにて「accepts_nested_attributes_for」を付与しないと入れ子のフォームができないので注意!!
    • entry_image.rbにて、image_idとentry_idへ複合ユニーク制約を付与するのを忘れないでください。

entry.rb

class Entry < ActiveRecord::Base
  # アソシエーションの設定
  has_many :images, through: :entry_images
  has_many :entry_images
  
  # viewにて入れ子のフォームを作成するために必要
  accepts_nested_attributes_for :images
end

image.rb

class Image < ActiveRecord::Base
    has_many :entries, through: :entry_images
    has_many :entry_images
    # ImageUploaderとカラムを紐づける
    mount_uploader :name, ImageUploader
end

entry_image.rb

class EntryImage < ActiveRecord::Base
  belongs_to :entry
  belongs_to :image
  
  validates :image_id, presence: true, uniqueness: {scope: [:entry_id]}
end

controllerの作成

  • それぞれのコントローラーで以下を記述して下さい
  • 説明・注意点
    • @entry.images.buildでentryテーブルとimageテーブルと紐付けます。
    • accepts_nested_attributes_for :imagesとmodelに記載した場合、画像の情報はparams[:entry][:images_attributes]に入ります。
    • images_attributesを許可して下さい。
def new
  @entry = Entry.new
  @entry.images.build
end

def create
  @entry = Entry.new(permitted_attr)
  @entry.save!
end

private
def permitted_attr
 params.require(:entry).permit(
  :title, :content, images_attributes: [:name]
 )
end

viewの作成

new.html.erb

<%= form_for @entry do |f| %>
  <%= f.fields_for :images do |i| %>
    <%= i.label :name, '画像' %>
    <%= i.file_field :name, disabled: false %>
  <% end %>
  <%= f.submit '登録'%>
<% end %>

以上で、entriesテーブル、imagesテーブル、entry_imagesテーブルに正しく画像が登録できるようになります。

さいごに

  • 多対多でも、リレーションをきちんと定義してRailsのお作法に則れば、画像アップロードが正しくできるという記事でした。本記事で触れた個々の内容に関して、詳しく説明された記事があるので以下に貼ります。
  • carrierwaveの基本的な設定は以下を参考にして下さい。
    morizyun.github.io

  • fogの基本的な設定は以下を参考にして下さい。 morizyun.github.io

  • accepts_nested_attributes_forに関する詳しい説明は以下を参考にして下さい。 ruby-rails.hatenadiary.com

参考

rails4 fields_forの要素に対してはfile_fieldが働かない? - 日々の記録。

macのターミナルでvim使用時に、optionキーを押すとカーソルが十字に変わり任意の場所にカーソル移動ができる

macのターミナルアプリでvimを使用するときに、optionキーを押すとカーソルが十字カーソルに変わり、クリックした場所にカーソル移動ができます。

f:id:biibiebi:20150913150742p:plain

例えば、上記では「u」の二文字目にカーソルがありますが、この状態で「option」キーを押下したままカーソル移動したい文字のところでクリックすれば、その文字の箇所にカーソルが移動されています。

こういう子ネタ、以外と知らなくて恥ずかしいんですよね・・・

他には、viで画面が壊れたとき(Enterキーを押しても次のプロンプトが表示されないとき)にclearコマンドで直るとか、最近になるまで知りませんでした・・・恥ずかしいし知っていると便利なのできちんと勉強しないとという感じですね。

疑問点

macでカーソル付きのスクショを取る方法は以下のページに書いてあるんですが、十字カーソルのスクショを取る方法はあるのでしょうか。 どなたか知っている方いたら教えてくださると嬉しいです。 inforati.jp

AWSのELBへSSL証明書アップロード時に「Unable to parse key; the body is encrypted.」エラー

ELBへSSL証明書をアップロードする際に以下のエラーが出ました。

f:id:biibiebi:20150913140340p:plain

原因

  • opensslで秘密鍵を作成する際に、パスワード設定し暗号化していたことが原因だった。

確認方法

  • 秘密鍵を参照し、2行目・3行目に以下の内容がある場合は暗号化されている。
$ cat server.key 
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,E3CB8B1CE0E5CBDF7819D18627823618

〜略〜
-----END RSA PRIVATE KEY-----

対処法

  • 以下のコマンドを実行する。ただし、秘密鍵名は「server.key」、作業ディレクトリは秘密鍵を配置しているディレクトリである。
$ openssl rsa -in server.key -out server.key 
Enter pass phrase for server.key:  # ←ここで最初に秘密鍵を暗号化したパスワードを入力する
writing RSA key
  • 秘密鍵の内容確認。Proc-Type、DEK-Infoの記述がないことを確認する。
$ cat server.key 
-----BEGIN RSA PRIVATE KEY-----
〜略〜
-----END RSA PRIVATE KEY-----
  • 以上が終了したら、ELBに証明書をアップロードする。

f:id:biibiebi:20150913142608p:plain

参考

www.digicert.ne.jp

ELBへ証明書のアップロード方法を知りたい方は以下を参照下さい。

dev.classmethod.jp

Sublime Text 3 で日本語検索ができない問題の解決法

この問題に当たるのは2回目で、1回目は以下の記事を参考に解決できました。

Sublime Text 3 で日本語を検索したとき文字が消える不具合を直す - MEMOGRAPHIX

しかし、一度解決し正常に日本語検索できていたのにも関わらず、同じ問題が発生しました。そこで調べてみたところ

  • 上記ページに書いてある設定は全て反映されている
  • 以下のゴミファイルが ~/Library/Application Support/Sublime Text 3/Packages/Default/ にある
    .Default (OSX).sublime-keymap.un~
    Default (OSX).sublime-keymap~

という2点が判明しました。そこで、これらのゴミファイルを削除したところ正常に日本語検索が出来るようになりました。