タイトル

Need for Answer

2019年6月19日水曜日

suの実行コマンドを動的に生成したい

suでコマンドを実行するとき…ありますよね。「動的に実行コマンドを作成したい」という要望があると思います

結論だけ言うと、suコマンドに環境変数を引き渡せばできます。

以下サンプル
#!/bin/sh
MSG="/usr/bin/screen -S mc -X stuff \"say $@\""
su execuser --preserve-environment -c "${MSG}"

2018年6月29日金曜日

AWS EC2のタグからホスト名を変更したい(AmazonLinux2/CentOS7)

EC2のNameタグについてる名前をHostnameにするコマンドです。
CentOS7及びAmazonLinux2でのコマンドになります
AWSコンソールで名前をつけたあと、実行するといいんじゃないでしょうか

INSTANCEID=`curl -s http://169.254.169.254/latest/meta-data/instance-id/`
Name=`aws ec2 describe-instances --region ap-northeast-1 \
             --instance-ids ${INSTANCEID} \
             --output text \
             --query 'Reservations[].Instances[].Tags[?Key==\`Name\`].[Value]'`
sudo hostnamectl set-hostname ${Name}
hostname

2018年6月28日木曜日

Elastic Load BalancingのCLBとALBは何がちがうのか(TCP的に)

ALB使ってますか!
正直CLBで良いんじゃない…って人、多いと思います!

CLBはL4でALBはL7…とか色々あると思いますが、あまり注目されてないポイントとして「TCP Keepaliveされるか?」というのがあります

[ユーザー]-[ELB]-[APサーバー]

という構成があるとします。

[ELB=CLB]
ユーザーアクセスが終了したあと、ELB-APサーバー間で数秒間TCP Keepaliveされます。正確に言うと「ESTABLISHED」のままになります。これはHTTP/TCPどちらで死活監視しても一緒です。

[ELB=ALB]
ユーザーアクセスが終了したあと、即時に「TIME_WAIT」に移行します。

これによって何が違うのか?というおはなしなのですが、APサーバーがdjangoやrailsのようなアプリケーション・サーバーの場合に非常に困ることになります。

ユーザー通信が終了しているにもかかわらず、そのプロセスがCLBのKeepaliveによって開放されないため、次の通信に即時に使えない状態になります。それが積み重なった結果、APサーバーのプロセスがCLBによって使い潰されます。

要は『ECSのバランサーにCLBを使わないほうがいい』というおはなしです

2017年11月13日月曜日

『Editors' Lounge #11 〜「けものフレンズ」と「DOMMUNE」の編集メソッド』の議事録

概要

平成29年11月11日 13:30〜18:00
御茶ノ水デジタルハリウッド
URL: Editors’ Lounge #11 〜「けものフレンズ」と「DOMMUNE」の編集メソッド

注意

フリートークスタイルで進んでいったので、話の基点からずれていったりしてます。
そういうものだと思ってください

第1部

福原慶匡×福岡俊弘

  • デジハリの大学院生
  • 横浜のDMM VRシアターも手がけている

プロフィール

大学時代 川嶋あいと出会いレコード会社を作った
4年前に家族にショッキングな出来事があって友人宅に転がり込む生活→そこでアニメと出会った
音楽を通じて秋葉原中心にアニメの仕事をしていた
ニコニコ動画を通じてクリエイターと出会い、創作活動を続ける
アニメの作り方を知らなかったので、本を読んだりググったりしてた
ニコニコ動画での活動から日テレから声がかかり、作品をつくることに→手さぐれ部活ものを作成
たつき監督とはTwitterで連絡を取り、コミケで出会った

運が良かったと思うので、「経験を言語化していきたい」と考えている

けものフレンズ

うちでPVを作ったら決まった(要はコンペ)
CGが良かったのは、動物の柄を省略することがなかったこと
演出・表現が良かったのでは無いだろうか
エンディングをちょっとづつ変えるとかの小ネタがすき(監督のアイデアだけど)

プロデューサーと監督との関係は

ヤオヨロズは一人で複数のポストを担当する(原画・動画・編集等)
作業を別人に渡すことが無いので、中間成果物を出力する必要がない
├事務的な手間が省ける
└最終形が見えているので効率が良い

アニメ作成作業は下記3点で遡ることができない

  • お金
  • 時間
  • 仁義

「監督がNGを出し、自分で修正作業する」は問題がない。アジャイルな作り方
本当はこんなことしたくないし、休みたい(笑)
やりたかったというより、この方法しかなかった
客観的にみて良い方法かは、前例が無いので判断できない

シナリオってどうやって精査したの?

普通は本読みを積み重ねて、スタッフ間で意識を共有する

「キャラクタから発信」と「ストーリーから発信」するもので、シナリオ作成のアプローチが変わる
テンプレートストーリーはキャラベースになる(こち亀とか)
ストーリーものはテキストベースだけで完結しがちである。特にゲーム系シナリオとか

アニメシナリオは、映像を足す隙間が重要
要はギャグのリアクションを文章で説明しても、面白さは伝わらない

何を見せるのか?見せないのか?
声優の伸びる声(音)を聞いて、セリフを調整したりもする

ここまでイメージできる人っていないと思う
それをできる人に全権を渡したいと思う

世間の反応について

監督が世捨て人みたいになってたので、世間の人気の実感がなかった
ラッキーパンチは無く、狙ったところにハマった感
ですが、その穴にハマる人が想定より多かった印象
びっくりしているのは監督より、周りの人たちだった

