PDFBoxを使ってPDFを作成する(その2)

PDFBoxを使ってPDFを作成しようとしたところ・・・という話でした。

5.改行、改ページができない

できない、と書きましたができるんです。
改行は
cos.newLine();
改ページは
page = new PDPage();
document.addPage(page);

でできます。でもそうじゃないんです!
長い文やページを超える文を出力するときに、自動で改行や改ページしてほしいんです!
結論。できません。
そういうものかもしれませんが、なんとなく自動でできるような気がしていました。
ということで、文字数/行数を自分でカウントして、よきところで改行/改ページを入れる方法で解決しました。
コードは汚いので割愛します。。

6.ファイル保存でOutOfMemoryError発生

今回、1000ページ(数百MB)以上のPDFを作成することもあったのですが、
document.save("sample.pdf")
のところでOutOfMemoryが発生することがありました。
調べたところ、ページ数が多いと発生することがあるという記事を見つけました。
(ちなみにJDK1.6限定で、1.7だと発生しないとのことです。今回の環境は1.6でした。)
この記事なんですが、リンク切れで表示できません。一応、URLはこちらです。
http://www.gcgate.jp/engineerblog/2013/12/06/223/
記事によると
・ある一定ページ数になったらPDFをファイルに書き込む
・その書き込んだPDFファイルを読み込みページを追加する
・繰り返す
で解決したということだったので、これを試したのですが解決せず。
いろいろ試して、PDFファイルを分割して保存する方法で解決できました。
これもコードは割愛しますが、ページ数を自分でカウントして、決まった件数のときにファイルを保存する、という流れです。
今回のケースは、ページ数が多いというより、ファイルサイズの大きさによるような気がします。
分割する際ファイルサイズでできればいいのですが、それは厳しいのでページ数で区切りました。

7.作成したファイルで検索ができない

すみません。これはまだ解決できていません。
1つ前の記事で書いた通り、今回日本語を表示するためにIPAゴシックを使いました。
すると、作成したPDFをAdobeのPDFリーダー等で開いて、検索しようとすると
検索できるファイルと検索できないファイルがありました。何か特定の文字が含まれると検索できないようなのですが、原因となる文字は特定できていません。
また、PDFBoxで何かしら対策ができるのか、も今のところ不明です。

他のライブラリは使っていないので比較ができないのですが、PDFBox、便利は便利だけどすごく使いやすくはない、というふわっとした感想で終わりたいと思います。
あ、公式サイトのFAQは結構役立ちました。

PDFBoxを使ってPDFを作成する(その1)

JavaでPDFファイルを作成することになり、いろいろライブラリを見た結果、一番よさげだったApache PDFBoxを使うことにしました。
一応やりたいことはできたものの、困ったことやわからないことがポロポロとあったので、そのあたり書き残しておこうと思います。
ごくごく基本的な使い方(HelloWorld的な)について説明しているページはいくつか見つけたものの、そこから先の細かい使い方を書いてくれているページがあまりなかったので、どこかの誰かの役に立てばいいなと思いつつ。。。

1.ダウンロード

公式サイトのダウンロードページからダウンロードします。

2.HelloWorld

特に難しいことはありません。以下のコードでHelloWorldと出力されます。正確には出力されたPDFファイルが作成されます。ですね。
細かい説明は省きます。
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
PDFont font = PDType1Font.HELVETICA_BOLD;
PDPageContentStream cos= new PDPageContentStream(document, page);
cos.beginText();
cos.newLineAtOffset(0f, 0f);
cos.setFont(font, 12);
cos.setLeading(12);
cos.showText("Hello World");
cos.endText();
cos.close();
document.save("helloworld.pdf");
document.close();

※PDPageContentStreamは、1ページにつき1回生成します。
1ページの中に異なるフォントや異なる文字サイズで出力する場合は、
cos.beginText();
から
cos.endText();
までを繰り返します。

3.日本語

必要に応じてフォントをダウンロードしてください。ちなみに今回はIPAフォントを使いました。
そして、
PDFont font = PDType1Font.HELVETICA_BOLD;
の部分を
PDFont font = PDType0Font.load(document, new File("/usr/share/fonts/ipa-gothic/ipag.ttf"));
とすることで、日本語も表示することができます。

4.画像

PDImageXObject ximage = PDImageXObject.createFromFile("photo.jpg", document);
cos.drawImage(ximage, 100, 100, ximage.getWidth(), ximage.getHeight());

で画像が表示できます。

