AWSを使ってみる. ( ELB 編 )
ELB*1は aws の構成の中で一般的にロードバランサ(負荷分散装置)と呼ばれるものを提供する機能です。
- ELB配下のロジックサーバ(インスタンス)に対して適切にトラフィックを分散して流すことができる
- 配下のサーバのヘルスチェックを行うことでサーバ障害等の発生時に自動的に障害サーバを切り離すことができる
- AZを分散して配下のサーバを配置した場合はまずAZ単位で分散した後にAZ内のサーバに分散することが可能。AZレベルの障害も回避可能。
- ELB自体の耐障害性を高めるためにRoute53 (DNSラウンドロビン) も併用するとさらによし。
- VPCと併用することでユーザのアクセスするサーバをELBとしてVPC内のサーバーを隠ぺいすることが可能。
ELBの構成手順
前回構成したVPCの中にプライベートIPのみを持つ複数のHTTPDサーバに対して外部からELB経由でアクセスしてみます。
User <====> ELB ( Public Subnet ) <----> EC2 ( Private Subnet ) x2
上のような構成をしてみます。ただしこの構成を実現する場合はプライベートサブネットをパブリックサブネットと同一のAZにする必要があります.
設定はEC2のマネージメントコンソールの左カラムのNETWORK & SSECURITY 内の Load Balancers が ELB の設定です。
まずはELBの管理上の名称を決めるのと、どのプロトコルの通信を転送するかを決定します。VPC内に設置するのでそれを選択します。
HTTPSをサポートする場合はこの間にSSL証明書関連の設定が挟まりますが、今回はHTTPでしたので次の項目であるヘルスチェック関連の設定を行います。今回はすべてデフォルトとしときます。
次にサブネットを指定します。配下にするEC2の属するサブネットではなくELBの属するパブリックサブネットを指定します。ELBは外部からのアクセスに利用する場合(一般的)はパブリックなセグメントに配置する必要があります。
次にELBに対するセキュリティグループを定義します。HTTPを外部から接続なのでデフォルトのままでOKとします
ELBに割り当てるインスタンスを指定します。ここでプライベートセグメントに属するインスタンスが選択肢に現れない場合はELBが配置されたAZと異なるパブリックセグメントでプライベートサブネットを定義している可能性が高いです。
同一AZという条件に沿っていればアサインするインスタンスはプライベートなセグメントに配置してあるものでもOKになります。
最後確認画面が出ますのでCreateでELBの作成完了です。
挙動確認
ELBに割り当てたインスタンスにhttpdをインストールして適当な /index.html を配置します。access_log を tail しているとELBのヘルスチェックアクセスがきて200応答をしていることがわかります
[root@ip-10-0-1-190 httpd]# tail -f access_log 10.0.0.87 - - [03/Mar/2014:10:36:22 +0000] "GET /index.html HTTP/1.1" 200 85 "-" "ELB-HealthChecker/1.0" 10.0.0.87 - - [03/Mar/2014:10:36:52 +0000] "GET /index.html HTTP/1.1" 200 85 "-" "ELB-HealthChecker/1.0" ..
ELBのマネージメントコンソールからヘルスチェックステータスを確認することが可能です。
ELBのDNS Nameをしらべて http でブラウザでアクセスしたらアクセスできると思います。
リロードするとアクセス元のインスタンスが切り替わっているのも確認できます。
便利な世の中になったもんだと実感しました。
AWSを使ってみる. ( VPC 編 )
VPC
今回はAWSのVPC*1を使ってみます。VPCを利用するとEC2などの仮想サーバを仮想的なプライベートネットワークで起動することが可能です。最近ではユーザがアクセスするサーバとシステムの中核となるサーバをネットワーク的に分離し、後者をプライベートネットワーク内に隠ぺいするシステム構成が多く見られます。
また、SSH等を用いてサーバにログインする際にパブリックIPが割り当てられている少数の踏み台のサーバを経由し、それ以外のサーバプライベートなネットワークでシステム管理するようなセキュリティを確保するためにも利用されます。
AWSコンソールからVPCを選択し、VPC Dashboard から 「Get started creating a VPC」を選択します。
するとどのような形態のVPCを作成するかを選択するメニューが表示されます。
- VPC with a Single Public Subnet Only
これはパブリックなサブネットを1つ作成する選択肢です。パブリックなサブネット内で起動したインスタンスはグローバルIPを付与することで外部のインターネットと接続することが可能です。
- VPC with Public and Private Subnets
これはパブリックなサブネットとプライベートなサブネットを1つづつ作成する選択肢です。プライベートなサブネット内で起動したインスタンスはパブリックなネットワーク内に設置したNATインスタンスを経由してインターネットに接続します。
VPCの作成
今回は「VPC with Public and Private Subnets」を作成してみます。次の画面で構成するネットワーク等の情報が出ますので必要に応じて変更します。
デフォルトでは以下の構成になります。
- 10.0.0.0/16 のネットワークでVPCを構成します。
- 10.0.0.0/24 のサブネットでパブリックなネットワークを構成します
- 10.0.1.0/24 のサブネットでプライベートなネットワークを構成します
- NATインスタンス(EC2)をm1.small構成でElasticIP付きでパブリックなネットワークに設置します
作成が完了すると EC2 Dashbord で EC2がひとつ起動し ElasticIPがひとつ割り当てられています。作られた2つのサブネットを確認してみます。
- パブリックサブネット: Routeのテーブルで一般IPの向き先はインターネットゲートウエイになっている。
- ブライベートサブネット: Routeのテーブルで一般IPの向き先はNATインスタンスになっている。
VPC内のサブネットにインスタンスを作成
まずはパブリックサブネットにEC2を立ち上げます。Step3 の Configure Instance Detail で属するネットワークを選択します。また、このサーバを踏み台に外部からSSH接続をするのでPublic IPを割り当てます。
普通にSSH接続できますし、外部へのアクセスも可能です
[ec2-user@ip-10-0-0-30 ~]$ ifconfig eth0 Link encap:Ethernet HWaddr 06:52:CF:61:65:2D inet addr:10.0.0.30 Bcast:10.0.0.255 Mask:255.255.255.0 .... [ec2-user@ip-10-0-0-30 ~]$ curl http://www.yahoo.co.jp/
次にプライベートサブネットにインスタンスを立ち上げます。ネットワークの選択でプライベート側を選択します。
IPがプライベートIPになって起動していることがわかります。
先ほどパブリックに起動したインスタンスを経由してプライベートなインスタンスに接続します
[ec2-user@ip-10-0-0-30 ~]$ ssh -i .ssh/***.pem ec2-user@ip-10-0-1-223.ap-northeast-1.compute.internal
SSH鍵をあらかじめパブリック側にSCPする必要がありますが問題なく接続できます。
[ec2-user@ip-10-0-1-223 ~]$ ifconfig eth0 Link encap:Ethernet HWaddr 0A:34:16:FB:8B:9F inet addr:10.0.1.223 Bcast:10.0.1.255 Mask:255.255.255.0 ... [ec2-user@ip-10-0-0-30 ~]$ curl http://www.yahoo.co.jp/
ただし、現在の状態ではプライベートセグメントから外部へのアクセスはまだできません。NATサーバのセキュリティ設定がされておらず、全部閉鎖状態になっているからです。
http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_NAT_Instance.html#NATSG
を参考に今回は設定してNATインスタンスに割り当てました。これでプライベートネットワークからHTTP/HTTPSの通信は外部に可能となります。
※NATサーバといっても通常のAmazonLinuxなので踏み台のサーバと兼用するとわざわざ踏み台サーバを準備することもないともいえそう。
AWSを使ってみる. ( EC2 : EBS, AMI 編 )
前回はAWSでEC2インスタンスを単純に起動するところまででしたが今回はEBS,AMIについて調べてみます。
EBS
EC2で利用できる永続的ストレージです。これを用いるとEC2にディスクデバイスを追加することが可能です。
- 容量の拡縮が数分で完了。
- AZ内で自動的にレプリケート
- 通常のボリュームの他に「プロビジョンド IOPS ボリューム」というものも選択できる。高速なIOPS。ストライピングも可能で更に超高速に。
- S3にスナップショットを保存可能
- スナップショットは共有可能
- EBSを保持している間は課金発生。デバイスアクセス毎に課金発生。
作成してみます。まずはManagement Console の EBS - Volumues を選択して「Create Volume」で作成。容量等を選択してCreateします。
作成したEBSがリストに追加されます。
これをEC2にアタッチするには右クリックしてAttach Volumeを選択しアタッチしたいEC2のIDを選択します。
アタッチが完了するとEC2上の /dev 以下にストレージデバイスが追加されます
$ ls -l /dev/xvd* brw-rw---- 1 root disk 202, 1 2月 24 08:26 2014 /dev/xvda1 brw-rw---- 1 root disk 202, 80 2月 24 08:59 2014 /dev/xvdf $ ls -l /dev/sd* lrwxrwxrwx 1 root root 5 2月 24 08:26 2014 /dev/sda1 -> xvda1 lrwxrwxrwx 1 root root 4 2月 24 08:59 2014 /dev/sdf -> xvdf
※この ln の関係の理由は EBSではデバイス名は、/dev/sd[f-p] の指定しかできず、最近のLinuxカーネルのデバイス名は、/dev/xvd[f-p]だという経緯らしい。
新規ののボリュームを作成した場合はファイルシステムを作成した後にマウントをすれば利用できます
$ sudo mkfs -t ext3 /dev/xvdf $ sudo mount /dev/xvdf /ebs_mount1 $ df Filesystem 1K-blocks Used Available Use% Mounted on /dev/xvda1 8256952 1222752 6950316 15% / tmpfs 304144 0 304144 0% /dev/shm /dev/xvdf 10321208 154232 9642688 2% /ebs_mount1
再起動したらmountが外れないようにするには /etc/fstab に以下のように追記する
/dev/xvdf /ebs_mount1 ext3 defaults 0 0
EC2をTerminateするときにはEBSボリュームは Delete on Termination の付いてないから残り続けるよと警告でます。
Detachして他のEC2を立ち上げて付け替えても当然うまく行きます。
SnapShot
EBSボリュームはスナップショットをS3にバックアップすることができます。EBSのボリュームを選択して Create Snapshotを選択する(もしくはSnapshotセクションでCreateしてEBSを選択する)だけです。スナップショットを作成しておけばEC2インスタンス作成時にそれを指定してEBSを作成することができます。Snapshotから新しいEBSを作成するので同一Snapshotのボリュームを複数のEC2が利用できることになります。
AWSを使ってみる. ( EC2 編 )
AWS*1 を利用するとインターネットシステムを構成するさまざまな物理的リソースを手軽に入手することができます。昔はレンタルサーバを借りて...とかしているとそんなに贅沢なリソースは確保できなしロードバランサーとかネットワークストレージとかDNSとかは個人レベルで構築するのって大変でしたが、そんな悩みをAWSは全て解決してくれます。個人でも(月額利用料さえはらえば)大規模なウエブサービスのシステムを簡単に構築できるなんて便利な世の中ですね。
EC2
今回は初めてということでAWSの基本となるサービスである仮想サーバ EC2 *2 を使ってみようと思います。AWSのアカウントを作成して事前準備(Paymentの設定など)をしてAWS Management Console を開きます。こんな画面です。
EC2を選択します。AWSはWorld-Wideにデータセンタがあり仮想サーバを使用する際にどのリージョン(データセンターのロケーション)を利用するかを選択します。今回はTokyoを選びます。(※AWSはリージョンおよびインスタンスタイプ(仮想サーバのスペック)によって時間単位の利用料金が異なりますので注意)
「Launch Instance」というボタンをクリックして仮想サーバを取得してみます。
- Step 1: Choose an Amazon Machine Image (AMI)
という画面がまず出ます。あなたの欲しいサーバ(Machine Image)は何ですか(Linuxですか?Windowsですか?64/32bitOSどちら?とか聞かれます)。AWSが提供する初期構成のものがデフォルトの選択肢で表示されますが、それ以外にもすでに特定のパッケージ(ソフトウエア)インストール済みのイメージも選択できます(物によっては追加時間費用がかかります)。また、自分であらかじめ作成したイメージや他の人が作成して公開したイメージとかも選択できます。自分で作成したイメージを選択するとサーバ増強などの場合に同じ構成のインスタンスを速攻で作成できます。
今回はAWSが提供するAmazon Linux 64bit を選択します (Amazon Linux はほぼ CentOS と同等+AWS Toolsのようです)
- Step 2: Choose an Instance Type
次に仮想サーバのマシンスペックについて選択します。とりあえずお試しの超低スペックなものから化け物級の超高性能のマシンまであります。当然時間単位の利用料金が異なりますのでそれを踏まえて選択します。選択の表でスペックが確認できますので用途に応じて(かつ値段に応じて)選択します。今回は最低スペックの t1.micro を選択します。
- Step 3: Configure Instance Details
Step 2:の段階で起動をすることもできますが、Detailの設定をすることもできます。ここでは Network (あらかじめ構築してあるプライベートネットワーク(VPCに属するように立ち上げるか) や、AZ(Availability Zone: リージョン内でも複数の物理的に離れたデータセンターゾーンがある。同一リージョン内でも対障害性を高めるために分散したりする)を選択できたりします。今回は項目を確認するだけで全てデフォルトで次に行きます。
- Step 4: Add Storage
ルートディスクサイズや拡張ストレージのボリュームを追加できます。これも今回は触らないで次に行きます。
- Step 5: Tag Instance
仮想サーバに対してTagがKey/Valueが追加できます。AWSツールなどでこの仮想サーバを特定したり,サーバを用途ごとにグルーピングして管理しやすいような名称をつけれます。用途は各自。
- Step 6: Configure Security Group
セキュリティポリシーを選択できます。このサーバに対して外部からの接続Port(SSH,HTTP,etc)の開放状況を指定します。
SSHがデフォルトでAnyになっているので MyIPを選択します(そうすると自動で自分が接続している外部IPを調べてセットしてくれます).
HTTP/80をAnyで追加してみます。
- Step 7: Review Instance Launch
最後に構成の確認をして「Launch」をクリックすれば仮想サーバが起動します。が、最初の起動直前にKeyPair の選択をします。これはSSH等で接続するための公開鍵認証のセキュリティキーを指定してください。ということです、既存に作成済みのKeyPairを選択するか新しいKeyPairを作成します。新規作成した場合は秘密鍵(*.pemファイル)もここでダウンロードできますのでココで保存しときます(再ダウンロードできないので注意)。
LaunchするとManagement Console で戻ってきたら立ち上げたインスタンスが表示されます。Selectすると下部のパネルに情報が表示されます。こんな感じに。
注意すべきは立ち上がった状態はもちろんのこと Stopした状態でも課金は発生します。使い終わったら(不要になったら)Terminateの状態にしましょう。右グリックでActionパネル開いてTerminateを選択します。
ただし、Terminateとは仮想サーバ上のデータも含めて全て消去(捨てる)して利用を終了するという意味なのでその辺も注意。
SSHでログイン
ログインするにはコンソールからSSH接続します
$ ssh -i xxxxxxx.pem ec2-user@ec2-54-238-115-217.ap-northeast-1.compute.amazonaws.com The authenticity of host 'ec2-54-238-115-217.ap-northeast-1.compute.amazonaws.com (54.238.115.217)' can't be established. RSA key fingerprint is 6d:07:4a:aa:30:e7:71:35:88:18:d4:42:41:7e:34:f8. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'ec2-54-238-115-217.ap-northeast-1.compute.amazonaws.com,54.238.115.217' (RSA) to the list of known hosts. __| __|_ ) _| ( / Amazon Linux AMI ___|\___|___| https://aws.amazon.com/amazon-linux-ami/2013.09-release-notes/ 9 package(s) needed for security, out of 30 available Run "sudo yum update" to apply all updates. [ec2-user@ip-10-134-152-93 ~]$
つながりました。 ec2-user ってなんか嫌だな。セキュリティ的にもこのまま使うのもイマイチなのでこれを変える場合は
# useradd keisyu # password keisyu # vi /etc/sudoers # sudo 設定 # mkdir /home/keisyu/.ssh # cp /home/ec2-user/.ssh/authorized_keys # chown -R keisyu:keisyu /home/keisyu/.ssh
これで自分のアカウントでログインできますし ec2-userは userdel ec2-user で消せます。とりあえずログイン時に言われたとおり
$ sudo yum update
するとよいですね。
ec2へHTTPアクセス
せっかくなのでapacheでもインストールして公開設定したHTTP/80を外部から確認できるかやってみます。apacheをインストールします
$ sudo yum install httpd $ sudo /sbin/service httpd start
これでapacheが立ち上がりました。
# cat /var/www/html/index.html <html><body> Hello! AWS World! by keisyu </body></html>
簡単にhtmlを作成してブラウザでアクセスしたら閲覧できました
nginxとリバースプロキシでモダンなシステム構成
nginx
今日は今どき?(といっても世間では既に主流な構成な感はありますが)nginx&リバースプロキシを用いたシステム構成を実験で作ってみたいと思います。
nginx はイベント駆動型のウエブーサーバでありApacheでいうところのMPM Prefork/workerとは異なる構成なのでメモリ使用量が少なく動作することと一つの処理が低コストな場合において同時接続数が多くても安定して動作することが期待できるウエブサーバです
Apacheをフロントに設置してシステムを構成する場合、一昔前はなどと3層のシステム構成(もしくはAPIを外した2層)にすることが主流でした。A
User <====> Apache <----> API <----> DB
C10K問題*1に直面するケースは少ないにしろ比較的大規模なサービスにおいて同時接続をサポートするとフロント(ユーザがアクセスするサーバ)を並列に並べる必要がでてきます.この問題を解決するためにフロントエンドにnginxを配置してユーザの接続を受け付け処理はバックエンドのサーバに流す(リバースプロキシ)の構成が流行っているようです。
User <====> nginx <----> WebServer <----> DB
- 静的コンテンツはnginx 側で配信
- 動的なコンテンツはリバースプロキシでバックエンドに配置されたウエブサーバに振り分ける
- nginx自体がロードバランサの役目も持っている
インストール
epel のリポジトリに少々古いですが(1.0.15-5.el6) パッケージがあるようなので yum でインストールしてみます。
$ sudo yum install nginx $ /usr/sbin/nginx -V nginx version: nginx/1.0.15 built by gcc 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) TLS SNI support enabled configure arguments: --prefix=/usr/share/nginx --sbin-path=...
nginxはapacheのDSOのような動的なモジュールの組み込みができず、コンパイルやり直しが必要らしいです。今の時点でのモジュールの組み込み具合は -V のオプションを付けて起動すると確認できます。とりあえずは何も考えずに起動 ( $ sudo /sbin/services nginx start )すると以下のような画面が立ち上がります。
詳しく見ていきます。設定ファイルは /etc/nginx/nginx.conf と、そこからincludeされる /etc/nginx/conf.d/*.confが主な設定ファイルです
$ ls /etc/nginx/conf.d/
default.conf ssl.conf virtual.conf
記載されている nginx.conf で設定のフォーマットとしては以下のように記述するようです。
coreモジュールの設定 events { eventモジュールの設定 } http { httpモジュールの設定 } server { virtual serverの設定 (conf.d/default.conf or virtial.conf) }
主要な設定
worker_processes | core | nginxのworkerプロセスの数, CPUの個数と同じにするのが効果的(それ以上にしても意味がない) |
---|---|---|
worker_connections | event | 一つのworkerプロセスが同時に処理できる最大コネクション数を設定 |
リバースプロキシの設定
せっかくなのでリバースプロキシの設定をやってみます。nginxを起動したサーバがゲストOSのCentOSでありバックエンドに相当するウエブサーバを
Amon2を使ったアプリ開発 (その2) - keisyuのブログ でつくったシンプルな掲示板と想定しますすなわち以下のようなややこしい感じです。
User(ホストPC) <----> nginx (CentOS:VirtualBox) <---> Server (ホストPC)
以下のようにconf.d/default.conf を編集します
upstream bbs_server { ip_hash; server 192.168.56.1:5000; } server { ... ... location / { proxy_pass http://bbs_server/; } ...
これで一応はリバースプロキシとして動作します。nginxのPort80 "/" にアクセスすると 192.168.56.1:5000 で起動する plackup されたWebサーバにアクアクセスしてコンテンツが応答されます。その他リバースプロキシの設定はたくさんあるので必要に応じて調べてみる(X-Forwarded-For とか)
最新版の利用
最新の安定版は1.4.5らしいです。これを利用するために本家からダウンロードしてコンパイルしてみます。configure で epel でインストールした版の -V で確認したオプションと同じものを定義してみることにします。
$ sudo rpm -e nginx # yum で入れたのを消しとく $ curl -LO http://nginx.org/download/nginx-1.4.5.tar.gz $ tar zxvf nginx-1.4.5.tar.gz $ cd nginx-1.4.5 $ ./configure --prefix=/usr/share/nginx ... #(epel版の -V で出てきたのをそのまま使う) $ sudo make install
configure で色々モジュールが足りないと言われて結局いかのものをyumでインストールした
pcre-devel, openssl-devel, libxslt-devel, gd-devel, perl-ExtUtils-Embed, GeoIP-devel
インストール完了すると
$ /usr/sbin/nginx -V nginx version: nginx/1.4.5 built by gcc 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) TLS SNI support enabled configure arguments: --prefix=/usr/share/nginx --sbin-path=...
最新安定バージョンで動作します。/etc/init.d/nginx がrpm -e で消えて install で生成されないけどググれば見つかる。
Elasticsearch 1.0 を使ってみた2。( perl からの利用と日本語全文検索 )
前回 Elasticsearch を利用してみて (Elasticsearch 1.0 を使ってみた。 - keisyuのブログ)検索に関する仕事を5年以上やってた経験があるだけに非常に便利な世の中になったもんだと感動しました。今回はPerlから利用して見る方法と日本語全文検索はどんな感じかを試してみたいと思います。
elasticsearch.pm
Elasticsearchのリファレンスに記載の通り (Elasticsearch.pm) cpanのモジュールがすでにあるようです。
$ cat cpanfile requires 'Elasticsearch'; $ carton install ... Successfully installed Elasticsearch-1.03 59 distributions installed
とりあえずリファレンス通りにやってみる
use strict; use warnings; use utf8; use Elasticsearch; use Data::Dumper; my $e = Elasticsearch->new( nodes => '192.168.56.101:9200', ); print Dumper $e->index ( index => 'myindex', type => 'mytype', id => 'doc3', body => { 'name' => 'Suzuki Ichiro', 'comment' => 'this document was inserted by perl module!' } ); print Dumper $e->get( index => 'myindex', type => 'mytype', id => 'doc1' ); print Dumper $e->search( index => 'myindex', body => { query => { match => { 'comment' => 'perl' } } } );
実行すると期待通りの結果が応答されます。
$ carton exec -- perl es.pl $VAR1 = { '_version' => 4, '_id' => 'doc3', '_type' => 'mytype', '_index' => 'myindex', 'created' => bless( do{\(my $o = 0)}, 'JSON::PP::Boolean' ) }; $VAR1 = { '_version' => 7, '_id' => 'doc1', '_source' => { 'comment' => 'Hello! Elasticsearch World!', 'age' => 40, 'name' => 'Yamada Taro' }, '_type' => 'mytype', '_index' => 'myindex', 'found' => bless( do{\(my $o = 1)}, 'JSON::PP::Boolean' ) }; $VAR1 = { 'hits' => { 'total' => 1, 'hits' => [ { '_source' => { 'comment' => 'this document was inserted by perl module!', 'name' => 'Suzuki Ichiro' }, '_id' => 'doc3', '_type' => 'mytype', '_score' => '0.11506981', '_index' => 'myindex' } ], 'max_score' => '0.11506981' }, 'timed_out' => bless( do{\(my $o = 0)}, 'JSON::PP::Boolean' ), '_shards' => { 'total' => 5, 'failed' => 0, 'successful' => 5 }, 'took' => 4 };
日本語全文検索
それではとりあえず何も考えずに上のサンプルで日本語のドキュメントを投入して日本語検索してみましたがうまくいきませんでした。
このindexを定義するときにmappingを指定せず登録されたデータから自動的に生成しましたので日本語の形態素解析をするanalyzerとして定義がフィールドにされなかったからだと思います。これを明示的に指定してindexを生成して日本語で検索ができるようにしてみます。
今回は comment という要素に対して NGram のインデックスをmappingにて定義してみます。
Elasticsearchが標準で搭載するNgramのアナライザに関してはこの辺が参考になります。NGram Tokenizer
以下の要領でindexを再定義します。
use strict; use warnings; use utf8; use Elasticsearch; use Data::Dumper; my $e = Elasticsearch->new( nodes => '192.168.56.101:9200', ); print Dumper $e->indices->delete( index => 'myindex', ); print Dumper $e->indices->create( index => 'myindex', body => { settings => { analysis => { analyzer => { my_ngram_analyzer => { tokenizer => 'my_ngram_tokenizer' } }, tokenizer => { my_ngram_tokenizer => { type => 'nGram', min_gram => 2, max_gram => 3, token_chars => [ "letter", "digit" ] } } } }, mappings => { mytype => { properties => { name => { type => 'string'}, comment => { type => 'string', analyzer => 'my_ngram_analyzer'}, age => { type => 'integer'} } } } } );
データを投入して検索してみると正しく結果が応答されるはずです
print Dumper $e->index ( index => 'myindex', type => 'mytype', id => 'doc4', body => { 'name' => 'Takahashi Daisuke', 'comment' => '日本語の検索が正しく動作するかの確認です。' } ); # 投入した直後はヒットしない可能性があるので注意。 print Dumper $e->search( index => 'myindex', body => { query => { match => { 'comment' => '京都' } } } ); # ヒットしない print Dumper $e->search( index => 'myindex', body => { query => { match => { 'comment' => '検索' } } } ); # ヒットする
HQの管理ツールからも検索が直接試せるのでここからでも確認できます。すごい便利!
Ngram ではなく 形態素解析にて検索したい場合はこの辺を参考にする。
以下の日本語形態素解析のpluginをインストールします。
elasticsearch/elasticsearch-analysis-kuromoji · GitHub
$ cd /usr/share/elasticsearch $ sudo bin/plugin -install elasticsearch/elasticsearch-analysis-kuromoji/2.0.0.RC1 $ sudo /sbin/service elasticsearch restart # /_nodes/plugin?pretty にアクセスしてpluginインストール確認
疲れたのでまた今度にする。
Elasticsearch 1.0 を使ってみた。
Elasticsearch (Elasticsearch.org Open Source Distributed Real Time Search & Analytics | Elasticsearch) がVer1.0となったらしいので使ってみました。
オープンソースのSearch Systemといえば solr (Apache Lucene - Apache Solr)かこれの2択みたいですが、最近はElasticsearchの記事が目立つような気がする。
1.0になったといってもそれ以前のバージョンも使ったことなかったのではじめて使ってみる状態。まあやってみます。
インストール
CentOSにインストールします。ここ (Elasticsearch.org Download ELK | Elasticsearch)からRPM版をダウンロードしてインストールします。
serviceに登録しましょう、と新設に教えてくれるのでそのとおりに登録します。
$ curl -LO https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.0.0.noarch.rpm $ sudo rpm -ihv elasticsearch-1.0.0.noarch.rpm $ sudo /sbin/chkconfig --add elasticsearch
JAVAが必要なのでそれもインストールします。JREをインストールしJAVA_HOMEの環境変数をセットします。
Java SE Runtime Environment 7 - Downloads | Oracle Technology Network | Oracle
$ sudo rpm -ihv jre-7u51-linux-x64.rpm $ export JAVA_HOME=/usr/java/jre1.7.0_51
動作確認
起動は簡単
$ sudo /sbin/service elasticsearch start Starting elasticsearch: [ OK ]
特に設定を変更せずデフォルトでプロセスを確認するとこんな感じです
/usr/bin/java -Xms256m -Xmx1g -Xss256k -Djava.awt.headless=true -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+HeapDumpOnOutOfMemoryError -Delasticsearch -Des.pidfile=/var/run/elasticsearch/elasticsearch.pid -Des.path.home=/usr/share/elasticsearch -cp :/usr/share/elasticsearch/lib/elasticsearch-1.0.0.jar:/usr/share/elasticsearch/lib/*:/usr/share/elasticsearch/lib/sigar/* -Des.default.path.home=/usr/share/elasticsearch -Des.default.path.logs=/var/log/elasticsearch -Des.default.path.data=/var/lib/elasticsearch -Des.default.path.work=/tmp/elasticsearch -Des.default.path.conf=/etc/elasticsearch org.elasticsearch.bootstrap.Elasticsearch
ドキュメントを見ても用語が混乱するので整理。
cluster | 一つの検索のシステム全体を示す |
---|---|
node | 複数のサーバ(Elasticsearchのプロセス)で分散して検索システムを構成することができる。その際の各々を指すもの。定義されているcluster名が同一ネットワーク内にあればそのclusterに自動で組み込まれる |
この辺の応答のJSONをみてみる。
$ curl -XGET 'http://localhost:9200/_cluster/state' $ curl -XGET 'http://localhost:9200/_cluster/stats' $ curl -XGET 'http://localhost:9200/_cluster/health' $ curl -XGET 'http://localhost:9200/_nodes' $ curl -XGET 'http://localhost:9200/_nodes/stats'
が、そんなことはせずともElasticsearchのモニタリングをする便利なプラグインがあるようです。
$ cd /usr/share/elasticsearch $ sudo ./bin/plugin --install royrusso/elasticsearch-HQ
これだけで http://localhost:9200/_plugin/HQ にアクセスすると以下のようなカッコイイ&多機能を予感させる画面が出てきた!!
なんか入れて検索してみる
とりあえずここでも概念的に頭を整理しないと混乱する
index | 一つの検索システムで複数のtypeを構成できる |
---|---|
type | 検索対象の郡(集合)を表す |
mapping | ドキュメントの各要素(検索Key)の属性等の定義 |
document | 個々の検索データ |
データの投入(index, typeは特に事前定義しなくとも勝手に作成されるのがデフォルトの挙動らしい), mapping も document のから自動的に識別されるらしい(頭がいい..が間違ってたり矯正したい場合は定義ファイルに書くみたい)
データの投入
PUTにて /[index_name]/[type_name]/[document_id] で JSON 形式でドキュメントを送信する.
$ curl -XPUT 'http://localhost:9200/myindex/mytype/doc1' -d '{ "name" : "Yamada Taro", "comment": "Hello! Elasticsearch World!"}' {"_index":"myindex","_type":"mytype","_id":"doc1","_version":1,"created":true} $ curl -XPUT 'http://localhost:9200/myindex/mytype/doc2' -d '{ "name" : "Tanaka Hanako", "comment": "Today is Febyrary 19. I like World Trip!"}' {"_index":"myindex","_type":"mytype","_id":"doc2","_version":1,"created":true} $ curl -XPUT 'http://localhost:9200/myindex/mytype/doc1' -d '{ "name" : "Yamada Taro", "comment": "Hello! Elasticsearch World!", "age":40}' {"_index":"myindex","_type":"mytype","_id":"doc1","_version":4,"created":false}
データを更新したい場合は同じdocument_idで上書きする感じ (レスポンスの createdがfalseになって_versionが加算される)
データの取得(個別ドキュメント)
$ curl -XGET 'http://localhost:9200/myindex/mytype/doc1' { "_index":"myindex", "_type":"mytype", "_id":"doc1", "_version":4, "found":true, "_source" : { "name" : "Yamada Taro", "comment": "Hello! Elasticsearch World!", "age":40 } }
検索する
ドキュメント単位, タイプ単位で検索できるようです
$ curl -XGET 'http://localhost:9200/myindex/mytype/_search?q=Hello' # 1件ヒット { "took":3, "timed_out":false, "_shards":{ "total":5, "successful":5, "failed":0 }, "hits":{ "total":1, "max_score":0.13424811, "hits":[ { "_index":"myindex","_type":"mytype","_id":"doc1","_score":0.13424811, "_source" : { "name" : "Yamada Taro", "comment": "Hello! Elasticsearch World!", "age": 40 } } ] } } $ curl -XGET 'http://localhost:9200/myindex/mytype/_search?q=world' # 2件ヒット { "took":3, "timed_out":false, "_shards":{ "total":5, "successful":5, "failed":0 }, "hits":{ "total":2, "max_score":0.13424811, "hits":[ { "_index":"myindex","_type":"mytype","_id":"doc1","_score":0.13424811, "_source" : { "name" : "Yamada Taro", "comment": "Hello! Elasticsearch World!", "age": 40 } },{ "_index":"myindex","_type":"mytype","_id":"doc2","_score":0.095891505, "_source" : { "name" : "Tanaka Hanako", "comment": "Today is Febyrary 19. I like World Trip!" } } ] } }
この状態でHQ確認すると確かにmyindexというインデックスが定義されています
検索の確認もHQ内でできる。すごく使いやすい。早くも神ツールの予感。
その他の詳しいことはリファレンスを読んでみることにする。
Elasticsearch - Reference [1.x]
今日はここまで。