2014年11月23日 星期日

Docker心得,以及Container怎麼自動加入本地域名

基於敏捷開發,我希望軟體開發的時候能夠隨時的自動測試,這樣才能夠隨心所欲的重構以及保證有基本的品質。在開發雲端應用的時候,常常會有很多台的伺服器需要相互運作。過去虛擬化的做法,常常是利用類似VMWare的虛擬機來建立整個機器。因為是虛擬化整台機器,每次安裝的速度之慢,根本不能拿來做自動化測試。尤其是在設定伺服器的過程中,常常就是Operation的領域,各出奇招,只要伺服器能照著自己的"魔術"正常運作就好了,至於要其他人看懂或接手,那就是另一個考驗了。

Docker,就是拿來解決這種VM開啟速度慢、耗費資源高的問題,但是又能讓應用程式互相跑得好像在不同機器上一樣的獨立。不只如此,Dockerfile的文件可以讓整個檔案結構、相依套件都好好的用同一種格式寫好,這樣一來就不是Operation個人的魔術了。我自己把Docker看做是一個綠色軟體的產生器,因為每一個應用包在Container裡面,都已具備所有的相依套件。如果想要公開自己開發的服務,給個Dockerfile再給個簡單的docker run,完成。裝好Container以後,保證能跑!所以現在很多套件都已經支援了Docker,也都附上了Dockerfile。

而基於敏捷開發,想要快速的增加開發雲端服務的迭代次數,就是非Docker莫屬了。利用Docker從官方的發布版本為基礎(ubuntu, centos, dabian)開始建立整套雲端服務,速度非常之快,已經達到能夠每次commit都自動測試的次數。但是我遭遇了一個問題:啟動了一個Container以後要怎麼知道它的IP呢?這個問題在過去的網路服務的架構早就已經遭遇過了,只是從不常關機的Virtual Private Server(VPS)換成變化更快的Container罷了。這麼頻繁的開啟伺服器,就必須要有Service Discover的機制。否則整天去管理開開關關的Container就夠煩的了。

待續....skydns + skydock

2014年7月24日 星期四

別讓make的頻率過快,gc不是隨時都在作用

我以為使用俱有gc的語言,就可以為所欲為的配置記憶體(反正有gc在後面擦屁股)。但是從C寫系統程式上來的經驗告訴我:真的有這麼好嗎?雖然抱持著懷疑,但還是先下手寫點code吧。

於是我開始寫go,不疑有他、放心的make([]byte,hugeSize),直到最近的案子中,需要模擬5萬條長連線到一臺測試機器。只送出了幾千個連線請求後,就被OOM Killer 關心了。code大概是這樣:

for {
        bigArray := make([]byte, 1024*1024*10)
readFromTcp(bigArray)
}

debug 之後讓我發現不要在一個for迴圈裏面make,尤其是我的測試需要跑5萬個迴圈,雖然每次回圈的make只用來讀取一次,但是gc並不會“瞬間”就把剛剛沒用到的記憶體清掉。因此,要善用每一次的make,盡可能地重複使用它。

bigArray := make([]byte, 1024*1024*10)
for {
readFromTcp(bigArray)
}

另外,參考 io.Copy() 裡面的實作方式,是在回圈之外先make一個小塊的記憶體,再用回圈的方式去將資料全部複製。

buf := make([]byte, 32*1024)
for {
nr, er := src.Read(buf)
if nr > 0 {
nw, ew := dst.Write(buf[0:nr])
if nw > 0 {

但,如果 io.Copy 頻繁的呼叫(1024次/s),記憶體以近32M/s的速度消耗,又該怎麼辦?可能就不能使用io.Copy,而是自己管理記憶體了。

有人提出以buffer pool搭配channel來明確(explicit)的還回記憶體,來減少make的頻率。在記憶體未使用完前,讓gc有機會工作。http://blog.cloudflare.com/recycling-memory-buffers-in-go

2014年7月23日 星期三

[]byte 轉型 string 必須注意 []byte 的長度

常常需要從 []byte 轉換到 string,來使用 string 的功能。
但是必須注意的是 []byte 並不一定是以 0x00 結束,如果就直接轉型到string,而直接使用strings的一些函式。“有時”就會造成不可預期的結果。像是我要從socket讀取資料,先建立了一個BUF_SIZE的[]byte array,這個大小是2M Bytes。

read_buf := make([]byte, BUF_SIZE)
byte_count, err := conn.Read(read_buf)
log.Println("Receive ", byte_count, " bytes\n", string(read_buf))

跑到Println的時候,發現而且ssh連線幾乎沒有反應。找了又找,後來發現到是Println花很久的時間。我才意會到,原來golang還是要處理結束字元。所以[]byte轉換string的時候,必須要知道byte的長度。因此Println改成下面代碼就解決了問題

log.Println("Receive ", byte_count, " bytes\n", string(read_buf[:byte_count]))

2014年7月6日 星期日

駭埕市



         第一次參加hackthon的我,懷著赤子之心去參加了這個駭埕市的活動。從題目的挑選、組隊、討論、田野調查、轉換題目,一直到最後面得到了第一名。這2天的活動就好像是自己開了一間公司的過程,一個隊伍(公司)最後能否獲得評審(客群)的青睞,其實從題目(產品)定位就決定了這間隊伍是站在哪一個位階。

         位階並不代表失敗與否,而是隊員們、員工們需要付出的勞力程度,大家要多拚才能達到一樣的獲利水平。我們這一隊"呱"花了非常多的時間在決定題目,大約3個小時的田野調查來打翻我們在冷氣房裡的決策。我們一直環繞著 Target Audience(TA) 的需求:
  1. 大稻埕的零售
  2. iBeacon
  3. 需要影片
  4. 需要能運作的App
我很幸運地參加到了4個學生有備而來的隊伍,因此他們的組合基本上已經符合了3,4的需求,剩下的只有題目的選定了。而題目的選定必須要在幾個小時內就能實做出來。

         題目或是產品必須要環繞在解決TA的問題,TA是最後買單的一群人。產品最後能不能獲利,並不是產品有沒有人做過,也不見得是單價過高,而是有沒有找到TA遭遇到的問題。2天的比賽題目就訂在那邊不會變。相較於開公司來說,可怕的是TA可能是會變的!我的意思不是TA本身會變,而是公司裡的人會變。因為技術達不到而變、因為預算燒光而變、因為人力而變。正是這麼多的因素會改變TA,新創公司才這麼有挑戰性....又....或者說是風險性...。

我認為一間新創公司能否抓到最準確的TA,你的員工必須是TA的一部分。