Azure SDK を 2.2 から 2.3 にアップグレードすると失敗する

Azure SDK 2.2 が入っている環境で Azure SDK 2.3 をインストールしようとして失敗して困った話。

いつもどおり Web Platform Installer から Windows Azure SDK 2.3 for .NET (VS 2012) - 2.3 を追加してインストールすると、Storage Emulator 3.2 のインストールで失敗したと言われる。

ログを見てみると "C:\Program Files (x86)\Microsoft SDKs\Windows Azure\Storage Emulator\WAStorageEmulator.exe" init -forcecreate -autodetect で失敗。

どうやらストレージの初期化で失敗している様子。SQL Server Management で (localdb)\v11.0 にアクセスすると WAStorageEmulatorDb32 はちゃんと作られている。とりあえずこれを消して再チャレンジするも失敗。

しょうがないので検索すると似たような人を発見。

ローカルDBを作り直さないといけないらしい。再度 WAStorageEmulatorDb32 を消してローカルDBを初期化。

C:\>sqllocaldb stop v11.0
LocalDB instance "v11.0" stopped.

C:\>sqllocaldb delete v11.0
LocalDB instance "v11.0" deleted.

C:\>sqllocaldb create v11.0
LocalDB instance "v11.0" created with version 11.0.

そして、再度 Azure SDK 2.3 をインストールすると成功した。なんだこれ。

Windows Azure PowerShell を使って Windows Azure クラウドサービスへのデプロイを自動化しよう

こんにちは、この投稿は PowerShell Advent Calendar 2013 の 5 日目の記事です。

はじめに

去年まで PowerShell とは縁がなく、自分には必要ない道具だと思っていました。

ところが、デプロイを自動化する業務で Azure PowerShell に初めて触れ、PowerShell の万能さに驚き、 今となっては Windows を使って仕事している人には PowerShell は必須の道具だと思うくらいに毒されてしまいました。 この投稿を機に Azure 使いが PowerShell に流入してくるといいなと思ってます。

今回作成するスクリプトは GitHub に置いていますが、 試すには Azure のサブスクリプションが必要です。 今回 Windows7 x64、Visual Studio 2012、Windows Azure SDK for .NET (VS 2012) - 2.2 の環境で検証しています。

Azure PowerShell

Azure PowerShell を使うと Web の Windows Azure 管理ポータルでできる操作はだいたいできます。 PowerShell のコマンドレットは MSDN で確認できるので、ざっと見れば雰囲気が掴めると思います。

Azure PowerShell の更新情報ですが、私はソースコードに含まれる ChangeLog.txt を確認しています。 着実にできることが増えてきているので、毎回のリリースが楽しみです。

Azure PowerShell のインストール&初期設定

では、最新版の Azure PowerShell を Web Platform Installer でインストールします。 直接 Web Platform Installer を起動してもいいし、 サイトからダウンロードしてきても OK です。 ただ Azure SDK も一緒にインストールされるので、環境を汚くしたくない人は VM などで試すのをオススメします 。

f:id:hikoma:20131206114239p:plain

インストールが完了したら PowerShell を起動して、サブスクリプションを設定します。

PS C:\Temp> Add-AzureAccount

ここで、説明が難しいのですが CurrentStorageAccountName を設定しろと怒られる場合があるので、適当に潰しておきます。

PS C:\Temp> Get-AzureSubscription -Current | Set-AzureSubscription -CurrentStorageAccountName _

以上で、PowerShell を使って Azure をあれこれ操作する準備が整いました。 簡単ですね。

デプロイパッケージの作成

