msgbartop
だめでつれづれな日記
msgbarbottom

20 6月 10 Apache JMeterでのIPv6アドレス指定方法

Apache JMeterでIPv6の試験を行いたいときにちょっと調査しました。

Q1) IPv4/IPv6両方の名前(A/AAAA)を持つホスト(例 : www.kame.net)をJMeterで指定すると?

A1)名前解決はA/AAAA両方で行いますが、実際のアクセスはA(IPv4)で行います。実際にはサンプラーの作りに依存すると思うのですが、LDAP/HTTPはIPv4でアクセスする模様です。

Q2) IPv6アドレスを直接指定する方法はあるか?

A2) あります。「サーバ名またはIP」入力欄に[2001:x::1]というような形式で指定すれば問題なく動きます。

14 2月 10 Jmeterの参考資料

Jmeterを利用してWebアプリに負荷・ストレステストを行いました。

Jmeterの使い方を探していたら、以下のページの資料が大変役に立ちました。

http://www.jasst.jp/archives/jasst07e/pdf/C2-1.pdf

忘れないようにメモっておきます。

12 2月 10 Hibernateのコネクション管理は使わない方向で。

最近はStruts2とHibernateを組み合わせてWebアプリを書いてます。

ある程度できてきたのでJmeterで負荷テストしてみると、あっという間にDBとの接続が埋まってしまい接続できなくなる事象が発生。「Too Many Connections」が出ます。getCurrentSession()でコネクションが自動で閉じられるはずなのですが、ちゃんとセッションが閉じられていないようです。ネットで調査したところ、同じような人が他にも多数いましたね。

で原因ですが、Hibernateでコネクション管理を利用することが問題だそうです。HibernateからC3P0を使う場合も同じです。

動きとしてはStruts2でアクセスする度にセッションを初期生成(new Configuration().configure().buildSessionFactory();)する仕様で、一回リクエストする度にセッションが増加するというもの。

対策としては、Hibernateのコネクション管理を利用せず、JNDI経由でDBCPのコネクション管理を利用する方式に変更することで正常に動作するようになった模様。

14 12月 09 hibernate の id generatorについて

hibernateを使ってアプリを書いているのですが、主キーの自動採番にアプリで実装するのが面倒くさかったので(かといってDBでシーケンスを使うのもいや)hibernateのgenerator機能を使ってみました。

書き方は簡単。generatorクラスには”uuid”を指定して、hibernateがランダム生成するようにしました。昔はuuid.stringやuuid.hexという定義名だったらしいですが、hibernate 3.0系からuuid.stringの廃止、及びuuid.hex -> uuidに名称変更があった模様です。

uuidの特徴は以下

  • 128ビットのUUIDアルゴリズムを利用し、長さが32の文字列IDを生成
  • Hibernateによって自動的生成されるので、id値セットが不要

xmlの書き方は以下

<hibernate-mapping>
	<class name="net.kinusati.hibernate.test" table="testtable" catalog="testdb">
		<id name="primaryKey" type="string">
			<column name="PRIMARY_KEY" length="32" />
			<generator class="uuid" />
		</id>
	</class>
</hibernate-mapping>

実際生成された値は”297eea25258866420125886932070006″という文字列でした。

注意点としては、uuidを利用する場合は32バイトのカラム長が必要であること。最初VARCHAR(20)にしていたので、原因判明まで時間がかかりました・・・

ちなみにuuid.stringと指定した場合、以下の例外が出ます・・