監督がニコニコ動画に自主制作アニメを毎月投稿している
数年続けており、けものフレンズを見る視聴者の反応が前もって予想できていた

視聴環境の変化について

シークバーによって、昔より2度見が簡単になった
ニコニコ動画で、他人の反応を確認しやすくなった

視聴者が「コメントを打ちたいタイミング」で間を作っている
音楽業界ではスピーカーではなくイヤホンで最終マスタリングしている
それと同じように、「ユーザーの視聴環境に合わせたものづくり」をしている

けものフレンズは、メディアやソーシャルに向いていた

  • 自分だけが気がついた(アハ体験)
  • それを共有発信したい(ソーシャルバズ)

監督と視聴者とのインタラクションが発生していた
そういった意味では、「ヤオヨロズが劇場アニメをヒットさせられるか」は課題だと思う

定性的価値と定量的価値

監督が相当先を考えているので、周囲との理解にディレイがある
「理解できていないけど現象が起きている」ので、周囲が納得している状態

一発目のひらめき・アイデアがすごい
たつき監督は元サンライズ

「これからのビッグヒットはこうなっていくのでは?」と考えている(定性的・定量的価値を備えている事)
定量的な価値がないと一般には広がらない(「けものフレンズ第一話1000万回再生!」とか)

例えば「けものフレンズの面白さは?」を他人に説明するのは難しい
「定性的価値を伝える方法」が課題

放送前にはたつき監督しかわかっていない状態
面白さをつたえるのは難しい・言語化できないので、定量的な物言いが重要

ハードの進化は人間の感性以上のものを作ることができず、限界がある
音や映像を良くしていっても、人間の能力に限界がある

商品の価値を高めるには、クリエイターが重要になってくる

ソフトの重要性をわかっているのがクリエイター
クリエイターの価値を伝えていくのがプロデューサー

米国はプロデューサーを育てる環境が充実している
日本はクリエイターは素晴らしいが、プロデューサーがポンコツ

ラブ米

売上はアレだが、IP的価値が高い作品
農林水産省やおにぎり協会、農協がスポンサードしてくれている
舞台やゲーム化も進んでいる
友人のボツゲーム企画がスタート
企画が通った話をエイプリルフールに伝えたので、全然信じてもらえなかった

音楽業界のはなし

水曜日のカンパネラのプロデュースもしている
音楽は色々なメディアにくっつきやすい
音楽の権利は難しい
大学在学中に初めて作ったのが権利会社で、JASRACと交渉したりしていた

アニメは二億五千万くらい制作費がかかる
音楽は制作費が安くなった。発信も簡単になった

音楽業界は映像業界の五年くらい先をいっている印象がある
映像は作るのが大変で、人数も必要
そういったムーブメントの中で、映像を有効活用する流れからYouTuberがうまれたんだと思う

音楽業界はデジタルによって簡単になり、制作コストもどんどん下がっている
ボーカルだけ大変だったが、初音ミクが発生した

デジタル化について

配信も、CDからデジタル配信に移っていった
世界2位の音楽業界なのに、日本はほぼCDの売上
アメリカはほぼ配信しかない
日本は音楽業界でもガラパゴス化が進んでいる

これをアニメに当てはめると、作画部分がデジタル化されていくと思う
今でもアニメ業界は紙文化なので、制作進行がアニメーターの作画を回収する仕事がある
だが、ヤオヨロズには制作進行が居ない

アニメ流通もデジタルに移行しているが、まだテレビで見る文化
フィジカルを借りる部分が多い

便利すぎたがゆえに、デジタルへの移行が進んでいないのでは
もう少しデジタルがすすむと、世界につながりやすくなると思う

テレビを中心にすると、総務省とつながるので著作権管理が楽
放送は免許事業なので、テレビという枠に縛られる

「日本でインターネットで面白いこと」をしづらい状況になっている

放送権利について

テレビ会社は、製作委員会に出資するだけで、テレビ放映権利も主題歌の音楽利用も海外への番組販売も権利を握っている。職権乱用っぷりがひどい。

頑張ったクリエイターにお金が渡る仕組みを作っていきたい
生活のためにやりたくない仕事をすることで、メインの仕事のクオリティが下がる
クリエイターがいい仕事をすることで、業界全体が潤うと考えている

天才に時間と金を与えると、勝手に面白いものをつくる
金があるからサボる人間は、天才ではない

契約は業界慣習がつよい
原盤権とか
(※注:このあたりは音楽権利関係の話が続いたので、割愛)

質疑応答

けものフレンズの今後について

途中報告もしたいのだが、大決定が出るまでは何もできない状況
「どのようにお伝えするか」も込みて協議中
まだ交渉段階なのでお待ちください
自宅前に週刊文春の記者がいてびっくりした

外部の交渉方法については

話し合いながら作っていっただけので、特にロスらしいロスもなかった
元がオリジナルなので、ロスよりも付加される情報が多かった

背景イラストレーターがほしいといった意味は

感性の合うチームを集めると、コミュニケーションロスが減る
時間のあるうちにスタッフを集めておきたいが、固定費が増えるのは悩み

業界の慣習にとらわれなかったのが成功の秘訣?

たまたまはまっただけで、失敗する人もいる

クリエイティブもビジネスもわかるプロデューサーがいないのが問題
会社で別れているのが問題 クリエイティブは制作会社・ビジネスは製作委員会
制作会社がビジネスを勉強していないのも問題だと思う

良いものを作るには

