2014年2月17日 星期一

[java] UnknownHostException in osx 10.9 with JDK7

週末硬碟掛點後,裝好 osx 10.9 與 JDK 7 上工的第一天,遇到了這樣的錯誤
Exception in thread "main" java.net.UnknownHostException: pj-pc.m.c.t: pj-pc.m.c.t: nodename nor servname provided, or not known
    at java.net.InetAddress.getLocalHost(InetAddress.java:1473)
    at net.muzee.paid.channels.Foo.main(Foo.java:8)
Caused by: java.net.UnknownHostException: pj-pc.m.c.t: nodename nor servname provided, or not known
    at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
    at java.net.InetAddress$1.lookupAllHostAddr(InetAddress.java:901)
    at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1293)
    at java.net.InetAddress.getLocalHost(InetAddress.java:1469)
    ... 1 more
把問題最小化後,可以用這樣的 code 來重現:
package net.muzee.paid.channels;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class HostTest {
    public static void main(String[] args) throws UnknownHostException {
        String localHostname = InetAddress.getLocalHost().getHostName();
        System.out.println(localHostname);

    }
}
看起來是在 osx 10.9 預設是沒有設 localhost 名稱,而 JDK 因為取不到名為 localhost 的記錄,就繼續正常的流程,取 domain 然後進行驗證。最後得出 UnknownHostException 的結論。
在一篇文章中找到,如何改變 osx 的 localhost 名稱。設定前是沒有值的情況:
qty:~ qrtt1$ scutil --get HostName
HostName: not set
設定完成後,就可以看到 localhost 字樣(如果你有其它需要,也能設成不同的值):
qty:~ qrtt1$ scutil --set HostName 'localhost'
qty:~ qrtt1$ scutil --get HostName
localhost

2013年5月3日 星期五

[idea] 反思快取機制


觀察著 Administor 忙碌地處理系統問題,時時監測 Server Loading、httpd 數量、總體記憶體用量,還有久久無法消退的 PENDING REQUEST。配合 Log 的狀態,使我反思一個問題:我們的快取,真的是我們要的嗎?

實作 WebService API 服務時,有些需要耗費大量資源的運算,在結果不太需要頻率更新的時候,我們通常會導入『快取機制』。當採用快取時,程式的流程會變成:


  1. 檢查快取是否有計算結果可用
  2. 如果有快取的結果,則馬上回傳。若沒有則進行 3.
  3. 進行耗費大量資源的運算
  4. 將運算結果放進快取
  5. 回傳結果


快取系統的概念,就是將一個計算結果放進一個具有計時器的儲存空間,當時間一到就會讓儲存的內容過期。在步驟 2. 取不到結果時,就是『計算結果』已經過期所致。因為沒有可用快取,而需走到步驟 3. 進行實際的資料存取。這概念說起來簡單,但別忘了,我們的程式類型是 WebService API。這表示同時間內,可能具有許多的 HTTP REQUEST 進來。若同時間有 N 個 REQUEST 走到步驟 3. 那就會同時有 N 個『耗費大量資源的運算』。

一般來說會使用 Guard Object(或 Barrier) 實作成 Future Pattern 來改善同時間 N 個『耗費大量資源的運算』的問題,在實作正確的情況下,即使 N 個 HTTP REQUEST 進來,也只會有其中一個進行真實的運算。不過因為 Guard Object 的效果,在 Server Administrator 看起來會像是有 N 個 HTTP REQUEST 處於 PENDING 的狀態。

每一個 PENDING 的 HTTP REQUEST 都會佔用系統資源。當 Server 需要持有更多的 HTTP REQUEST 時,那麼就有可能拖慢他的效能。至少 Guard Object 擋住的是真實的 Thread,這個 Thread 綁定的相關資源就佔在那了,至少在 Java Web 來說,Session 跟它的內容物就佔了一些空間。若沒有將 Guard Object 設計好,那可能這 PENDING 會持續到永遠,並且一直累積新的 PENDING REUQEST。

沒設計好不代表有 Bug 實際存在那裡,而是有隱含的『強假設』沒有被處理。像是對 DB 做 SQL Query,『一定』會有資料回來。若 DB 的 Connection Pool 耗盡的行為是『無限等待』,那麼 Guard Object 就會連帶著『甲你攬牢牢』緊抓不放,這就是典型的『強假設』。Guard Object 應該有個停損點來釋放抓住的 HTTP REQUEST,但是實在無法精確預設這個耗時的運算要多久,怎麼設定 timed out 都會成為魔術數字。最後,它可能是一個巨大的 timed out。

