2013年1月4日金曜日

Node.js:Apache ThriftでTwitter

Apache Thriftを使ってNode.js用のTwitter APIを作成します。
引用元はこちら

1.Thriftのインストール

今回、環境はMacなので、homebrewを使ってインストールします。
$ brew install thrift
==> Installing thrift dependency: boost
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/boost-1.49.0.lion.bottle.tar.gz
######################################################################## 100.0%
==> Pouring boost-1.49.0.lion.bottle.tar.gz
/usr/local/Cellar/boost/1.49.0: 9053 files, 226M
==> Installing thrift
==> Downloading http://www.apache.org/dyn/closer.cgi?path=thrift/0.8.0/thrift-0.8.0.tar.gz
==> Best Mirror http://ftp.meisei-u.ac.jp/mirror/apache/dist/thrift/0.8.0/thrift-0.8.0.tar.gz
######################################################################## 100.0%
==> ./configure --disable-debug --prefix=/usr/local/Cellar/thrift/0.8.0 --libdir=/usr/local/Cellar/thrift/0.8.0/lib --without-haskell --without-java --without-python --without-ruby --without-pe
==> make
==> make install
==> Caveats
Most language bindings were not installed. You may like to do the
following:

    gem install thrift
    easy_install thrift

If anyone figures out the steps to reliably build a set of bindings, please
open a pull request.
==> Summary
/usr/local/Cellar/thrift/0.8.0: 72 files, 5.3M, built in 3.0 minutes

2.thriftファイル作成

自動生成に必要なthriftファイルを新規作成します。
ファイル名をtweet.thriftとします。
struct Tweet {
    1: string text,             // 本文
    2: optional i32 id,         // ユニークなID
    3: optional i32 created_at  // 投稿日時(UNIXタイム)
}

service TweetService {
    i32 post(1: Tweet tweet),
    Tweet get(1: i32 id)
}

3.定義ファイルからコードを生成

Thriftを使って定義ファイルからコードを生成します。
公式ドキュメントには下記形式でジェネレートするよう書かれています。
thrift --gen <language> <Thrift filename>

言語はNode.jsで、先程のthriftファイルを指定します。
$ thrift --gen js:node tweet.thrift

gen-nodejsディレクトリ配下にTweetService.jsとtweet_type.jsというファイルが生成されました。
$ tree gen-nodejs
gen-nodejs
├── TweetService.js
└── tweet_types.js

0 directories, 2 files

4.Node.js用のThriftモジュールインストール

npmコマンドからインストールします。
$ npm install thrift
npm WARN package.json node@0.0.0 No README.md file found!
npm http GET https://registry.npmjs.org/thrift
npm http 200 https://registry.npmjs.org/thrift
npm http GET https://registry.npmjs.org/thrift/-/thrift-0.7.0.tgz
npm http 200 https://registry.npmjs.org/thrift/-/thrift-0.7.0.tgz
thrift@0.7.0 ../../../node_modules/thrift

5.サーバー実装

server.jsというファイル名にします。
var thrift = require('thrift');

var TweetService = require('./gen-nodejs/TweetService');

// Tweet ID
var id = 0;
// Tweet ストレージ
var tweets = {};

// Thrift サーバーの生成
var server = thrift.createServer(TweetService, {
    // post コールバック
    post: function(tweet, result) {
        // Tweet IDを生成
        tweet.id = ++id;
        // created_at を UNIX タイムから生成
        tweet.created_at = parseInt(new Date() / 1000);
        // Tweet を保存
        tweets[tweet.id] = tweet;

        console.log("[Post]", tweet);
        result(tweet.id);
    },

    // get コールバック
    get: function(id, result) {
        console.log("[Get]", id);
        result(tweets[id]);
    }
});

// Thrift サーバーを起動
server.listen(8888);

6.クライアント実装

client.jsというファイル名にします。
var thrift = require('thrift');

var TweetService = require('./gen-nodejs/TweetService'),
    Tweet        = require('./gen-nodejs/tweet_types').Tweet;

// Thrift サーバーに接続
var connection = thrift.createConnection('localhost', 8888);
connection.on("error", function(err) {
    console.error(err);
});

// クライアントを生成
var client = thrift.createClient(TweetService, connection);

// Tweet を生成
var tweet = new Tweet({ text: "<3 Node.js!" });

// Tweet を投稿
client.post(tweet, function(err, id) {
    // エラー処理
    if(err) {
        return console.error(err);
    }

    // Tweet ID を表示
    console.log("[Post]", id);

    // Tweet を取得
    client.get(id, function(err, posted_tweet) {
        // エラー処理
        if(err) {
            return console.error(err);
        }

        // 投稿済み Tweet を表示
        console.log("[Get]", posted_tweet);
        // 接続を解除
        connection.end();
    });
});

7.実行

①サーバー起動
②クライアント実行
の順に実行します。
$ node server.js > server.log &
[1] 53557
$ node client.js 
{Post} 1
{Get} { text: '<3 Node.js!', id: 1, created_at: 1357202427 }

Tweetが投稿され、Tweet情報が出力されました。

2012年3月28日水曜日

Java/リフレクションメモ その1


対象クラスの全てのフィールド(privateを除く)名称と値を取得して、Mapリストに詰めて返却する機能。

* 利用側

List<Map<String, Text>> testMapList = LogText.getFieldsMapList();
if (testMapList == null) {
 return;
}

MapReduce mapReduce = new MapReduce();
int index = 1;

for (Map<String, Text> map : testMapList) {
 String fieldName = TestUtil.getCutSquareBracketKeyString(map);
 Text text = (Text) map.get(fieldName);
 
 try {
  mapReduce.map(null, text, null, null);
 } catch (Exception e) {
  e.printStackTrace();
 }
}
* API