文字の表示にしろ画像の表示にしろ、それぞれ表示位置を指定できるので、1つのページに文章と画像を表示することももちろん可能です。
表示位置は、実際に出力してみて、微調整した方がいいと思います。
また、画像の表示は文字の表示に比べてかなり時間がかかります。(画像のサイズが大きいと特に)

ここまでが基本的な使い方になります。日本語も表示できる、画像も表示できる、よしよし・・・と思ったのも束の間、ちょこちょこと問題が発生するのでした。

続く

SpringでNeo4jを利用する際の注意点

spring-bootからNeo4jを利用する場合、spring-data-neo4j(neo4j-ogm)と言ったライブラリでアクセスする事になります。
その際、バグと思われる現象に遭遇しましたので、忘れないように記しておきます。

概要

ValueObjectの配列またはリストをフィールドにもつEntityを作成します。
Neo4jにValueObjectをNodeとして登録させたくない為、フィールドをコンバータで文字列シリアライズしSaveを行いました。
Saveは正常に行われ、Neo4jへのストアされた内容も想定通りのものでしたが、このエンティティをLoadすると、コンバータの処理で型キャストエラーが発生しLoadに失敗します。

詳細

  • LoadできるEntity
    下記のEntityはSave、Loadが行えます

 

  • LoadできないEntity
    下記のEntityはSaveできるが、Load時にエラーが発生する

ValueObjectのListフィールドを追加する。フィールドをコンバーターにより文字列(Json)に変換する

このエンティティをSave後にLoadを実行すると、下記のような例外が発生し失敗します。スタックトレースから、キャストエラーが確認できます。

ここで発生している例外がListからStringへの変換例外だった為、なぜ発生するのか原因がわかりませんでした。Load時に行う処理は文字列(JSON)からValueObjectへの変換のはずです。なぜListを文字列にCastしようとしているのか、、、

原因

スタックトレースを追っていくと、GraphEntityMapperクラスに問題がありそうです。
当該箇所を確認してみます。

配列、Listの場合の分岐があります。どうやら、デシリアライズ先のフィールドがList(配列)の場合のみここで型の変換を行っています。

Neo4jのNodeは、プロパティに数値、文字列、真偽値またはそれらの配列を持つ事ができます。そのため為のロジックだと思いますが、コンバータの有無を確認せずに型変換を行っています。Writerの中でCallされるコンバータは文字列を期待ていますがListが渡される為、文字列にキャストを行おうとし例外となりました。

対応

色々試行錯誤した結果、当該部分を削除する対応を取りました。
テストして見る限り、動作に変わりは無いようなのですが、

まとめ

