Apache JMeterでIPv6の試験を行いたいときにちょっと調査しました。
A1)名前解決はA/AAAA両方で行いますが、実際のアクセスはA(IPv4)で行います。実際にはサンプラーの作りに依存すると思うのですが、LDAP/HTTPはIPv4でアクセスする模様です。
A2) あります。「サーバ名またはIP」入力欄に[2001:x::1]というような形式で指定すれば問題なく動きます。
Jmeterを利用してWebアプリに負荷・ストレステストを行いました。
Jmeterの使い方を探していたら、以下のページの資料が大変役に立ちました。
http://www.jasst.jp/archives/jasst07e/pdf/C2-1.pdf
忘れないようにメモっておきます。
最近はStruts2とHibernateを組み合わせてWebアプリを書いてます。
ある程度できてきたのでJmeterで負荷テストしてみると、あっという間にDBとの接続が埋まってしまい接続できなくなる事象が発生。「Too Many Connections」が出ます。getCurrentSession()でコネクションが自動で閉じられるはずなのですが、ちゃんとセッションが閉じられていないようです。ネットで調査したところ、同じような人が他にも多数いましたね。
で原因ですが、Hibernateでコネクション管理を利用することが問題だそうです。HibernateからC3P0を使う場合も同じです。
動きとしてはStruts2でアクセスする度にセッションを初期生成(new Configuration().configure().buildSessionFactory();)する仕様で、一回リクエストする度にセッションが増加するというもの。
対策としては、Hibernateのコネクション管理を利用せず、JNDI経由でDBCPのコネクション管理を利用する方式に変更することで正常に動作するようになった模様。
hibernateを使ってアプリを書いているのですが、主キーの自動採番にアプリで実装するのが面倒くさかったので(かといってDBでシーケンスを使うのもいや)hibernateのgenerator機能を使ってみました。
書き方は簡単。generatorクラスには”uuid”を指定して、hibernateがランダム生成するようにしました。昔はuuid.stringやuuid.hexという定義名だったらしいですが、hibernate 3.0系からuuid.stringの廃止、及びuuid.hex -> uuidに名称変更があった模様です。
uuidの特徴は以下
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)
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系と違ってstruts 2.x系のサンプルがActionSupportサブクラスにインスタンス変数を持たせた上で、それをJSPに出力する物しか見つけられなかったのでどきどきしましたが、問題なしということですね。ほっとしました。
プログラムのお勉強と言うことで、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)
今更です。
Apache2.2からはTomcat連携時にmod_proxy_ajpでできちゃうんですね。mod_jkとの棲み分けはどうなったんだろうと気になるが、気にせずインストール
./configure --enable-proxy --enable-proxy-ajp
<Location / > ProxyPass ajp://localhost:8009/ </Location>
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";
?>
勉強になりました・・・