<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[愛雅小鋪]]></title>
  <link href="http://ayaya.tw/atom.xml" rel="self"/>
  <link href="http://ayaya.tw/"/>
  <updated>2012-04-29T09:03:04+08:00</updated>
  <id>http://ayaya.tw/</id>
  <author>
    <name><![CDATA[ayaya]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[安裝與設定 HAProxy]]></title>
    <link href="http://ayaya.tw/blog/2012/04/29/setup-haproxy/"/>
    <updated>2012-04-29T08:01:00+08:00</updated>
    <id>http://ayaya.tw/blog/2012/04/29/setup-haproxy</id>
    <content type="html"><![CDATA[<p><a href="http://haproxy.1wt.eu/">HAProxy</a> 是一套 TCP/HTTP Load Balancer.
原本想說 <a href="http://nginx.org/">nginx</a> 似乎終於要支援 proxy websocket 了,
結果 1.2 釋出後還是搞不定, 於是決定跳槽&#8230;
應該說是加入新的工具, 因為 HAProxy 沒辦法完整取代 nginx.
HAProxy 提供了很完整的 proxy 能力,
不過它並不是 web server, 所以沒有 serve static file 的能力,
所以 nginx 就變成 serve static file 專用的 server 了&#8230; XD</p>

<h2>安裝</h2>

<p>在 Arch Linux 下要從 AUR 安裝, 我用 <code>yaourt</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>yaourt -S haproxy
</span></code></pre></td></tr></table></div></figure>


<h2>設定</h2>

<p>打開 <code>/etc/haproxy/haproxy.cfg</code> 你會看到 global, defaults 和一堆 listen,
由於本文只打算作為快速入門用, 就不詳細解釋這些東西在幹嘛了
(懶 + 很多還不知道 XD).</p>

<h3>事前</h3>

<p><code>listen</code> 區塊是結合 <code>frontend</code> 與 <code>backend</code> 功能的區塊,
你可以在這裡把 header 解析和 backend server 一起設定,
不過我的需求有點複雜, 所以還是 <code>frontend</code> 和 <code>backend</code> 乖乖分開寫&#8230;
所以先砍掉所有的 <code>listen</code> 區塊吧!</p>

<p>為了測試, 請先把 <code>global</code> 中的 <code>chroot</code>, <code>uid</code>, <code>gid</code>, <code>daemon</code> 關掉
(使用 <code>#</code> 開頭表示註解), 並打開 <code>debug</code>.</p>

<h3>nginx backend + virtual hosts 設定</h3>

<p>我們打算讓 nging serve static file,
以這個 blog 來說就是把所有來自 ayaya.tw 的請求都往 80 port 丟.</p>

<p>在前端我們想要 listen 8080 port, 所以寫一個 <code>frontend</code> 區塊:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>frontend all 0.0.0.0:8080
</span></code></pre></td></tr></table></div></figure>


<p>接著, 寫下比對的條件:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>frontend all 0.0.0.0:8080
</span><span class='line'>  acl is_blog hdr_beg<span class="o">(</span>Host<span class="o">)</span> -i ayaya.tw
</span><span class='line'>  use_backend static <span class="k">if </span>is_blog
</span></code></pre></td></tr></table></div></figure>


<p><code>acl</code> 指令在符合指定條件 (<code>hdr_beg(Host) -i ayaya.tw</code>) 時,
會將指定的值 (<code>is_blog</code>) 設定為 true.</p>

<p>在這裡我給的條件是:
當 header (<code>hdr</code>) 中的 Host 欄位以 ayaya.tw 開始 (<code>beg</code>) 時,
將 is_blog 設定為 true. <code>-i</code> 則表示無視大小寫.</p>

<p>下一行看起來就很 ruby: 如果 <code>is_blog</code> 就使用 <code>static</code> 這個 backend.</p>

<p>所以來設定 <code>static</code> 這個 backend:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>backend static
</span><span class='line'>  timeout server 30000
</span><span class='line'>  timeout connect 4000
</span><span class='line'>  server static01 127.0.0.1:80 check
</span></code></pre></td></tr></table></div></figure>


<p><code>static01</code> 是我給 server 取的名字, 它的位置在 <code>127.0.0.1:80</code>,
<code>check</code> 則是告訴 HAProxy 定時檢查 server 狀態,
預設是用 <code>OPTIONS /</code> 檢查,
你可以使用 <code>option httpchk</code> 改以其他 method/path 檢查.</p>

<p>透過以上的設定, 就可以將 http://ayaya.tw:8080 導至 server 本機的 127.0.0.1:80.</p>

<h2>啓動</h2>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>haproxy -f /etc/haproxy/haproxy.cfg
</span></code></pre></td></tr></table></div></figure>


<p>這個時候就可以連上 ayaya.tw:8080 試試看能不能正確取得檔案了.
沒有問題的話, 就可以和 nginx 互換 port 讓 HAProxy 跑在前面了.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>sudo /etc/rc.d/haproxy start
</span></code></pre></td></tr></table></div></figure>


<p>別忘了打開 <code>global</code> 中的 <code>chroot</code>, <code>uid</code>, <code>gid</code>, <code>daemon</code>, 關掉 <code>debug</code>&#8230;</p>

<h2>Snippets</h2>

<h3>WebSocket</h3>

<p>WebSocket 需要比較持久的連線, 所以在 backend 中將時間拉長&#8230;</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>frontend
</span><span class='line'>  acl is_websocket hdr<span class="o">(</span>Upgrade<span class="o">)</span>  -i WebSocket
</span><span class='line'>  acl is_websocket hdr_beg<span class="o">(</span>Host<span class="o">)</span> -i ws
</span><span class='line'>  use_backend your_websocket_backend <span class="k">if </span>is_websocket
</span><span class='line'>
</span><span class='line'>backend
</span><span class='line'>  timeout queue 5000
</span><span class='line'>  timeout server 86400000
</span><span class='line'>  timeout connect 86400000
</span></code></pre></td></tr></table></div></figure>


<h3>讓 backend 保有 client ip</h3>

<p>不設定這個的話, backend 永遠都會得到 HAProxy 所在的 ip address.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>global
</span><span class='line'>  option forwardfor
</span></code></pre></td></tr></table></div></figure>


<h3>HTTP basic auth</h3>

<p>把 <code>LIST_NAME</code>, <code>USERNAME</code> 和 <code>PASSWORD</code> 換成你喜歡的:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>userlist LIST_NAME
</span><span class='line'>  user USERNAME insecure-password PASSWORD
</span><span class='line'>
</span><span class='line'>backend
</span><span class='line'>  acl is_authenticated http_auth<span class="o">(</span>LIST_NAME<span class="o">)</span>
</span><span class='line'>  http-request auth realm Who<span class="se">\ </span>are<span class="se">\ </span>you? <span class="k">if</span> !is_authenticated
</span></code></pre></td></tr></table></div></figure>


<p>字串不能用引號包, 要用 \ escape 空白&#8230;</p>

<h3>啓用 HAProxy 內建後台</h3>

<p>把帳號密碼換成你喜歡的:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>backend stats
</span><span class='line'>  stats <span class="nb">enable</span>
</span><span class='line'><span class="nb">  </span>stats uri /
</span><span class='line'>  stats realm Global<span class="se">\ </span>statistics
</span><span class='line'>  stats auth admin:1234
</span></code></pre></td></tr></table></div></figure>


<h3>Hot-reconfigure</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>haproxy -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid -sf <span class="k">$(</span>cat /var/run/haproxy.pid<span class="k">)</span>
</span></code></pre></td></tr></table></div></figure>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[安裝與設定 Thinking Sphinx (含中文支援)]]></title>
    <link href="http://ayaya.tw/blog/2012/04/11/setup-thinking-sphinx-with-chinese-support/"/>
    <updated>2012-04-11T15:56:00+08:00</updated>
    <id>http://ayaya.tw/blog/2012/04/11/setup-thinking-sphinx-with-chinese-support</id>
    <content type="html"><![CDATA[<h2>開發環境篇</h2>

<p>環境:</p>

<ul>
<li>Mac OS X</li>
<li>使用 Homebrew</li>
<li>使用 rvm, ruby 1.9.3, rails 3.1</li>
</ul>


<h3>安裝 Sphinx</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>brew install sphinx
</span></code></pre></td></tr></table></div></figure>


<h3>安裝 Thinking Sphinx</h3>

<p>in Gemfile:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">gem</span> <span class="s1">&#39;thinking-sphinx&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<p>然後 <code>bundle install</code>.</p>

<h3>設定索引</h3>

<p><a href="http://freelancing-god.github.com/ts/en/indexing.html">看這裡</a></p>

<h3>設定 Thinking Sphinx</h3>

<p>首先加入中文支援, in <code>config/sphinx.yml</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='yaml'><span class='line'><span class="l-Scalar-Plain">development</span><span class="p-Indicator">:</span>
</span><span class='line'>  <span class="l-Scalar-Plain">ngram_len</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">1</span>
</span><span class='line'>  <span class="l-Scalar-Plain">ngram_chars</span><span class="p-Indicator">:</span> <span class="s">&quot;U+3000..U+2FA1F&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>接著執行 <code>rake ts:conf</code>,
這個 task 會產生設定檔 <code>config/[environment].sphinx.conf</code>,
請不要加入 git, 因為這個檔案會包含 <code>database.yml</code> 的資訊,
因此請將它加入 <code>.gitignore</code>.</p>

<h3>建立索引</h3>

<p>執行 <code>rake ts:index</code> 後會建立索引, 並儲存於 <code>db/sphinx/</code>,
同樣的這個目錄也應該加入 <code>.gitignore</code>.</p>

<p>這個 task 需加入 crontab, 約半小時執行一次.</p>

<p>如果使用 whenever, 可在 <code>config/schedule.rb</code> 中加入:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">every</span><span class="p">(</span><span class="mi">30</span><span class="o">.</span><span class="n">minute</span><span class="p">)</span> <span class="p">{</span> <span class="n">rake</span> <span class="s1">&#39;ts:index&#39;</span> <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>啟動 searchd</h3>

<p>執行 <code>rake ts:start</code>, 若看到 <code>Started successfully (pid xxxxx).</code>,
表示順利啟動成功.</p>

<p>必須要啟動 searchd 才能進行搜尋, 否則會噴 <code>Riddle::ConnectionError</code>.</p>

<h3>注意事項</h3>

<p>若有變更資料庫或者索引, 必須執行 <code>rake ts:rebuild</code> 重新建立索引.</p>

<h2>生產環境篇</h2>

<p>環境:</p>

<ul>
<li>Arch Linux</li>
<li>使用 yaourt</li>
<li>使用 rvm, ruby 1.9.3, rails 3.1</li>
<li>使用 Capistrano</li>
</ul>


<h3>安裝 Sphinx</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>yaourt -S sphinx
</span></code></pre></td></tr></table></div></figure>


<h3>設定 Thinking Sphinx</h3>

<p>加入中文支援, in <code>config/sphinx.yml</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='yaml'><span class='line'><span class="l-Scalar-Plain">production</span><span class="p-Indicator">:</span>
</span><span class='line'>  <span class="l-Scalar-Plain">ngram_len</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">1</span>
</span><span class='line'>  <span class="l-Scalar-Plain">ngram_chars</span><span class="p-Indicator">:</span> <span class="s">&quot;U+3000..U+2FA1F&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>設定 Sphinx 執行檔位置, in <code>config/sphinx.yml</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='yaml'><span class='line'><span class="l-Scalar-Plain">production</span><span class="p-Indicator">:</span>
</span><span class='line'>  <span class="l-Scalar-Plain">ngram_len</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">1</span>
</span><span class='line'>  <span class="l-Scalar-Plain">ngram_chars</span><span class="p-Indicator">:</span> <span class="s">&quot;U+3000..U+2FA1F&quot;</span>
</span><span class='line'>  <span class="l-Scalar-Plain">bin_path</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">/usr/bin/</span>
</span><span class='line'>  <span class="l-Scalar-Plain">searchd_binary_name</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">sphinx-searchd</span>
</span><span class='line'>  <span class="l-Scalar-Plain">indexer_binary_name</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">sphinx-indexer</span>
</span></code></pre></td></tr></table></div></figure>


<h3>設定 Capistrano</h3>

<p>在 <code>config/deploy.rb</code> 中加入:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">namespace</span> <span class="ss">:deploy</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">namespace</span> <span class="ss">:thinking_sphinx</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">task</span> <span class="ss">:stop</span><span class="p">,</span> <span class="ss">:roles</span> <span class="o">=&gt;</span> <span class="ss">:app</span> <span class="k">do</span>
</span><span class='line'>      <span class="n">run</span> <span class="s2">&quot;cd </span><span class="si">#{</span><span class="n">current_path</span><span class="si">}</span><span class="s2"> &amp;&amp; RAILS_ENV=</span><span class="si">#{</span><span class="n">rails_env</span><span class="si">}</span><span class="s2"> bundle exec rake ts:stop&quot;</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">task</span> <span class="ss">:restart</span><span class="p">,</span> <span class="ss">:roles</span> <span class="o">=&gt;</span> <span class="ss">:app</span> <span class="k">do</span>
</span><span class='line'>      <span class="n">run</span> <span class="s2">&quot;cd </span><span class="si">#{</span><span class="n">release_path</span><span class="si">}</span><span class="s2"> &amp;&amp; RAILS_ENV=</span><span class="si">#{</span><span class="n">rails_env</span><span class="si">}</span><span class="s2"> bundle exec rake ts:stop ts:rebuild&quot;</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">before</span> <span class="s1">&#39;deploy:update_code&#39;</span><span class="p">,</span> <span class="s1">&#39;deploy:thinking_sphinx:stop&#39;</span>
</span><span class='line'>  <span class="n">after</span> <span class="s1">&#39;deploy:restart&#39;</span><span class="p">,</span> <span class="s1">&#39;deploy:thinking_sphinx:restart&#39;</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>第一次 deploy 時得先拿掉 <code>before 'deploy:update_code', 'deploy:thinking_sphinx:stop'</code>,
因為這個時候還沒有安裝 Thinking Sphinx, 會找不到 <code>ts:stop</code> 這個 rake task.</p>

<p>順便一提 <code>ts:rebuild</code> 也會順便把 searchd 開起來, 所以就不用再跑 <code>ts:start</code> 了.</p>
]]></content>
  </entry>
  
</feed>

