2011年2月11日 星期五

用程式來產生程式的祕密武器

用程式來產生程式的祕密武器
文/王建興 (清華資工所博士班研究生) 2011-02-10

http://www.ithome.com.tw/itadm/article.php?c=65842
處理形態類似的程式碼,不只是可以設法讓它們可以重複使用,還能利用自動化機制動態產生

程式碼產生器(code generator)顧名思義,便是一種用來產生程式碼的程式。在很多場合中,我們花了大量的時間,在撰寫一些形式重複的程式碼,不僅浪費時間、也浪費力氣。但是,如果仔細觀察,你會發現這些程式碼的撰寫其實都有共通的規則,而這些規則是可以歸納出來的──對我們來說,這正是好消息。

無法表達出規則的事物,難以用程式處理,但只要有規則可循.就有辦法運用程式來自動化完成。也就是說,只要找出或者定義出這類程式碼共通的規則,我們就可以撰寫專門的程式,並依照這些規則,來產生有著共通規則的程式碼。

找出重複程式撰寫程序之間的共通規則
舉個例來說,有一陣子,在我們的應用中會需要使用到DTO(Data Transfer Object),而這些DTO和資料庫中的表格是有對應的關係,也就是說,每一個資料庫表格,我們都希望透過一個DTO來表示,而且,這DTO必須像是一個JavaBean,所以,它會有一些getter/setter函式,將所對應的表格的資料欄(column),轉成JavaBean的屬性(property)。例如,我們可能有一個叫做User的資料表格,它有firstName、lastName、telephoneNo、address、birthday等資料欄位,欄位有些是字串型別、有些則是日期的型別。最初的時候,我們可能是用人工的方式來撰寫對應的DTO,所以這麼寫:


接著,針對每一個資料表,我們都會需要撰寫對應的DTO類別,然後再逐一針對其每個資料欄,也撰寫對應的getter/setter函式(像getFirstName()及setFirstName())。

其實,從上述來看,你會發現其中的規則十分簡單,撰寫起來當然沒有什麼難度。但是,如果一個系統需要動用到數十個,甚至上百個資料庫表格,那麼,就得利用人工,逐一查看資料表格的schema,看看每個表格究竟有那些資料欄,然後其型別又該對應到程式語言中的那些型別(例如上例中的birthday欄位在Java中是對應到java.util.Date型別),然後寫下每個DTO類別中的getter/setter函式。

這整個過程,因為都透過人工作業的方式進行,不僅繁瑣、耗費時間,甚至容易出錯。而且這一類的程式碼,因為沒有什麼獨特之處,程式設計者撰寫起來也覺得乏味,單純只是勞力罷了。

像上述的情境,就十分適合使用程式碼產生器來產生這一類的程式。我們可以怎麼解決這個問題呢?若使用Java,首先,我們可以撰寫程式(例如,利用JDBC的API)來取得資料庫中的表格、每個表格中有什麼資料欄、每個資料欄是什麼資料庫型別。在讀取到這些資料後,將資料庫型別自動的查表對應到Java中的型別後,便可以仿照上述程式碼中的形式,自動的輸出.java原始檔。

這只是一個很簡單的程式碼產生器,卻可以節省掉人工作業的繁瑣、花費的大量時間,也可以提高正確性,同時也不致於讓程式設計人員必須面對無聊的工作。這正是程式碼產生器的主要作用所在。

資料庫操作與UI對應免人工
其實在我們的開發生活中,也時常看到程式碼產生器的蹤影。很多報表程式,因為都具有共通的若干規則,所以也很容易利用程式碼產生器,允許透過設定的方式,直接將報表程式碼產生出來。而所謂資料庫操作的CRUD(Create、Read、Update、Delete)程式碼,以及對應的使用者操作介面(UI),因為具有單純的共通規則,但撰寫起來相當累,因此也是程式碼產生器主要的應用範圍。

此外,現在Web前端的應用程式開發已經成了重要的領域,而這些應用程式也大量使用JavaScript來撰寫。而其中,也有不少類型的程式碼,例如操作的選單,撰寫的規則都相似,但是寫起來又累,因此,使用程式碼產生器,透過設定一些參數(例如總共需要那些選項,字體的大小、顏色等等),便可以產生對應的JavaScript程式碼。

由此可見,只要程式碼撰寫規則明確,又需要大量人工介入的,就適合用程式碼產生器來自動產生。

為何開發工具可以做到所見即所得?
一些提供所見即所得的使用者介面設計工具,允許程式設計者透過所見即所得(what you see is what you get,WYSIWYG)的方式,利用拖拉元件的操作方式,便可以設計應用程式的UI。

這種設計方式可以說是軟體開發的革命性概念。有些支援上述概念的開發環境,在實作上,是將程式設計者在所見即所得的操作環境下所製作完成的使用者介面,產生某個中介的檔案(例如,可以利用XML格式的檔案來記錄),來記錄程式設計者所設計出來的使用者介面,包括使用了那些視覺元件,每個元件的尺寸大小、元件擺放的位置,以及元件所擺放的容器、事件處理函式、屬性值設定……等等。有了這中介的檔案之後,整合開發環境便可以基於這個中介檔的內容,產生出相對應的程式碼。