org.hibernate.MappingException: could not instantiate id generator
	at org.hibernate.id.IdentifierGeneratorFactory.create(IdentifierGeneratorFactory.java:98)
	at org.hibernate.mapping.SimpleValue.createIdentifierGenerator(SimpleValue.java:152)
	at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:192)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1294)
	at org.hibernate.console.ConsoleConfiguration$3.execute(ConsoleConfiguration.java:492)
	at org.hibernate.console.execution.DefaultExecutionContext.execute(DefaultExecutionContext.java:64)
	at org.hibernate.console.ConsoleConfiguration.execute(ConsoleConfiguration.java:94)
	at org.hibernate.console.ConsoleConfiguration.buildSessionFactory(ConsoleConfiguration.java:487)
	at org.hibernate.eclipse.console.workbench.LazySessionFactoryAdapter.getChildren(LazySessionFactoryAdapter.java:43)
	at org.hibernate.eclipse.console.workbench.BasicWorkbenchAdapter.getChildren(BasicWorkbenchAdapter.java:99)
	at org.hibernate.eclipse.console.workbench.BasicWorkbenchAdapter.fetchDeferredChildren(BasicWorkbenchAdapter.java:105)
	at org.eclipse.ui.progress.DeferredTreeContentManager$1.run(DeferredTreeContentManager.java:234)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)
Caused by: org.hibernate.MappingException: could not interpret id generator strategy: uuid.string
	at org.hibernate.id.IdentifierGeneratorFactory.getIdentifierGeneratorClass(IdentifierGeneratorFactory.java:109)
	at org.hibernate.id.IdentifierGeneratorFactory.create(IdentifierGeneratorFactory.java:92)
	... 12 more
!SUBENTRY 2 org.hibernate.eclipse.console 4 150 2009-12-04 08:06:18.760
!MESSAGE org.hibernate.MappingException: could not interpret id generator strategy: uuid.string
!STACK 0
org.hibernate.MappingException: could not interpret id generator strategy: uuid.string
	at org.hibernate.id.IdentifierGeneratorFactory.getIdentifierGeneratorClass(IdentifierGeneratorFactory.java:109)
	at org.hibernate.id.IdentifierGeneratorFactory.create(IdentifierGeneratorFactory.java:92)
	at org.hibernate.mapping.SimpleValue.createIdentifierGenerator(SimpleValue.java:152)
	at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:192)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1294)
	at org.hibernate.console.ConsoleConfiguration$3.execute(ConsoleConfiguration.java:492)
	at org.hibernate.console.execution.DefaultExecutionContext.execute(DefaultExecutionContext.java:64)
	at org.hibernate.console.ConsoleConfiguration.execute(ConsoleConfiguration.java:94)
	at org.hibernate.console.ConsoleConfiguration.buildSessionFactory(ConsoleConfiguration.java:487)
	at org.hibernate.eclipse.console.workbench.LazySessionFactoryAdapter.getChildren(LazySessionFactoryAdapter.java:43)
	at org.hibernate.eclipse.console.workbench.BasicWorkbenchAdapter.getChildren(BasicWorkbenchAdapter.java:99)
	at org.hibernate.eclipse.console.workbench.BasicWorkbenchAdapter.fetchDeferredChildren(BasicWorkbenchAdapter.java:105)
	at org.eclipse.ui.progress.DeferredTreeContentManager$1.run(DeferredTreeContentManager.java:234)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)

07 12月 09 Struts 1.x / Struts 2.xでのスレッドセーフ(thread safe)について

Javaについてあまり詳しくなかったので、フレームワークと言語勉強をかねてStruts2 + hibernateでお勉強用Webアプリを制作していますが、なれない言語のため正直手こずっています(C/Perlの方が簡単・・)

でJavaといえば気になるのがスレッドセーフ(thread safe)。他言語でのスレッドセーフの作り方はわかるので、共用変数にステータスを持たせる等を行わなければスレッドセーフになることはわかるのですが、Struts2のサンプルプログラムを見ていて疑問に思ったことが。

import com.opensymphony.xwork2.ActionSupport;

public class indexAction extends ActionSupport {

    public String execute() throws Exception {
        return "success";
    }

    public String message;

    public String hello() throws Exception {
        message = “いえいえこちらこそこんにちは。”;
        return "hello";
    }
}

上記はatmarkitの記事で@いう間にWebアプリを作れる「Struts 2」入門から抜き出した物ですが、ActionSupportのサブクラスにインスタンス変数を持たせた上、インスタンス変数にメッセージを代入した物を、JSPにはき出すようにしています。

<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
 <%@ taglib prefix="s" uri="/struts-tags" %>
 <html>
 <body>
 <s:property value=”%{message}”/>
 </body>
 </html>