チーム作りが重要
アニメは制作に2年かかる
プロデューサーは、「仕事の割り振り」の責任が大きい
プロジェクトの大きさによって、人を見る目をチェックポイントを変えている

まとめ

けものフレンズは新しいメソッドで作られた
先行者メリットが発生しやすい

海外をみているが、「日本で作っているものが悪い」わけではない
ターゲットの狙い方が問題
バイリンガルよりバイカルチャーが重要
今後人工知能の同時通訳によって、言語の壁が取り払われる可能性がある

第2部

宇川直宏×高橋幸治

DOMMUNEの活動およびカウンターカルチャーについて
画像に対する解説が多いので、議事録はなしで

2017年9月15日金曜日

nintendo switchのLANプレイの注意点

LANプレイしてますか!

要は複数台のnintendo switchを有線LANで繋いで、ローカル通信で快適に遊んじゃお!というものです。Splatoon2だと「観戦モード」という、LANプレイでしか操作できないモードもあるんですよ。

…なのですが、このLANプレイのハマりどころがあります。それは

「無線LANがつながる環境だと、有線LANより優先される」

です。要は「LANプレイをするときは、無線LANにつながらないようにしておきましょうね」ということです。やり方は下記2つ。

  1. 無線LANのパスワードを変更・または削除
  2. 機内モードにする
機内モードにすると、無線でコントローラが繋がらなくなるのでご注意ください。

Switch-Fightstickの注意点

Switch-Fightstick使ってますか!要は「USBジョイスティックのふりをして、Splatoon2のドット打ちを代行してくれる」ってプロジェクトです。

Windows環境でのインストール方法は「Splatoon2で自動ドット打ちしてくれるやつ試した」にて素晴らしくまとまってます。ありがたや

…3つほどハマったポイントがあったのでご紹介しておきます

