2012年12月24日 星期一

[cloud] MiCloud 的信任危機


公司首次使用 MiCloud 的第一個月帳單出來了,但其中覺得不愉快的部分是因網路流量超過免費額度而被收錢。使用者付費是件理所當然的事!心中還是很在意沒有替公司省到這筆錢覺得不甘心。

回憶到 2012/12/17 突然接到同事轉接來的 MiCloud 人員的電話,主要意圖是關切我們的網路流量,對方是說我們的流量異常,向我們確認是否有為電腦中毒。當下開 MiCloud 的未出帳單,看起來二台機器的流量還在額度之內。第二天不放心又看了一次,它就到了超量的情況。


第三天又看了,似乎又回到原樣。經過了 20 號的結算日。該算的費用都出來了,流量果真又回來了。即使在這事件的幾十天前,有詢問過客服為何帳單估的誤差很大。客服是回應網頁上紅字標明的『**此未出帳單金額僅供參考,實際以結帳後之金額為主。』這句話雖然沒什麼可以挑剔之處,但它的誤差實在大到令人費解之處,特別是在網路流量計算的部份。

於是開始上網找了一些能統計流量的程式,最後我選用 vnstat。主要是它分天顯示流量的功能相當方便:

..
..


算起來每日會使用 20 至 30 G 的流量,若以均值 25 G 來算,與超量的機器的天數吻合。
花了幾天看了統計結果後,我明白了另一件事。原來我對 MiCloud Console 網頁上提供的數據失去了信任感。


上圖的機器是開始以 vnstat 統計流量時就建立的(2012/12/19)。到目前為止(2012/12/24 00:00),它顯示給客戶的流量依然是 0。

..
..

vnstat 計算已達 130 G,簡單來說剩 70 G 不到的免費額度。因為這些數字是跟算錢有關的當然要計較些。放那麼不準的數據給客戶看,那不如別放了吧。單純只是增加不信任感的作用罷了。



2012年8月22日 星期三

[jetty] 使用 deploy xml


簡單地說,一般我們要 deploy 新的 war 需要放在 jetty config 檔設的目錄中,預設是 $JETTY/webapps 目錄,若想 undeploy 只需將 webapps 下的 web module 移掉即可。而 deploy xml 則是另一種 deploy 的方法,你只要寫一個 xml 檔,指定你的 web module 路徑,並將 xml 檔放在 $JETTY/contexts 內即可:

..
..

只要將這個檔放在 $JETTY/contexts 目錄下,jetty 會偵測到它,並依你指定的 context path 與 war 的位置部署程式。另外,我在 webdefault.xml 有加 gzip filter 的設定,剛開始用 deploy xml 部署時沒有指定 webdefault.xml 就沒有吃到 gzip filter 參數。若您有額外改變 webdefault.xml 設定,就要記得在 deploy xml 指定。

2012年8月19日 星期日

[log] 久違的講課:Java Web & JDBC


因為答應了要替朋友去上課,內容是我幾乎不太寫的 Java Web。一方面是工作的主軸早就不是寫 Java Web 的內容,另一方面寫 Java Web 有它痛苦的地方。趁機寫寫課後心得作為之後上課的參考 :)

..
..

內容主要為 JDBC Programmaing 與 Web Programming 二個部分。JDBC 簡單地示範基本的 API 使用後,下一個範例就直接切入使用 Connection Pool、Commons DBUtils,在 Web 方面也是相似的安排,但多加了個不倚懶 Servlet API 完全由土炮簡單的 Web Server,並設計 Handler Class 開始。

這是我自己覺得『理想』中的 Java Web Programming 的學習路線,當然這個單純寫書教導 Java Web Programming 是不同的目標。書本需要帶給人最完整的知識,即使不值得使用的技術也是需要列上去,通常也包含大部分 API 的說明,同時也有許多為人詬病的功能。

就以 JSP 來說,它一開始的目標是為了解決 Servlet 沒有好用的 template engine 解決方案,但卻 release 了許多超出一個 template engine 本身應負擔的功能。這能想像成是一種變形的『破窗效應』,自從有人在專案內寫 scriptlet 做一些稍為複雜的邏輯後,scriptlet 就成為一種惡名昭彰的存在,而 JSP 也提供自訂 taglib 的功能,而在規格內的 JSTL 就有許多不適合在 JSP 內使用的東西,像 Database Query。在些不見得需要的功能就必需在寫書或教學時展示它,在這次的內容安排,我僅使用了 EL 與 JSTL Core 或一些變數的判斷與顯示,像是檢查使用者有沒有登入的 if 與顯示 TODOs 的 forEach 這類簡單的邏輯,若未來課程有提到 i18n 頂多再加個 fmt 相關的 taglib,還有些性質相近或易混淆的功能就不提,像是 include 部分就只教 JSP Directive include。JSP Action 或 JSTL 的 include 就完全不在內容之中。。以單純做 View Presentation 來說,並不需要太多的功能。

