Search on the blog

2018年1月18日木曜日

Scalaのapply、unapplyについて

applyの説明


class Human(val name: String, val age: Int) {
}

object Human {
  def apply(name: String, age:Int) = {
    new Human(name, age)
  }
}

としておくと、以下のようにインスタンスを生成できる。

val h = Human("taro", 20)

コンパニオンオブジェクトのapplyがファクトリメソッドとして使われるので、newと書かなくてもインスタンスを生成できる。

unapplyの説明


class Human(val name: String, val age: Int) {
}

object Human {
  def unapply(h: Human): Option[(String, Int)] = Some((h.name, h.age))
}

としておくと、以下のようにパターンマッチで使える。

val h = new Human("taro", 20)
h match {
  case Human(name, age) => println(s"name=$name, age=$age")
  case _ => println("unknown")
}


ケースクラス

case classを使ってあんなことやこんなことができるのは、実はapply、unapplyが自動生成されていたかららしい。

case class Human(name: String, age: Int) {
}

val h = Human("taro", 20)
h match {
  case Human(name, age) => println(s"name=$name, age=$age")
  case _ => println("unknown")
}

2017年11月1日水曜日

L2接続とL3接続の違い

Ciscoのページがとても分かりやすかった。

違いを表にまとめておく。
レイヤー OSIモデル アドレス 通信単位 接続対象
L2 データリンク層 MACアドレス フレーム LAN内の端末
L3 ネットワーク層 IPアドレス パケット LAN同士

2017年10月30日月曜日

GCPとjavascriptでaccess trackerを作る(3)

backend(リクエストを受けてpub/subに流すコンポーネント)がほぼ出来上がった。

https://github.com/Kenji-H/access-tracker-backend/tree/v0.9.2

進捗
  • google container engineのクラスタを立てた
  • deploymentとserviceの定義を書いた
  • READMEを書いた
  • alpineで動かすとgcpのライブラリのロードでこけることがわかったのでfixした

動作確認
データを投げる。
$ cat test.json
{
  "userid": "610KZ4G0CBTI419Y",
  "timestamp": 1509290846000,
  "pageid": "test-page-001",
  "browser": "chrome",
  "country":"japan"
}
$ curl -H 'Content-Type:application/json' -d @test.json xxx.xxx.xxx.xxx/pv

アプリケーションのログを確認する。
$ kubectl --namespace=backend logs -f access-tracker-backend-xxxxxxxx
received request for URL: /pv
success: {"userid":"610KZ4G0CBTI419Y","timestamp":1509290846000,"pageid":"test-page-001","browser":"chrome","country":"japan"}

pub/subにデータが流れたことを確認する。
gcloud beta pubsub subscriptions pull test --auto-ack --max-messages 1000
│ {"userid":"610KZ4G0CBTI419Y","timestamp":1509290846000,"pageid":"test-page-001","browser":"chrome","country":"japan"} │ 165859404777865 │            │

次やること
  • droneサーバを立てる
  • unittestを書く
  • CI/CDの設定をする

2017年10月29日日曜日

GCPとjavascriptでaccess trackerを作る(2)

https://github.com/Kenji-H/access_tracker/tree/v0.9.1

今日の進捗
  • pub/subにデータをpublishする部分を実装した
  • データをvaldationする機能を実装した
  • expressに404と500のhandlerを追加した

新しく学んだこと
  • node.js向けのgcp client libraryは基本非同期処理で書くようになっているが、callbackを省略するとpromiseオブジェクトを返してくれる。
  • promiseオブジェクトをチェーンで繋げて書くとうまく書けそうだが、繋げたいメソッドの入出力がうまくハマらなかったり、細かい例外処理をしたかったりすると、自分でpromiseオブジェクトを作成した方が書きやすい感じがした。たぶん自分のnode.js力が低いだけで、慣れてきたらもっとうまく書けそう。
  • gcpのcredentials/projectidは環境変数に入れるとすっきりする。
  • jsonをバリデーションしたい場合は、jsonschemaというライブラリを使うといいらしい。
  • expressにはエラーハンドラを登録することができる。404のハンドラの定義はファイルの一番下部でやらないといけない。