1・makeが動かない
make: Interrupt/Exception caught (code = 0xc00000fd, addr = 0x4217b3
「make -v」は動くのに、「make」だと上記のエラーを吐いて動かない。これは、makeの参照するPATHの中に「()」等が含まれているとなります。(例:c:\Program Files(x86))

下記2つの注意点を守れば大丈夫です。デフォルトインストールしたなら発生しない問題です。
  1. makeをインストールするフォルダにスペースやカッコを含まない所に入れる
  2. windowsのPATHの先頭に、「makeをインストールしたフォルダ」を追加
参考:
make: Interrupt/Exception caught (code = 0xc00000fd, addr = 0x4217b3 | HDRLab :


2・PILのエラー
ImportError: No module named PIL
このエラーはPythonモジュールが不足で発生します。下記コマンドを入力してください。
pip install image

3・make中にエラー
C:\Program Files\Git\bin\sh.exe: *** Couldn't reserve space for cygwin's heap, Win32 error 0
Windows8以降で発生します。このファイルをダウンロードして、「"C:\WinAVR-20100110\utils\bin\"」に入れてください(デフォルトインストールの場合)

参考:
Arduino Playground - Eclipse

2016年4月6日水曜日

NGINX Luaのshared dictionaryの使用容量を調べたいのまき

nginx lua使ってますか!
worker間でメモリ共有するのに、shared dictionary使いますよね!

こんな感じで定義します
http {
        lua_shared_dict HOGE 30m;
}

…なのですが、これって実際どれくらいメモリ確保すればいいのかわかんないですよね。
ということで、こちらを調べようという話です。agentzh氏が作ってくださったngx-shmを使います。

まずはnginxのworkerのプロセスIDを調べます。masterじゃないですよ、workerですよ!

#ps aux | grep nginx
root     46581  0.0  0.0 103304   856 pts/0    S+   12:50   0:00 grep nginx
root     56272  0.0  0.1 118384 19492 ?        Ss   Mar30   0:00 nginx: master process
nobody   56273  2.2  0.7 215004 125824 ?       S    Mar30 180:48 nginx: worker process
nobody   56274  2.2  0.6 191208 102056 ?       S    Mar30 182:14 nginx: worker process
nobody   56276  2.2  0.6 195812 106524 ?       S    Mar30 181:37 nginx: worker process
この場合56273ということがわかりましたので、このPIDをngx-shmに渡します。こんな感じです
#./ngx-shm -p 56273
Tracing 56273 (/usr/local/openresty/nginx/sbin/nginx)...

shm zone "HOGE"
    owner: ngx_http_lua_shdict
    total size: 3072 KB

Use the -n <zone> option to see more details about each zone. 30 microseconds elapsed in the probe.
これだと確保容量だけしかわからないので、メモリ使用量の詳細を調べます
#./ngx-shm -p 56273 -n HOGE
Tracing 56273 (/usr/local/openresty/nginx/sbin/nginx)...

shm zone "HOGE"
    owner: ngx_http_lua_shdict
    total size: 30720 KB
    free pages: 27912 KB (6978 pages, 176 blocks)

32 microseconds elapsed in the probe handler.
これが調べたかった結果です!メモリ確保しすぎですね!

2015年8月1日土曜日

pebble timeを買ってはいけない理由(を無理やり考える)のまき

pebble timeが一般発売されましたね!
早速購入してみましたので、pebble watchと比較したレビューをしようかな!と思います。

Pebble watchのレビューはこちら⇒
Need for Answer: あえてこのタイミングでPEBBLE WATCHをつかってみたのまき

公式のWebで購入して到着までの期間は、11日でした。だいたい2週間をみればいいんじゃないかと思います。受け取り時の注意なのですが、pebble timeは関税(1200円)がかかります。用意しておきましょう。

ということでパッケージ!kickstarter版とは異なりますね!


バンドを比較すると、止め輪が2つになってたり、エッジが微妙に異なってますね!

バネ棒は22mmで前作と変わりません。バネ棒がバンドから外せないので、バンド交換するときはバネ棒を調達する必要があります。



背面!充電端子が背面になりました。


ということでやっとタイトルの話をします。

下の方に微妙な点を並べてみましたが、私はそんな気にしてないのでマイナスと考えてなかったりします。気になる人もいるかと思いますので。

まず、pebble timeはpebble watchよりも画面が暗いです。特に待機時の画面が暗い&液晶がガラスの奥にあるので、周りが暗くなるとそうとうみえづらいです。

まぁシェイクすれば画面が明るくなるんで、そんなに支障はないですが。


充電端子が背面です。普通に使ってると問題ないのですが、背面を遮るバンドを使っているとこんな感じになります。めんどい。


といっても充電は5~7日間隔で十分なので、そこまでストレスじゃないです。


あと微妙にどうでもいい変更点として、watch face変更がめんどくさくなりました。『盤面をコロコロ切り替えてた』という人は、ストレスなんじゃないかと思います。まぁボタンの上下が過去未来のタイムラインに割り当てられたので、しょうがない話ですね。

あとは『現時点(2015年8月現在)ではiOSしかもってないと日本語フォント適用できない』とかめんどくさいこともあるのですが…。


ということで色々書いてみたのですが、pebble timeでカレンダー連携がすごく良くなったので、微妙な不満点を完全に払拭できると思います。

安い買い物とは思いませんが、スマートフォンを便利にする投資としてはいいんじゃないかなーと思います!

2015年7月4日土曜日

nginx_luaでhtmlを書き換えたい!のまき

レスポンスボディ、書き換えてますか!

…唐突ですが、OSSとか使ってるとちょっとした修正、加えたいってあると思うんですよ。

パッチ当てるのも面倒くさいなーという時、「リバースプロキシでレスポンスボディを書き換えてしまう」という方法もありますよーという話です。実現する選択肢は色々あるのですが、今回はnginx_luaで実現しました。

やってることは、「nginxでリバースプロキシしたhttp_bodyを、luaスクリプトで書き換え」という感じです。こんなかんじで設定すれば、Apacheで動いてるAPサーバーをSPDY対応させつつ書き換えられますね!

 server {
    listen 443 ssl spdy;

    ssl on;

    ssl_certificate your_server.crt;
    ssl_certificate_key your_server.key;

    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    add_header Alternate-Protocol 443:npn-spdy/3;
    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";

    location / {
      proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto https;


      proxy_pass http://localhost:80;

        body_filter_by_lua
        '
        replacestr = "$1http://www.google.com/url?q=$2"
        ngx.arg[1] = ngx.re.gsub(ngx.arg[1],"(href=\\")(https?.*?\\")", replacestr)
        ';
    }
 }


2015年6月19日金曜日

golangでHTTPのbodyを読み捨てたい!…のまき

golang書いてる人だったら、httpリクエストをひたすら繰り返すアタックツール、書きますよね!

…ということでソースをそのまま公開すると「アタックを繰り返すプログラムを公開し続けるだけのヤンチャなプログラマー」になっちゃうので、その際学んだことを書こうかな?というお話。

http接続処理のとこだけ抜粋するんですが、重要なのは「バッファ読み捨て」というところです。

なんでここが重要なの?という話なのですが、バッファを読み捨てないと「http接続が完了する前に、Client側でTCP接続を切断しちゃうから」なのです!

ちなみにバッファ読み捨ての行をコメントアウトしても、レスポンスコードは取得できたりします。

…なんでかはioutilのソースを読むといいんじゃないかなーと思います!

// HTTP接続
func httpRequest(tr *http.Transport) {

        // HTTP接続
        client := &http.Client{Transport: tr}
        r, err := client.Get(url)

        if err != nil {
                fmt.Println(err)
                return
        }

        // Body Close処理
        defer r.Body.Close()

        // バッファ読み捨て
        io.Copy(ioutil.Discard, r.Body)

        // レスポンスコード
        response := r.StatusCode
        fmt.Println(response)

}

2015年6月17日水曜日

golangでfluentdのストレステストツールを書きましたのまき

fluent-attacker-rpsという、Fluentdサーバーに負荷をかけるツールを作りました!fluentdサーバーにいっぱいデータ登録したいときに使って下さい!

…というと2行でお話終わっちゃうので、一応使い方とか説明しようかなーと。

go run fluent-attacker-rps.go -h 192.168.0.1

という感じで実行すると、こんな出力がされます。

=====================================
Insert Keys=> 3000 RPS Set => 300 Message Length => 1000
=====================================
0 loop - TaskSet Done.
300 loop - TaskSet Done.
600 loop - TaskSet Done.
900 loop - TaskSet Done.
1200 loop - TaskSet Done.
1500 loop - TaskSet Done.
1800 loop - TaskSet Done.
2100 loop - TaskSet Done.
2400 loop - TaskSet Done.
2700 loop - TaskSet Done.
3000 Task - All Job Done.
=====================================
Exec Time => 10.389512Sec Real RPS => 288.752743rps(96.250914%)
=====================================

終わりましたね!fluentdサーバーにどんなデータが来ているかといいますと、こんな感じです!
2015-06-17T11:48:19+09:00       test.tag        {"ID":"0","md5":"1cea7c2ef3b6019d774fd46a90ef127b","strings":"zrv5xl4igns0qvm6rdki5jq5qrq6wfko3gahmk41idbh5udjk6hvus3wjw1659x51fu7oe6xfc6c163s6ee7stunspm2drdcaap4mgk0khexs17chdg5hjzx4u15h7hc5ui3i256hfon1i294fh9e3dlatpfeks5o8b8lyj8lgp7oqzmsyme94qc88btpahp51ua5lbzt606p76lnxmpj7y7z0hmcb0oic8fmm0km0zg97ag4orm4scql1qvgp5b2av0o8om5k2bc5wpdutvgb22n2alf0e4tf7v42v0h9rd20ye2y3lkj5cczegurle8socvwlz9wjg7379b37w1958kpryai16yqjgxno39g7u3i1xky4oqaeuhmr2aeu0of5yhabakwgrp94oxtjlhncof5lqasudwgvmkdzh75jwia2milduhy05tf0cszg99kqoqixwpu2bsuy4vqaopu1e5x9f9ba5bsvz31a4zzt97ybs92taaalqvp4y9bsrjhc0fxwxxmdd9a89e6hldttqap08za7xmcuq8a2bvczmg1n21t0do78qeg0c79as2tpujxwyrraxijjhjsnap1kfh702jkrjlqv8v6ik6u2ys7z2b5xhh66jhtx9fnj571igv8yedtosb050omt6h62rcyaibk4gcuj6iez2g70kol9zrfiwow7o17467qrf14wwxoskavqw0t64azei1kbzsm5uncb3nspwb6tyjmyopef6yprxbvtylsx18h34rw2x3v69dh3eqv28jc1z2pnny8qgrjle5fdn2pvjuby9197f3kr3f6r031j651zb9egbqtqzgncvim02i33wbs20msvrmt1cldkwkd7qhac39e6u0hoes0e6yh9g24idnclqkwx72vbrdb5ziu425qm58j6e8rcs9nyqyevb33idwhvruhna2wo7pgkqnwgyfkv6n0laavw09t06lo1pc0s82gxexgfznroazqlc"}
2015-06-17T11:48:19+09:00       test.tag        {"strings":"j4t29f6dyejou4h320ggfxi7u4f4kzr3kzxv9u852pzqw8ft238fdqmr42eha0g826nn2vyu79n2wmjtuj17lc1n0jpbqw8bnpcie3csc34ixkiaeuy6n1xczg3uvk11h1lh3kd005xepund2bz2xpj0fha4c4h3acqxvns5x7p6wtes87trldkn8ze51qhhzrql41kx1sxcg4m6aidc406qldco4d6g6k8enbk6oblmyb6v9txdq6aigpn13thgnshi0c5yremnrw2l7bbee8jccqqvpwe035ov8oqk84xzsr2wg1kzgj4xiudg1zxajdn4q661hy4qh6f8bfqa9v4nedn2c1x5nsinkgsr3zw8t6hzdl0bxapt0aysf0qap6ak7x1k2ec09ucxz98u59yjx7b49l5tv7x8xde9bm8e503ayl51ojtmgapu5227mucnlqyr4v78xvvdta85z3160a06my9ndhmyrlboghl025cqda74dpfrbuxjguu2eamhujzeimfpcd91as0fbxj31conls96yby622i9le6cnoj54vjdstj75cg6mksguush2hg39kjs75j1nd46jjyuioxlz8cesedc00i2zg8apipzodmosp69eo0alxkxkr3xnz0u9n9hcbyan3wywiu8efr729y73afwerc8yji8ioaxivs71d3143tzk02b7toaea4j7bdz2snmqrodjtabvnwe5l90ivxl8oflae4cvkiafcvkwwi4nlh3vw98os4ftskbgvj7b6he2rtags1isqh1fszd9379upustge9gvp8pgl25gcw7xu2lre6jkx11i306gckvf5k8m6mr4iufbax80m25zyyjlac7tlty4mg24t1h7pacwo7tzf3s4vtubi7aisupo30x1w3yjlmlxiojz5ckmsp1sppntm173uqi9fw6kydxfikyzpd0iaa3sctuqigemjwq72skxsbwjhrzj8q391wjslw","ID":"1","md5":"93464e057d8babe65f77801432dc27fe"}
2015-06-17T11:48:19+09:00       test.tag        {"ID":"2","md5":"d4a115141322905aa3e21dc8ea91349c","strings":"8x0pwax2q60gbdlzbe0hq7zp5w57zt03g6qq0y6a7g9x6a9wzhjmhxx30hjtbok4wnlxgczusrenbtwbyus89ihz1czpbr75g1djbmdbfoq6c6me5xrh3w5t01bfkrccw0kiharjc1c3rb73g74d7mkvjxqk0htgkrkrr23innjjdzybn4l5q4g62d8vfpbk6reycp22jv1aavza6z8egcrh8jboewllr5dvvif8tiouqil0ncvkzpugp3s4hakzvob1b1t83lf97adwuh5177vcu54ek816vslydwqkvhseblxzpf7lwjn5te9p0t4zgoy3txhn9paswxce6rp6f8ozrldxcc0sv96o5kn1s2z6negjc12s11406z0fxpa01ybhqxtovmmiix867x8ebfoi86lcp4upo6xplwpj0kvzhaiq1o6yo2z0gh9fd6z5od0201yy6c9hk5b9eflcv72kd8wg2sric04vl43o0kv0yc3hmc4v4xcgnra0iqreipdu0fiop2je5xl8npg3gryqv27504vvu5lrtimyxhy6sqjazrrz19od263tl4mbwqlvxx0dlb7unr3563p01symis6p2pc8pkyuhgs0zb9q4lukvdqnnk2uqu42dl488drbvhs7iypxkgqxk049n5ofuj42fik7v7mmanwliw4bdei6a2q5hw1ws9kn9sl9h74dg264gtmh2ybvl0xpk0dcgxdun0ksz0aa5uoruswt49v2xs3iaf7edl3jju0u7a4cq1v8ocrb1k4hxqdninhjuxha9kdztkx2uzxiec56fpqyf66m519vnv11dff0s3rnn5f2o72amhyybl5mf5yv3bx185usi4re6rpq0sasf2dem6rb99zk9fgg2gpqrxzarm810si24bfoear4iuey45b4dqfk4p0thyypc5ii2o19a107uthif4tr0qlad44atr9xaw0nq7ehpkhawl6sy06thl6084ri13us"}

RPSとか投稿数とか調整できますので、「fluentdサーバーのスペック決めるのどーすんだろ?」とか「ログがロストしてないんだろか?」とか実験するといいんじゃないかなーと思います!

追記)念のため言っておきますが、Newで作った接続を使いまわしていないのは「大量のTCP接続来たらどうなるのかなー?」という試験のためです!アホの子をみるような目でソースを見るのはやめてね!

2015年6月12日金曜日

golangでRPSをそれなりっぽく実装するのまき

golang書いている4割位の人が悩む問題として、「RPS(Requests Per Second)をどうやって実装するか?」があると思います。…多分。

ということでこんなかんじで実装しましたよ、というお話。
ちなみにコードのほとんどはmattn氏のBig Sky :: Golang の channel の使い所 : の引用です。

以下サンプルコード。

// RPSから間隔を計算
func calcInt(x int) int64 {
        return int64(1 / float64(x) *1000 *1000)
}

func main() {
    // Channel宣言
    task := make(chan int)        // TaskQue用
    taskquit := make(chan bool)   // SetTask停止用
    workerquit := make(chan bool) // JobWorker停止用

    // WaitGroup作成
    wg := &sync.WaitGroup{}

    // Job Worker
    go func() {
    loop:
        for {
            select {
            case <-taskquit:
                workerquit <- true
                break loop
            case job := <-task:
                wg.Add(1)
                なんかの処理(job)
                wg.Done()
            }
        }
    }()

    // SetTask Worker
    go func() {

        // RPS間隔計算
        interval := calcInt(rps)
        sleepWait := time.Duration(interval) * time.Microsecond

        for i := 0; i < key; i++ {
            task <- i
            time.Sleep(sleepWait)

            // Log Print
            if i%rps == 0 {
                fmt.Printf("%d loop - TaskSet Done.\n",i)
            }
        }
        taskquit <- true
    }()

    // WaitGroup終了まで待つ
    wg.Wait()

    <-workerquit
}

2015年6月4日木曜日

ErastiCache for RedisでFailOverが発生すると何がおこるのか?のまき

これからタイトルどおりのお話をするのですが、Multi-AZ構成を取っていたとしても何がおこるか知らない人多いんじゃないでしょうか?AWSのドキュメント見ても、挙動の記載が無いのです。

結論から言うと、2パターンあります。
  1. Read Replicaがprimaryに昇格し、旧primaryはread replicaとして同期
  2. 自身の持っているイメージからデータを復元(read Replicaが使えない場合)
1から説明しますと、Multi-AZのRead Replicaが存在する場合は素直に切り替わります。これはDNSで切り替わるため、Primary Endpointに紐付いたNodeが、新しいprimaryに切り替わリます。その際、降格したread replicaはデータが空の状態で同期を開始します。

問題は2です。primaryがread replicaに降格するのですが、そのタイミングでデータをローカルにバックアップします。正確に言うと、こんなかんじの流れです。
  1. 障害検知したタイミングで、データをローカルにバックアップ
  2. 再起動
  3. データが空の状態でredisが起動
  4. 新primaryに問題ない場合はread replicaとして起動し、primaryからデータ同期
  5. 新primaryに問題がある場合はprimaryとして起動し、1.からデータを復元
何が問題か?という話なのですが、1~5の間は『read,writeがロックされた状態』になります。つまり長時間redisにアクセス出来ない状態になります。

…大変っすね!


2015年5月28日木曜日

New ReicのScalability analysisって何?

New Relic使ってますか!

というか、New Relicの「REPORTS」項目、見てますか!
今回はその中の、「Scalability analysis」について解説しようかな、というお話。

…「Scalability analysis」とは、読んでそのままの意味でスケーラビリティ分析をしてくれるものです。つまり「インフラがボトルネックになっているか?」がわかるのです!すごい!

では、読み方。2つのキャプチャを見てみましょう。




このグラフから何を読みとくか?というと、「rpm(Requests Per Minutes)が上昇しても、応答速度にムラが無いか?」です。横軸がrpm、縦軸が平均応答速度です。「右端のカラーチャート」と「グラフ内の点」を照らし合わせると、「いつのアクセスなのか?」がわかります。つまり何時頃にはどれくらいのrpmだったのか?がわかります。

そもそもの話ですが、rpmはユーザーアクセス数に比例します。具体的には「夜中は少なく、昼は多い」ということになります。こういった時刻ごとの変化も一目瞭然ですね。

さて「rpmが上昇」ということは、「1台のサーバーで対応するユーザー数が上昇」ということです。…ということは「インフラリソースが不足すると、応答速度が遅くなる」と考えられます。逆に考えると、「応答速度が安定しているということは、インフラリソースは充足している」事になります。

ということで結論としては、「線グラフが水平」「点が集中して上下の幅が少ない」というのが、インフラリソースが充足しているいい感じ、になります。

右肩上がりや、点がバラバラになっている場合は、どこかにボトルネックがあるという事ですね。

2015年5月23日土曜日

golangでredisに超大量にデータを入れ続けるプログラムを書きましたのまき

件名通りなのですが、redisにダミーデータを入れ続けるだけのgolangプログラムを書きました!
みんなもつかってね!

…なーんてプログラム使う人居ないと思うので、書いてた時に学んだことを共有しようかなというお話。


■コンソール出力すると極端に遅くなる
golangが早いのはご存知なことだと思うのですが、思ったよりコンソール出力が遅いです。
超大量データを処理する際、毎行ログ出力するのは無駄が多いです。

100行に一回出力とか間引きした方がいいですよ、ということですね。


■Network I/Oはコネクションプーリング等の工夫が必要
処理が早いということで、CPU以外の部分にもボトルネックが来る可能性があります。
redisへのアクセスを毎回切断していたら、あっという間にTCP接続を使い切ってしまいました。

コネクションを使いまわす、を早い段階で考えたほうがいいですね。


■ifでgoroutineを呼び出すときに、ループ数が極端に多いと落ちる
goroutineはループに入る前にスレッド(みたいなもの)を事前に用意するっぽいです。10万ループとかをgoroutineで非同期化すると、「signal: killed」で落ちます。

…ということでどうするかという話なのですが、「gorc」いうパッケージを使うと回避できます。goroutineの同時並列実行数に制限がかけられるため、リソースを使い切るのが回避できます。すごい。

※追記)sync.Poolとかsync.Cond使うとsyncでもスロットル制御出来る気がします!書いたこと無いけど!