ふと思ったのが、そういえばStruts1系だとActionサブクラスは一つだけインスタンス化されるという記事。

atmarkit記事掲載のstruts2のサンプルだと、スレッドセーフではないのでは?と思っていたら、以下の記事が。

Struts 1.x Vs Struts 2.x

  • Struts 1.x : Actionサブクラスはsingletonだから、スレッドセーフ or synchronizedにしないとだめ。Actionサブクラスにインスタンス変数を持たせてリクエスト毎の状態やメッセージを管理してはいけないということですね。
  • Struts 2.x : ActionSupportサブクラスはHTTPリクエスト毎に生成されるため、スレッドセーフ問題は発生しない。ActionSupportサブクラスにインスタンス変数を持たせて、リクエスト毎のメッセージを代入しても、問題なくスレッドセーフです

struts 1.x系と違ってstruts 2.x系のサンプルがActionSupportサブクラスにインスタンス変数を持たせた上で、それをJSPに出力する物しか見つけられなかったのでどきどきしましたが、問題なしということですね。ほっとしました。

28 9月 09 python始めました

プログラムのお勉強と言うことで、pythonに取り組み出しました。文法はよくわからないんですが、なんか、きれいにPGかける気がしますね。

とりあえず、MySQLに含まれるInnodb/MyISAMの全テーブルを抽出し、最適化するスクリプトをPythonで書いてみましたので、掲載します。かるくしょぼいです。あとはこれをCRONで定期的に流すようにしますか。

#!/usr/bin/env python

import sys
import MySQLdb

HOST = "127.0.0.1"
USER = "root"
PASS = "hogehoge"
DB = "mysql"

try:
    con = MySQLdb.connect(user = USER, passwd = PASS, db = DB)
    cursor = con.cursor()

    sql = "show databases"
    cursor.execute(sql)
    result = cursor.fetchall()

    for d in result:
        if d[0] == 'information_schema' or d[0] == 'mysql':
            continue

        sql = "show table status from %s" % d

        cursor.execute(sql)
        result = cursor.fetchall()

        for t in result:
            sql = ""
            if t[1] == 'InnoDB':
                sql = "ALTER TABLE %s.%s Engine = InnoDB" % (d[0],t[0])
            elif t[1] == 'MyISAM':
                sql = "OPTIMIZE TABLE  %s.%s" % (d[0],t[0])
            else:
                continue

            cursor.execute(sql)
            result = cursor.fetchall()
            print result

    con.close()

except MySQLdb.Error, e:
    print "Unexpected error %d %s" %  (e.args[0], e.args[1])
    sys.exit(1)

exit(0)

12 9月 09 Apache2.2 + Tomcat

今更です。

Apache2.2からはTomcat連携時にmod_proxy_ajpでできちゃうんですね。mod_jkとの棲み分けはどうなったんだろうと気になるが、気にせずインストール

コンパイル時

./configure --enable-proxy --enable-proxy-ajp

httpd.conf編集

<Location / >
  ProxyPass ajp://localhost:8009/
</Location>

25 8月 09 PHPでシグナルを取り扱うときの注意点

PHPでシグナルハンドルしようと思い、コーディングしたが、思うように動作しない。

<?php
function signal_handler($signal)
{
    echo "signal = $signal\n";
    exit($signal);
}

pcntl_signal(SIGTERM, "signal_handler");
pcntl_signal(SIGHUP,  "signal_handler");
pcntl_signal(SIGUSR1, "signal_handler");
posix_kill(posix_getpid(), SIGTERM);

echo "finished\n";
?>

何故だ!?と思ったら、ticksの定義が必要という。

<?php

declare(ticks = 1);

function signal_handler($signal)
{
    echo "signal = $signal\n";
    exit($signal);
}

pcntl_signal(SIGTERM, "signal_handler");
pcntl_signal(SIGHUP,  "signal_handler");
pcntl_signal(SIGUSR1, "signal_handler");
posix_kill(posix_getpid(), SIGTERM);

echo "finished\n";
?>

勉強になりました・・・