Hatena::ブログ(Diary)

#9 Backyard RSSフィード Twitter

2012年03月02日

GAE で Scala Lift を動かす

Google App Engine (GAE) 1.6.3 で Scala + Lift を動かしてみます。とりあえず作業の前提として:

  • サーブレット開発の知識を持っている。
  • 適当な WAR プロジェクトを GEA にデプロイしていて Java サーブレットや JSP が動かせている。

Scala ライブラリの追加

Scala 公式サイトから最新版 (例として 2.9.1) のアーカイブを落とし、内包されている scala-2.9.1.final/lib/*.jar を WEB-INF/lib にコピーします。ランタイムに必要な作業はこれだけ。ビルドを行う開発端末は各 JAR ファイルにクラスパスを通して下さい。

Scala でテスト用のサーブレットを作成します。

package org.koiroha.aaa.server
import javax.servlet.http._
class TestServlet extends HttpServlet {
  override def doGet(request:HttpServletRequest, response:HttpServletResponse){
    response.setContentType("text/plain; charset=UTF-8")
    response.getWriter().println("hello, world")
  }
}

テスト用のサーブレットを web.xml で URL とマッピング。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  version="2.5"
  xmlns="http://java.sun.com/xml/ns/javaee">
  <servlet>
    <servlet-name>TestServlet</servlet-name>
    <servlet-class>org.koiroha.aaa.server.TestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>TestServlet</servlet-name>
    <url-pattern>/test/greeting</url-pattern>
  </servlet-mapping>
</web-app>

ローカルで動作確認を行ったあと GAE にデプロイして動作すれば Scala の導入は完了です。

Lift の準備

Google App Engine 1.6.3 のシステムプロパティ

GAE でアプリケーションを登録したので環境調査も兼ねて取得したすっぴん状態のシステムプロパティを載せておきます。値は Javaリテラル表記です。

NameValue
com.google.appengine.application.id"appid"
com.google.appengine.application.version"1.357195764071108954"
com.google.appengine.runtime.environment"Production"
com.google.appengine.runtime.version"Google App Engine/1.6.3"
file.encoding"ANSI_X3.4-1968"
file.separator"/"
java.class.version"50.0"
java.specification.name"Java Platform API Specification"
java.specification.vendor"Sun Microsystems Inc."
java.specification.version"1.6"
java.vendor"Google Inc."
java.vendor.url"http://wiki.corp.google.com/twiki/bin/view/Main/JavaPlatform"
java.version"1.6.0"
java.vm.name"OpenJDK Client VM"
java.vm.specification.name"Java Virtual Machine Specification"
java.vm.specification.vendor"Sun Microsystems Inc."
java.vm.specification.version"1.0"
java.vm.vendor"Sun Microsystems Inc."
java.vm.version"1.6.0"
line.separator"\n"
os.name"Linux"
path.separator":"
user.dir"/base/data/home/apps/s~appid/1.357195764071108954"

標準のシステムプロパティに比べてかなり控えめですが、OpenJDK 1.6.0 (多分 GEA カスタム版) を使用していてアーキテクチャ不明の Linux を使用していることが分かります。

com.google.appengine.runtime.environment は Eclipse などのローカル環境では "Development" となるので、本番環境と開発環境で動作を切り替える場合に使用できます。

なおアプリケーションでシステムプロパティが必要な場合は WEB-INF/appengine-web.xml で追加することができます。

2012年03月01日

hbase hbck

  • HBase のリージョン数を調べるにはコマンドラインから hbase hbck を実行。
  • リージョン分割指定でテーブルを create した後、大量のエラーと共に Status: INCONSISTENT と出る場合はリージョン分割がまだ済んでいない。しばし待て。

2012年02月29日

Log4j + syslog の設定

Log4j を syslog へ転送する時はファシリティと Syslog サーバが指定できる。log4j.xml の <appender> → <param> 指定は該当する Appender クラスのプロパティ名と同じなので、詳しくは API リファレンスの setter を参照。
SyslogAppender (Apache Log4j 1.2.17 API)

例えば

  • <param name="facility" value="local4"/> … ファシリティ local4 を使用
  • <param name="facilityPrinting" value="false"/> … ファシリティを出力しない
  • <param name="header" value="false"/> … タイムスタンプとホスト名を出力しない

など。

タグを指定するプロパティは存在しないが、これはケースバイケースで対応可能。

固定値で良い場合
PatternLayout 上で直接指定 ("[myapp] %m%n")
プロセスごとに変えたい場合
起動時のシステムプロパティで指定 ("[${syslog.tag}] %m%n"、起動オプションに -Dsyslog.tag=myapp 追加)
スレッドごとに変えたい場合
アプリケーションから NDC や MDC で指定 ("[%X{tag}] %m%n"、アプリ内でスレッド開始時に MDC.put("tag", "myapp"); 追加)
出力ごとに変えたい場合
アプリで出力するたびにフォーマット (logger.info("[" + myapp + "] ...") )

コードは通常の Log4j と変わらず。設定ファイルも概ね以下のようなイメージで構成できる。

import org.apache.log4j.*;
public class A{
  public static void main(String[] args){
    Logger logger = Logger.getLogger("org.koiroha.myapp");
    logger.info("hello, world");
    return;
  }
}

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <appender name="syslog" class="org.apache.log4j.net.SyslogAppender">
    <param name="threshold" value="info"/>
    <param name="syslogHost" value="localhost"/>
    <param name="facility" value="user"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="conversionPattern" value="${org.koiroha.appname} %m%n"/>
    </layout>
  </appender>
  <root>
    <priority value ="info"/>
    <appender-ref ref="syslog"/>
  </root>
</log4j:configuration>

$ java -Dlog4j.configuration=log4j.xml -Dorg.koiroha.appname=sample1 A
2012-02-29 16:30:37,425  INFO myapp- [sample1] hello, world
$ java -Dlog4j.configuration=log4j.xml -Dorg.koiroha.appname=sample2 A
2012-02-29 16:30:41,633  INFO myapp- [sample2] hello, world

ただし 1024 バイト以上のメッセージとなる場合は 2 以上のパケットに分割されるため、2つめ以降にタグは付けられない。

2012年02月28日

HFile と Memstore のメモ

  • store files は HFile の事。
  • Key-Value 不変マップ。
  • HFile はブロックに分けられていて、最後にブロックインデックスが付属している。
  • ブロックインデックスは HFile がオープンされた時に読み込まれメモリ上に保持される。
  • デフォルトのブロックサイズは 64kB。
  • 更新データは最初 write-ahead log (WAL) と呼ばれるコミットログに書き込まれメモリ内の memstore に保存される。
  • データの大きさが許容量を超えたら HFile としてディスクにフラッシュされる。
  • フラッシュが終わるとコミットログ内の最新未フラッシュ更新まで破棄される。
  • memstore の内容をディスクにフラッシュしている間、読み込み/書き込み処理はブロックされない。
  • これは、既存のいっぱいになった領域がファイルに書きこまれている間に、新しく作成した空の領域を更新するよう、メモリ上の memstore をローリングすることでアーカイブされる。
  • memstore 上のデータはディスク上の HFile の内容と全く同じようにキーでソートされている。このため保存時に特にソートなどの処理は行われない。

2012年02月17日

protocol error: bad line length character と出たら

SSH 接続できるはずのサーバに git で接続できないと思ったら:

git clone ssh://git.myserver/git/hoge
Password:
fatal: protocol error: bad line length character: [31

SSH でのターミナル接続時に何かログインメッセージのようなものを表示していませんか? これが git-ssh 間のプロトコルに紛れて悪さをします。