package main

import (
  "crypto/md5"
  "crypto/rand"
  "encoding/hex"
  "flag"
  "fmt"
  "github.com/garyburd/redigo/redis"
  "github.com/mr51m0n/gorc"
  "math/big"
  "runtime"
  "strconv"
  "time"
)

var (
  pool *redis.Pool
  host string = "localhost:6379" // redis-server接続情報
  key int = 150000 // 投入するKEYの数
  val int = 10000 // 文字列の長さ
)

// redis ConnectionPooling
func newPool(server string) *redis.Pool {
  return &redis.Pool{

    MaxIdle: 3,
    IdleTimeout: 240 * time.Second,

    Dial: func() (redis.Conn, error) {
      c, err := redis.Dial("tcp", server)

      if err != nil {
      return nil, err
    }
    return c, err
  },

  TestOnBorrow: func(c redis.Conn, t time.Time) error {
    _, err := c.Do("PING")
    return err
    },
  }
}


// val用にrandomな文字列を生成する
func random(length int) string {
  const base = 36
  size := big.NewInt(base)
  n := make([]byte, length)
  for i, _ := range n {
    c, _ := rand.Int(rand.Reader, size)
    n[i] = strconv.FormatInt(c.Int64(), base)[0]
  }
  return string(n)
}


// gorc
var gorc0 gorc.Gorc


