2012年12月8日 星期六

TrafficScript log

在TrafficScript中,有提供一個log物件,並提供error, info, warn等操作方式,log的寫法是:
log.info("string that need to log...");

而,如果要操作到字串的相加,則是使用"."來串接兩個字串...
例如:顯示"url=目前連進的url"這樣的一串文字..
$rawurl = http.getRawURL();
log.info('url='.$rawurl);

而在所有設定就緒後
尚需要確認Virtual Server的log記錄功能是否打開...


等設定都OK之後,您就可以在進入頁面(Home)看到相關的Log資訊(當然,您需要有Request進入才會Trigger相對應的Log)...


2012年12月7日 星期五

Using TrafficScript to Redirect Page

Page redirect在網頁中,一般只要一行HTML或是JavaScript就可以完成
但是跑一段HTML或JavaScript卻需要一台HTTP Server!
許多網路上的服務主機移轉,其實沒必要再那麼費資源∼

在TrafficScript中,只要在Request Rule中指定redirect的位置即可
例如,我有一台server要從http 80 port遷移到https 443 port
那Listen在該位置80 port的Virtual Server Request Rule可以這下:


另外,可以搭配http.getRawURL()來針對每一個Path的導向都做直接重導的動作:

$rawurl = http.getRawURL();
http.redirect("https://your.server.domain.name/".$rawurl);


2012年12月2日 星期日

Stingray簡介

不是第一篇講簡介好像又點奇怪,不過就當做給不認識Software Load Balancer的朋友一個參考啦...

Stingray原名Zeus,為Riverbed公司所購買之Zeus公司產品,專職負載平衡與網路流量管理相關功能。
研究Stingray的緣起是越來越多的專案使用到網路層的Load Balancer,因大型的軟體架構中,時常需要有負載平衡及Cluster的架構,而仰賴Apache或是簡單的Load Balancer軟體常常不能滿足需求,而硬體方式的Load Balancer像是BigIP或是Cisco相對應的負載平衡設備都往往超出預算而又超出一般軟體工程師可以觸及的範圍,在這些條件之下,Stingray反而圖顯了一些他存在的重要性。

以下針對幾個個人認為Stingray價值核心的部份列出給大家參考:
  • 本身為軟體:這部份對軟體工程師而言是好消息,不需觸及硬體部份即可將一些網路之構想以Stingray所提供之介面實現,當然設定者本身也必需具備部份網路架構之基礎,方可收事半功倍之成效。另外,不少網路設備提供可程式化介面,但往往由於網路設備下所關係到的節點數量龐大,導致安全性上考量而無法釋放給軟體工程師太多空間進行管理與設定,而本身為軟體的優勢,讓您可以在任何節點部署架構,而佈至於影響到太多的網路節點。
  • 提供各種程式語言實作之API介面:提供各種語言之API介面,也是方便系統架構與軟體工程師之特性,這部份讓系統環境中許多不定因素或是需要大量判斷之路由規則不在是夢想。
  • 提供友善的Web管理界面:Web的管理介面通常是一套系統必備的工具,而Stingray提供的Web介面也出奇的簡單,並可在介面中對軟體或系統進行重新啓動的操控,這部份也讓管理者可以減少在外部網路環境還需要SSH連線到作業系統的需求。

目前Stingray系列以model區分有三個系列:1000 Model, 2000 Model, 4000 Model,功能模組上稍有差異,其中2000系列以上提供的Global Load Balancing是最大差異,該功能提供使用者可以依地區性來進行區域網址的導向,簡單的說,就是可以做到讓美國的IP連線美國的主機、台灣的IP連線台灣的主機... 

其他有些不錯的功能像頻寬管理、服務等級監控...等功能也是2000以上系列才有提供,不過這些開發測試版本都可以直接使用喔,唯差在頻寬限制而已...

在官方網站簡介中,Stingray之安裝規格最小為2GB,筆者曾試過1GB的Ubuntu可以正常安裝,且可以運作,不過考慮到穩定性,建議還是依照官方建議規格進行安裝,會比較好唷~

