AWS + java + JAX-RS + session のメモ

beanstalkでさっとdynamodbのセッションを作る

Amazon DynamoDBによるTomcatセッション永続化とフェイルオーバー | Developers.IO

eclipseで普通にやるとsession用のdynamodbのテーブルが日本以外のリージョンにできてしまうので、context.xmlに以下の属性値を加える。

regionId="ap-northeast-1"

jax-rs

最初にbeanstalkでdynamodbセッション連携付きで適当なjavaアプリケーションをデプロイし、その後に同じEnvironmentにJAX-RSのアプリケーションをデプロイしたら、最初に作ったdynamodbのセッション機構が生き残っていた。
とりあえずはこれでいい。

sessionを触る

web services - How Can I Retrieve The Session Id from a Jax RS Webservice? - Stack Overflow

@Path("/session-id.txt")
public class SessionIdResource
{
@GET @Produces(MediaType.TEXT_PLAIN)
public String getSessionId( @Context HttpServletRequest request ){
return request.getSession(true).getId();
}
}

最終的にpom.xmlのdependenciesに以下を追記

<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-java-sdk</artifactId>
  <version>1.9.22</version>
</dependency>
<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>servlet-api</artifactId>
   <version>2.5</version>
   <scope>provided</scope>
</dependency>

=========しきりなおし===============

上記のやり方でJAX-RS上でDynamoDBに接続しようとしたところ、classpathの問題が発生した。

SEVERE: Servlet.service() for servlet [Jersey Web Application] in context with path [] threw exception [org.glassfish.jersey.server.ContainerException: java.lang.NoClassDefFoundError: Could not initialize class com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient] with root cause
java.lang.NoClassDefFoundError: Could not initialize class com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient

よくわからなかったので、jax-rs周りからやり直すことにした。


JAX-RS
JAX-RS(Jersey)を使ってみる - azuki note

DynamoDB
周回遅れエンジニアノート: DynamoDB で tomcat の session を管理する
AWS - DynamoDBのドキュメントAPI、JSON対応したから簡単なサンプルで紹介する part1 - Qiita

private void getUser(String uid, String tableName) {
    	//LOGGER.info("getUser start");
    	AWSCredentials credentials = new BasicAWSCredentials("XXXXXX", "XXXXXX");
        AmazonDynamoDBClient client = new AmazonDynamoDBClient(credentials);
        client.setEndpoint("dynamodb.ap-northeast-1.amazonaws.com");
        System.out.println("ok");
        
        DynamoDB dynamo = new DynamoDB(client);
        Table table = dynamo.getTable("User");
        Item item = table.getItem("uid", "abcde");
        //AttributeをMap<String, Object>でまわせるのは便利
        for (Map.Entry<String, Object> attribute : item.attributes()) {
            System.out
                    .println(attribute.getKey() + ", " + attribute.getValue());
        }
        //LOGGER.info("getUser end");
    }

JDK1.8をcentosに入れて、デフォルトのjavaを入れ替える で jstatで監視

jstatを使ってヒープの監視がしたかったのでいれる。

このサイトの通りでいけた。
How to Install Java 8 (Jdk 8u31) on CentOS/RHEL 7/6/5

cd /opt/
wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u31-b13/jdk-8u31-linux-x64.tar.gz"
tar xzf jdk-8u31-linux-x64.tar.gz

cd /opt/jdk1.8.0_31/
alternatives --install /usr/bin/java java /opt/jdk1.8.0_31/bin/java 2
# alternatives --config java
alternatives --config java

alternatives --install /usr/bin/jar jar /opt/jdk1.8.0_31/bin/jar 2
alternatives --install /usr/bin/javac javac /opt/jdk1.8.0_31/bin/javac 2
alternatives --set jar /opt/jdk1.8.0_31/bin/jar
alternatives --set javac /opt/jdk1.8.0_31/bin/javac

### check
java -version
# java version "1.8.0_31"
# Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
# Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)

###
vim /etc/bashrc
===============
export JAVA_HOME=/opt/jdk1.8.0_31
export JRE_HOME=/opt/jdk1.8.0_31/jre
export PATH=$PATH:/opt/jdk1.8.0_31/bin:/opt/jdk1.8.0_31/jre/bin
===============