// メイン処理
func main() {
  runtime.GOMAXPROCS(runtime.NumCPU())

  flag.Parse()

  // Timer Set
  start := time.Now()

  // redis Pooling Start
  pool = newPool(host)

  // Redis DataInsert
  for i := 0; i < key; i++ {
    gorc0.Inc()
    go setredis(i, val)

    gorc0.WaitLow(100)
  }


  // Log Print
  fmt.Print(key)
  fmt.Printf("Keys - Set Done.\n")

  // Timer Print
  end := time.Now()
  fmt.Printf("%f秒\n", (end.Sub(start)).Seconds())
}


// stringからmd5から作る
func GetMD5Hash(text string) string {
  hash := md5.Sum([]byte(text))
  return hex.EncodeToString(hash[:])
}


func init() {
  gorc0.Init()
}


// redisにデータを投入するだけの処理
func setredis(k, v int) {

  c := pool.Get()
  defer c.Close()
  defer gorc0.Dec()


  vals := random(v)
  keys := GetMD5Hash(vals)


  c.Do("SET", keys, vals)


  // 100処理ごとにログ表示(非同期なので順番が適当)
  if k%100 == 0 {
    fmt.Print(k)
    fmt.Printf("Keys - Set Done.\n")
  }
}

2015年5月4日月曜日

