メタプログラミングRuby読みメモ 1

メタプログラミングRuby読んだメモです。

1章 頭文字M

  • 多くのプログラミング言語では、コンパイラ後は変数やメソッドは実体を失う
    • メモリ上に配置されるだけの存在となる
  • 一方Rubyのような言語は、言語要素が残る
  • 言語要素について尋ねることもできる
  • これはイントロスペクションと呼ばれる
  • Object#classObject#instance_variables など

  • ActiveRecordではイントロスペクションを用いてクラス名を調べ、同名のテーブルへのマッピングなどの機能を実現している

  • メタプログラミングとは、言語用添えお実行時に操作するコードを記述することである

2章 オブジェクトモデル

  • 全ての言語要素はオブジェクトモデルの中に存在する
    • このメソッドはどのクラスに所属するものなのか
    • このモジュールをインクルードしたらなにが起こるのか

オープンクラス

  • Ruby ではクラスの定義の中に入ったときに初めてクラスが定義される
  • 定義されているクラスをもう一度記述すると再オープンとなり、既存のクラスに記述されたメソッドなどを追加する
  • いつでも既存のクラスを再オープンし、修正できる。この技法をオープンクラスと呼ぶ

オープンクラスの問題点

  • メソッドを追加しようとして同名の既存のメソッドを書き換えてしまう可能性がある
  • このような既存メソッドの書き換えをモンキーパッチと呼ぶ

オブジェクトモデルの内部

  • インスタンス変数
    • Object#instance_variablesで確認することができる
    • Ruby のオブジェクトのクラスとインスタンス変数には何のつながりもない
  • メソッド
    • Object#methods で一覧を取得できる
    • オブジェクトにはメソッドはなく、インスタンス変数とクラスへの参照しかない
    • 全てのオブジェクトはクラスのインスタンスであり、クラスに属している
    • メソッドはオブジェクトではなくクラスに存在する
  • クラスの真相
    • クラスはオブジェクト
    • Ruby の Class クラスのインスタンスはクラスそのもの
      • 他のオブジェクトのように操作することもできる
    • プログラム実行時に新しいクラスを生成したり、書き込むこともできる
    • クラスのクラスメソッドは Class クラスのインスタンスメソッド
  • モジュール
    • Class クラスのスーパークラスは Moduleである
      • つまり全てのクラスは"new, allocate, superclass"を継承したモジュールである
    • どこかでインクルードするときはモジュールを選択し、生成や継承をするときはクラスを選択する
    • クラスはオブジェクトであり、クラス名は定数である
  • 定数
    • 大文字で始まる参照は全て定数
      • クラス名やモジュール名も含めて
    • Rubyは定数の値も変更できる
    • 定数と変数の明確な違いはスコープ
    • プログラムにある全ての定数はファイルシステムのようにツリー上に配置されている
    • Moduleクラスは定数を呼び出すインスタンスメソッドとクラスメソッドを持っている
      • インスタンスメソッドのModule#constants は現在のスコープの定数全てを返す
      • クラスメソッドのModule#constantsは現在のプログラムのトップレベル定数を返す
    • 定数をまとめるモジュールのことをネームスペースと呼ぶ