例如,中介檔內記錄了需要動用到的使用者介面元件,那麼便能以此,分別產生出建立這些元件的程式碼,然後再依據所記錄的尺寸、擺放位置,一一設定各個元件的尺寸及擺放的位置。當然,像事件處理函式的設定,也能依這中介檔來產生。

在上述例子中說明了,程式碼產生器除了協助程式設計者,處理一些枯燥乏味的煩人的重複性工作之外,也可以提供另一種更直覺產生程式碼的途徑。就像這個例子,透過所見即所得的視覺化操作環境,來設計應用程式的使用者介面,最終將設計出來的產生轉化產生出對應的程式碼。雖然,使用者也可以透過人工手寫的方式來寫下使用者介面的程式碼,但是,和所見即所得的視覺化操作方向相較起來,終究不那麼直覺。這也是程式碼產生器的另一個優點──用不同、但更直覺的方式來表現應用程式應具備的功能,接著再將其轉化成為對應的程式碼,大幅的簡化產生程式碼的過程。

在我們的日常開發生活中,時常都可以觀察到可以應用程式碼產生器的地方。俗語有云,程式設計者「要吃自己的狗食(dog food)」。倘若能查覺可以運用程式碼產生器來簡化日常開發工作、提升開發生產力的地方,程式設計者可以考慮自己開發專屬的程式碼產生器,來自動產生對應的程式碼。

網站服務效能持續負荷的幕後英雄伺服器負載平衡

網站服務效能持續負荷的幕後英雄
http://www.ithome.com.tw/itadm/article.php?c=65773
文/陳思翰 2011-02-10

許多大型入口網站,背後是由數十個伺服器群組提供服務,而每個群組又有數十到上百臺伺服器,管理者可以使用伺服器負載平衡,讓這些龐大的流量,透過演算法來平均分配到各臺伺服器上


許多大型入口網站,背後是由數十個伺服器群組提供服務,而每個群組又有數十到上百臺伺服器,來同時提供網頁存取與服務。雖然有了大量的伺服器,但它們是如何分配網路流量呢?

管理者可以使用伺服器負載平衡(Server Load Balancing,SLB),讓這些龐大的流量,透過演算法來平均分配到各臺伺服器上。

在提到伺服器負載平衡之前,要先了解什麼是負載平衡。負載平衡是種技術,它能均勻分配工作負載給多組網路、電腦等硬體資源設備。

而負載平衡通常分為兩種,一種是針對應用服務系統的伺服器負載平衡,它能將大量的網路需求,平均分配給多臺具有相同功能的應用程式伺服器,讓服務不因過大流量變慢或中斷;另一種是偏重頻寬管理的廣域網路負載平衡(也稱為Multi-Homing),它用來整合實體線路,提供內部網路更大的上傳、下載頻寬。而有些廣域網路負載平衡設備,會附加伺服器負載平衡功能,但與專門的伺服器負載平衡設備相比,這方面的功能則顯得基本許多。

專門的伺服器負載平衡設備,通常會提供多項的平衡演算法及健康診斷。演算法方面,通常會提供輪詢、加權法、最少連接等,讓管理者能對服務群組的狀態,選擇最佳的平衡模式。除了基本的演算法外,也有廠商提供腳本功能,讓管理者自訂規則,讓特殊用戶的連線能直接導向效能較好的伺服器上。

而健康診斷方面,會有L3、L4、L7等三個層級的監測,管理者能針對伺服器的類型及重要性,選擇所需層級。像是針對FTP伺服器僅需使用到L3的Ping,來監測伺服器是否還在運作。但像線上購物網站,就需要使用L7,來監測網頁內容是否正常出現──假設網頁中的價錢遭到駭客竄改,有些伺服器負載平衡設備的健康診斷機制可以在偵測到時,將這臺有安全疑慮的網頁伺服器視為服務失效,並把它從服務群組中移出,避免錯誤資訊展示出去。

除了上述兩項主要功能外,通常各廠商會再提供一些特殊的負載平衡功能,像全球伺服器負載平衡(GSLB)、防火牆負載平衡(FWLB)功能,或是透過內建的硬體,提供SSL連線加速、壓縮HTTP資料等功能。

而伺服器負載平衡設備,價格從數十萬到上百萬元都有,如果規模與流量不是特別大的網站,使用軟體也能做伺服器負載平衡,像Window Server上的網路負載平衡功能(NLB),與Linux Virtual Server(LVS),都是透過軟體實做伺服器負載平衡的例子。不過上述兩種作業系統,其內建的功能較為基本,但對於小型網站已足夠使用。