次に、デプロイパッケージを作成します。 ビルドも PowerShell で記述したいところですが、残念ながらそのノウハウを持ち合わせておりません。 普通に MSBuild を用いてパッケージを作成します。 Visual StudioWindows Azure クラウドサービスプロジェクトを作成し(今回は省略)、生成された ccproj に対して Publish ターゲットで msbuild をすれば OK です。こんな感じになるかと思います。

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <OutputDir>$(MSBuildProjectDirectory)\output</OutputDir>
    <BuildProperties>VisualStudioVersion=11.0;Configuration=Release;Platform=AnyCPU</BuildProperties>
  </PropertyGroup>

  <ItemGroup>
    <ProjectFile Include="$(MSBuildProjectDirectory)\**\*.ccproj"/>
  </ItemGroup>

  <Target Name="Build">
    <MSBuild Targets="Publish" Projects="@(ProjectFile)"
             Properties="$(BuildProperties);PublishDir=$(OutputDir)\" />
  </Target>
</Project>

このファイルを適当な名前(今回は PowerShellDeploySample.msbuild)で保存し、コマンドプロンプトmsbuild を実行します。Visual Studio のコマンドプロントで msbuild を叩くか、下記のように msbuild.exe のフルパスを直接叩いても大丈夫です。 VisualStudioVersion=11.0 は Azure SDK for .NET のバージョンに応じて修正してください。

C:Temp> C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe PowerShellDeploySample.msbuild /t:Build

output フォルダに作成された cspkg と cscfg ファイルがデプロイパッケージです。

PowerShell でデプロイ

では、デプロイを始めましょう。 今回は「 ステージング環境にデプロイ → ステージング環境で動作確認 → 運用環境に切り替え 」 というシナリオでデプロイを行いたいと思います。

Blob ストレージにパッケージをアップロード

まず、cspkg ファイルと cscfg ファイルを Azure Blob ストレージにアップロードします。 この作業は必須ではないのですが、管理ポータルから再デプロイがやりやすくなるのでオススメです。

では、アップロードしましょう。 まずは、ストレージアカウントが必要なので作成します。

PS C:\Temp> $storageAccountName = 'deployaccount'
PS C:\Temp> New-AzureStorageAccount -StorageAccountName $storageAccountName -Location 'East Asia'

StorageAccountName は Azure 内で一意である必要があるので、試す場合は変更してください。 次に、Blob を入れるコンテナが必要なので作成します。

PS C:\Temp> $blobContainerName = 'deploycontainer'
PS C:\Temp> $storageKey = Get-AzureStorageKey -StorageAccountName $storageAccountName
PS C:\Temp> $storageContext = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageKey.Primary
PS C:\Temp> New-AzureStorageContainer -Context $storageContext -Container $blobContainerName

最後に Blob をアップロードします。

PS C:\Temp> $cspkgFile = Get-Item *.cspkg
PS C:\Temp> $cscfgFile = Get-Item *.cscfg
PS C:\Temp> $cspkg = Set-AzureStorageBlobContent -Context $storageContext -Container $blobContainerName -File $cspkgFile
PS C:\Temp> $cscfg = Set-AzureStorageBlobContent -Context $storageContext -Container $blobContainerName -File $cscfgFile

次に、アップロードしたパッケージを、ステージング環境にデプロイします。

ステージング環境にデプロイ

まずはクラウドサービスを作成します

PS C:\Temp> $cloudServiceName = 'PowerShellDeploySample'
PS C:\Temp> New-AzureService -ServiceName $cloudServiceName -Location 'East Asia'

ServiceName は Azure 内で一意である必要があるので、試す場合は変更してください。 次に、ステージング環境にパッケージをデプロイします。

PS C:\Temp> $pakcageUri = $cspkg.ICloudBlob.Uri.AbsoluteUri
PS C:\Temp> New-AzureDeployment -ServiceName $cloudServiceName -Slot Staging -Package $pakcageUri -Configuration $cscfgFile

これで、デプロイ完了だ! ステージング環境で動作確認やるぞ! と行きたいところですが、実はまだインスタンスの起動終わっていません!!!実際に確認してみます。

PS C:\Temp> $deployment = Get-AzureDeployment -ServiceName $cloudServiceName -Slot Staging
PS C:\Temp> $deployment.RoleInstanceList.InstanceStatus
CreatingVM
CreatingVM

