2010年10月14日

加速Blogger的SyntaxHighlighter載入速度

不久前發表過一篇Blogger加掛SyntaxHighlighter的教學,最近發現有些速度上的問題。因為一次用了二十幾個<script ...>,所以在網誌每一頁載入時,這些*.js程式碼也會全部都被讀取一次,造成頻寬和記憶體的消耗。

把一些不常用的程式語言拿掉,可以讓速度快一些,但需要的時候還要去修改HTML樣板,感覺很麻煩。

我仔細研究SyntaxHighlighter的autoloader,才發現這功能可以做到「需要用到某個程式語言的著色時,才載入對應的*.js程式碼」,這樣一來不但可以使用SyntaxHighlighter支援的所有程式語言,而且只有在需要用到的時候才實際載入。

修改方式如下:

先找到<b:skin>標籤,在此標籤前加入以下代碼。
<!-- SyntaxHighlighter  3.0.83-->
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shAutoloader.js' type='text/javascript'/>

再找到</body>標籤,在標籤前加入以下代碼。
<!-- SyntaxHighlighter  3.0.83-->
<script type='text/javascript'>
SyntaxHighlighter.autoloader(
  'applescript            http://alexgorbatchev.com/pub/sh/current/scripts/shBrushAppleScript.js',
  'actionscript3 as3      http://alexgorbatchev.com/pub/sh/current/scripts/shBrushAS3.js',
  'bash shell             http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js',
  'coldfusion cf          http://alexgorbatchev.com/pub/sh/current/scripts/shBrushColdFusion.js',
  'cpp c                  http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js',
  'c# c-sharp csharp      http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js',
  'css                    http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js',
  'delphi pascal          http://alexgorbatchev.com/pub/sh/current/scripts/shBrushDelphi.js',
  'diff patch pas         http://alexgorbatchev.com/pub/sh/current/scripts/shBrushDiff.js',
  'erl erlang             http://alexgorbatchev.com/pub/sh/current/scripts/shBrushErlang.js',
  'groovy                 http://alexgorbatchev.com/pub/sh/current/scripts/shBrushGroovy.js',
  'java                   http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js',
  'jfx javafx             http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJavaFX.js',
  'js jscript javascript  http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js',
  'perl pl                http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPerl.js',
  'php                    http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js',
  'text plain             http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPlain.js',
  'py python              http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPython.js',
  'ruby rails ror rb      http://alexgorbatchev.com/pub/sh/current/scripts/shBrushRuby.js',
  'sass scss              http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSass.js',
  'scala                  http://alexgorbatchev.com/pub/sh/current/scripts/shBrushScala.js',
  'sql                    http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js',
  'vb vbnet               http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js',
  'xml xhtml xslt html    http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js'
);
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.all()
</script>

測試:
<pre class="brush: groovy">
println 'Hello World'
println 1 + 2 + 3
</pre>

用Firefox的Firebug外掛,在"網路"監測的功能中,就可以看到實際的作用情形。

2010年10月11日

快快樂樂認識 Groovy 的 Grapes 及 grab()

Grape (The Groovy Adaptable Packaging Engine or Groovy Advanced Packaging Engine) is the infrastructure enabling the grab() calls in Groovy, a set of classes leveraging Ivy to allow for a repository driven module system for Groovy. This allows a developer to write a script with an essentially arbitrary library requirement, and ship just the script. Grape will, at runtime, download as needed and link the named libraries and all dependencies forming a transitive closure when the script is run from existing repositories such as Ibiblio, Codehaus, and java.net.
from http://groovy.codehaus.org/Grape

Grape是一項Groovy的提案(proposal),它用來解決Java長久以來令開發者困擾的一個問題「每次都要到處抓*.jar的函式庫套件」。

Grape的作法是提供一個Grab()方法,指定 groupId(group)、artifactId(module)、version 三個設定值,Groovy程式在執行時,會自動幫忙下載指定的函式庫檔案。

在不久之前,我們通常使用Maven來處理這麻煩事;但是在目前新的Groovy發行版,我們已經可以直接使用Grape的功能,它的實現方式是使用 @Grab 這個標記(annotation),我們直接在一段Groovy程式碼中,直接嵌入@Grab的宣告,不必透過其他軟體(只需要安裝好JDK、Groovy),就可以獨立完成指定的函式庫下載、再執行程式。

舉例來說,安裝好Groovy之後,我們使用 GroovyWS 寫一段 Web Services 的測試程式,需要引用 groovyx.net.ws.WSClient 這個類別。

很不幸地,預設安裝好的Groovy並沒有提供我們需要的套件,也就是缺少了 groovyws-0.5.2.jar 這個檔案。

以下的程式碼加入 @Grab ,再第一次執行的時候會比較慢一些,因為會自動下載 groovyws-0.5.2.jar 以及它相依的套件,第二次以後因為已經取得套件,就會略過直接執行。真的沒有看錯,除了指定版本的套件以外,連這個版本的套件所依賴的其他相關套件, Grape 也會一併幫我們下載。我想任何一個寫過稍微大一點的 Java 程式的人,都會清楚處理相依套件的麻煩,就像沒有yum工具的時代,需要到處找rpm檔案的那種痛苦。

@Grab(group='org.codehaus.groovy.modules', module='groovyws', version='0.5.2')
import groovyx.net.ws.WSClient