而管理者在評估實作伺服器負載平衡時,需先考量網路規模及流量大小,如果是流量小的企業形象網站,就可以選擇自行架設軟體;如果是入口網站或學校的選課系統,這類瞬間流量大且需多臺伺服器的服務,使用專屬硬體設備可能較為合適。而在選購時,也可依照網站本身的特定需求挑選,有的產品特重在SSL連線加速,若是偏重電子金融服務的線上交易,可以搭配該類型產品。文⊙陳思翰

Round Robin

輪詢法
輪詢法是眾多負載平衡演算法中,最基本的演算法之一。其演算法是將服務群組中,所有節點(伺服器)權重設為相同。並基於這樣的條件,輪流詢問每一節點,因為各節點權重相同,所以會照著順序輪到,以供應服務。

但這種作法有個缺點,由於群組內伺服器的權重與負載相同,所以只適用於,群組內所有伺服器效能都相同的情況。因此實際在應用輪詢法時,大多是與其他演算法聯合使用。

Weighted

加權法
通常服務群組中的伺服器,每臺效能可能不盡相同,要讓它們做負載平衡時,就要依據效能來評估能承載的壓力。要應用加權法,需對各伺服器設定權值,而在負載平衡時,將較多連線導向效能好的伺服器上,而效能差的伺服器僅需處理較少連線。

而加權法通常也會與其他演算法混合使用,如最少連接數與輪詢法。

WAN Load Balancing,WLB

廣域網路負載平衡
許多人經常分不清WLB與SLB的差異,甚至以為兩者功能相同,實際上並不一樣。當網路環境存在兩條以上線路時,為了管理上的方便,大多會使用WLB來整合多條對外線路,來平衡企業對內、對外網路的負載量。WLB功能有整合線路、流量控制、線路備援等,假設內部網路有重要服務時,管理者可以透過WLB,給予伺服器保證流量。另外,它的線路備援功能也能讓服務保持不中斷。

Least Connection

最少連接法
最少連接法是一種針對伺服器連線數,來進行負載平衡的演算法。該演算法會透過負載平衡設備,對服務群組中的伺服器送出一個需求,來取得各伺服器的當前連線數,並依據這數值,將真正的伺服器連線,指向最低連線數的伺服器。但因為這時所得到的連線數,並不能完全呈現該臺伺服器真實的服務負載壓力,所以設定時,大多對伺服器設置連線數上限,來防止連線數超過負載,進而造成伺服器當機。

Global Server Load Balancing,GSLB

全球伺服器負載平衡
一個大型的國際級網站,背後可能有多個機房,來同時承擔來自世界各地的流量。而在這些機房中間,就是透過全球伺服器負載平衡來做流量負載。而GSLB基本概念其實跟SLB相似,只是規模變得更大,從群組內的多臺伺服器,變成了多個分散各地的資料中心。管理者使用GSLB,將來自世界各地的流量分析其地域位置,並依照所在地,來分配到距離最近的機房進行處理,以便提供給使用者最佳的服務。

Network Load Balancing,NLB

網路負載平衡
SLB大多用硬體方式實做,不過有些規模較小的網站或服務,會使用軟體的方式做SLB。透過軟體做SLB有兩種例子,一種是Linux 作業系統的LVS(Linux Virtual Server),另一種則是Windows Server的NLB功能,使用Windows Server 2003與2008的管理者,不需付費就能使用內建的NLB來做伺服器負載平衡。

不過NLB功能較陽春,且消耗的效能會造成伺服器負擔。

Least Request

最少需求法
最少需求法與最少連接法相似,不過它所監測的數值,並不是當前連線數,而是連線數中的需求數(一個連接網站的動作,分成HTTP Request和HTTP Response)。在HTTP 1.0時,連線數等同需求數,但是到HTTP 1.1時,一個連線數能同時包含多個需求。也因為這樣,透過連線數評估網路壓力已不準確,所以才衍伸出最少需求法。而這種作法會根據受監測伺服器的需求數,來分配網路連線。

Firewall Load Balancing,FWLB

防火牆負載平衡
它指的是利用實體線路的平衡,讓流量可以平均分配在多臺防火牆上。防火牆是網路安全中所不可缺少的,不過由於系統規則檢查時,經常使網路變得緩慢,而且一旦防火牆不能運作時,還會造成內外網路中斷。而有了防火牆負載平衡,能將線路分攤給多臺防火牆,提升處理效率。FWLB還可以做到防火牆的線路備援,當防火牆不能運作時,還能讓防護繼續保持。

Health Check

健康診斷
健康診斷大致上分成L3、L4、L7等三種層級,每個層級監測的目的都不同,像L3是使用ICMP的Ping,來確定伺服器是否在線上,L4是用TCP、UDP監測服務埠,L7則是監測應用服務及網頁內容。

這些功能,除了可以監測伺服器狀態,還能監測網站的重要內容。假設內容被竄改時,伺服器負載平衡設備則會將該網頁從服務群組移除,避免錯誤資訊呈現到使用者端。