この InstanceStatus が全て ReadyRole になるまで待つ必要があります。 ReadyRole になったら、ステージング環境にアクセスしてみます。 接続先 URL は $deployment から取得することができます。

PS C:\Temp> $deployment.Url.AbsoluteUri
http://5bb82cb2a3be4e66ba9b7f5941ecc71d.cloudapp.net/

この URL にアクセスすれば、ステージング環境の動作確認ができます。

ステージング環境を運用環境に移す

一通りステージング環境で動作確認ができたら、運用環境に移します。 ここでは Azure の Vip スワップという機能を利用します。

PS C:\Temp> Move-AzureDeployment -ServiceName $cloudServiceName

操作はこれだけです。接続先 URL を確認します。

PS C:\Temp> (Get-AzureDeployment -ServiceName $cloudServiceName -Slot Production).Url.AbsoluteUri
http://powershelldeploysample.cloudapp.net/

この URL にアクセスして、動作確認ができたらデプロイ成功です!

ビルドとデプロイのスクリプト化

以上の手続きに、コメントやエラー処理などを入れたスクリプト Deploy.ps1 を GitHub に上げています。 Deploy.ps1 を直接叩いてもいいし、PowerShellDeploySample.msbuild でサンプルプロジェクトをビルドしてデプロイを試してみることもできます。 ちょっとエラー処理やりすぎている感じがしますが -ErrorAction SilentlyContinue でも普通に動くので、裁量はお任せします。

さいごに

Azure PowerShell 自体はコマンドレットのパラメータを見ながら使うだけなので割とさくっとスクリプトは書けるようになると思います。 Azure PowerShell の最大の敵は Azure 側の更新が遅いということに尽きると思います。 スクリプトの検証に時間がかかるので、ほんのささいなミスでがっかりすることが何度あったことやら。 それに加えて、Azure 側の操作はたまに失敗します(特にストレージ周り)。 例外を捕捉したら、リトライ処理が必要なケースが度々出てきます。 とは言っても PowerShell のおかげで例外処理自体は記述しやすいかと思います。

Windows Azure PowerShell Cmdlets で No certificate was found in the certificate store with thumbprint ~ が出たら

はまったのでメモ。

C:\Users\<ユーザー名>\AppData\Roaming\Windows Azure Powershell\ に入っているファイルを消して、 Set-AzureSubscription や Select-AzureSubscription をやり直すだけ。

Azure の管理画面を開いて、管理証明書の値を確認して、以下のコマンドを実行すると作り直されました。

Import-Module Azure

$subscriptionName = "<サブスクリプションの値>"
$subscriptionId = "<サブスクリプション IDの値>"
$thumbprint = "<サムプリントの値>"