次やること
  • gkeのクラスタを立てる
  • gkeでコンテナを動かす
  • プロジェクト構成を整理する(デプロイの単位は分けるつもりだったが、レポジトリ自体も分けた方がすっきりしそう)

2017年10月28日土曜日

GCPとjavascriptでaccess trackerを作る(1)

 最近GCPを使ったインフラ構築と、javascriptへの興味が高まっているので、勉強がてら何か作ってみることにした。

作りたいやつの機能
  • サーバサイドはnode.jsで書く。REST APIでページビュー情報をPOSTしたり、ページビュー情報をGETしたりできる。
  • POSTされた情報はGCPのpub/subにpublishされる。
  • GETするときはpub/subからsubscribeする。
  • サーバ自体はGCPのcontainer engineで動作する。
  • クライアントサイドはReact.jsで書く。
  • グラフライブラリを使ってかっこいいグラフを表示する。
  • Websocketを使ってリアルタイムにグラフが更新されるようにする。
今日の進捗
node.jsでサーバを書いて、Dockerで動くようにした。

https://github.com/Kenji-H/access_tracker/tree/v0.9.0

ローカルでの動作確認方法は以下のとおり。

まず、dockerを起動。
$ cd server
$ docker build -t test .  
$ docker run --rm -p 8080:8080 test

クライアントからリクエスト送信。
$ curl localhost:8080/status
$ curl -H 'Content-Type:application/json' -d '{"userid": "610KZ4G0CBTI419Y", "timestamp": 1509130332, "url": "kenjih.com", "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"}' localhost:8080/pv

dockerにログが出ていることを確認。
received request for URL: /status
received request for URL: /pv
userid: 610KZ4G0CBTI419Y
timestamp: 1509130332
url: kenjih.com
userAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36

2017年10月21日土曜日

Signal Handler in Python

PythonでSignal Handlerを書いて遊んでみた。

プログラム
Python 3で動作確認してます。
遊び方
まず上記のPythonプログラムを起動します。
$ python sample.py

プログラムを起動したら以下の表を参考にシグナルを送ってみてください。
シグナル キーボードから コマンドラインから
SIGINT ctrl + c kill -INT プロセス番号
SIGTSTP ctrl + z kill -TSTP プロセス番号
SIGTERM - kill プロセス番号
SIGKILL - kill -KILL プロセス番号

プログラムを停止したい場合は、SIGKILLを送ってください。
プログラムのプロセス番号は以下のコマンドで調べることができます。
$ pgrep -f "python sample.py"

単一障害点とは

まえがき
システム全体のアーキテクチャを考えるときに、「単一障害点」という概念が大事らしい。
意味は一目瞭然だけど、大切な概念っぽいので調べてみることにした。

語句の意味
その単一箇所が働かないと、システム全体が障害となるような箇所のこと。
ちなみに英語だとSingle Point of Failure(SPOF)というらしい。

単一障害点の例
コンポーネント 説明
アプリケーションサーバ アプリケーションサーバが一つしかないと、クリティカルなエラーが発生したときにユーザがシステムを利用できなくなってしまう。よってサーバをレプリケーションしておくことでSPOFにならないようにする必要がある。
ディスクストレージ ディスクストレージが故障するとデータの読み書きができなくなり、システム全体が利用不可になってしまう可能性がある。よってRAIDなどの冗長構成を取る必要がある。
ネットワークスイッチ ネットワークスイッチが故障と、ネットワーク内のサーバ間の疎通ができなくなってしまう。よって冗長なスイッチとネットワーク構成によって、SPOFを解決する必要がある。

トレードオフ
SPOFを解決するためには、レプリケーションや冗長構成などが必要となるので、コストがかかる。
どこまでSPOFの排除に取り組むかはコストとのトレードオフも考えて決定しなければならない。