koboのKoboReader.sqliteをメンテナンスするのまき

電子書籍リーダのkobo使ってますか!
長期間使っていると不安定になりますよね!

…というのは、書籍データの中身をsqliteというファイルに保存しているのですが、『電子書籍データを読み込む度に肥大化し続ける』という困った設計になってます。

今回のお話は、このファイルをシェイプアップする方法です。
Windowsの『PupSQLite .NET Framework4』というソフトを使います。

まずkoboデバイスの「.kobo/KoboReader.sqlite」というファイルを一旦HDDにコピーします。
PupSQLiteに先ほどのKoboReader.sqliteを読み込ませます。

するとこんな画面が出ますので「SQL入力」を押して、タブをオープンします。


さて、ここからはSQLを使います。
『ウィンドウに下のSQLを入力して、稲妻ボタンを押す』という流れです。



件数を確認してみましょう。
select count(*) from content ;
select count(*) from content where ___UserID='cbz_user';

多分すごい数字(数千~数万)が出てきたと思うので、レコードの削除をします!
delete from content where ___UserID='cbz_user';

先ほどのSQLをもう一度流してみましょう。成功していればレコード数が減少しているはずです。
select count(*) from content ;
select count(*) from content where ___UserID='cbz_user';

レコード数は減ったので、膨れ上がったファイルをシェイプアップします。画面上にある「最適化」ボタンを押してください。見た目には変わらないのですが、ファイルサイズが縮小されます。