spring-data-neo4jでList(配列)フィールドにコンバーターを設定する場合は、本現象が発生します。
また、本現象ですが、キャッシュオブジェクトが利用されると再現しませんのでご注意ください。凄くハマりました(–;

Solr Cloudを動かしてみる

シーマークの山本です。

Apache Solr は全文検索エンジンとして様々なところで使われており、もはや特殊なプロダクトでは無く、検索機能を実現するならSolrというほどコモディティーとしての広がりを見せています。Solrバージョン5からはSolr Cloud機能が実装され、検索「エンジン」から検索「システム」へと変貌を遂げてきています。

そこで、Solr Cloudを使って検索システムを構築する方法についてまとめていきたいと思います。ただ、Solr Cloudのチュートリアルにある付属のサンプルを動かす方法ではなく、実際の商用プロジェクトで必要になりそうな「こんな時どうする」的なTipsを中心にまとめていきます。

構築する検索サービスの想定(=要件)

商用で提供する検索サービスであれば最低限気にすることではありますが、今回説明していくためのサービス想定、言い換えれば要件を列挙しました。

  1. AmazonのAWSや、Microsoft Azureなどのクラウド環境で複数台のサーバインスタンスを使ってSolr Cloudを構築する
  2. 検索サービスが止まらないよう高い可用性を実現する
  3. 検索サービスで提供する機能が増え、Solrの設定を変更する場合でも簡単に行える
  4. 利用者が増えても検索速度が落ちないよう簡単に負荷分散できる
  5. 検索対象データが増えても検索速度が落ちないよう簡単に拡張できる

こう書いてみると、なかなか大変そうな要件ではありますが、Solr Cloudを使えば、案外簡単にできちゃったりする(かも)のでご安心を。

 

1. 開発環境の構築

まず、「要件1 複数サーバを使って構築すること」をいきなり実現しようとすると、AWSのアカウントだったり費用がかかったりするので、まずは自分のPC上で開発環境をつくるところから始めましょう。

開発環境ですが、私がMac派なので、Macを前提に書いていきます。ただ、Windowsとまるっきり違うかどうかと言えば、あまり差異はないはずです。明らかに違うところは補足を入れます。

1.1 Solrのダウンロード

まずは、Solrのダウンロードです。執筆時点では 6.2.1 が最新でした。

https://lucene.apache.org/solr/mirrors-solr-latest-redir.html

ダウンロードしたSolrをお好きなところに展開します。

 

1.2 検索サービス用のSolr configセット

検索サービスとしてどのようなデータをインデックスし、どのように検索させるかを定義するため、Solrではいくつかの設定ファイルを用意する必要があります。通常のSolrとは異なり、Solr Cloudで利用するSolr設定ファイルセットは、zookeeperという別のミドルウェアに登録し管理することになります。

Solr設定ファイルの内容については、本題からはずれることもあり、Solrダウンロードパッケージに含まれるサンプルである「techproducts」用の設定ファイルをそのまま利用します。既にあるので、それを適当なところへコピーします。

 

次は、Solrの設定から一旦はなれ、Solr Cloudを構成する名脇役 zookeeperの設定についてです。

 

1.3 zookeeperを設定する

zookeeperって初めて聞いたって人もいるかと思いますので、軽く紹介を。

https://zookeeper.apache.org/

Apache zookeeperは、複数のサーバインスタンスで構成される分散システムにおいて、設定情報の同期、グルーピングや名前付けの管理を提供するミドルウェアです。

Solr Cloudでは、Solr設定ファイルの集中管理と配布、Solrサーバの管理(shards / Replica、solr nodeの生死等)をzookeeperが提供しています。

zookeeperのインストールは、上記のzookeeperのサイトからダウンロードして、Solrと同じく好きなところに展開します。(もし、Mac環境でbrewをお使いであれば、brew install zookeeperでインストールも可能です)

執筆時点での stableなバージョンは 3.4.9 でした。

http://ftp.jaist.ac.jp/pub/apache/zookeeper/stable/zookeeper-3.4.9.tar.gz

zookeeperは、検索システムの設定情報や構成情報を集中的に管理しています。zookeeperが止まれば、Solr Cloudも停止します。そこで、zookeeperの可用性を高めるため、zookeeperを複数台のサーバーで稼働させます。できれば、Solr Cloudとは異なる専用サーバを用意することが望ましいです。また複数台と言ってもzookeeperの特性上、奇数台で運用をすることが要件となっています。つまり、3台、5台構成をとることが必要です。開発環境では1台の中で3プロセスを起動するようにしましょう。

まず、3プロセス用のzookeeper設定ファイルを用意します。

そして、格納されるデータディレクトリ(dataDirで指定されているディレクトリ)を作成し、そこに設定ファイルを追加します。

これで、zookeeperを起動する準備が整いました。さて起動させましょう。

一応止めるコマンドも。

これで、zookeeperの準備は整いました。

 

1.4 Solr configファイルセットのzookeeperへの登録

1.2 で用意したSolr設定ファイルセットをzookeeperに登録しましょう。登録する際、zookeeper上で管理するための名前を付ける必要があります。ここでは「techp」としました。

これで、Solr Cloudで利用される設定ファイルセットがzookeeperで「techp」という名前で管理されました。

 

1.5 Solr cloudの立ち上げ

本体であるSolr Cloudを立ち上げましょう。複数台で構成するのでしたよね。開発環境なので、1台で複数インスタンスを立ち上げましょう。今回は4台構成とします。

まず、そのための準備です。

では、立ち上げます。Solrの待受ポートは通常は8983なんですが、4つのインスタンスを立ち上げるため、8983, 8984, 8985, 8986として起動します。

これで、4インスタンスがSolr Cloudとして立ち上がっています。

念のため、停止させるコマンドも。

 

1.6 collectionの作成

Solr Cloudでは、検索データをとりまとめる単位をCollectionと呼んでいます(通常起動のSolrでcoreと呼ばれていたものと同じ概念です)。Collectionを作成しましょう。Solr Cloudでは、複数台のサーバにうちどれか1台に対して操作するだけで、Solr Cloud全体に反映されます。

パラメータの説明です

パラメータ設定内容
-ctechproductsCollection名
-ntechpzookeeperで登録されている設定ファイルセット名
-shards2シャード数。1つのインデックスを複数に分割する場合。通常SolrでいうShardsと同じ意味。
-replicationFactor2レプリカ数。レプリケーションとしていくつコピーを作成しておくかの指定。通常Solrではreplication用Solrの数と同じ意味。
-p8984操作対象とするSolrインスタンス。今回であれば、8983, 8984, 8985, 8986のどれか

 

作成されたことを、Solr管理画面で確認してみましょう。

localhost8983

 

1.6 データの投入

Solr Cloudへのデータ投入は様々な方法があります。これについては本題からはずれるため、サンプルで用意されているデータファイルをコマンドを使って投入してみましょう。ここでも、複数台のうちどれかにデータを投げれば、Solr Cloud全台に反映されます。8984, 8986 に投げてみる例です。

検索できるかどうか、Solr管理画面で確認してみましょう。

solrsearch

できましたね。

今回は、ここまでといたします。残りの部分は、後日アップいたします。

 

性能診断分析サービス事例 その3

シーマークすずきです.

最近,つけ麺にハマっています.自分的には約7年周期でつけ麺がマイブームになる,という事実...

さて,性能診断分析サービスの事例,第3段となります.今回は,性能向上です.

■サイト利用者から「ページが遅い」の声

あるコンシューマ向けWebサイトを運営しているお客様の事例です.その会社の事業部の責任者は,「ページが遅い」というサイト利用者からの意見が多くなってきていることを課題の一つとして認識していました.実際に,自分でブラウザで試してみても,時々詰まったような遅いページがあったり,特定のページが極端に遅い,という経験を実際に体感していたのです.サービス責任者としては,お客様のニーズに応えることが最も重要です.Webサイトとしてニーズに応えることに加えて,リーズナブルな応答時間内に,という性能観点の目標もあるのです.そこで,サービス責任者は「ページが遅い」というサイト利用者からの声に対して何らかの改善策を具体的に検討することになりました.

 

■暗中模索

まず,開発パートナー会社さんとインフラを提供しているインフラ会社さんに現行システムの性能向上のための施策案を検討してもらいました.しかし,開発パートナー会社さんからは,簡単に云えば「マシンが遅いからだと思う」や「DBが遅いから仕方ない」とか「デザインが重いから」という様なポイントが出てきて,インフラ会社さんからは,「アプリが遅いからどうしようもない」とか「DB側は遅いSQLが無いので問題ではない」という指摘が出てきてしまい,お客様のサービス責任者の方も困ってしまいました.「取り合えず,自分たちじゃない」という反応だったからです.現行システムを請け負っている会社としては,仕事を増やしたくないとか責任範囲外なので,ということをお客様に伝えたい気持ちがあるのでしょう.一種の自己防衛本能です.

サービス担当者は,暗闇の中で何かを探すような感じで,手がかりが分からないままに「手探り」状態でなんとかして問題を解決しなければなりません.そんな文字通り暗中模索の頃にお客様からご連絡を頂きました.

 

■まずは現状把握

まずは状況を正確に把握しなければ,対策案もでてきません.そこで性能診断分析サービスのアプリケーションの挙動を数値で計測する技術が活きてきます.本番環境で数値で計測した結果は何よりも説得力があります.仮に改善内容の方法にアプリの改修が絡んだ場合でも,開発パートナー会社さんも計測した数値で説明すると,「なるほど,これは改修の効果が期待できますね」ということでご納得してタスク化してもらえます.逆に,開発会社様からは,「本番サービス環境下では,このメソッドがこんなに時間がかかっているのですね.意外だなぁ.」と新たな発見をしてもらえることもあります.ともかく,本番サービス環境のアプリケーションの挙動を数値で計測することから作業を開始しました.

 

■課題は何か?

次は,課題は何か?です.お客様のWebサイトにはたくさんのメニューやコーナーがあります.まずは,そのメニューやコーナー事に時間毎応答回数や平均応答時間をまとめました.予めお客様から頂いていた,このWebサイト内のビジネス上の重要度が高いメニューやコーナー,重要シナリオ(ページ遷移)と見比べてみると,課題が明確になってきました.どうやら,以下の2つが優先的に対処すべき課題でした.

  • 検索メニューの応答性能が10秒以上になることが多々ある.
  • お申し込みメニューの平均応答時間が遅い.

サイト全体のプログラムを分析するのはそれはそれで時間と手間がかかりますが,ある程度絞って注力することで,深い診断と分析が可能となり,結果としてスピーディに成果を得ることができます.

お客様と相談し,改めて今回の課題に対する目標は,

  • 検索メニューの応答性能が悪化する原因を特定し,対策案を検討し,提案する.目標は平均処理時間30%短縮.
  • お申し込みメニューの平均応答時間を20%短縮.

となりました.

■処理内容の詳細分析

本番サービス環境で実際に稼動しているアプリーケーションの稼動状況を映し出すことにより,様々なことがわかってきます.

まずは,「検索メニュー」の方のリクエスト状況の分析です.特に,平均応答時間だけで見ているとスパイクして遅い応答リクエストが見えにくくなります.つまり,リクエスト回数が多いサイトでは,リクエスト数である分母が非常に大きいため,平均することで,時々発生している遅いリクエストが見えなくなってしまいます.性能診断分析チームが分析する際には,「平均値とは丸められた値である」ということを強く意識し,その計測区間の最大値(その計測区間内で一番遅かったリクエスト応答時間)も一緒にプロットするようにします(下図).こうすることで,実態が見えてきます.実際には10秒以上の応答時間だったリクエストは多発していることがハッキリしました.

 

更に,一回の検索リクエストの処理内容の内訳を以下の様に横軸が時間の図化することで,どのような処理に時間がかかっているのかが分かります.

この見える化は強力です.ここの事例とは別のお客様の例では,Webの1ページの画面を処理するために,アプリケーションから同等SQLが300回実行されている実態がこの図化によって明らかになったこともありました.一回のSQLが50ミリ秒だとしても,300回×50ミリ秒で15000ミリ秒,つまり,15秒です.しかも,よくよく分析してみると実は,1回のSQLで十分だったいうことがありました.既存のDAOコンポーネントを部品化した開発を行い,ループ中からDAOを呼出す作りだったのです.SQLは”表”で結果が取れるにもかかわらず...インフラ側のDB管理者は遅いSQLはチェックしていることが多いですが,流石に1アクセスの処理で大量にSQLを発行しているのか,複数リクエストにより1発づつ発行されているかは意識していません.

さて,話を戻します.図中のsearch()が横に細い時は全く問題ありません.しかし,横に長くなるケース,要は,処理時間が延びてくる現象が確認されました.塵も積もれば山となります.図から推察するに,search()はループ中で必要な処理回数呼ばれる様です.図では80回前後呼び出されている絵です.search()メソッドが10ミリ秒なのか20ミリ秒なのかは,高々10ミリ秒の差ですが,比率では2倍の差になります.つまり,大量に発行されている場合は,全体が3秒だった処理が2倍の6秒になる訳です.しかもその呼出回数が多数であるならば,さらに時間がかかります.遅くなっている原因は,カットオーバー後,取り扱いデータ量が増え,search()メソッドが順次遅くなってきているためでした.開発側と相談し,該当ソース箇所をレビューした結果「四重ループ」が確認されました.

 

■多重ループに注意

プログラムでループ処理を書くことは簡単です.もちろん,ループ処理の中でループを書くこともできます.更に,一番内側の処理で別のメソッドを呼出し,呼出したメソッドの中で別のループを実装する.簡略化すると以下の様なコードでした.

※実際のコードはもちろん,もっと処理内容があります.

このsomeMethod()メソッドのコードは四重ループです.二重ループの内側で二重ループを持つメソッドを呼び出しているのです.性能的に危険なループです.経験豊富なプログラムならば臭うことでしょう.

上の簡略ソースの変数outer,innerのいずれも10ならば1ミリ秒以下.あっという間です.

outer,innerいずれも100として,私の作業PC上でsomeMethod()メソッドの応答時間は50ミリ秒程度でした.これも問題ないです.

outer=100,inner=1000ならば,6秒程度.ちょっと遅い.

outer,innerいずれも1000になれば,10分は返ってきません.しかも,その間ハードウェア的に1コアはCPU100%になります.

そもそも変数outerやinnerが10000になる可能性があるならば,設計段階で実現不能なロジックとして除外しなければなりません.ブラウザーで検索ボタンを押してから,10分待っている利用者はいないでしょうから,outer/innerが1000でもWebアプリケーションとしては既に現実的とは云えないでしょう.

少し脱線しますが,forループやwhileループとして見えないループもあります.再帰呼出です.再帰呼出で有名なフィボナッチ数列を例にします.

フィボナッチ数列のJavaプログラムは,以下の様な再帰呼出が典型的な実装コードです.

さて,質問です.Nがいくつぐらいまでが現実的でしょうか?最近の高速なCPUを搭載したマシンでもN=50でfibonacci()関数は現実的な時間で終了しません.高々N=50です.forループは1個しか見えないのに.

話しを戻します.多重ループは指数的に処理時間が延びることを理解しなければなりません.事例では,四重ループの内側の処理効率を見直して改善することで劇的に応答時間が改善しました.

■チューニングの鉄則

プログラムをチューニングする際の鉄則は,チューニング効果の高い箇所から手を入れる,ことです.例えば,全体が10秒のリクエストであれば,その処理時間の内訳が大きい箇所をチューニングするのが効果を得やすい訳です.元々1秒しかかかっていないメソッドを一生懸命チューニングして処理時間を半分にしても,0.5秒しか短縮できませんが,元々8秒かかっている場所を半分にできれば,4秒の短縮なのです.

性能診断分析サービスの性能向上を目的とした現場の場合は,「もっとも少ない工数で,もっとも高い効果」が得られる対策案を提案しなければなりません.そのためには,どうしても本番サービス環境でアプリケーションの挙動を数値で計測する必要があったのです.

 

■もうひとつの課題

「お申込みメニューの20%短縮」の方です.Webサイトの場合,検索して,購入する,又は,申し込みをする,ことが一般的です.利用者に検索してもらうのは,次のアクションとして購入や申し込みをしてもらうためです.一般にWebサイトの最重要機能は「申し込み」と云っても過言ではないでしょう.注文も申し込みの一種です.最近だと「申し込み」の後に「共有」することも大切な機能になってきているようです.つまり,SNSなどに購入した事をツブヤき,お友達と買った事実を共有するという機能です.このサイトは共有はありませんでしたが,「申し込み」機能は重要な機能でした.直接,売上に影響するトランザクションです.この画面遷移を詳細にモニターしました.

申し込みの一連のリクエストの前後で大量のXMLファイルのI/OとXMLパース処理が見つかりました.開発会社様に確認すると,マーケティングデータの収集のための処理でした.それにしても,ファイルから都度読みだしているし,しかも,XMLパースを毎度行っています.その後,更にバックエンドにXML電文を作成し,http通信でそのXMLを数回投げています.応答もXML形式で返ってきて,その返信をパースして解釈後,ログ記録用XMLを作成してログ出力していました.

ディスクからの読みだしはOSキャッシュに載れば性能はある程度確保できますが,ディスクへの出力は極力避けたい訳です.詳しく出力ファイルの場所を確認すると,悪い事に,NFS上への出力でした.高負荷でないWebサイトなら特に問題ではありません.しかし,高負荷サイトの場合は気にしなければなりません.複数台のWEBアプリケーションサーバが水平分散できないからです.また,NFSサーバの障害で,全てのWEBアプリケーションサーバに影響をおよぶことも問題なのです.言い換えれば,ビジネスの停止になってしまうリスクがあるからです.

以下に挙げる2つの主な対策案を提示しました.

1)WEBアプリのファイル出力はローカルファイルへ.