jstatでメモリの使用率を監視

# 調べたいプロセスのIDを調べる
jps -v

# 5秒に一回監視
jstat -gcutil -t ${TARGET_PID} 5000

オンメモリ高速KVSをjavaのstatic変数で実現する

やりたいことは、メモリの高速さをフルに活かした超シンプルなKVS。
用途は、機械学習アルゴリズムのモデル用。
・大量のKeyValue値を高速に読み書きできること。
・モデルはシリアライズを使って、ファイルに保存/読み込みもできるようにしたい。
・サーバを再起動したり、しばらく使わないときは、ファイルにしておく。
・モデルを更新したい時もメモリ上のデータに対して高速に操作できる。
そういうシンプルで高速なオンメモリKVSが欲しかった。


しかし、以前にも書いたように、メモリの高速っぷりを活かしたシンプルなKVSはありそうでなかった。
Redisはネットワーク越しに使われることが前提とされているとかなんとかで、その辺りがボトルネックになって素のメモリ処理に比べると桁違いに遅かった。
Tokyo CabinetはTokyo Tyrantと違ってインターナル用途が想定されているものの、レコード数が1億くらいに増えると急に重くなって使い物にならなくなった。(もしかしたらパラメータ調整がんばればいけるかも という印象)

じゃあもういいってことで、pythonの共有メモリを使って実現しようとしたが、子プロセスを管理したりとかいろいろ厄介そうだったのでこれも断念。


で、行き着いたのが、javaのstatic変数。そして、そのデータを使うのもjavaに限定。
同じプロセス内なので、素のメモリ操作と同じレベルの高速性が期待できる。
その代償として、そのデータの使用はすべて同じJAVAアプリケーション内に限られるので、機械学習の計算ロジックなどはすべて同じアプリケーション上に書く。
もはやKVSでもなんでもないわけだが、、

で、それをGlassfishなどのインスタンスとして実現する。
計算結果を返すインターフェイスなんかも用意してあげてAPI化する。


でもやっぱりなんか違和感がある。ただメモリの内容を他のプロセスと共有するだけのことがどうして簡単にできないんだろう

JSON形式のマルチバイト文字(UTF16)をUTF8変換する

JSON系モジュールを使わずに直接まともに見れる形に変換したいが、なかなか情報がなかった。

use Encode;

## test
print encode("UTF-8", "\x{3042}"); ## "あ"

## 変換したいUTF16な文字列
my $str = '\u3042';

$str =~ s/\\u(:xdigit:{4})/chr eval "0x$1"/eg;
$str = encode("UTF-8", $str);
print "$str¥n"; ## "あ"

参考:
utf16の記号のutf8へのエンコード(もしくはマッチ又は削除)がう - Perl | 教えて!goo

scale_x_datetimeの引数がないとか言われて使えない

  • 問題

scale_x_datetimeの引数がないとか言われて使えない

p1 <- p1 + scale_x_datetime(major="2 weeks")
以下にエラー continuous_scale(aesthetics, "datetime", identity, breaks = breaks, :
使われていない引数 (major = "2 weeks")

  • 解決

Google グループ

require(scales)

で解決

Neo4jインストールなど

情報推薦エンジンつくるにあたって、いろいろやってみたところ、KVSやRDBではパフォーマンス的にきついことがわかった。
ので、まずはグラフDBを導入したい。

グラフデータベース「Neo4j」の 導入の導入



というわけで手順

neo4jインスコcentOS
http://yum.neo4j.org/

起動など
[root@vb]# service neo4j start
[root@vb]# ps aux | grep neo4j
[root@vb]# service neo4j stop
[root@vb]# service neo4j restart

やめ

ダウンロードしてくるタイプでインストール。
ただし、一般ユーザでやると変なことになったので、rootで、やった。

./bin/neo4j startででてくるWARNINGはこれで解決
ubuntu - neo4j and max open files - Stack Overflow

Starting Neo4j Server...process [4669]... waiting for server to be ready............ OK.
http://localhost:7474/ is ready.

WARNINGきえた

localhost:7474を見るとクオリティの高いチュートリアルが受けられる。