public static List<Map<String, Text>> getFieldsMapList() throws Exception {
 Field[] fields = TestLogText.class.getDeclaredFields();
 List<Map<String, Text>> textLinkedList = new LinkedList<Map<String, Text>>();
 for (Field field : fields) {
  HashMap<String, Text> map = new HashMap<String, Text>();
  Text text = new Text(field.get(field.getName()).toString());
  map.put(field.getName(), text);
  textLinkedList.add(map);
 }
 return textLinkedList;
}

2012年2月7日火曜日

Linux CentOS 5.4でPHPインストール

PHPバージョンは5.3.10
 wget http://jp2.php.net/get/php-5.3.10.tar.gz/from/jp.php.net/mirror
 tar xvzf php-5.3.10.tar.gz
 cd php-5.3.10/

configure実行。非常に多くのオプションがあるので、詳細については./configures --helpを参照。
 ./configure --with-apxs2 --enable-mbstring --enable-zend-multibyte --with-mysql
--with-apxsでApacheに組み込む。

apxs2やmysqlにパスが通っていない場合はフルパス指定, 64bitの場合は--with-libdir=lib64を指定する。
 ./configure --with-apxs2=/usr/local/apache2/bin/apxs --enable-mbstring --with-zlib-dir=/usr/lib --enable-zend-multibyte --with-mysql=/usr/local --with-libdir=lib64

最後に下記MSGが表示されればOK
 Thank you for using PHP.

make実行
 make
 configure: error: xml2-config not found. Please check your libxml2 installation.
と表示されたので、libxml2-devel をインストール
 yum install libxml2-devel

改めて
 make

make testでコンパイルしたものが実行可能か確認する。
 make test

rootユーザにて、make install実行
 make install

php.ini-developmentを移動する。
※php.ini-productionは運用系のファイル
 [root php-5.3.10]# cp -p php.ini-development /usr/local/lib/php.ini

httpd-confに"AddType"がある部分に追加する。
 AddType application/x-httpd-php .php

Apache再起動
 /etc/rc.d/init.d/httpd restart

phpファイル配置
 /usr/local/apache2/htdocs/pigg/phpinfo.php
 <?php
     phpinfo();
 ?>

"hostsで設定したドメイン/phpinfo.php"にアクセスして、PHPの情報が表示されればOK.
 http://dev.pigg.ameba.jp/phpinfo.php

2011年11月12日土曜日

Linuxメモ その2


updatedb
ファイル名やコマンド名を格納した"slocate.db"というデータベースを作成する。
パスを度忘れした場合に便利。findだとデフォルトが配下の検索となり利便性にかける。
※ただし、findは検索にワイルドカードを利用できるため、状況に応じて使い分けること。

データベースは下記クーロン(パスは環境により異なる)により1日に1回定期的に更新されるが、マシンが常時起動中でないと正しく更新されないケースがあるため、新しく機能をインストールした場合は再度実行したほうがよい。
 /etc/cron.daily/slocate.cron

尚、updatedbコマンドはサーバ内のすべてのファイルをチェックするため、サーバの容量が多くなればなるほど時間がかかるため、下記の通りバックグラウンドで実行するか、

 updatedb &

インデックスする必要のないファイル・ディレクトリを除外するとよい。
 updatedb -e "【除外するディレクトリ】"
 updatedb -e "/tmp,/var/tmp,/usr/tmp"

locate
 locate [filename or directoryname]
前述のデータベース生成後、指定したファイル名 or ディレクトリ名で検索する。
※もちろん、"find / -name [ファイル名]"でも全検索は可能だが、locateのほうが高速。

2011年11月1日火曜日

DeNA松信氏講演 MySQL MHA説明会(2011/09/13)

標題の通り、DeNAの「MySQLスペシャリスト Oracle ACE Director」の松信嘉範氏の講演を聞いた。

★オープンソースMySQL MHA(http://code.google.com/p/mysql-master-ha)について
 ・MHAはMobageの150系統を超えるマスター・スレーブペア環境に導入されている。
  滅多にクラッシュすることはないが、OSやH/W障害で落ちる。
  OSダウン検知は、ダウン検知に10秒、フェイルオーバーに4秒程かかる。
 ・IP切り替えは環境に依存するため外部スクリプトで提供している。
 ・スレーブのずれに関していえば、5.5の準同期レプリケーションを組み合わせれば、データ消失をほぼ防げる。
 ・その他、遅いトランザクションを発見するツール(slow-queryではなく)の紹介

★サービスの増強と縮退について
 ・ゲームタイトルの人気を正確に見積もることは困難
  想定外の人気が出た場合はスレーブを追加し、水平分割によりマスターを追加する。
 ・ダウンタイムなしでマスタを切り替えるには、
   1.更新を一時止める
   2.マスターから既存スレーブにレプリケーション完了したことを確認する。
 MHAではこれらを0.5~3.0秒で1クリックで行うことができる。かつ、データの不整合が起きたことは一度もなし。



松信氏は他にもこんなことを述べていた。

 ・オープンソース製品を使うことでコストダウンにつながり、結果会社に貢献することができる。
 ・技術を発信することはサービス企業の義務


勉強になります!


---------------------------------------------------------
松信 嘉範Yoshinori Matsunobu

MySQLスペシャリスト Oracle ACE Director

2006年から2010年8月まで、MySQL開発元のMySQLAB(現オラクル)にて、日本およびアジアのリード・コンサルタントとして従事。
100を超える国内外の顧客に対してMySQLパフォーマンスチューニング、高可用ソリューションなどを提供してきた。
2010年9月からDeNAにて「MySQLスペシャリスト Oracle ACE Director」。
主な著書に「Linux-DBシステム構築/運用入門」や「現場で使えるMySQL」などがある。