$myCert = Get-Item cert:\\CurrentUser\My\$thumbprint
Set-AzureSubscription `
  -SubscriptionName $subscriptionName `
  -SubscriptionId $subscriptionId `
  -Certificate $myCert

Get-AzureService

Azure の管理証明書を変更した時に、ローカルからもその証明書を消したら発生するのかな?

自炊した PDF をドラッグアンドドロップで kobo 形式に変換

いろいろ kobo ちゃん叩かれているけど、デバイスは別に悪くないと思うんだけど。

で、こいつは自炊した PDF を奇麗に表示できない問題があるんですけど、ChainLP とか使って変換すれば読めるようにはなります。この記事がすごくわかりやすいです。

そんで、今回はこの一連の作業をお手軽にするのが目的です。(PDF より cbz 形式に変換した方が、サクサク読める気がするので cbz に変換します)

ChainLP のインストール

まずは、ChainLP をここからダウンロードして適当な場所に展開します(ここでは C:\ChainLP40b12 とします)。ChainLP.exe が起動しない場合は、.Net Framework 4 をインストールしないといけいないかもしれません。

そんで、画像ファイルを cbz に変換するために、zip3j037.lzh と zip232dN.zip をここからダウンロードしてきて展開し、ZIP32J.DLL と ZIP32.DLL を ChainLP のフォルダに入れます。

設定ファイルを作成

次に ChainLP の設定ファイルを作ります。

ChainLP.exe を起動し、サイズを 600x800 に変更します。あとは PDF の画質に合わせて、ページ補正を変更したり、本文ボールド化を設定します。一通り設定が終わったら、編集メニューにある設定の別名保存を選択し kobo.ini として ChainLP と同じフォルダに保存します。

f:id:hikoma:20120802000355p:plain

PDF から cbz にコンバートする

以上で準備は完了です。コマンドプロンプトを開き、以下のコマンドを打てば PDF から cbz に変換することができます。

c:\ChainLP40b12> ChainLP.exe -b -ini kobo.ini -i "<PDFファイル>" -o "<出力ファイル>.cbz"

コンバートをバッチファイルにする

それで、この変換をバッチファイルにするとこんな感じになりました(ダウンロード)。

この kobo.bat に PDF ファイルをドロップすれば、コンバートされて出来た cbz ファイルが kobo.bat の横に出来上がります。PDF を複数ドロップすれば、全て変換されます。

バッチの中身を簡単に説明すると、

  • CHAINLP_DIR は ChainLP をインストールしたフォルダですので、適宜書き換えてください
  • SETTING は ini ファイルの場所です。%~n0 はバッチのファイル名で kobo.bat の場合は kobo という値になり、kobo.ini が読み込まれます。ですので、ファイル名を kobo-comic.bat にすれば kobo-comic.ini の設定を使って変換できます
  • OUTPUT_DIR は cbz の出力先で %~dp0 はバッチがあるフォルダです。好きなフォルダに変更してオッケーです

おまけ

本当は ini ファイルを使わず、直接 ChainLP.exe のパラメータを指定したかったのですが、高さの指定が分からなかったのであきらめました。ChainLP.exe -h でパラメータを確認できるので、興味があればチャレンジしてください。

また、出来上がった cbz ファイルの実体は zip ファイルなので、アーカイバに関連付けておくと捗りますね。

Java と MySQL で時差を正確に扱う方法。

最近は C#SQL Server を使っているので、JavaMySQL で遊ぶ時間がなくなってしまいました。ちょっと眠っていたネタがあったので忘れる前に書き残しておきます。

日時の国際化

日時の国際化というと、時差の変換が一番イメージしやすいかと思います。例えば twitter の場合、海外のツイートでも、タイムラインでは日本時間で表示されますよね?これを実装する場合、内部的には UTC 時間で保存しておいて、表示する人のタイムゾーンに合わせて時差を変換してやるのが一般的かと思います。

保存先に RDB を使う場合、WHERE で絞り込んだり、ORDER BY でソートする分には、タイムゾーン変換は不要なので、レコードを取得した後にアプリケーション側でタイムゾーン変換をすれば問題ありません。

だけど、GROUP BY を使って日ごとに集計をする場合、UTC をその人のタイムゾーンの日時に変換してから、GROUP BY する必要が出てきます。東京のように UTC との時差が固定(+9時間)の場合は、その分だけ足し引きして GROUP BY すればいいのですが、サマータイムがある国など時差が変動する場合、単純に足し引きすると、変わり目で時差がずれてしまうことが簡単に起きてしまいます。

 

例えば、2012年のアメリカでは 3月11日の2時にサマータイム(Daylight Saving Time)が始まり、時計が3時に進みました。

UTC太平洋標準時
PST (UTC-8)
太平洋夏時間
PDT (UTC-7)
3月11日 08:00 3月11日 00:00  
09:00 01:00  
10:00 02:00 03:00
11:00   04:00
|   |
3月12日 00:00   17:00
|   |
06:00   23:00
07:00   3月12日 00:00
08:00   01:00

このように、3月11日は実質 23 時間ですので(UTCで 3月11日8時から3月12日7時)、この日だけ 23 時間で GROUP BY するようにしないといけません。こういう場合は、DB 側でもタイムゾーン変換をする必要が出てきます。

 

タイムゾーン変換を行う場合、変換の元になるタイムゾーンの情報が必要になります。tz database と呼ばれる有名なデータベースがあり、多くのシステムはこれを元にタイムゾーン変換を行っています。サマータイムや政治的な理由でどこかの国のタイムゾーン情報が変わるたびに、データベースも更新されていて、年に何回も更新されています。現在は ICANN と IANA が管理していて、FTPのリストを見ると 2011 年は a から n まで 14 回更新されていることがわかります。

本題

それで、ここから本題なんですけど、アプリケーションとデータベースの両方でタイムゾーン正確に扱いたい場合、同一のタイムゾーン情報を参照しないと、変換が一致しないケースがでてきます。

そこで今回は JavaMySQLタイムゾーン変換を合わせる方法の一つを紹介したいと思います。試すには MySQLMaven と Git が必要です。Java では Joda Time というライブラリを使います(最近はデファクト?)。今回はうるう秒は扱いません。今年の7月1日に8時59分60秒が挿入されるというホットな話題なので少し調べてみたのですが、話すと長くなってしまうので気が向いたら別エントリで。Joda Time も未サポートみたいですし。

ビルド

まず tzcode と tzdata を IANA からダウンロードして同じディレクトリに展開します(今回は latest)。

wget ftp://ftp.iana.org/tz/tzcode-latest.tar.gz
wget ftp://ftp.iana.org/tz/tzdata-latest.tar.gz
mkdir tz
tar xvzf tzcode-latest.tar.gz -C tz
tar xvzf tzdata-latest.tar.gz -C tz

mysql_tzinfo_to_sql を使って、タイムゾーンデータのSQLファイルを作成します(参考)。

cd tz
make TOPDIR=.. posix_only
cd ..
mkdir output
mysql_tzinfo_to_sql etc/zoneinfo > output/tzinfo.sql

次に Joda Time (2.1) のタイムゾーン情報を変更してビルドします(参考)。 

git clone git://joda-time.git.sourceforge.net/gitroot/joda-time/joda-time
cd joda-time
git checkout -b v2.1_tz tags/v2.1
cp ../tz/* src/main/java/org/joda/time/tz/src
git clean -f
mvn clean package
mv target/*.jar ../output
# git commit -a -m "update tzdata to latest version"
cd ..

これで output ディレクトリに sql と jar ファイルが出来上がり。tzinfo.sqlmysql データベースに流し込めばタイムゾーンが更新されます。joda-time.jar はクラスパスに入れてあげてください。

以上で JavaMySQLタイムゾーン情報が一致し、時差を正確に扱えるようになりました。

テスト

試しに MySQLタイムゾーン変換できるか試してみましょう。

mysql -uroot mysql < output/tzinfo.sql

次にテーブルを作って、データを挿入。

mysql> CREATE TABLE tz (id int AUTO_INCREMENT PRIMARY KEY, dt DATETIME NOT NULL) ENGINE=InnoDB;
mysql> INSERT INTO tz(dt) VALUES ('2012-03-11 08:00'),('2012-03-11 09:00'),('2012-03-11 10:00'),('2012-03-11 11:00'),('2012-03-11 12:00'),('2012-03-11 13:00'),('2012-03-11 14:00'),('2012-03-11 15:00'),('2012-03-11 16:00'),('2012-03-11 17:00'),('2012-03-11 18:00'),('2012-03-11 19:00'),('2012-03-11 20:00'),('2012-03-11 21:00'),('2012-03-11 22:00'),('2012-03-11 23:00'),('2012-03-12 00:00'),('2012-03-12 01:00'),('2012-03-12 02:00'),('2012-03-12 03:00'),('2012-03-12 04:00'),('2012-03-12 05:00'),('2012-03-12 06:00'),('2012-03-12 07:00'),('2012-03-12 08:00');

CONVERT_TZ を使って、タイムゾーン変換してみると。

mysql> SELECT dt UTC, CONVERT_TZ(dt, 'UTC', 'America/Los_Angeles') LA FROM tz;
+---------------------+---------------------+
| UTC                 | LA                  |
+---------------------+---------------------+
| 2012-03-11 08:00:00 | 2012-03-11 00:00:00 |
| 2012-03-11 09:00:00 | 2012-03-11 01:00:00 |
| 2012-03-11 10:00:00 | 2012-03-11 03:00:00 |
| 2012-03-11 11:00:00 | 2012-03-11 04:00:00 |
| 2012-03-11 12:00:00 | 2012-03-11 05:00:00 |
| 2012-03-11 13:00:00 | 2012-03-11 06:00:00 |
| 2012-03-11 14:00:00 | 2012-03-11 07:00:00 |
| 2012-03-11 15:00:00 | 2012-03-11 08:00:00 |
| 2012-03-11 16:00:00 | 2012-03-11 09:00:00 |
| 2012-03-11 17:00:00 | 2012-03-11 10:00:00 |
| 2012-03-11 18:00:00 | 2012-03-11 11:00:00 |
| 2012-03-11 19:00:00 | 2012-03-11 12:00:00 |
| 2012-03-11 20:00:00 | 2012-03-11 13:00:00 |
| 2012-03-11 21:00:00 | 2012-03-11 14:00:00 |
| 2012-03-11 22:00:00 | 2012-03-11 15:00:00 |
| 2012-03-11 23:00:00 | 2012-03-11 16:00:00 |
| 2012-03-12 00:00:00 | 2012-03-11 17:00:00 |
| 2012-03-12 01:00:00 | 2012-03-11 18:00:00 |
| 2012-03-12 02:00:00 | 2012-03-11 19:00:00 |
| 2012-03-12 03:00:00 | 2012-03-11 20:00:00 |
| 2012-03-12 04:00:00 | 2012-03-11 21:00:00 |
| 2012-03-12 05:00:00 | 2012-03-11 22:00:00 |
| 2012-03-12 06:00:00 | 2012-03-11 23:00:00 |
| 2012-03-12 07:00:00 | 2012-03-12 00:00:00 |
| 2012-03-12 08:00:00 | 2012-03-12 01:00:00 |
+---------------------+---------------------+
24 rows in set (0.00 sec)

ちゃんと変換できましたね!後は GROUP BY でもなんでもやっちゃってください。

ついでに

Google Closure Library を使うと JavaScript でもタイムゾーン変換もできちゃいます。詳しいことは id:teppeis による、時を超えた JavaScript で解説されています。goog.i18n.TimeZone 用のタイムゾーンデータを作る必要が出てきますが、残念ながら公式な作成方法が提供されていません!どうやら pytz から作られているようですが、GWT で使われているデータを参考に 自力で tz database から作らないといけないようです。ただ、Closure では 標準時差 (std_offset) を一つしか設定できず、標準時差の変更に対応していません。。。って細かい話は置いておいて、先ほど作成した Joda Time からの方が少しは楽に生成するかと思います。Joda Time がやっていることを真似すれば JavaScript でも上手くタイムゾーンを扱えるので、興味があればソース読んで勉強してみてください。

最後に

この記事では tz database から JavaMySQL 用のタイムゾーン情報を生成する方法を紹介しました。肝心なことは、タイムゾーン情報は頻繁に変更されるので、タイムゾーン変換する時は、元になったタイムゾーン情報が何かを意識するようになってもらいたいなと思います。

(追記)

とは言っても、普通の使い方で影響が出る範囲はほとんどないと思うので、神経質になる必要はないんじゃないかと思います。

Synclogue に転職しました

 

2012年5月31日を持ちましてサイボウズ株式会社を退職しました。

新卒で入社してから4年間、いろいろな人にお世話になりました。本当にありがとうございます。

6月1日から Synclogue (シンクローグ)というベンチャー企業でお世話になります。

 

サイボウズでは、目立った活動はしていないのですが、ここ2年半くらいは kintone(キントーン) というアプリケーションプラットフォームを開発していました。

ドラッグアンドドロップでお手軽にフォームを設計できるのがウリですが、その裏側でレコードを格納するスキーマレスなデータベースを管理する部分をメインに、サーバーサイド全般の開発を担当していました。JavaMySQLは大好きです。

クライアントサイドもいろいろやりましたが、最後に id:ama-chiPhone アプリ用のウェブページを作ったので、アプリストアに登場する日をお楽しみに。

 

サイボウズには刺激を与えてくれる優秀なエンジニアが多く、4年間開発に没頭することができました。自分が感じたサイボウズの良いところを挙げると

  • ウェブアプリ開発に必要な技術を上から下まで(CSSからDBまで)高いレベルで実践できる環境がある
  • インフラ、ミドルウェア、モバイル、パッケージ製品などウェブアプリ以外の開発力もちゃんとある
  • 開発プロセス、チームががっちりしているので、開発のみに集中できる
  • 品質保証がしっかりしていて、レビューや試験に対しても時間を多く使える
  • ラボの凄い人と交流(仕事も)でき、考え方が変わってしまうくらいの刺激になる
  • 勉強会も盛んで、新しい技術のキャッチアップも早い
  • なんだかんだ親切な人が凄く多くて、みんな助けてくれる

こんな感じで、製品の正しい作り方を学び実践してきた手応えはあり、製品開発に関しては自信を持ってできるようになれたんじゃないかなと思います。ここまで成長できたのはサイボウズのおかげです。

 

その反面、いろいろな立場の人が開発に関わるので、自分の判断で行動できる部分が限られます。不具合を直したくても手を出せなかったり、新しい機能をいろいろ試してみるにも工数の調整が必要だったり、やりたいことをやるためにエネルギーを使わないといけないもどかしさはありました。

それでもプログラマという立場で得意なことをやるのは楽しいし、ちゃんと成果も出るので居心地は悪くはなかったのですが、自分のキャリアを考えた時にもっと幅広い経験を積みたいと考えていました。

そんな時に Synclogue という凄い野望のスタートアップに参加する機会を頂くことができました。技術的なハードルは高く挑みがいのあるプロジェクトで、完成したら凄い製品になるのは間違いありません。

職場を変えないと新しいチャレンジができないのは自分の力不足です。Synclogue では、新しい仲間と協力し、本気でぶつかりあって、世の中に役立つ素晴らしい製品を作りたいという気持ちでいっぱいです。

 

最後に、これからも kintone とサイボウズが進化していく姿をすごく楽しみにしています。
今までありがとうございました!これからもよろしくお願いします!

 

 f:id:hikoma:20120525181045j:plain
すばらしい仲間と一緒に働けたことを誇りに思っています。

Javaの暴走スレッドを見つける (2)

前に、コマンドだけで見つけるやり方を書いたのですが、このやり方だと瞬間的なデータしか取得できません。そこで ThreadMXBean にある getThreadCpuTime メソッドを使う方法を試してみました。このメソッドは指定したスレッドの合計 CPU 時間を返してくれるので、CPU 時間を2回取得し、その間の時間で割れば、平均 CPU 使用率を得ることができます。10秒間で95%以上使っているスレッドを検知するみたいな使い方ができそうです。

コードはこんな感じになりました。

process メソッドの中で、前回 process メソッドが呼ばれた時からの CPU 使用率の平均を求めて、threshold 以上だった場合に、handle メソッドを呼び出してくれます。maxDepth は取得するスタックトレースの深さを指定する変数です。

デフォルトでは、このクラスがロードされている JVM のスレッドを監視しますが、JMX で接続すればリモートの JVM にもアタッチできます。Maven Tomcat Plugin などでサクッとテストする場合には MAVEN_OPTS に以下のパラメータを指定すれば JMX を受け付けてくれるようになります。

  • -Dcom.sun.management.jmxremote
  • -Dcom.sun.management.jmxremote.port=<port番号>
  • -Dcom.sun.management.jmxremote.ssl=false
  • -Dcom.sun.management.jmxremote.authenticate=false