<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>きのこる庭 &#187; サーバ・インフラ系</title>
	<atom:link href="http://kinokoru.jp/archives/category/%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bb%e3%82%a4%e3%83%b3%e3%83%95%e3%83%a9%e7%b3%bb/feed" rel="self" type="application/rss+xml" />
	<link>http://kinokoru.jp</link>
	<description></description>
	<lastBuildDate>Wed, 09 Jan 2019 03:18:33 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.2</generator>
		<item>
		<title>DockerでAngular+Nodeのサーバを立てた話</title>
		<link>http://kinokoru.jp/archives/1557</link>
		<comments>http://kinokoru.jp/archives/1557#comments</comments>
		<pubDate>Thu, 01 Mar 2018 12:54:02 +0000</pubDate>
		<dc:creator>Nisei Kimura</dc:creator>
				<category><![CDATA[サーバ・インフラ系]]></category>
		<category><![CDATA[ツール系]]></category>
		<category><![CDATA[Angular]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Node]]></category>

		<guid isPermaLink="false">http://kinokoru.jp/?p=1557</guid>
		<description><![CDATA[<p>最近Win機を購入して 仮想環境どうしようかなーと思っていたのだが、「せっかくだし使い慣れたVagrantではなく思い切ってDockerでつくってみるか」と思い立ったので 勉強がてらDockerでサーバを立ててみた。 前 [...]</p>
<p>The post <a rel="nofollow" href="http://kinokoru.jp/archives/1557">DockerでAngular+Nodeのサーバを立てた話</a> appeared first on <a rel="nofollow" href="http://kinokoru.jp">きのこる庭</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>最近Win機を購入して 仮想環境どうしようかなーと思っていたのだが、「せっかくだし使い慣れたVagrantではなく思い切ってDockerでつくってみるか」と思い立ったので 勉強がてらDockerでサーバを立ててみた。</p>
<h2>前提となる環境</h2>
<p>* Windows 10 Home Edition<br />
* Docker Toolbox</p>
<h2>やったこと</h2>
<p>1. Angular+Node用のDockerfile及びimageの作成<br />
2. 1で作成したimageをもとにコンテナを作成しつつ、ホストマシン上でコードをいじれるようマウント<br />
3. 実際にサーバを立ち上げてみる<br />
4. ホスト上からコードに修正を加えてみる<br />
<span id="more-1557"></span></p>
<h2>1. Angular+Node用のDockerfile及びimageの作成</h2>
<p>とりあえずNodeでサーバを立てて Angular動かしてみるかということになった。</p>
<p><a href="https://hub.docker.com/r/monostream/nodejs-angular-cli/" target="_blank">https://hub.docker.com/r/monostream/nodejs-angular-cli/</a></p>
<p>ひとまず ↑を参考にして以下のような感じでDockerfileを作成。</p>
<pre class="brush: plain; title: ; notranslate">
FROM node:alpine

RUN apk add --quiet --no-cache bash &amp;&amp; \
    yarn global add @angular/cli &amp;&amp; \
    yarn cache clean &amp;&amp; \
    rm -rf /var/cache/* /tmp/*

EXPOSE 4200

WORKDIR /home/node

COPY ng_apps ng_apps

CMD [&quot;/bin/sh&quot;]
</pre>
<p>Angularでserveした際のデフォルトのポートが4200なので、4200番を開放している。<br />
また、ng_apps という空ディレクトリをコピーしているが、これはホストマシンとの共有を想定したディレクトリ。Angularアプリケーションを配下に置いておくことでホストマシンから直接コードをいじれるようにしたかった。Dockerfileを作成したら、同ディレクトリにて以下コマンドを実行。</p>
<pre class="brush: plain; title: ; notranslate">
docker build -t angular-test .
</pre>
<p><b>Successfully tagged angular-test:latest</b>という文言とともにイメージが作成される。</p>
<h2>2. 1で作成したimageをもとにコンテナを作成しつつ、ホストマシン上でコードをいじれるようマウント</h2>
<p>以下のようにdocker run でコンテナを作成する。</p>
<pre class="brush: plain; title: ; notranslate">
docker run --name angular_test_server -d -it -p 80:4200 -v $(pwd)/ng_apps:/home/node/ng_apps angular-test
</pre>
<p>-v オプションにて ng_appsディレクトリをマウントしつつ、ポートは80番で叩けるようにした。<br />
引き続き以下のコマンドを実行し、作成したコンテナに入り、Angularが適切にインストールされているかどうかを確認する。</p>
<pre class="brush: plain; title: ; notranslate">
docker exec -it angular_test_server /bin/sh
ng --version
</pre>
<p><a href="http://kinokoru.jp/wp-content/uploads/2018/03/angular_cli_1.jpg"><img src="http://kinokoru.jp/wp-content/uploads/2018/03/angular_cli_1.jpg" alt="angular_cli_1" width="781" height="377" class="aligncenter size-full wp-image-1560" /></a></p>
<h2>3. 実際にサーバを立ち上げてみる</h2>
<p>コンテナに入ったままng_appsディレクトリに移動し、ng new コマンドによって myappというアプリケーションを立ち上げる。<br />
ここで一つ問題が発生する。Windowsの場合、Virtualbox経由で共有ディレクトリをつくった場合ゲストマシン側でそのディレクトリにシンボリックリンクを貼ることができない。これにより<b>共有ディレクトリ上で npm install が通らず、結果的に ng new myapp がコケる</b>という事態に陥る。そこで npm install の際に <b>&#8211;no-bin-links</b> オプションをつける必要があるのだが、Angularでこれをやりたい場合は以下のようにする模様。</p>
<pre class="brush: plain; title: ; notranslate">
ng new myapp --skip-install
cd myapp
npm install --no-bin-links
</pre>
<p>これによって共有ディレクトリ上でも無事Angularアプリケーションを置くことができた。あとはnpm installが完了したら以下のコマンドでサーバの立ち上げを行う。</p>
<pre class="brush: plain; title: ; notranslate">
ng serve --host 0.0.0.0
</pre>
<p>今回はDockerのデフォルトネットワーク経由のため、ホストマシンのブラウザから 192.168.99.100 にアクセス。</p>
<p><a href="http://kinokoru.jp/wp-content/uploads/2018/03/voila.jpg"><img src="http://kinokoru.jp/wp-content/uploads/2018/03/voila-1024x627.jpg" alt="voila" width="1024" height="627" class="aligncenter size-large wp-image-1561" /></a></p>
<p>表示された。</p>
<h2>4. ホスト上からコードに修正を加えてみる</h2>
<p>せっかくマウントしたわけだし、ホスト上からコードをいじってみる。とりあえず簡単な例として初期に表示されるページのタイトルを変えてみることにする( パスはmyapp/src/index.html )。</p>
<p><a href="http://kinokoru.jp/wp-content/uploads/2018/03/koushin.jpg"><img src="http://kinokoru.jp/wp-content/uploads/2018/03/koushin.jpg" alt="koushin" width="856" height="345" class="aligncenter size-full wp-image-1562" /></a></p>
<p>こんな感じでいじって再度ゲストマシン側にて<b>ng serve &#8211;host 0.0.0.0</b>を実行すると…</p>
<p><a href="http://kinokoru.jp/wp-content/uploads/2018/03/voila2.jpg"><img src="http://kinokoru.jp/wp-content/uploads/2018/03/voila2-1024x725.jpg" alt="voila2" width="1024" height="725" class="aligncenter size-large wp-image-1563" /></a></p>
<p>無事更新が反映された模様。</p>
<p>The post <a rel="nofollow" href="http://kinokoru.jp/archives/1557">DockerでAngular+Nodeのサーバを立てた話</a> appeared first on <a rel="nofollow" href="http://kinokoru.jp">きのこる庭</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://kinokoru.jp/archives/1557/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>「秒間●リクエスト」の具体的な定義がモヤモヤしていたので調べてみた話</title>
		<link>http://kinokoru.jp/archives/1121</link>
		<comments>http://kinokoru.jp/archives/1121#comments</comments>
		<pubDate>Sun, 12 Jul 2015 03:54:18 +0000</pubDate>
		<dc:creator>Nisei Kimura</dc:creator>
				<category><![CDATA[サーバ・インフラ系]]></category>
		<category><![CDATA[検証・考察]]></category>

		<guid isPermaLink="false">http://kinokoru.jp/?p=1121</guid>
		<description><![CDATA[<p>最近個人的にアプリケーションのみならず ミドルのあたりを触る機会が増えて、サーバのパフォーマンスを意識するようになってきた。 とはいえそのあたりの負荷テストに対する認識等、割とざっくりとやってしまっていたので ここらで一 [...]</p>
<p>The post <a rel="nofollow" href="http://kinokoru.jp/archives/1121">「秒間●リクエスト」の具体的な定義がモヤモヤしていたので調べてみた話</a> appeared first on <a rel="nofollow" href="http://kinokoru.jp">きのこる庭</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>最近個人的にアプリケーションのみならず ミドルのあたりを触る機会が増えて、サーバのパフォーマンスを意識するようになってきた。<br />
とはいえそのあたりの負荷テストに対する認識等、割とざっくりとやってしまっていたので ここらで一度しっかり落とし込んでおこうと考え、色々調べてみた。</p>
<p>特に<strong>「秒間にさばけるリクエスト数って、何をもって秒間●リクエストって言えるのか」</strong> とか、<br />
<strong>「秒間リクエストを測る際に、ユーザごとの端末の違いは考えなくて良いの？例えば有線のPCと3Gのスマホだと全然速度違うから、サーバ-クライアント間のコネクションが続く時間も変わってきてしまうんじゃないの？」</strong><br />
とか色々考えていたけど、調べているうちに自分なりに何となくハッキリしてきたので 情報の整理がてら共有。<br />
もしかしたら認識誤りで 間違った事を言っているかもしれないので、その場合はご指摘いただければ本当に嬉しいです。<br />
<span id="more-1121"></span></p>
<h3>「秒間リクエストを測る際に、ユーザごとの端末の違いは考えなくて良いの？」について</h3>
<p>結論から言うと、<strong>サーバが秒間でさばけるリクエスト数はユーザが使用しているネット回線には依存しない</strong>。</p>
<p>これは速度の差が発生するのがどこのネットワークにおいてかを考えるとわかりやすいかも。<br />
PCでもスマホでも ユーザ側のネットワークにおける速度が変われど、サーバ側における通信の速度は(PC/スマホごとにネットワーク側で別々の処理が行われていない、またはサーバ側でリクエスト元のIPに対して特定の帯域制限等をしていない 等の限りにおいて)変わらないことがわかる。<br />
以下はそれを示した図である。</p>
<p><a href="http://kinokoru.jp/wp-content/uploads/2015/07/network1.jpg"><img src="http://kinokoru.jp/wp-content/uploads/2015/07/network1.jpg" alt="network" width="650" height="412" class="aligncenter size-full wp-image-1134" /></a></p>
<p>ユーザ側のネットワークの帯域制限(図で言うと Aくんの使用しているWiFiのネットワークにおける帯域制限)とか媒体のネットワークは、飽くまでユーザ側のネットワークにおけるものであり、さらに言うと、サーバ自体のネットワーク領域は同じなので、ユーザ側のネットワークの帯域はサーバがさばける秒間リクエスト数には関係しない。</p>
<p>ので、秒間リクエスト数を測る際に 秒間リクエストに直接関わってくるネットワーク周りの問題は、サーバ側のネットワークが提供しているスペック、つまり以下の部分となる。</p>
<p><a href="http://kinokoru.jp/wp-content/uploads/2015/07/network2.png"><img src="http://kinokoru.jp/wp-content/uploads/2015/07/network2.png" alt="network2" width="650" height="412" class="aligncenter size-full wp-image-1137" /></a></p>
<p>上記の赤枠で囲まれたネットワーク部分からサーバ間通信( アプリケーション自体のレスポンス、DBサーバのレスポンス速度等 )等を見て最終的なレスポンスの速度を判断し、ボトルネックを見つけて改善し続けていく工程が「秒間●リクエストをさばく」という事の意味なのかなと思った。</p>
<h3>つまり「秒間●リクエスト」とは</h3>
<p><strong>「秒間●リクエストをさばける」事が保障するのは、その量のリクエストが来た時にサーバがダウンすることなく稼動し続けられる事</strong>、及び<strong>システム全体におけるボトルネックの特定が可能になる事</strong><span class="supl">( アプリケーションの特定のSQLクエリが重く、結果的にAPサーバで遅延が発生している、各サーバ上では処理に時間がかかっていないがネットワークの帯域のスペックがそもそも微妙でレスポンスが遅れている 等)</span>である。<br />
言い換えると、<strong>サービスがユーザにとってサクサク見られるかどうかを&#8221;完全に保障するわけではない&#8221;</strong>。</p>
<h3>「秒間で沢山リクエストをさばける＝ユーザがサクサクページを見られる」ではない</h3>
<p>勿論、サーバが十分にリクエストをさばくことができないと 待ち行列ができてレスポンスが遅延してユーザがサクサクページを見られないので、<strong>サーバが想定されるリクエストを十分にさばけることは最低限保障されている必要があるが、さらにユーザがサクサクページを見られるようにするための工夫は秒間リクエストの話とは別に別途必要になる</strong>。<br />
例えば以下のような事を考慮する必要がある。</p>
<h4>1. ターゲットとするユーザが主に使用するであろう端末</h4>
<p>有線で見れば速いページでも、スマホ媒体向けに提供されている特定の回線で見たら遅い、且つサービスが提供するターゲットとなるユーザがスマホ媒体 なんてこともあるので、(当たり前だけど)ターゲットとする人達が利用するであろう端末での速度面の検証作業は必須になるだろうなあと思う。<br />
それでもって、<strong>明らかに媒体に対してコンテンツのサイズが大きすぎる場合は圧縮したりキャッシュを利用したり何なりの手立てが必要になる</strong>。</p>
<h4>2. ターゲットとするユーザの居住地</h4>
<p>基本的にインターネットは様々な異なるネットワークを経由してできているため、距離が遠ければ遠い程 パケットがネットワーク上を移動するのに要する距離・時間が長くなる。<br />
更に、国によっては 海外IPのサーバに対して自動で検閲が入るようになっている関係で遅くなったり、一つの国の中でも南部と北部で異常に重くなったりする事もあるそうなので、<strong>特に海外ユーザ向けにサービスを展開する場合は基本的に サービスを提供するユーザに近い場所にサーバを置くのが良い</strong>らしい。</p>
<h3>まとめ</h3>
<p>・ <strong>サーバ側で「秒間●リクエスト」をはかる時、ユーザ側のネットワーク帯域までは見ない</strong><span class="supl">( ユーザが有線を使っていようが3G回線を使っていようが、最終的に到達するサーバ周りのネットワーク領域は同じで、サーバ側のネットワーク領域側で特別な設定をしていない限りレスポンスの速度も基本的に同じだから )</span><br />
・ <strong>「秒間●リクエストをさばける」事が保障するのは</strong>、<strong>その量のリクエストが来た時にサーバがダウンすることなく稼動し続けられる事</strong> と <strong>システム全体におけるボトルネックの特定が可能になる事</strong><br />
・ 「秒間で沢山リクエストをさばける＝ユーザがサクサクページを見られる」ではない<br />
・ ただし必要最低限の秒間リクエスト数をクリアできないと 勿論ユーザへのレスポンス遅くなる<br />
・ ユーザがサクサクコンテンツを利用する上で、<strong>秒間リクエスト数の話とは別にターゲットとなるユーザの媒体とか居住地は別途考慮する必要はある</strong></p>
<p>…という認識です。</p>
<p>僕自身 まだまだ勉強不足な部分もございますので、「ここの部分根本から認識間違ってるよ」という部分がございましたら、優しくマサカリを投げていただければ幸いです。。。(´・_・`)</p>
<p>The post <a rel="nofollow" href="http://kinokoru.jp/archives/1121">「秒間●リクエスト」の具体的な定義がモヤモヤしていたので調べてみた話</a> appeared first on <a rel="nofollow" href="http://kinokoru.jp">きのこる庭</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://kinokoru.jp/archives/1121/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VagrantでUbuntuサーバを2台立ててMySQLでマスタスレーブ構成にしてみた</title>
		<link>http://kinokoru.jp/archives/871</link>
		<comments>http://kinokoru.jp/archives/871#comments</comments>
		<pubDate>Sun, 12 Oct 2014 04:14:16 +0000</pubDate>
		<dc:creator>Nisei Kimura</dc:creator>
				<category><![CDATA[サーバ・インフラ系]]></category>
		<category><![CDATA[ツール系]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Vagrant]]></category>
		<category><![CDATA[レプリケーション]]></category>

		<guid isPermaLink="false">http://kinokoru.jp/?p=871</guid>
		<description><![CDATA[<p>久々の更新。 土曜日は これまで何となく使っていたVagrantを本格的にいじっていたけど、知れば知る程便利だなあ。 Vagrantfileって Gruntfileみたいに何となくいじるのが面倒くさそうな印象があったんだ [...]</p>
<p>The post <a rel="nofollow" href="http://kinokoru.jp/archives/871">VagrantでUbuntuサーバを2台立ててMySQLでマスタスレーブ構成にしてみた</a> appeared first on <a rel="nofollow" href="http://kinokoru.jp">きのこる庭</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>久々の更新。<br />
土曜日は これまで何となく使っていたVagrantを本格的にいじっていたけど、知れば知る程便利だなあ。<br />
<strong>Vagrantfile</strong>って Gruntfileみたいに何となくいじるのが面倒くさそうな印象があったんだけど、実は全くそんな事がなくて 寧ろ<strong>ちょろっとやれば誰でも簡単にいじれるようになるくらい学習コストが低かった</strong>(まだChefと絡めていないので Chefと連携させると若干話が変わってくるかもしれないけど)。<br />
というわけで今回は Vagrantを使ってUbuntuサーバを2台立てて MySQLでレプリケーションを構成してみた話を。<br />
今回に関してはどちらかというとVagrantよりMySQL寄りの話になります。<br />
Vagrantに関しては boxの構造とかVagrantfileの事とか 色々と整理できたので 後日 初心者向けにvagrantの基本的な事柄についてまとめます。<br />
<span id="more-871"></span></p>
<h2>Vagrantfileの設定</h2>
<pre class="brush: ruby; title: ; notranslate">
# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = &quot;2&quot;

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
    config.vm.box = &quot;Ubuntu_13&quot;
    config.vm.box_url = &quot;http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-1310-x64-virtualbox-puppet.box&quot;

  config.vm.define :ubuntu_1 do |ubuntu_1|
    ubuntu_1.vm.network :private_network, ip: &quot;192.168.33.10&quot;
  end  

  config.vm.define :ubuntu_2 do |ubuntu_2|
    ubuntu_2.vm.network :private_network, ip: &quot;192.168.33.11&quot;
  end  
end
</pre>
<p>こんな感じで Ubuntuの13.10を2台立てて、IPは192.168.33.10 と 192.168.33.11 の連番で割り振る。</p>
<pre class="brush: plain; title: ; notranslate">
$ vagrant up
</pre>
<p>ポートフォワードでこけるかなーと思ったら、Vagrantが勝手に衝突の解決をしてくれて localhost:2222 と localhost:2200 の2つを立ててくれた。うーん便利。<br />
うまくサーバが2つ立ち上がったかを確認するために pingを飛ばしてみる。</p>
<pre class="brush: plain; title: ; notranslate">
$ ping 192.168.33.10
PING 192.168.33.10 (192.168.33.10): 56 data bytes
64 bytes from 192.168.33.10: icmp_seq=0 ttl=64 time=0.294 ms
64 bytes from 192.168.33.10: icmp_seq=1 ttl=64 time=0.273 ms
64 bytes from 192.168.33.10: icmp_seq=2 ttl=64 time=0.450 ms
64 bytes from 192.168.33.10: icmp_seq=3 ttl=64 time=0.463 ms
^C
--- 192.168.33.10 ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.273/0.370/0.463/0.087 ms

$ ping 192.168.33.11
PING 192.168.33.11 (192.168.33.11): 56 data bytes
64 bytes from 192.168.33.11: icmp_seq=0 ttl=64 time=0.453 ms
64 bytes from 192.168.33.11: icmp_seq=1 ttl=64 time=0.669 ms
64 bytes from 192.168.33.11: icmp_seq=2 ttl=64 time=0.749 ms
64 bytes from 192.168.33.11: icmp_seq=3 ttl=64 time=0.601 ms
^C
--- 192.168.33.11 ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.453/0.618/0.749/0.109 ms
</pre>
<p>うん、うまく立ち上がってくれてる。</p>
<p>実際にsshでサーバに入るときは vagrantユーザで以下のように入る。また、vagrantユーザのデフォルトのパスワードは vagrant。</p>
<pre class="brush: plain; title: ; notranslate">
$ ssh vagrant@192.168.33.10
$ ssh vagrant@192.168.33.11
</pre>
<p>今回はセキュリティの話ではないので、秘密鍵の設定やiptablesの設定等は省略。</p>
<h2>MySQLをインストール</h2>
<p>何はともあれマスタサーバ、スレーブサーバにMySQLが入っている必要がある。立ち上げたばかりの Ubuntuサーバであれば、まずはapt-get updateを打つ必要があるので、2つのサーバに対してこんな感じでコマンドを打つ。</p>
<pre class="brush: plain; title: ; notranslate">
$ sudo apt-get update
$ sudo apt-get install mysql-server
</pre>
<p>親切にもインストールの際にMySQLのrootログイン用パスワードの設定画面が出てきてくれるので、お好みのパスワードを設定しておく。</p>
<h2>マスタサーバ側の設定</h2>
<p>my.cnfの設定をする。</p>
<pre class="brush: plain; title: ; notranslate">
$ sudo vi /etc/mysql/my.cnf
</pre>
<p>mysqld の項目に以下の2つを加える。</p>
<pre class="brush: plain; title: ; notranslate">
[mysqld]
log-bin
server-id=1
</pre>
<p>log-bin は「スレーブサーバと同期を取る為に必要なバイナリログを出力する」という設定。<br />
server-idは任意の数値で構わないが、スレーブサーバがマスタサーバのデータベースを参照するのに利用するので、スレーブサーバと重複しないようユニークなものを設定する必要がある。</p>
<p>また、mysqld設定の下にbind-addressに関する以下のような設定がある。このままだと外部サーバからの接続を受け付けてくれないため、ここではコメントアウトしてしまう( セキュリティを考慮するのであれば、別途 allow-hostsやdeny-hostsの設定が必要になりそう )。</p>
<pre class="brush: plain; title: ; notranslate">
# bind-address = 127.0.0.1
</pre>
<p>一連の設定が終わった所でmysqlを起動(デフォだとインストール後立ち上がっているみたいなのでrestartに)。</p>
<pre class="brush: plain; title: ; notranslate">
$ sudo mysql restart
</pre>
<p>とりあえず「test」っていうデータベースを作成して、こんな感じで「user」テーブルを作成する。話を簡潔にするために内部エンコーディング等諸々の設定は省略。</p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; CREATE DATABASE test;
mysql&gt; USE test;
mysql&gt; CREATE TABLE users ( user_id INT PRIMARY KEY AUTO_INCREMENT NOT NULL, user_name VARCHAR(30) UNIQUE NOT NULL );
</pre>
<p>スレーブサーバがアクセスできるようにユーザをつくる。</p>
<pre class="brush: plain; title: ; notranslate">
mysql &gt; GRANT REPLICATION SLAVE ON *.* TO 任意のユーザ名@192.168.33.11 identified by '任意のパスワード';
</pre>
<p>「test.*」じゃ駄目なの？って思ったけど、「レプリケーションはグローバルな設定だから駄目よ」みたいなニュアンスの事で怒られるから駄目みたい。</p>
<p>スレーブサーバへのコピーを取る際にデータベースに更新がかからないようテーブルをロック。<br />
ロックしたら、マスタのステータスを見る。</p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; FLUSH TABLES WITH READ LOCK;
mysql&gt; SHOW MASTER STATUS;
</pre>
<p>ここで表示されたマスタステータスのFileとPositionは 「どの時点からレプリケーション取り始めればいいの？」という事をスレーブに教えてくれる大事な情報になるのでメモしておくこと。僕の場合、Fileはmysql-bin.000001、Positionは742。 </p>
<p>その後 tarで固めてスレーブサーバにtarファイルをコピーする。</p>
<pre class="brush: plain; title: ; notranslate">
$ tar cvf test.tar.gz /var/lib/mysql/test
</pre>
<p>なお、<strong>InnoDBの場合 データベースのディレクトリだけコピーしても「show tablesするとテーブルが出るのに、desc や selectをしようとすると table doesn&#8217;t exist と怒られてしまう」…という問題がある</strong>らしく、僕も若干ハマった。解決方法としては <strong>/var/lib/mysql/ 下にある「ib」から始まるファイルもコピーする必要がある(さらに、コピーした後mysqlを再起動する必要がある)</strong>ということらしく(また、この際 権限がmysqlにある事をチェックすること)僕の場合はこれで解決した。<br />
(参考: <a href="http://stackoverflow.com/questions/7759170/mysql-table-doesnt-exist-but-it-does-or-it-should" target="_blank">stackoverflow: Mysql > Table doesn&#8217;t exist. But it does(or it should)</a>)</p>
<p>コピーを取り終えたらロックの解除を忘れずに。</p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; UNLOCK TABLES;
</pre>
<p>なお、今回はディレクトリをそのままコピーする方法でやったけれど、mysqldumpを使う方法もあるらしいので、ディレクトリコピーでうまくいかなかった人はこちらの方法を試してみると良いかもしれない。<br />
<strong>( 2014.10.12 18:00 追記 &#8211; 試してみた所、mysqldump の方が ib系のデータを書き換えたり権限を書き換えたりする手間が省けるので総合的に楽でした。また、mysqldumpでの方法については以下のリンクを参考にさせていただきました )</strong></p>
<p>(参考: <a href="http://wadslab.net/wiki/index.php?MySQL%20%A5%EC%A5%D7%A5%EA%A5%B1%A1%BC%A5%B7%A5%E7%A5%F3%A4%CE%A5%BB%A5%C3%A5%C8%A5%A2%A5%C3%A5%D7%BC%EA%BD%E7" target="_blank">MySQL レプリケーションのセットアップ手順</a>)</p>
<h2>スレーブサーバ側の設定</h2>
<p>こちらも /etc/mysql/my.cnf を編集して mysqldにserver-idを付加しておく。この際マスタのserver-idと重複しないよう注意すること。</p>
<pre class="brush: plain; title: ; notranslate">
server-id=2
</pre>
<p>マスタサーバでコピーしたtarファイルを /var/lib/mysql/下で展開。</p>
<pre class="brush: plain; title: ; notranslate">
$ tar xvf test.tar.gz
</pre>
<p>権限まわりの確認は必ず行うこと。また、上にも書いたように InnoDBの場合は ibから始まるファイルもコピーしておかないと「テーブルが表示されるのに参照できない」問題が発生する可能性があるので注意。</p>
<p>準備ができたらMySQLを立ち上げる。</p>
<pre class="brush: plain; title: ; notranslate">
$ service mysql restart
</pre>
<p>いよいよマスタサーバと同期させるぞう。<br />
…とその前に、念のためにtelnetを叩いてスレーブからマスタサーバにアクセスできるか確認しておこう(3306はMySQLのデフォのポート)。</p>
<pre class="brush: plain; title: ; notranslate">
$ telnet 192.168.33.10 3306
</pre>
<p>これで通ればOK。</p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; CHANGE MASTER TO
          MASTER_HOST='192.168.33.10',
          MASTER_USER='上記のGRANTオプションで設定したユーザ名',
          MASTER_PASSWORD='上記のGRANTオプションで設定したパスワード',
          MASTER_LOG_FILE='SHOW MASTER STATUSで確認したファイル名',
          MASTER_LOG_POS=SHOW MASTER STATUSで確認したposition;
mysql&gt; Query OK, 0 rows affected (0.00 sec)
mysql&gt; START SLAVE;
mysql&gt; Query OK, 0 rows affected (0.00 sec)
</pre>
<p>スレーブのステータスを見て Slave_SQL_Runnningが YES になっていることを確認すること。<br />
また Last_IO_Errorあたりに変なエラーが出ていないか確認すること。<br />
例えば 上手くコネクションが貼れていない場合は「error connecting to master」なんてエラーが出る。<br />
↓ (例) マスタに上手く繋げていない時の スレーブのステータス。<br />
<a href="http://kinokoru.jp/wp-content/uploads/2014/10/9.jpg"><img src="http://kinokoru.jp/wp-content/uploads/2014/10/9.jpg" alt="9" width="800" height="427" class="aligncenter size-full wp-image-893" /></a></p>
<h2>レプリケーションのテストをしてみる</h2>
<p>早速 レプリケーションが上手く構成できているかどうかテストしてみる。<br />
まずはマスタサーバのtestデータベースにアクセス。</p>
<p>念には念を入れて ちゃんとマスタにアクセスしているかどうかを確認。</p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; SHOW MASTER STATUS;
mysql&gt; SHOW SLAVE STATUS;
</pre>
<p>ちゃんとマスタにいることが確認できたら、ドキドキしながらデータを入れてみる。</p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; INSERT INTO users (user_name) VALUES ('hogeman');
</pre>
<p>次にスレーブサーバのtestデータベースにアクセス。</p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; SELECT * FROM users;
</pre>
<p>スレーブサーバにも&#8217;hogeman&#8217;のデータが入っていたら成功。正常にレプリケーションが構成できていることになる。<br />
「あれ…？反映されないぞ？」という場合は再度 SHOW SLAVE STATUS; でエラーが出ていないか確認してみる。</p>
<h2>その他の処方箋</h2>
<h3>Q. MySQLをstartさせたり stopさせたりしてたら MySQLが起動できなくなった。</h3>
<p>「Job failed to start.」とか「Can&#8217;t connect to local MySQL server through socket.」とか怒られる場合は 該当ディレクトリにsocketファイルがあるかどうかを確認する。socketファイルが無ければ touchコマンドか何かで socketファイルを作成し、権限を mysql:mysql に設定してあげる。<br />
その後「sudo /etc/init.d/mysql start」「sudo mysql start」「sudo service mysql start」をそれぞれ試してみる。<br />
大体はこれで解決するらしいけど、それでも駄目なようなら my.cnf ファイルが間違っている可能性があるのでチェックすること。<br />
(例えば bind-address を複数設定しようとしていたり。bind-addressは一つのホストしか受けつけない)</p>
<h3>Q. あれこれいじってたら スレーブ側で duplicate entryが出るようになってしまった。</h3>
<p>スレーブ側でレプリ遅延が起きている。<br />
こういう場合はSHOW SLAVE STATUS; でエラーログを追跡しながら 親と整合性を合わせる必要がある。<br />
一個ずつ慎重にレプリ遅延している箇所を見ながら SQL_SLAVE_SKIP_COUNTER を回していく作業。</p>
<p>スレーブをストップして、</p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; STOP SLAVE;
</pre>
<p>整合性を合わせながら SLAVE_SKIP_COUNTERを回して( SLAVE側に直接insert処理をかけてしまったり 整合性が合わなくなってしまった所は 別途 スレーブに追加してしまったデータを削除して AUTO_INCREMENTのスタート値を調整して…等の作業が発生する感じになるのかな…？ )、</p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
</pre>
<p>再開する。</p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; START SLAVE;
</pre>
<p>ただしskipに関しては トランザクション処理等を行う場合の挙動について若干注意が必要みたい。<br />
<a href="http://www.percona.com/blog/2013/07/23/another-reason-why-sql_slave_skip_counter-is-bad-in-mysql/" target="_blank">(参考: Another reason why SQL_SLAVE_SKIP_COUNTER is bad in MySQL)</a></p>
<p>The post <a rel="nofollow" href="http://kinokoru.jp/archives/871">VagrantでUbuntuサーバを2台立ててMySQLでマスタスレーブ構成にしてみた</a> appeared first on <a rel="nofollow" href="http://kinokoru.jp">きのこる庭</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://kinokoru.jp/archives/871/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>【MySQL】インデックス指定の順序が気になったので、MySQLの構文解析ロジックを検証してみた話</title>
		<link>http://kinokoru.jp/archives/306</link>
		<comments>http://kinokoru.jp/archives/306#comments</comments>
		<pubDate>Tue, 25 Mar 2014 10:49:09 +0000</pubDate>
		<dc:creator>Nisei Kimura</dc:creator>
				<category><![CDATA[サーバ・インフラ系]]></category>
		<category><![CDATA[検証・考察]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://kinokoru.jp/?p=306</guid>
		<description><![CDATA[<p>ご無沙汰です。 本当は「数千万件のデータが入ったテーブルでインデックスを構築したらパフォーマンスが劇的に改善された話」というタイトルで書こうと思ったのだけど、書いているうちに内部構造が気になり出したので上記のタイトルに変 [...]</p>
<p>The post <a rel="nofollow" href="http://kinokoru.jp/archives/306">【MySQL】インデックス指定の順序が気になったので、MySQLの構文解析ロジックを検証してみた話</a> appeared first on <a rel="nofollow" href="http://kinokoru.jp">きのこる庭</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>ご無沙汰です。</p>
<p>本当は<strong>「数千万件のデータが入ったテーブルでインデックスを構築したらパフォーマンスが劇的に改善された話」</strong>というタイトルで書こうと思ったのだけど、書いているうちに内部構造が気になり出したので上記のタイトルに変更。</p>
<h2>まずはパフォーマンスが改善された話から</h2>
<pre class="brush: sql; title: ; notranslate">

SELECT A FROM hoge WHERE B = ~~~ ORDER BY C DESC;

</pre>
<p>hogeは数千万件のデータが入ったテーブルで、その中から結果約4万件程のデータのうち A の部分をSELECT。条件としては、カラムBの値が~~~に合致するときで、更には Cという別のカラムで並び替えるというクエリになっている。</p>
<p>結果的に</p>
<pre class="brush: sql; title: ; notranslate">
ALTER TABLE hoge ADD INDEX foo ( B, C, A );
</pre>
<p>というインデックスを張ることによって、<strong>それまで2分以上かかっていたselect文が 0.1秒～0.2秒まで短縮されたという某赤いモビルスーツも驚きのパフォーマンス改善を見せた</strong>。</p>
<p>正直インデックスの劇的な威力に感動して、その喜びをブログにつづろうと思い立った所、以下の疑問が生まれたというのが始まり。</p>
<p>すなわち、</p>
<p>何で↓じゃだめなの？</p>
<pre class="brush: sql; title: ; notranslate">
ALTER TABLE hoge ADD INDEX foo ( A, B, C );
</pre>
<p>という話(どこかのブログで「<strong>インデックスは順序左から書かないと意味無いよ</strong>」と書いていたので)。</p>
<h2>仮説</h2>
<p>なんとなーく最近コンパイラをいじっていて記憶に新しい<strong>構文木的なにおい</strong>がするなあと感じた。</p>
<p>そこで、MySQLの構文解析機構を調べてみたところ、</p>
<p>案の定字句解析と構文解析をそれぞれ<strong>Flex</strong>と<strong>Bison</strong>で行っているようなので、勉強がてらMySQLの構文解析ロジックを見てみることにした。</p>
<h2>調査</h2>
<p>丁度GoogleがMySQLのコードを出していたので、MySQLの構文定義部である<strong>sql_yacc.yy</strong>の中身を拝見。</p>
<p><a href="http://code.google.com/p/google-mysql/source/browse/sql/sql_yacc.yy?r=d15790ab618324fb1729aa212b244cad5cb9778f" target="_blank">http://code.google.com/p/google-mysql/source/browse/sql/sql_yacc.yy?r=d15790ab618324fb1729aa212b244cad5cb9778f</a></p>
<p>まずは<strong>式全体の構文</strong>を探す。<strong>1600行目</strong>でみっけ。</p>
<pre class="brush: cpp; title: ; notranslate">
/* Verb clauses, except begin */
statement:
alter
| analyze
| backup
| binlog_base64_event
| call
| change
| check
| checksum
| commit
| create
| deallocate
| delete
| describe
| do
  :
  :
  :

</pre>
<p>中には「select」もしっかり定義されていたので、続いて<strong>select</strong>を探す。</p>
<p><strong>6638行目</strong>から始まっているのがそれっぽい。</p>
<pre class="brush: cpp; title: ; notranslate">

select:
select_init
{
LEX *lex= Lex;
lex-&gt;sql_command= SQLCOM_SELECT;
}
;

/* Need select_init2 for subselects. */
select_init:
SELECT_SYM select_init2
| '(' select_paren ')' union_opt
;

</pre>
<p>どんどん掘り下げていった結果、だいたいこんな感じになりました。</p>
<p><a href="http://kinokoru.jp/wp-content/uploads/2014/03/trees.png"><img class="aligncenter size-full wp-image-310" alt="trees" src="http://kinokoru.jp/wp-content/uploads/2014/03/trees.png" width="630" height="500" /></a></p>
<h2></h2>
<h2>考察</h2>
<p><strong>選択するカラム</strong>と <strong>where句、order by句、 having 句、group by 句などの条件</strong>が<strong>明確に分断されていました</strong>。</p>
<p>つまり、<strong>select_from の部分は、よくあるコンパイラの factor = ( expression ) 的な感じで先に解析されていて、解析が終了した後でSELECT_SYM とがっちゃんこするのではないか</strong>と予想(定かではありません)。</p>
<p>こう考えると</p>
<pre class="brush: sql; title: ; notranslate">
ALTER TABLE hoge ADD INDEX foo ( B, C, A );
</pre>
<p>になるのはそこまで不思議な話ではないかなと感じた。</p>
<h2></h2>
<h2>実際はどうだったのか(2014.03.26追記)</h2>
<p>記事の公開後、友人から「<strong>covering index</strong> 的な話では」とご指摘をいただきました。</p>
<p>Covering Indexに関しては 以下の記事がとても参考になった。</p>
<p><a href="http://blog.livedoor.jp/sasata299/archives/51336006.html" target="_blank">MySQLでインデックスを使って高速化するならCovering Indexが使えそう</a></p>
<p>もう少しDBまわりの勉強もしないとなあと思いつつ、また新しいことを勉強させていただいた上にMySQLの内部構造にもちょこっと触れられたので 結果としては良かったかなと思った。</p>
<p>The post <a rel="nofollow" href="http://kinokoru.jp/archives/306">【MySQL】インデックス指定の順序が気になったので、MySQLの構文解析ロジックを検証してみた話</a> appeared first on <a rel="nofollow" href="http://kinokoru.jp">きのこる庭</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://kinokoru.jp/archives/306/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>はじめてのVagrant ～ CentOS6.5 + ApacheでWebサーバを立ててみる</title>
		<link>http://kinokoru.jp/archives/196</link>
		<comments>http://kinokoru.jp/archives/196#comments</comments>
		<pubDate>Fri, 17 Jan 2014 10:29:00 +0000</pubDate>
		<dc:creator>Nisei Kimura</dc:creator>
				<category><![CDATA[サーバ・インフラ系]]></category>
		<category><![CDATA[ツール系]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[Vagrant]]></category>
		<category><![CDATA[VirtualBox]]></category>

		<guid isPermaLink="false">http://kinokoru.jp/?p=196</guid>
		<description><![CDATA[<p>Vagrant？ 簡単に言うとインフラ構築の自動化。 例えば 手動でやろうとすると、OS入れる度に VMでディスクイメージ読み込ませて あれやこれやと細かい初期設定しないといけないけど、Vagrantを使えばたった3つの [...]</p>
<p>The post <a rel="nofollow" href="http://kinokoru.jp/archives/196">はじめてのVagrant ～ CentOS6.5 + ApacheでWebサーバを立ててみる</a> appeared first on <a rel="nofollow" href="http://kinokoru.jp">きのこる庭</a>.</p>
]]></description>
				<content:encoded><![CDATA[<h2><a href="http://kinokoru.jp/wp-content/uploads/2014/01/logo_vagrant-81478652.png"><img class="aligncenter size-full wp-image-217" alt="logo_vagrant" src="http://kinokoru.jp/wp-content/uploads/2014/01/logo_vagrant-81478652.png" width="248" height="64" /></a></h2>
<h2>Vagrant？</h2>
<p>簡単に言うと<strong>インフラ構築の自動化</strong>。<br />
例えば 手動でやろうとすると、OS入れる度に VMでディスクイメージ読み込ませて あれやこれやと細かい初期設定しないといけないけど、Vagrantを使えばたった3つのコマンドで上に書いた事を勝手にやってくれる。<br />
<strong>Vagrantは chefのようなツールと合わせて使えば超強力</strong>と巷では言われていて、要するに<strong>ソフトウェアのインストールまで自動化してくれる</strong>。<br />
これはどういうことかというと…</p>
<p><strong>インフラ構築にいちいち時間かける必要もなくなるし、ミスも防げるし、チーム開発の場合は 新しく入ってきた人でもすぐに環境構築できるし、何より「俺の環境では動いたよ」も減る。</strong></p>
<p>個人で勉強用に開発環境立てては壊しまくったりする場合にもかなり便利だけど、チーム開発でも圧倒的な力を発揮。</p>
<p>とりあえず 今回に関しては Chef を使用せずに VagrantでOSだけ入れてもらって、動作確認の意味合いを込めてWebサーバの立ち上げをやってみる。</p>
<p>因みにVMを動作させる環境はフリーで落とせる VirtualBox を使用。</p>
<p><span id="more-196"></span></p>
<h2>CentOS導入編</h2>
<p>最新の<a href="https://www.virtualbox.org/wiki/Downloads" target="_blank">VirtualBox</a> と <a href="http://downloads.vagrantup.com/" target="_blank">Vagrant</a> をインストール。</p>
<p>あとはコマンドラインで以下の3つのコマンドを叩くだけ。</p>
<pre class="brush: bash; title: ; notranslate">

vagrant box add centos https://github.com/2creatives/vagrant-centos/releases/download/v6.5.1/centos65-x86_64-20131205.box
vagrant init centos
vagrant up

</pre>
<p>※各OSとboxURLに関しては <a href="http://www.vagrantbox.es/" target="_blank">こちら</a> に掲載されているものを参考にさせていただきました。</p>
<h2>Webサーバ編</h2>
<p>VagrantでOS立てる時に Vagrantfile という設定ファイルがローカルにできているのでそれを編集。</p>
<pre class="brush: bash; title: ; notranslate">
 # config.vm.network :private_network, ip: &quot;192.168.33.10&quot;

</pre>
<p>の行のコメントアウト部分(#)を消す。<br />
( 因みに192.168.33.10 は vagrant で設定されているデフォルトのipアドレス )</p>
<p>続いてvagrantのサーバにアクセス。</p>
<p>( Macとかなら「<strong>vagrant ssh</strong>」 ってコマンドで打てば良いけど、<strong>Windows環境とかで怒られる場合はPuttyとか別のSSHクライアントを使用する</strong>こと。なお、Windowsの場合もユーザ名とかホストとかポートとか諸々の情報は「vagrant ssh」で出てきます )</p>
<p>インストールとか httpdの編集とかするんで、最初に su で root になっておくと良いかも( Vagrantの場合、デフォのルートパスワードは vagrant )。</p>
<p>とりあえず細かい設定とか抜きにして単純にWebサーバ立てるだけなら まずは httpd くらいで十分なので</p>
<pre class="brush: bash; title: ; notranslate">
 yum install -y httpd

</pre>
<p>みたいな感じで httpd を入れてみる。</p>
<p>インストールしたら</p>
<p>/etc/httpd/conf/httpd.conf</p>
<p>をvi か何かで編集。</p>
<p>( 敢えて vim ではなく vi と書いたのは、vagrant経由でcentosをそのままインストールした時に vim がインストールされていなかったため。vimを使う場合は yum -y install vim とかで入れる )</p>
<p>ServerName の部分を 192.168.33.10 に。</p>
<p>続いて<br />
/var/www/html/ の下のindex.html( 無ければ作成 )<br />
を vi か何かで起動して一行目に お決まりの「Hello World」を。</p>
<pre class="brush: bash; title: ; notranslate">

service httpd start

</pre>
<p>( 次からhttpdが自動起動されるように chkconfig httpd on にしておくと良いかも )</p>
<p>ブラウザで</p>
<p>http://192.168.33.10/</p>
<p>にアクセス。</p>
<p>「<strong>Hello World</strong>」が表示されればOK。</p>
<p>今回はWebサーバ構築だけだったけど、念のために<strong>ポート変更</strong>とか<strong>ルートログイン禁止</strong>とか<strong>パスワードログインから公開鍵認証に切り替えたり</strong>とか <strong>ServerTokensを Prod にしたり</strong>とか <strong>ServerSignatureをoffにしたり</strong>とか、最低限のセキュリティ設定はしてあげると良いかも。</p>
<p>( トップのロゴはVagrantの公式ホームページ <a href="http://www.vagrantup.com/" target="_blank">http://www.vagrantup.com/</a>  からお借りしています )</p>
<p>The post <a rel="nofollow" href="http://kinokoru.jp/archives/196">はじめてのVagrant ～ CentOS6.5 + ApacheでWebサーバを立ててみる</a> appeared first on <a rel="nofollow" href="http://kinokoru.jp">きのこる庭</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://kinokoru.jp/archives/196/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