Operating System: SoftwareLinux 2.6.22 or later (x86, x86_64), Solaris 10 (SPARC, x86_64), OpenSolaris 2009.6 (x86_64)
Virtual Environment: Virtual ApplianceVMware vSphere 4, VI3 (3.5), XenServer 5.5, OracleVM 2.1, VMware ESXi 4.1 and 5.0
Recommended Hardware: CPUIntel Xeon / AMD Opteron / Oracle SPARC
Recommended Hardware: Memory2 Gb
Recommended Hardware: Disk space10 Gb
表:建議安裝規

2012年11月30日 星期五

苦惱訂單系統沒有額外LOG記錄,Stingray幫你通通記下來

當LoadBalancer不再只有流量重導與負載平衡時候,您也可以透過LB來做一些特殊的事情...
這邊展示從HTTP協定著手,將LB所負載之WEB上的Log做一個額外的紀錄...

[系統URL或API URI範例]
[POST] https://your.ip.address:port/cloudstore/simonsu/order/OD-01346

Create Body:(當post上面url時候,實際是送這邊的資料出去)
{"order_id":"OD-01346","username":"simonsu","price":"1000"}
Response Body:(當post完成時候,系統回傳資訊)
{"status":"OK"}

這邊透過一個Request Rule與一個Response Rule來組成這個服務,
其中Request部分記錄使用者傳入參數
而Response部分記錄系統回傳完成訂購之資訊
回傳部分,可以透過某些檢查機制來確認是否要進行Log動作...

[RULE_CREATEORDER_LOG_REQ]
$rawurl = http.getRawURL(); # ex: /cloudstore/simonsu/order/OD-01346
$method = http.getMethod(); # ex: POST
$post = http.getBody(); # ex:
{"order_id":"OD-01346","username":"simonsu","price":"1000"}
$arr = string.split($rawurl,'/'); $ want to get user
$user = '';
if ( array.length($arr) >= 2 ) {
  $user = $arr[1];
}
if ( string.startsWith( $rawurl,"/cloudstore") &&
    string.regexmatch($method, 'POST') ) {
  log.info('>>>>>>>YES GOT CREATE ACTION!!!!');
  # pass the parameter to response rule
  connection.data.set("post", $post);
  connection.data.set("user", $user);
}


[RULE_CREATEORDER_LOG_RESP]
$user = connection.data.get("user");
$post = connection.data.get("post");
$resp = http.getResponseBody();
# Query the mapi2 for record the post and the response
# All things in url can process from node.js using req.params.[name]
# All thinsg in POST column can process from node.js using req.body
$new_url = "http://log.server.ip.address:port/logOrder/".$user."/".string.urlencode( $post );
if($resp != '{"status":"Failed"}'){ $result = http.request.post($new_url, $resp,"Content-Type: application/json");
log.info('>>>create order result='.$result);
}

接收Log的程式,也相當簡單,這邊展示使用Node.js的接值方式
至於儲存部分,則依據自己實作啦∼

[Node.js Server (Using ExpressJS)]
# app.js
app.get('/logOrder/:user/:post', route.createOrderLog);
# route/index.js
exports.createOrderLog = function(req, res){
//post data取值,直接接回body取值
 var order = req.body;
 res.writeHead(200, {'Content-Type': 'application/json'});
//url列的參數取值,使用req.params.[name]取值
 order.user=req.params.user;
 order.post=JSON.parse(req.params.post);

  //TODO: 使用您prefer的儲存方式存檔
 console.log('Get create order request...., %s', JSON.stringify(order));
//回應狀態
 res.end(JSON.stringify(order));
}

已上面的範例,做後可以看到console的Log

[LOG]
Get create order request...., {"status":"OK","user":"simonsu","post":{"order_id":"OD-01346","username":"simonsu","price":"1000"}}

TrafficScript的基本文字運算


官方的教學文章中提到許多文字操作的的範例,相當具有參考價值,這邊擷取精華部分呈現:

使用RE的範例:
$id ="user=Joe, password=Secret";
if(string.regexmatch( $id,"^user=(.*), password=(.*)$")){
   log.info("Got UserID: ".$1.", Password: ".$2 );
}

文字大寫寫轉換:
$string ="AbCdEfG"; $upper =string.toUpper( $string );# returns "ABCDEFG" $lower =string.toLower( $string );# returns "abcdefg" HTML文件標籤與特殊字元encode: $xss ="<script>alert('Hello!');</script>"; 結果:"&lt;script&gt;alert('Hello!');&lt;/script&gt;" $safe =string.htmlencode( $xss );

文字中跳脫字元轉換:
$str =string.escape("Hello World!\r\n"); 結果:"Hello%20World!%0D%0A"
使用HTTP BASIC authentication方式加密帳密: $enc =string.base64encode("user:passwd"); http.setHeader("Authorization","Basic ".$enc );
HEX加解密: string.hexEncode() string.hexDecode(). AES cipher加解密: $encrypted =string.encrypt( $plaintext, $passphrase ); $plaintext =string.decrypt( $encrypted, $passphrase );

TrafficScript的URL運算

文字的操作在程式語言上一直是不可或缺的技巧,TrafficScript中也提供基本的文字操作
這邊簡單介紹url切割取出中間欄位的方式

取出URL,並透過"/"切割字元,然後從array中取出第二個元素:
$rawurl
= http.getRawURL(); # ex: /cloudstore/simonsu/product1/AB1234
$arr = string.split($rawurl,'/'); $ want to get user (simonsu)
$user = '';
if ( array.length($arr) >= 2 ) {
  $user = $arr[1];
}

另外,網址是開始於什麼字元、結束於什麼字元、包含什麼字元,也是常用的方式:
if ( string.startsWith( $rawurl,"/cloudstore") && 
string.endsWith( $rawurl,"AB1234") && 
string.contains( $rawurl,"simonsu") &&
    string.regexmatch($method, 'POST') ) {
# do your jobs...
}


Stingray Rule的http操作

http這個物件在Stingray中有許多有用的操作,這邊列出幾個常用的:

  • http.getRawURL(); 取出使用者連到LB的網址,值的部份不包含IP、PORT與協定,僅從Context開始之後 ex:/Wiki/en/somepage.jsp
  • http.getMethod(); 取出連線時候的http method,可以作為判斷RESTful操作方法之使用 ex: GET or POST
  • http.getBody(); 取回連線時候送進LB的內文,一般用在Request Rule中 ex: {"title":"hello","content":"test 123"}
  • http.getResponseBody(); 取回使用者要求之回應內容,一般用在Response Rule中 ex: <html>....</html>


Stingray Rule中的一進一出

Stingray的rule中有分所謂的Request Rule與Response Rule,而真正的作用是在針對User Request跟Server Response兩件事情增加操作的規則。下面展示兩個Rule中怎麼彼此交換資料來達到某些特定的操作目的:

這邊假設管理人員需要針對伺服器的連線時間過長(在此為5秒)的這個Event增加操作,操作中會去觸發一個HTTP的連線,連線中就可以由開發人員撰寫相關程式來達到通知、記錄、甚至Cloud Scale Out的目的...

此邏輯的設計包含:

  1. Request Rule(RULE_SET_RESP_TIME_FLAG)做進入時間記錄
  2. Response Rule(RULE_SET_RESP_TIME)做回應時間記錄,並操作HTTP連線動作


Rule的原始碼如下:

RULE_SET_RESP_TIME_FLAG.rule
$tm = sys.time(); connection.data.set("start", $tm);


RULE_SET_RESP_TIME.rule

# Response time in (integer) seconds above
$THRESHOLD =5;
# which requests are logged.
$start = connection.data.get("start");
$now = sys.time();
$diff =($now - $start);

if( $diff >= $THRESHOLD ){
   $uri = http.getRawURL();
   $node = connection.getNode();
   log.info ("SLOW REQUEST (". $diff ."s) ". $node .":". $uri );
   # Doing scale out...
   http.request.get("http://your.server.ip.address:300/scaleout" );
}