def proxy = new WSClient("http://localhost/api/SimpleTest.asmx?wsdl", this.class.classLoader)
proxy.initialize()

如果你堅持認為 @Grab 寫在程式碼裏面很礙眼,Grape也提供另一種選擇,也就是 grape 指令。它的格式如下:
grape install []

查詢已經安裝的套件可以用:
grape list

以剛才 GroovyWS 的例子來說,以下的 grape 指令能完成與 @Grab 相同的工作:
grape install 'org.codehaus.groovy.modules' 'groovyws' '0.5.2'
(這道指令實際上會自動下載數十個.jar檔案,相信我,你不會真的想要一個一個慢慢抓!!!)

因此,如果不想再程式碼裏面寫 @Grab 宣告,就可以把需要用到的套件,都用 grape 指令寫程 bash 或 batch 批次檔,讓我們在development或production階段都能自動完成相依套件的安裝,而不必東找西找還擔心漏掉其中一個。

另外一個好處就是,這些我們的程式需要用到的相關套件,並不必跟程式碼放在一起,Grape預設會把套件檔案都保存到 $USER_HOME/.groovy/grapes 這個資料夾,因此我們只需要維護自己寫的程式碼,而不必在lib資料夾中放一堆雜七雜八的*.jar檔案。

因此...
對於使用SVN管理的Java專案來說,不再需要把雜七雜八的一大堆*.jar檔案放到SVN repository,麻煩的事交給Grape就對了。
對於一個簡單的Groovy程式碼,只有一個檔案,但不小心引用很多個套件,只要簡單地放個 @Grab 宣告,就可以把它發佈出去,而不必夾帶一堆*.jar檔案,還要告訴End User如何設定正確的CLASSPATH。

2010年10月6日

用 VirtualBox 建構開發、測試、服務環境

在建置新的伺服器時,我嘗試用虛擬機器提供對外服務(WEB、FTP、SSH、SVN、MySQL等),而實體機器僅供內部網路存取,這樣做可以建立第一道網路防線,當入侵事件發生時,影響範圍可以被隔離在虛擬機器中。

而虛擬機器的軟體,我選擇不必付費的VirtualBox,對流量不大的網路服務來說,用VirtualBox已經可以提供相當足夠的效能。

伺服器架構:
實體機器 Ubuntu 10.04 Desktop + VirtualBox 3.2.8
虛擬機器(1) Ubuntu 10.04 Server Master
虛擬機器(2) Ubuntu 10.04 Server Slave
虛擬機器(3) Fedora 13
虛擬機器(4) Windows XP

在這新的架構變得很容易維護,當實體機器掛點時,若開機硬碟沒問題,Ubuntu+VirtualBox只要換到新的硬體上就能立即運作;即使開機硬碟也掛點,重灌Ubuntu+VirtualBox並不會需要超過一小時。

對虛擬機器來說,備份的方式有很多選擇,可以從虛擬機器內部系統進行日常備份,也可以定期用實體機器備份整個虛擬機器,或是定時將Master虛擬機器sync到Slave虛擬機器,還可以建立Snapshot等。多了這些方便的措施,也不用擔心伺服器軟體進行全面升級後會發生問題,因為一切都可以先模擬測試一遍。

很多服務並不需要一台獨立的機器,例如SVN、GIT的repository server,只要建立一個記憶體256或512MB的虛擬機器,就足以應付日常需求,以目前新購PC記憶體一條都是2GB起跳的情況,分給四個虛擬機器用都綽綽有餘。

在開發階段使用的工作站,我也同樣以VirtualBox建置可以快速切換不同系統的開發環境,再多的選項組合,例如Windows+Linux+FreeBSD+SQL Sever+Oracle+PostgreSQL+Apache+Tomcat+...等,可以分別建立各專案專屬的虛擬機器,提供開啟後立即可用的開發環境。這樣一來,只需要一台工作站就可以同時在不同開發環境之間切換。

工作站架構:
實體機器 Ubuntu 10.10 Desktop + VirtualBox 3.2.8
虛擬機器 數十種不同組合的開發環境

雖然虛擬機器也要開關機,不過VirtualBox可以不用真的關機就把虛擬機器「關閉」,並且「儲存機器狀態」。其他的虛擬機器軟體也有同樣功能,但是目前用起來VirtualBox給我的感覺最快速,即使虛擬機器設定2G或4G記憶體大小,不管儲存、還原都在滿意的時間內就完成動作,而且還原後可以立即順暢地繼續作業,並不會感到回應遲鈍。在同時需要操作很多個開發環境時,可以把幾個暫時用不到的虛擬機器先關閉,等需要用的時候再還原,因此這功能是否能順暢就很重要。

VirtualBox只需要簡單的設定,將「啟用IO APIC」打勾,就可以直接開啟VMWare的虛擬機器,不僅相容且執行效能也感覺不到差異。將VMWare的虛擬機器轉換給VirtualBox使用很簡單,因此我使用VirtualBox同時管理這兩種異質的虛擬機器。

要建構可以流暢執行多虛擬機器的硬體並不難,因為三個影響效能顯著的零組件:多核心處理器、記憶體、硬碟都已經非常便宜。假設一部四核心、16GB記憶體、8TB硬碟的PC可以同時運作10個虛擬機器,只要購入四部PC就可以打造一個能玩得很開心的實驗環境。
lyhcode by lyhcode
歡迎轉載,請務必註明出處!