開発会社とインフラ会社が別々だと,インフラ会社さんの運用の手間が楽な方の設定にされてしまうことがあります.設定ファイルの変更で入力パスを変更可能な場合,多くの場合は,一か所の変更で反映できる,という理由からNFS上に置かれる事が多々あります.性能的な観点は全く考慮されません.入力ファイルはNFS上に置き,出力ファイルはローカルディスクに設定変更を提案しました.

2)キャッシュの利用

バックエンドに数回投げているXMLのうち,数回は履歴を紹介する電文でした.これは「履歴」ですから,過去の記録です.後から追加はありますが,変更される内容ではありません.従って,キャッシュが効果的に機能します.memcacheやredisなどのKVSを利用し,オブジェクトをキャッシュする仕組みをご提案しました.キャッシュ機能は機能的には単純です.後から機能を追加することは比較的容易です.効果は非常に高いです.

■目標達成.更にもっと.

ご提案した内容を対策後,後日,本番環境で効果測定を行いました.2つの課題箇所の両方とも目標を達成していました.お客様も喜んでいました.喜んでいるのも束の間,応答時間が速くなることを知ってしまったため欲が出たのでしょう.「更にもっと速くしたいのですが,どうすればよいでしょうか?」と相談を受けました.文章が長くなってしまったので,今回はここまでとします.次回は高負荷,高性能を実現するためのサーバ側の対策案についていくつかご紹介していきたいと思います.