これでPupSQLiteでの作業は終了です。

あとはkoboの.koboディレクトリにKoboReader.sqliteを書き戻してあげれば作業完了です。

2015年4月23日木曜日

freeboardで華麗にダッシュボードるのまき

いきなりですがダッシュボード作ってますか!KPIとか表示したくないですか!

RubyですとDashingとかあると思うですが、運用つらいです!(ダッシュボード作ってみるとわかるんじゃないかな)

ということで今回オススメするのがfreeboardです。利点は「ブラウザのみで動くので、サーバーが不要」という一言につきます。あとGUIベースで気軽に編集できるとこですかね。

もう少し詳しく説明しますと、freeboardは「HTML+Ajaxで動く静的ページ」です。つまり『freeboardのソースをPCのローカルに置けば、ブラウザが外部データソースを定期的に取得する』という事です。簡単に図解。


ということで「外部データソースを作るだけでダッシュボード作り放題だぜ!」というのがこの話で訴えたいことなのですが、一つ注意する事があります。

それは「外部データソースが出力するレスポンスヘッダにAccess-Control-Allow-Origin:*がないとデータ取得できない」ということです。なんで?と言われますとAjaxの決まりだからとしか言い様がないのですが…。

これさえ気をつければ気軽にデータソースサーバー作れますね!

あえてこのタイミングでPEBBLE WATCHをつかってみたのまき

さて、2015年4月24日といえばAppleWatchの発売日ですね。これでAndroid WearとApple Watchと、スマートウォッチデバイスが揃ったわけですね。

…という2大巨頭の間で、Samsung GearやらSmartWatch(SONY)やらという独自規格が乱立している中で「PEBBLE WATCH」という商品があるのをご存知でしょうか?

実はこの製品は2013年から出荷されているのですが、思ったより話題になってない(気がする)ので紹介してみようかなと。




特徴はこんな感じです。
  • 安い(99USD/送料込)
  • Android、iOS対応
  • 電池が7日間持つ
  • 電子ペーパー採用で、太陽光下でも問題なく閲覧できる
  • 日本語対応(Cryingneko氏のご対応)
  • 防水なので、手洗いや雨など気にしなくていい
  • バイブ、ジャイロセンサーを備えている
  • モノクロ

…という感じで、スマートウォッチとして必要最低限機能を揃えていると思います。スペック紹介おしまい。

実際使ってみた感想としては、『スマートフォン通知を手元で確認できるのは、想像以上に便利』という一言につきます。

『手元のバイブで通知を見逃すことが無い』というのはセールスポイントだと思うのですが、なにより『その通知に反応するべきかどうか』を即座に判断できるのが、ストレスが溜まらないことに気がついたのです。

つまり『通知が来たからスマホを取り出す』『気がついてないかもしれないからスマホを確認する』という、『漠然とした面倒さ』から開放されるんです。

満員電車内とか読書中・PC操作中などのちょっと手が放せない状況で非常に有効ですし、スマートフォンをかばんにいれている人とかも便利に使えるんじゃないかなーと。

正直な話Android WearでもApple Watchでもいいと思うのですが、『ちょっとお試しで使ってみたい』という気軽さで購入できるのがPebble Watchのいいところなんじゃないかな―と思います。

2015年4月17日金曜日

json_rest_serveを公開しましたのまき

GItHUB => json_rest_server

オンメモリKVSサーバーが欲しくなって、コード書きました。
特徴としてはこんな感じです。
  • golang
  • HTTP REST APIなので、クライアントはcurlとかでも大丈夫
  • オンメモリで高速動作
  • スレッドセーフ
  • 一応管理機能もついてる
と、機能を限定してる感じですね。

…で、これで何がしたかったの?という話なのですが、fluentdのデータをダッシュボードで可視化する時のストレージにしたかった、ということなのです。べんり。


2015年4月13日月曜日

fluent-plugin-in_http_healthcheckをリリースしましたのまき

Rubygems => fluent-plugin-in_http_healthcheck
GitHUB => fluent-plugin-in_http_healthcheck

『HTTPリクエストに対し、HTTPステータスコード200を返すだけ』のfluentdプラグインを作りました!

ELBとかGoogle Cloud Computingのロードバランサー配下に、fluentd配置したいとき使うといいんじゃないかな―と思います!というかそれ以外使い道あるんでしょうか!

…ということで一応解説しますと、fluentd標準の『in_http』プラグインは『jsonまたはmessagepack』以外のデータが投稿されるとエラーを返すのですね。なので、L7レイヤーでサービス監視しているロードバランサーには、何らかの応答(status:200)をする必要があるのです。

ということで、『fluentdとしてはなんのデータも処理しないプラグイン』が必要ということでした。