在 JSP 上要寫 Business Logic 其實是非常不得已的,這樣寫不僅讓你的 Business Logic 散落於各 JSP 檔,或是做一些 Java Bean 來處理 Business Logic,但這始終不是個解法。因為整個商業流程還是控制在 JSP 內,採用 Model 2 的型式實作才能真的將邏輯集中,並且較能讓設計清晰、明確。

針對 Model 2 的部分,我選用的例子是改寫原 Model 1 的例子而來。它不單純是將 request 對象改成 Controller (Servlet),而是仿 Web Framework 做 Action Mapping 的方法,透過 Servlet 進行 matching & dispatching。我們有個『微型』的 Web Framework,並直接在程式內 hardcode mapping,儼然是個小巧可用的 Web Framework。若曾寫過 WebWork 的人,可能會找到一點熟悉的感覺。

實際上執行起來發覺時間有限。也許是我把 4 小時想得太長,而對於學生能跟得上實作的時間估得太短。這樣的教學效果不盡理想。過程中有些小狀況,像是安裝課程要使用的 mysql,因為學生之前專案有先安裝過,所以同時裝另一份 unzip 版就會出現許多奇怪的現象。另外,自己沒有 win 7 的環境,也缺乏在同樣的環境測試是否 lab 能做得起來的機會。這些意外倒是比較可惜的地方。這部分的改進方案,是採用 embedded db,像是 h2。減少練習地安裝 mysql 不成功的變數。


2012年8月15日 星期三

[ec2] attach elastic ip

最近想要讓特定 autoscaling 的 instance 自動設定 elastic ip。從 boto 查了一下相關的 API,寫起來蠻容易的:

..
..

有了 script 後,在開機後執行它就行了 :D

這樣就能利用 autoscaling 固定建 1 個特定的 instance 並獲得 ip,用在可以『掛』點一會兒的 server 配合 spot instance type 真是窮人的 server 服務方案啊!

2012年8月2日 星期四

[centos] 最小安裝後無網路可用

一時興起下載了 CentOS-6.3-x86_64-minimal.iso 在 VBox 安裝起來,開機後竟然沒有網路可用。應是是預設沒有開啟,於是在網路上找到解法,要改網路設定檔,把開機啟動的選項設為 yes:

..
..

改好設定 reboot 後,完成 VBox 的 NAT port forward 就可以開始練習操作嚕 :D

[ec2] 開啟 ssh login by password 筆記


使用 ec2 ami 建出的 instance 預設是使用 *.pem 登入的,若是計劃將讓一般的使用者也能登入,就必需修改 /etc/sshd_config:


PasswordAuthentication no

改成

PasswordAuthentication yes

如果需要允許 root 登入可加開(最好是不要,或是你有限制登入 ip 的前題下):

PermitRootLogin yes

改完後別忘了指定新密碼給 root,並重新載入 sshd_config:

/etc/init.d/sshd reload
需注意的是在 /etc 下有二個檔 ssh_config 與 sshd_config,別改錯檔了。
千萬要記得限制可登入的 IP(/etc/hosts.allow 或使用 ec2 security group)


2012年6月20日 星期三

[ec2] 取得 EC2 Tags

工作的關係,開始大量使用 ec2 服務,其中一部分是撰寫『爬蟲』類。這些爬蟲大多數的內容是一樣的,但可能依爬的對向會使用不同的 rule 執行。並且有監控爬蟲的程式通知現在『生態系』不平衡了,需要多放一點特定類型的爬蟲。



在概念上,大家的程式幾乎都一樣的,那我就不用為每一種類型建一個 AMI 作為爬蟲的樣版。若將 ec2 instance 想成物件,大概是這種感覺:

Crawler c = new Crawler('type')c.run()

我們只需在『建構子』指定不同的參數,當 ec2 instance 建立起來後,讓它『找尋生命的意義』(找到自己的參數)然後開始工作。有幾個方式能做到 cloud-init,這是蠻流行的方式,我曾試著使用它加速 instance 的初始安裝。在 ec2 instance 上能塞資料的地方很多,而我們的參數也不佔什麼空間,今天靈機一動,決定將它放到 tag 內,若將它表現成 java code 是這種感覺:

Crawler c = new Crawler(EC2Instance.current().tag('type'))
c.run()


所以,我們需要做的事有:


  • 撰寫啟動 script 並讓它接受參數指定我們要啟動的程式
  • 實作取得特定 tag 的方法


本來以為 ec2 instance metadata 就會有 tag 資訊,查了一些資料發現在幾年前有人提議要將 tag 資訊加入,但目前仍沒看到。好在 aws api 蠻容易使用的,我們可以配合 ec2-metadata query tool 先取得 instance id,再查出此 instance id 擁有的 tag:

..

..


所以,實際上我們實作時,決定用 tag 內 handleClass 的值當作 Crawler 啟動參數:

Crawler c = new Crawler(EC2Instance.current().tag('handleClass'))
c.run()

將它設置好,建成 AMI。而建立 ec2 instance 時,記得指定需要的 handleClass 就能依需要動態建出不同功用的 instance。