什麼是Open Telecom Platform?
OTP是Ericsson為了大型分散式容錯系統寫的erlang library,這已經是standard erlang library。OTP包括完整的web browser, FTP server, .. 等等。OTP特色就是Behavior framework。
OTP Behavior
OTP把常用的code pattern包成behavior application framework,只需要填入callback來handle event即可。其他所有fault tolerance, scalability, dynamic-code upgrade, 都不用擔心了,因為都被behavior framework implement好了,類似java j2ee container (我也不知道那是啥 哈哈)。以下一步步示範怎麼從最簡單的server,長到OTP genserver裡面的server。
server1: 擁有callback的最可能簡單的server形式
這邊可以明顯看到我們在start function中接受一個Mod參數,此Mod參數必須implement
1. init(): 提供initial state
2. handle(): 就是真正的request handler
所以client先使用start來spawn一個process,然後用Name來bind這個server process的Pid。
然後再呼叫rpc來對sever下Request。注意rpc function也有 receive/end clause,這是對caller process來說安裝一個message receiver。
所以當Mod在loop中根據目前的State handle了Request之後,loop會遞迴呼叫自己,這時候Mod:handle()處裡的則是新的State1,所以 Mod本身不會有State,符合immutable的本性。
mod1
接下來該寫mod1。可以看到server1.erl 其實就是個骨架而已,Mod1.erl才是真正的server implementation。
可以看到mod1的確implement了必要的 callbacks。所以這個server initial state是一個空的 dictionary,另外可以handle add和find兩種Request,並且接受新的Dict當作新的state,並且回傳改變過的Dict,相信dict:store()應該也是immutable implementation,意即回傳一個copy。
client實際上能看到的應該只有add和find function,handle function理論上client不該使用。
重點是:callback的implementation完全不用管concurrency model!!!!! 這很強大。
client1
在client process:啟動service process:
2> server1:start(mod1, mod1).
true
這邊把Pid寫成mod1,其實是寫死的,因為我們在mod1.erl裡面也寫死Pid為mod1。
使用add
3> mod1:add("Sonny", "Office").
ok
使用find
4> mod1:find("Sonny").
{ok,"Office"}
就這樣,不過這樣其實蠻不直覺的interface!!!!
server2: transaction thru error handling
server1進化成serever2,藉由catch exception來確保"transaction semantics"執行。可以看到在loop function裡面,如果執行了callback handle function失敗的話,loop會recursively calls itself with "OldState",所以下一個message來要求執行handle()仍然是使用OldState,也就是transaction失敗的話不會改變狀態。
但是如果沒有catch 任何exception 的話,loop就會recursively calls itself with NewState。
rpc function裡面也幫client新增了一個對crash atom的handler,直接exit,所以其實有改變了client 的behavior!
Server 3: A Server with Hot Code Swapping
另一個可以神奇做到的是server code熱切換,意即不用把server給停下來。只要改動loop:
可以看到當loop match到swap_code這個atom的時候,先送一個ack給message sender,然後loop很簡單的就靠recursion重啟了,並且使用了新的callback function,而且state不會改變!
這就是stateless的好處!!! 這在imperative server應該非常困難做到。
Server 4: A Becoming Server
這有點新時代的意味了?!既然可以dynamic swap module,那甚至可以dynamic swap loop function!
一個本來在idle無所事事的server:
可以切換成以下的service:
只要送一個message給此process即可:
沒有留言:
張貼留言