這樣的設計,可能對於避免過於耗費 CPU,或短其大量取用記憶體能有較好的效果,但對於耗時的運算可能不是個好方法。在這種架構下,要處理耗時運算的 work around 方法就是定期地發出 HTTP REQUEST 讓失去的快取被補上,並『祈禱』每次等待的都是『機器人』而不是真的 API 使用者。

一切的根源來自於快取模型的限制:時間到了,資料就會消失。而我們的程式就是依賴這個特性去實作的!當資料不見了就執行運算得到新的結果,將它放入快取之內。辜且稱之為:『被動式快取模型』。

理想的情況是:只有系統啟動的第一次,使用者會等待需要快取的運算。快取的資料過期了,仍可繼續使用。在背景快取服務會利用資料存取的 Callback 主動更新內容。相對於我們原先對快取機制的認知,稱作『主動式快取』。

若我們的快取模型是這樣的,那麼只會有第一回合的使用者在等待時間較久,而我們對於快取的 timed out 設定也更有彈性。這樣只需真實地考慮一份資料的更新週期,不太需要在乎使用者是否會等待過久的問題。一來快取的更新不再由使用者發出的 HTTP REQUEST 觸發,這能減輕不必要的 PENDING REQUEST。同時,讓總體的連線等待時間下降,理論上來說,系統整體的負載也會降低。

(此文撰寫於 2011/12/29 日,由於 posterous 要結束了,重貼回 blog)

[daily] 減分


看了 Soft_Job 版最近對於各篇求才文章的推文,其實感覺挺差的。一個職務貼出來,從薪資到期望的能力被『鄉民審判』,這只是將 Soft_Job 版的這一項附加功能給拒絕掉罷了。就客觀條件來看,會什麼語言、使用過什麼工具或 Library 與 Framework。甚至要求到一些 Debug 跟 Trace 等診斷用工具的結果可能都讓人感覺失望。常得到的回應是,要求那麼多,那薪水是多少?有沒有年薪百萬?或是薪水那麼少,要求那麼多,然後又接著一陣的口誅筆伐。漸漸地,大家習慣由列出的客觀條件來扣分,只有對薪水超優的加分。同樣的情境換到別的討論,也是採用預設的扣分動作來進行思考。

我們應該不會以討厭的程度來選擇伴侶吧?即使有一個以上的選擇,我們仍會用喜歡的程度來決定伴侶的。外在客觀的條件只有一開始,你決定要不要去接近他才是影響因素。真的產生了互動,才知道你是否能接納他,甚至發現新的優點。相對的,是否有未在客觀條件中,但你無法接受的缺點呢?像是對於金錢觀的異同,或是月光光的卡奴?

將條件列地詳細並不是為了給大家批判的,而是充份說明公司內有機會接觸到的相關技術。每個人進公司並不太可能一下子就會用上所有列出的需求項目。那可能得輪過幾種不同的專案或者開發項目後才可能遇上,並且也非百分之百的出力。而這些需求的內容,能幫助閱讀者瞭解什麼呢?看到後,讀閱者可以思考,是否有打死都不想碰的領域?如果是這樣的,那你就得將這間公司的優先序往後挪。請注意,只是往後挪而已。如果那個公司仍是你有興趣的不妨進一步談談,說不定,你不想接觸的項目,已經有人包辦了。

像我前一次找工作時,有幾個條件是得在面試時才問得出來的。就拿對我來說,我心中有設定二點要求:

一、要有版本控制系統的工作環境。
二、希望有使用 Issue Tracker。

但後來找到的工作呢?版本控制系統雖然有,但是沒有 changeset 概念的 CVS。有 Bug Tracker,但上面的東西是以 Product 為主的,跟我先前以 RD 任務為單位的使用情況不同,而我開發的多為軟體元件,似乎跟它沒有相關。

即使與心中的條件都不同,但我仍在那工作著!當然是因為談過也相處過後覺得有其他的誘因可以讓我放棄原來設定的條件。我們著手推版本控制系統的世代交替。另外,我專門負責一些軟體元件的製作,大部分的時程可以與產品本身平行。讓我有較充裕的時間維持產出品值的穩定。還有一部分的 Server Side Tool 是由我開發的,只要能達到需求,內部要如何設計其實有很大的自由度的,能不時滿足一下想要玩架構的心情。

好的工作環境得花時間談來的,單看條件就決定,那不就跟古早的作媒是一樣的事嗎?

單純由薪資過濾確實是相當便利而迅速。但你可能會後悔一開始沒有多花時間,而且還暗爽一下省了不少時間。最後,卻因為一開始的偷懶而最後繞了一大圈才知道付出的代價原來這麼大。

(此文撰寫於 2011/11/5 日,由於 posterous 要結束了,重貼回 blog)

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 服務方案啊!