メソッドの呼び出し

  • メソッド探索
    • オブジェクトのクラスを探索してメソッドを発見している
    • レシーバのクラスから継承チェーンを上りながら探索する
      • レシーバ: 呼び出すメソッドが属するオブジェクト
      • 継承チェーン: クラスのスーパークラススーパークラスのスーパクラス...からなる継承関係
        • インクルードするとモジュールがインクルードしたクラスの上に挿入される
        • prepend を用いるとクラスの下にモジュールが挿入される
    • Kernel
      • Rubyにはどこからでも呼び出せるメソッドがある(print など
      • これはKernelモジュールのprivateメソッドである
      • ObjectクラスがKernelモジュールをインクルードしているので全てのオブジェクトの継承チェーンに挿入されている
  • メソッドの実行
    • メソッドを実行するには発見したメソッドが誰から呼び出されたか知っている必要がある
    • それがレシーバでありこれを参照するキーワードがself
    • レシーバを明示しないメソッド呼び出しは全てselfに対する呼び出しとなる

トップレベ

  • Rubyのプログラムを開始したとき、メソッドをなにも呼び出していない時のselfはmainと呼ばれるオブジェクトである
  • これをトップレベルコンテキストと呼ぶ

クラス定義とself

  • クラスやモジュール定義の内側では、selfはクラスやモジュールそのものになる

private

  • private は二つのルールに従っている
    • 自分以外のオブジェクトのメソッドを呼び出すにはレシーバを明示的に指定する必要がある
    • private はレシーバを指定できない
      • self."privateなメソッド"な呼び方も明示的にselfを指定しているので呼び出すことができない
    • この二つのルールを合わせるとprivateのついたメソッドを呼び出すのは自分しかできなくなる

Refinements

  • クラスの修正をする時の問題点は、変更がグローバルに及ぶこと
  • refine をつけるとusingメソッドを使って明示的に有効化しないと有効にならないようにできる
  • using "モジュール"を呼び出した時点から有効化される
  • Refinements はモジュール定義の終わりまで有効

ゲームにおけるWebサーバーって何

昨日から続くサーバーサイドエンジニアについて考えようの第二弾です。
書いている時点ではなにも見えていないので大枠から考えながら学ぶことを考えて行こうと思います。

ゲームにおけるWebサーバーって何?

ソーシャルゲームにおけるWebサーバーの役割は、
ネイティブアプリなどのクライアント側からのリクエストを受け取りレスポンスを返す一般的なWebサーバーと同じものです。

これを容易に実現するためにRuby on RailsなどのWEBフレームワークを用いて開発されます。

ゲームに限りませんが、Webサーバーには多数のクライアントからのリクエストを受け取り処理する必要があります。
しかし、1つのサーバーで多くのリクエストを捌くには限界があります。
そこで複数台数のサーバーを用意してリクエストを分散して処理を行い、
負荷分散するということが行われています。

負荷分散ってなに?

ふわっとした理解のものを見つけたので負荷分散について色々読んでみようと思います。

www.fujitsu.com

knowledge.sakura.ad.jp

負荷分散の目的は、拡張性と可用性を持たせることが目的のようです。
拡張性とは、用意したサーバーで処理ができない際に、クライアントに影響なくサーバーの台数を増やしたりすることが可能となることです。
可用性とは、システムを停止させないようにする負荷分散の役割の一つです。
サーバーに対して生死確認を行い、死んでいるサーバーにはリクエストを送らず切り離すことで、
システム全体を停止させることを回避できます。

負荷分散についてのページを読んでいるとまた気になる単語があったりしたので、
次はその単語について勉強したりしようと思います。
進め方はこのまま手探りで...

ゲームのサーバーサイドエンジニアってなんだろう

ソーシャルゲームのサーバーサイドエンジニアとして仕事をして1年半が経ちました。

今までバイトもせず世間知らずのまま社会に出て新卒として初めて仕事につきました。
初めての一人暮らしで家事や家計の管理、見知らぬ土地での気候の違いや環境の違い、
まぁ色々と不安はあったのですが新しい生活での楽しみで結構なんとかなってます。

これまで夢や目標もなく、なんとなく流されながら生きてきましたが、
それでも選択肢はいくつかあって、その一つが情報系の大学への進学でした。
強い理由はありませんでしたが、コンピューターの中なら何でもできる!神になれる!
と思って情報系の道へ進みました。 そこからは何となく流れで生きて、ゲームが好きだしゲーム会社もいいなと思い今の仕事につきました。

サーバーサイドエンジニアって何?

今まで人生を流されながら生きてきたので、これまで自分を振り返ったことありませんでした。
運だけは自信があるのでこのまま流れたままでも生きていけると思うのですが、
仕事に就き、プロとして生きて行くには流されるだけで学べるペースでは自分の心が先に折れるなと思いました。

これまで見ないフリをしてましたが、今の私は自分のレベルも把握できておらず、
どう学んでいけばいいのか自分で考えられない状況です。

そこで、自分を振り返りつつ足りない力を埋めていくために、 まず、サーバーサイドエンジニアって何だろうという大枠を考えながらブログを書こうと思いました。

で、サーバーサイドエンジニアって何なのよ

Webサービスは、お客さんの目に映る部分とそこで使われるデータを処理する部分では大抵異なる技術が使われている(多分)。
サーバーサイドエンジニアは目に見えない部分、データの処理や管理を行う部分を担当するエンジニアです。

私はゲームのサーバーサイドエンジニアをしているので、ここで扱うデータは、
ユーザー情報や、アイテム、ゲーム内通貨などです。

ソーシャルゲームには新規開発と運用保守という二つのフェーズがある。
新規開発はもちろんこれからリリースされるゲームの機能を開発していく段階なのですが、
運用保守というのはリリースされたゲームをお客さんがゲームを不具合なく楽しんでもらえるように維持し、
また新しい遊びを提供するために機能開発を行っていくフェーズである(多分)。

私はすでにリリースされているタイトルへ配属されたため運用保守の仕事を行っています。

・・・と書いたところで、思いつきで書き始めたものなのでこの記事の落としどころがわからないことに気づきました。
飽きてきたので一旦ここで終わってまぁちょこちょこ疑問を出しながらわからない所を減らして行こうかと思いました。

参考書を読んだメモ : SQLアンチパターン I部1章

SQLアンチパターン

データベース論理設計のアンチパターン

ジェイウォーク(信号無視)

  • 多対多の交差テーブルを避けるためにカンマ区切のリストを使うアンチパターン

目的: 複数の値を持つ属性を格納する

  • 列に値を一つのみ格納する場合は簡単。整数、日付、文字列に対応した型を選択し、値がその型の1つのインスタンスであることを表現する
  • あるアカウントは複数の製品を持つ場合があり、ある製品はただ一つの連絡先を参照しているデータベースがある
    • 製品とアカウントの間には多対多の関係がある
  • 製品が複数の連絡先を持つ場合があることがわかり、製品からアカウントに対する1対多の関連をサポートする必要ができた
  • 複数の連絡先を持つにはどうするか

アンチパターン: カンマ区切りフォーマットのリストを格納する

  • データベースの構造に対する変更を最小限に抑えるためにアカウントid列をVARCHAR型の列で再定義しカンマ区切のリストとして持つようにした
  • この変更は一見テーブルや列を新たに追加せず、変更は1つの列のデータ型のみなのでうまくいってるように見える

特定のアカウントに関連する製品の検索

  • 全ての外部キーが文字列連結されて1つのフィールドに格納されていると、クエリを作ることが難しくなる
  • 島嘉靖による比較ができなくなるため、パターンマッチが必要になる
  • インデックスを使うメリットも得られなくなる
  • パターンマッチ構文は、各種データベース製品において異なるため、SQLはベンダー中立でなくなる

特定の製品に関連するアカウントの検索

  • カンマ区切のリストを使って参照先のテーブルと結合するのは手間がかかる

集約クエリの作成

  • 集約クエリはカンマ区切リストではなく複数行に対して使われるように設計されているため細工を行う必要がある

特定の製品に関連するアカウントの更新

  • リストの追加は簡単だが、ソート順の維持が難しくなり、削除処理も複雑になる

アカウントIDの妥当性検証

  • VARCHAR型の列のため正数値でなく文字列も入れこめてしまう

区切り文字の選択

  • 整数値の区切りリストではなく、文字列の区切りリストであった場合区切り文字の選択や区別にコストがかかるようになる

リストの長さの制限

  • 要素の長さによってリストに格納できる制限が変わってしまう

アンチパターンの見つけ方

  • このリストでサポートしなくてはならない最大のエントリ数は?
    • VARCHEAR列の最大値を決定しようとしている時に生じる疑問
  • SQLで単語境界を一致させる方法を知ってる?
    • 正規表現で文字列の一部を取得しようとしている
  • リストのエントリに絶対使われない文字って何だっけ?
    • 区切り文字を探している時に出てくる文言

アンチパターンを用いてもよい場合

-クエリパフォーマンスの向上のために用いる場合がある - カンマ区切りフォーマットのデータが必要で、かつリスト内の各要素への個別アクセスが不要な場合など - ただし非正規化を採用するには十分に検討してからの方が良い

解決策: 交差テーブルを作る

  • アカウントIDを製品テーブルに格納するのではなく、新たに作成したテーブルの各行にアカウントidを一つずつ格納する
  • このテーブルによって、製品とアカウントは多対多の関係になる
  • テーブルが二つのテーブルを参照する外部キーを持つとき、そのテーブルは交差テーブルと呼ばれる

特定のアカウントに関連する製品の検索/特定の製品に関連するアカウントの検索

  • 特定のアカウントに関連する製品の検索は交差テーブルを結合することで簡単にできる
  • 結合はクエリパフォーマンスを低下させるが、アンチパターンの解決策よりも効果的にインデックスを使える

集約クエリの作成

  • 単純なクエリで扱える

製品の連絡先の更新

  • 交差テーブルへの挿入や削除で簡単に行える

アカウントIDの妥当性検証

  • 外部キーを用いて別テーブルの値を参照することで入力の妥当性検証を行える
  • 参照整合性を保証させることができる
  • 外部キー制約により、存在するアカウントのみが格納できる
  • データ型によって入力制限ができる

区切り文字の選択

  • 区切り文字は不要

リストの長さの制限

  • テーブルに物理的に格納できる行数のみ

交差テーブルの他のメリット

  • インデックスを用いることで、リストの部分文字列とマッチさせるよりパフォーマンスは向上する
  • 列を加えることにより、エントリに属性を追加できる

東証記者会見メモ

東証記者会見メモ

経緯

  • 朝07:04, 売買システムのデスク装置の故障し、相場情報配信業務や売買監視業務に異常が発生
  • 注文売買系のサーバー、運用系のネットワーク
  • 運用系のネットワークの共用ディスク装置1のメモリ故障
  • 本来であればフェイルオーバーで切り替わるはずが正常に行われなかった
  • この結果事象として
  • 情報配信ゲートウェイサーバーの配信処理に異常
  • 売買監視サーバーの監視処理異常が発生
  • 情報配信ゲートウェイサーバーから相場情報が配信できなくなった
  • 証券会社からの注文ゲート、参加者ゲートウェイと情報配信ゲートを遮断、売買を停止した
  • 2号機のみで稼働する状態には出来たが、全体の状況を見て売買を開始するためには全体再起動を行う必要がある
  • 故障したメモリを交換、システム全体の再起動、正常に稼働していることを確認
  • 遮断処理、1->2への切り替えを人的に監視を当分行う

質疑応答

  • 故障箇所の特定は?
    • ログから機器の故障だと判明
    • 直接外部と繋がっている部位ではない
    • 監視は常時行なっており、異常はない
  • 過去にも障害があったが?
    • フェイルオーバーができる設計
    • 各サーバーでフェイルオーバーのテストも実装前に行なっている
    • テストは異常なし
    • ハード部分の根本原因は掴めていないが調査中
  • アローヘッドの内と外どこが故障したのか
    • アローヘッドってシステムの名前か
    • 内側
    • アローヘッドはいくつかのサーバーからなる。そのサーバーの一つが故障した
  • 共有ディスクのメモリとは何を保存しているのか
    • ジョブ、機器のid,アドレスなど共有で必要な情報を集めて各サーバーの処理に提供している装置
    • 銘柄の情報などを送るジョブが動かず情報配信ゲートウェイで異常が発生した
    • 取引が始まる前の前処理ができなかった
      • 当日の基準の値段、今日の時間の制約など処理
  • 詳しい説明がHPになかった、売買停止時間いつ?
    • 情報の発信については原因の究明に時間がかかったため
    • ある程度分かった時点で速やかにお知らせした
    • 8時54分に停止した
  • システム障害でハードの故障はレアだけどシステムのミスじゃないか
    • ハードウェアの故障は確認している
    • なぜフェイルオーバーできなかったか究明
  • 責任はどこ?再起動すれば午後にはできたのでは?
    • 責任の所在は、機器を納入しているベンダーさんにはない
    • 既に朝に証券会社から注文を受け付けている。リセットすると連続性が保たれない証券会社側に混乱が生じるため丸一日止めた
  • 同じケースが生じた場合、終日売買停止になるのか?なぜシステム障害が行うのか?原因がわからないのなら正常化しないのでは
    • 注文を受け付けたのちに同じケースになった場合は同じような対応になる
    • 自動的にフェイルオーバーが行われなかった理由の判明はしていないが、故障したのはメモリ、1台でも動作可能なことははっきりしている
    • 強制的に1号機を切断することで人的に対応できる
  • 1台で動かしたことはこれまであるのか?
    • 本番ではないが、テスト済み
  • これまでに同じことがあったのか、最後に交換したのはいつか
    • 2019年11月稼働でまだ1年経っていない
  • 当分人的監視体制行うが当分はいつまでか?今日中にシステム再立ち上げうまくできるのか?できなかった時どうするのか
    • 具体的な条件が掴めるまでは人的監視を行う
    • 正常化の目処は立っている
  • 両方壊れた場合どうなるのか。大規模災害の時はどうするのか
    • 両方壊れた場合は中止になる
    • データセンターはプライマリ、セカンダリとして存在する
    • プライマリの中にあるサーバー
    • セカンダリは大規模災害など起きた場合に稼働させるもの。24時間内に立ち上げられるようなもの

参考書を読んだメモ : 1冊ですべてわかるネットワーク運用・保守の基本 4章, 5章

1冊ですべてわかるネットワーク運用・保守の基本

メンテナンス用ネットワークの基本

メンテナンス用ネットワークの概要

  • 業務用ネットワークとメンテナンス用ネットワークを分離していないと障害がおきたときリモート対応ができない

メンテナンス用ネットワークの整備

  • メンテナンス用ネットワークの要件
    • 業務用とポート番号を分ける
    • 対象のネットワークが全て収容でき拡張も考慮したポート数を持つスイッチを用意する

ネットワーク運用設計と障害対応の基本

ネットワークの可用性設計

  • 重要度を考える
  • 最重要
    • ネットワークやシステムの停止は許されない
    • ネットワーク全体の完全二重化
  • 重要
    • 瞬時に対応が必要
  • 一般
    • 2-4時間以内の復旧

冗長化のレベル

  • 万が一装置が故障してもサービスを継続して提供できるようにネットワークやシステムを構築することを冗長化
  • 両アクティブ
    • 複数台の装置を同時に稼働
    • 障害が発生すれば該当装置のみ停止させる
  • アクティブスタンバイ
    • 1つを稼働させてもう一つをスタンバイさせる
  • コールドスタンバイ
    • アクティブとスタンバイの同期を取らない

冗長化の全体像

障害対応

ネットワークのどこに障害があるのか

  • 通信事業者網内障害
    • WANでの障害
  • 構内ネットワーク障害
    • LAN部分での障害
    • スイッチ
    • ICMPによる疎通確認
    • インターフェースの状態確認
  • ネットワーク品質問題
    • 通信自体はできるがいつもと違う
  • ネットワークシステムの障害
    • システムの障害なのか、装置単体の障害なのか

参考書を読んだメモ : 1冊ですべてわかるネットワーク運用・保守の基本 3章

1冊ですべてわかるネットワーク運用・保守の基本

ネットワーク運用監視の基本

ネットワーク運用監視業務

  • ネットワーク運用監視業務とは何を監視するのか
    • ネットワーク機器本体やポートが正常に稼働しているか
    • ネットワーク機器のCPUやメモリに負荷がかかってないか
    • WAN回線の使用率が増えてないか

ネットワーク監視装置

  • 監視ソフトをインストールしたサーバー
    • 主な監視ソフト
      • WebSAm, JP1, Zabbix
  • 死活監視
    • 機器のIPアドレスに対してPingを送信し、本体が稼働しているかを監視する
  • MIB監視
    • 機器のCPUやメモリの異常値などの本体の内部まで監視する

ネットワーク監視装置の主な機能

  • 構成管理
    • ネットワークの接続線や階層をビジュアルで表示
  • 障害管理
  • 性能管理
    • 期間単位でレポートを生成
    • 閾値を一定回数超えるとアラートを出力

一般的な運用監視

  • pingによるものとSNMPを使った監視がある

ping を使った監視

  • ping を送り応答が帰ってくるかどうかで監視する(死活監視
    • ポーリング

SNMPを使った監視

  • SNMPサーバーからネットワーク機器の監視や制御をするときに使われるプロトコル
  • MIB監視とSNMPトラップを収集する監視
  • MIB監視は、pingよりも詳しく状態を知ることができる
    • 送受信パケット数、CPU使用率、メモリなどの機器のリソース
  • SNMPを使うための条件
    • IPネットワーク環境がある
    • 管理用サーバーがある(SNMPサーバー)
    • SNMPプロトコルに対応した機器である
  • SNMPの構成要素
    • マネージャ
      • 監視サーバー上(SNMPサーバー)にインストールして使うソフトウェア
      • SNMPプロトコルを使ってネットワークの運用や管理に必要な情報を収集し処理する
    • エージェント
      • ネットワーク機器やサーバー上の機能
      • 機器の状態情報を通知する
    • SNMPプロトコル
      • アプリケーション層
      • UDPパケットに乗せてやり取りをする
      • ポート番号は161と162
    • MIB
      • SNMPで管理されるネットワーク機器やサーバーが、自分の状態を外部に知らせるために公開する管理情報
      • インターフェースの稼働状態、トラフィック量などの詳細情報が含まれる
      • MIBの構造はツリー構造になっている
  • ポーリング
    • マネージャーが定期的にエージェントから管理情報を引き出す動作
  • トラップ
    • ルーターやスイッチ自身の状態に障害が起きたときSNMPサーバーへ情報を通知する
    • エージェント側からの通知
  • SNMPプロトコルでマネージャがエージェントと通信する際にはコミュニティネームの設定が必要

NetFlow を使ったトラフィック分析

  • NetFlow はトラフィックの情報を可視化して分析するためのシステム

フロー

  • ネットワーク上を流れる共通の属性を持ったパケットの集まり
  • 送信元IPアドレスと宛先IPアドレス、送信元ポート番号と宛先ポート番号などの属性が同じであれば同一のフロー
  • あるユーザーが社内のポータルサイトにアクセスした場合その処理は1フローとみなす

パケットキャプチャ

  • パケットのヘッダとペイロード(実データの中身)をキャプチャして解析する
  • データ量が多いのが欠点
  • リアルタイム分析には向いていない