網站架構調整後有感: 要學習另一個陣營的技術,還真是條不歸路,越挖越覺得要摸索的東西越多 @@ 照例前面先來點碎碎念,正題後面再來。這年頭,大型的佈署是少不了 Linux + OpenSource Solution 的,再加上我吃飯的傢伙 ASP.NET 的下一版 (vNext, .NET Core) 也要正式跨各種平台了,不熟悉一下 Linux 以後怎麼會有能力把寫出來的 code 搬到 Linux 上面執行? 不過,要跨到完全另一個生態體系的環境,還真要下點決心才跨得過去… 所幸,我挑對了切入點 (把自己的 BLOG 從 BlogEngine 轉移到 WordPress, 架設在 NAS + DOCKER 環境),這幾個月下來,也算累積了不少的心得 :D 要在 Linux 的世界裡打滾,最痛苦的就是安裝各種軟體了,只能說那真是地獄… @@,尤其是對於不熟 Linux 的人來說更是如此。現在有各種套件安裝的工具,向是 APT-GET 之類的,其實已經簡化很多了,但是難的在後頭,各種的 configuration 都要自己編 conf 檔,而每套系統用的語法都不一樣… 我不論是在 Coding 或是 System Admin 時,都很講究系統架構。因此往往預設的安裝我都不滿意,我都會想盡辦法用最基礎的模組,搭建出我認為最理想最適合的架構。很多組態都必須自己研究摸索,都需要碰到進階的安裝設定,這也是要開始認真用 Linux 的我最大的障礙… 然而我的目的不是要熟悉這些 configuration 啊,我目的是架設出期望的系統,來解決後續的問題,這些繁瑣的安裝設定機制 (除非必要,像是這篇要講的 Rewrite ) 就能省則省… 所幸 Docker 的出現,正好給了我這種人一個機會,我只要搞定最基本的 Docker 執行環境,其他安裝就簡單了,找到正確的 container image 就一切搞定。加上我用的 NAS 內建 Docker 的支援,連 Linux + Docker 架設都免了… 至於為何要這麼大費周章的熟悉 Linux ? 轉貼一則最近看到的新聞… 連 Microsoft CEO Satya Nadella 都公開表示 “Linux is Best for Cloud” 了,多年的 Microsoft 信徒軟絲當然要花時間去研究一下.. XD
Microsoft Agrees Linux is Best for Cloud
Ever since the new CEO, Satya Nadella, has taken the place of the Linux-hater Steve Balmer, the change in Microsoft’s rhetoric regarding Linux has been clear. Now, Microsoft is officially recommending Linux on Twitter.
好,看到分隔線,就代表正題開始! 前面幾篇有跟到的讀者們,應該都知道我之前在研究甚麼.. 為了在我能力範圍內用最快的方式搭建能夠執行 .NET Core 的 Linux 環境,我選用了 Synology NAS + Docker 來踏出第一步. 為了快速熟悉各種實作技巧,我把自己的 BLOG 從原本的 BlogEngine ( ASP.NET ) 轉移到 WordPress (現在還是 PHP, 以後要變成 Node.js 了)。前兩篇說明了用 Apache 做前端的 Reverse Proxy, 同時也為了 新舊系統的文章轉址,用 Apache 的 RewriteMap 解決 400 篇文章 x 6 種網址格式,多達 2400 種組合的新舊網址轉址。 就當越用越熟練之際,我擔心的問題來了! NAS 再好用,他終究不是正規的 SERVER … NAS 的硬體都不怎麼樣,我的 Synology 412+ (Atom 2701D + 2GB RAM) 很快地就碰到瓶頸了,多開兩個 container 就明顯 的感覺的到回應變慢了… 於是我決定開始把我的 BLOG 系統轉移到 Ubuntu Server 上,用專屬的硬體來架設 (NB)。架設的硬體其實也很巧,是我老姊請我幫她處理掉的舊 NB。拿舊的 NB 其實很適合,一來省電,二來 Linux 省資源, 跑 Windows 跑不動,換成裝 Linux 跑個人 BLOG 其實還綽綽有餘,三來 NB 內建的電池正好當成 UPS,也省了一筆開銷… 。接手的 NB 硬體只是貧弱的 Intel Pentium P6100 + 4GB RAM,不過不管在運算能力或是 RAM 都遠比 我現在的 NAS 強… 於是架好 Ubuntu Server + Docker 後就開始動手了
先來看看這次我想調整的架構圖。第一張圖是現有的架構,就是兩個月前剛轉移 BLOG 用的架構: 第二張是我想調整的新架構,也就是這次要做的:
這次的調整,我決定沿用之前的架構,就是前端用 Reverse Proxy 來發布藏在後面的 WEB application, 因為後面有好幾個 Docker Container 需要同時用一個 IP + 80 port 發布,這層是跑不掉的。加上大量舊網址轉址的需求,我不想把這個複雜度加在 WordPress 上面,所以這需求就落在 Reverse Proxy 身上。原先的架構中,Reverse Proxy 是用 Apache Httpd 來負責 (因為 NAS 內建 apache httpd, 而且已經把 port 80 佔住了,沒辦法換掉),現在自己架設 Ubuntu Server 就沒有這些限制,我當然就改用現在當紅的 NGINX 來代替。 既然都用 Docker 了,其實找到正確的套件,設定一下就搞定,單純系統安裝的部分我就跳過去了。架構上調整的兩個較大的工程我補充一下:
調整後的架構跟效能,應該都會遠比原本的好。直到現在用了 Docker, 才開始對當年學 UML 的 deployemnt diagram 有感覺… 後來 Visual Studio Team Suite 也出現過這個功能,可以繪製 deploy diagram (強的是還能跟你實際的 code 雙向同步)。但是當年的實作上,總覺得實際要處理的問題遠比 diagram 要複雜得多,系統架設跟UML表達的架構,中間距離還很遠,往往高階架構都只在架構師腦袋裡,真正執行的工程師則被一堆設定的細節給淹沒了,直到現在有了 container 技術,才開始覺得佈署系統就真的跟 deployment diagram 上講的是同一件事,真的就是把元件拉出來,按照設計圖一個一個擺到定位,線接一接就完成了。 Volume-Container 的應用,有機會再另外寫一篇吧,先來看看 NGINX Reverse Proxy 的部分: 在上一篇在解決新舊系統網址對應最主要的技巧,就是如何簡潔又有效率地做好 2400 條轉址的需求。主要就是用 Apache 的 RewriteMap 來兼顧 Rule 的撰寫及對照表的維護。而同樣的機制,在 nginx 上也有,不過語法不大一樣,我先貼一段 example:
# map blogengine with slug (encodded title) format
if ($uri ~* "^(/columns)?/post(/\d+)?(/\d+)?(/\d+)?/(.*).aspx$") {
set $slug $5;
return 301 /?p=$slugwpid;
}
Nginx 的 Map 簡潔到不能再簡潔了,加上他用的 C Like 設定擋語法,老是讓我有個錯覺,覺得我在寫得是 script 而不是在寫設定擋…
然而簡潔到極致的 Map 用法,我看了半天才看出他的端倪… 上面這幾行,背後有條看不見的線,把 $slug 跟 $slugwpid 這兩個變數串起來…
當我把某個數值 assign 給 $slug
時,Map 的機制就會偷偷的啟動,用 $slug
的值去查表,把查到的結果放到 $slugwpid
, 然後接著 run 後面
的 script / config. 上面這幾行,意思就是每個 request, 會把他的 URI 部分 (不含 hostname) 抓出來,用後面的 regular express 比對,
抓出第五個 match ($5)
的內容,指定到 $slug
這個變數內。接著透過 MAP 的機制,下一段指令 return 301 /?p=$slugwpid;
就是
用 HTTP 301 的方式轉址,轉到 /?p=xxxx
這樣的網址。 這看不到的機制,靠的就是整個 nginx 設定擋的另一個部分定義 MAP 的效果:
map $slug $slugwpid {
include maps/slugmap.txt;
* 0;
}
Map 這精巧的機制想通後就很簡單了,Map 的宣告後面直接接兩個變數,一個是原變數 ($slug), 另一個是查表後對照的結果變數 ($slugwpid)。你在任何地方把數值指定給 $slug 的話,同時間另一個變數 $slugwpid 的值就會被替換掉。 說穿了不值錢,這些可是我研究了好一陣子才搞懂的。研究的過程中我也去找了 NGINX for Win32, 這樣測是起來比較方便,有需要快速體驗或測試 nginx 的朋友可以參考。用這個來研究設定擋的寫法,可以省掉很多時間 (畢竟我還是 windows 操作比較熟悉…) 最後就是對照表的定義了。NGINX 的設定蠻有彈性的,如果你的對照表不多,可以直接寫再 CONF 裡面就好。不過我的狀況有四百多篇文章,我選擇放到外部檔案再引用。我貼片段的對照表內容出來:
GoodProgrammer1 65; # 2008/09/27, 該如何學好 "寫程式" ??
IBM-ThinkPad-X111- 252; # 2005/06/28, IBM ThinkPad X111 ...
e6b0b4e99bbbe5b7a5e697a5e8aa8c-1-Cable-TV-e99da2e69dbf 146; # 2007/09/12, 水電工日誌 1\. Cable TV 面板
e5a682e4bd95e59ca8e59fb7e8a18ce6aa94-(NET)-e8a3a1e99984e58aa0e9a18de5a496e79a84e8b387e69699 180; # 2007/02/28, 如何在執行檔 (.NET) 裡附加額外的資料?
X31-2b-e99b99e89ea2e5b995e79a84e68c91e688b0-_ 273; # 2005/03/06, X31 + 雙螢幕的挑戰 @_@
e588a9e794a8-NUnitLite2c-e59ca8-App_Code-e4b88be5afabe596aee58583e6b8ace8a9a6 215; # 2006/10/29, 利用 NUnitLite, 在 App_Code 下寫單元測試
格是很簡單,就是新舊對照的值,一筆一行。兩個字串用空格隔開,最後用 ; 結尾。如果有需要的話, # 之後的字串會被當成註解忽略掉,就像上面這樣。還好這格式跟之前 Apache 用的 RewriteMap TXT 格是很類似,我用文字編輯器簡單替換一下其實就搞定了 看了 NGINX 官網的說明,他的 MAP 彈性大很多,除了靜態的字串對應 ( key / value pair ) 之外,可以包含萬用字元,也可以包含 Regular Express, 也就是說他也包含某些運算能力在 Map 裡。我擔心的是這麼一來 MAP 也許就無法像 Apache 一樣,把 Map 編譯成二進位的 Hash table 格式,大量查表的效能也許會受影響… 這邊我就沒有像上次一樣查 benchmark 了,不過新環境運算能力本來就強很多了,同時 nginx 本身效能也比 apache 強的多,加上我的舊文章數量又是固定的 (400),數量還不算太大,也不會再繼續成長下去,測試過沒有明顯的影響,我就暫時不理它了 XD 好! 寫到這邊,其實搬家動作大概就告一段落。雖然如此,也是花掉我幾個下班休息時間才搞定的… 我想應該很多人跟我一樣,想從熟 Microsoft 領域,跨越到 Linux / Open Source 的領域而不得其門而入的困境吧? 我這系列文章都會用實際的案例,說明我 “為什麼” 會這樣做,而不是只有單純的 step by step. 畢竟比我熟這些操作的人太多了,人外有人.. 這應該輪步道我來寫。而我真正想分享的,是這些架構規劃面的經驗。希望我這些實作的案例 & 紀錄,可以幫到跟我一樣從 Microsoft Solution 要跨越到 Linux 這邊的人 :)
http://columns.chicken-house.net/post/GoodProgrammer1.aspx http://columns.chicken-house.net/columns/post/GoodProgrammer1.aspx http://columns.chicken-house.net/post/2008/07/10/GoodProgrammer1.aspx http://columns.chicken-house.net/columns/post/2008/07/10/GoodProgrammer1.aspx http://columns.chicken-house.net/post.aspx?id=52e998ee-ee02-4a66-bb27-af3f4b16c22e http://columns.chicken-house.net/columns/post.aspx?id=52e998ee-ee02-4a66-bb27-af3f4b16c22e
Redirect 301 /post/2008/07/10/GoodProgrammer1.aspx /?p=65 Redirect 301 /columns/post/2008/07/10/GoodProgrammer1.aspx /?p=65 Redirect 301 /post/GoodProgrammer1.aspx /?p=65 Redirect 301 /columns/post/GoodProgrammer1.aspx /?p=65 Redirect 301 /post.aspx?id=52e998ee-ee02-4a66-bb27-af3f4b16c22e /?p=65 Redirect 301 /columns/post.aspx?id=52e998ee-ee02-4a66-bb27-af3f4b16c22e /?p=65 # 以下略過這方法 "暫時" 解決我的燃眉之急了,的確可以把大部分的文章轉到正確的內容,不過連我自己都看不下去了,這樣做的缺點還真不少:
RewriteEngine ON RewriteMap slugmap "txt:/volume/slugmap.txt" RewriteRule "^(/columns)?/post(/\d+)?(/\d+)?(/\d+)?/(.*).aspx" "?p=${slugmap:$5}" [R=301,L]真正的 match 比對,一行就搞定了。當然,要搭配他提供另一個文字檔當作對照表,像這樣把全部 400 篇的 slug-id v.s. wp post id 對照表列出來:
# blogengine post slug ==> wp post id RUNPC-2008-11 52 VCR-e5b08fe79aaee887aae5b7b1e8b2b7e5a49ae5a49a 225 e6b0b4e99bbbe5b7a5e697a5e8aa8c-5-e9858de68ea5-cable-e7b79a 142 e58d87e7b49ae5a4b1e69597-Orz 201 e6adb8e6aa94e5b7a5e585b7e69bb4e696b0-CR2-Supported 197 e6adb8e6aa94e5b7a5e585b7e69bb4e696b0---CR2-Supported 197 Community-Server 281 x86-x64-e582bbe582bbe58886e4b88de6b885e6a59a 85 e58e9fe4be86-XmlWellFormedWriter-e4b99fe69c89-Bug- 48 e5808be4babae6aa94e6a188-2b-e78988e69cace68ea7e588b6 40 video-e5b08fe79aaee887aae5b7b1e59083e69db1e8a5bf-II 244改用這個做法,原本的效能問題,就分兩個部份解決掉了。一來需不需要進行轉址,只需要進行一次 regular expression 計算就能知道。每一個 http reques 不會浪費太多時間去重複 400 次的運算。如果 match 成功需要轉址,用 hash table 查表也很快,完全不會受到 400 筆的影響.. 繼續查下去,文字檔的效能還是稍差,所幸 apache 有提供工具,可以把它編譯為二進為 dbm 檔案,效能更好.. 細節我就不多說了,官方文件都有寫..
繼上一篇講完我落落長的研究過程後,這篇補上昨天想寫最後卻沒加進去的內容,就是一樣的動作改用我自己的 NAS 所提供的 Docker 環境來做 (官網)。試過之後只有一個感想... 果然買現成的實在輕鬆太多了 XD,如果不是很在意效能,只是想有個環境驗證看看,想避開整套 Linux 從無到有的 setup 過程的人可以試看看!
廢話上一篇都講過了,直接進入主題.. 這步驟跟昨天的比起來,實在是簡單太多了,這篇改一改就變成葉佩雯了,以後寫 ASPNET5 的人應該都去買台 NAS 才對... 不知以後會不會有 Visual Studio + NAS 同捆包? XD
以下是 step by step 的步驟:
16-系列 : | RS2416RP+, RS2416+, RS18016xs+ |
---|---|
15-系列 : | RC18015xs+, DS3615xs, DS2415+, DS1815+, DS1515+, RS815RP+, RS815+, DS415+ |
14-系列 : | RS3614xs+, RS3614xs, RS3614RPxs, RS2414RP+, RS2414+, RS814RP+, RS814+ |
13-系列 : | DS2413+, RS3413xs+, RS10613xs+, DS1813+, DS1513+, DS713+ |
12-系列 : | DS3612xs, RS3412xs, RS3412RPxs, RS2212RP+, RS2212+, DS1812+, DS1512+, RS812RP+, RS812+, DS412+, DS712+ |
11-系列 : | DS3611xs, DS2411+, RS3411xs, RS3411RPxs, RS2211RP+, RS2211+, DS1511+, DS411+II, DS411+ |
10-系列 : | DS1010+, RS810RP+, RS810+, DS710+ |
[caption id="attachment_411" align="alignleft" width="334"] from: blog.docker.com[/caption]
Microsoft 官方宣布能在 Linux 上面運行 .NET (v5) 應用程式.. 其實這已經不是什麼新聞了,去年 Microsoft TechEd 2014 North America 就正式的發布這個消息了,不過因為種種原因,去年看到這新聞的時候,只停留在 "看看" 的階段而已,直到現在時機成熟了才開始動手研究。一來是因為官方的開發工具 Visual Studio 2015 已經 RTM 了 (這麼大的軟體,實在不大想安裝 preview 版本).. 二來 Docker 用的很高興,NAS / Ubuntu Server 也都已經準備好,執行環境我也上手了.. 萬事俱備只欠東風,於是今天就趁周末,把 .NET Core 版的 "Hello World" 丟到 Docker 裡面執行的任務給搞定了 :D
Microsoft 自從新任 CEO Satya Nadella 上任後,宣布了一連串改變,我覺得對未來影響最大的就是 .NET Open Source + Support Linux 這件事了。我認為這決策帶來的影響,遠遠大於 ASP.NET5 本身開發技術及架構上的改變 (例如 MVC6.. 動態編譯.. Dependency Injection 等等)。因為前者影響的是整個 .NET 生態的改變,可能會影響到將來大型應用部屬的架構決策,而後者影響的只是開發團隊,完全是不同層級的問題..。如果你的職責是 system architect, 那千萬別忽略這個改變.. 以後 "混搭" 風格的架構一定會越來越盛行,不管是在 windows server 上面,或是在 Linux server 上都是。
在這兩年內,另一個很快竄起的技術: Docker, 也是另一個關鍵。Docker 這才出來兩年就紅翻天的 Container 技術,這種東西實在太對 architect 的胃口了。過去 VM 的技術沒甚麼不好,不過最大的問題就是: 充分虛擬化之後,帶來的副作用是多一堆 "虛擬" 的機器要管理... 每個 VM 裡面都要裝一套 OS,不論是 Linux or Windows,都要花力氣去維護,要執行這些 OS 也要花費運算資源... 舉個慘痛的經歷,我就碰過在同一台實體機器上,上面的 10 台 VM 都開始掃毒,那狀況真的只能用 Orz 來形容... 上面的 APP 都還沒認真在跑,系統就被 OS + AntiVirus 給拖垮了...
Docker 只虛擬化 Application 的執行環境,巧妙的避開了 VM 過度使用帶來的副作用... 舉例來說,如果你的應用規模不大,只要一台最低規格的 VM 就跑得動的話,你會為了架構考量把他分裝在三台 VM,實作三層式架構嗎? 應該沒人會這麼幹吧? 除非你要展示應用架構,或是可預見的將來會需要 scale out, 不然這樣搞只是自找麻煩而已。 但是現在用了 Docker 你就可以盡可能的採用你認為最理想的架構,分成幾個獨立的 container 可以維持架構上的正確性,同時也不必擔心架構帶來效能的折損。
因為這個原因,了解這種跨界的應用,對我來說遠比了解 ASP.NET5 本身 coding 帶來的改變還重要的多。裝了 Visual Studio 2015 之後,第一件事不是先寫看看 MVC6,而是先弄了個 Hello World, 試看看該怎樣丟到 Linux 上面跑.. 為了這件事,前置作業就花了快一個月... 有在 follow 我的 facebook 或是訂閱 blog 的就知道,之前我都在研究 Docker ,包括在 NAS 上用我理想的架構,來架設我自己的 blog.. 也弄了台差點要被扔掉的舊筆電,架了台研究用的 Ubuntu Server .. 接下來主角要上場了,就是 .NET CoreCLR !
這時 command prompt 已經變了,由原本的 chicken@localhost:~$ 變成 root@93462d92e941:/# , 代表 shell 已經啟動成功,且順利進去 conainer 內了,接下來我就可以把它當作 VM 開始大玩特玩..
原本只是想在 NAS 上簡單玩玩 Docker, 為了接下來的 ASP.NET 5 做準備.. 不過實在太好用,還沒開始做正事 (ASP.NET 5), 就先把原本的 BLOG 從 GoDaddy 的 hosting 搬回來放 NAS 了,順手也架了 reverse proxy ... 現在 NAS Docker 有正式用途了, 而 NAS 的運算能力又很有限 (我的是 DS-412+, CPU 只是 atom d2700, 雙核而已, 1GB RAM), 裝沒幾個就跑開始擔心了,於是就開始想另外搞一個可以隨便玩得 docker engine 環境..
其實 PC 上弄個 VM 是很容易啦,windows 10 內建的 hyper-v 根本就不用花甚麼功夫, 不過我想弄個像 NAS 這樣省電不大需要去管它, 24hr 開著隨時都可以用.. 就把腦筋動到古董要丟掉的筆電.. 我老姊正好有台筆電要丟掉,找我幫他先把硬碟資料清掉她才敢丟...一切都來的太巧了! 於是這台就被我拿來大整修一番...
這台的規格是 Acer Aspire 5742Z: