轉(zhuǎn):http://cryolite.iteye.com/blog/419235
1.receive子句的消息匹配模式:如果消息很簡(jiǎn)單,使用atom就可以描述的話,沒(méi)必要使用tuple,tuple會(huì)消耗更多的內(nèi)存,而且減慢了進(jìn)程的處理速度。
2.i()列出當(dāng)前進(jìn)程的詳細(xì)信息,regs()列出所有注冊(cè)進(jìn)程和端口的詳細(xì)信息。ets:i()列出所有ets表的詳細(xì)信息。
3.atom不會(huì)被垃圾回收,因此為所有進(jìn)程都進(jìn)行注冊(cè)有可能會(huì)耗盡內(nèi)存。建議只對(duì)長(zhǎng)生命周期的進(jìn)程進(jìn)行注冊(cè)。
4. 給pid發(fā)送消息不會(huì)有任何錯(cuò)誤,哪怕該進(jìn)程不存在;但是,當(dāng)注冊(cè)的進(jìn)程不存在時(shí),通過(guò)注冊(cè)名給它發(fā)消息會(huì)出錯(cuò)。
5. 進(jìn)程對(duì)接收到的消息不進(jìn)行處理(匹配)應(yīng)視為一種bug,因?yàn)檫@些未被處理的消息會(huì)不斷的在進(jìn)程的mailbox里堆積,最后引起內(nèi)存泄露,然后,系統(tǒng)崩潰。mailbox過(guò)大的另一個(gè)問(wèn)題是,每次收到新消息,所有的舊消息都要過(guò)一遍,從而減緩了進(jìn)程的處理速度,表現(xiàn)為CPU占用率很高。
此外,大容量mailbox的進(jìn)程還會(huì)遲滯那些發(fā)消息給它的進(jìn)程(因?yàn)镋rlang runtime為了使大容量mailbox的進(jìn)程能及時(shí)進(jìn)行處理,它會(huì)主動(dòng)放慢那些給這個(gè)進(jìn)程發(fā)送消息的進(jìn)程)
但是,丟棄這些消息又會(huì)使調(diào)試?yán)щy,因此,最好確保在日志中記錄下這些不能處理的消息。
通過(guò)優(yōu)化代碼、對(duì)OS和Erlang VM精心調(diào)試可以糾正此類問(wèn)題。
另外同步化發(fā)送消息的進(jìn)程是一種辦法,發(fā)送進(jìn)程發(fā)送一個(gè)消息然后等待一個(gè)確認(rèn)會(huì)減慢maibox的消息增長(zhǎng)速度。
同步化的副作用是減少了接收處理進(jìn)程的最大吞吐量,但至少不會(huì)使系統(tǒng)當(dāng)?shù)簟?br /> 6. Erlang無(wú)法完全避免死鎖,例如進(jìn)程A同步調(diào)用進(jìn)程B(A給B發(fā)送消息,然后等待B返回響應(yīng)消息),后者(B)又同步調(diào)用進(jìn)程A。
7. 進(jìn)程的優(yōu)先級(jí)可以通過(guò)調(diào)用process_flag(priority, Priority)進(jìn)行調(diào)整,但是不鼓勵(lì)調(diào)整進(jìn)程的優(yōu)先級(jí),甚至應(yīng)該完全禁止使用。
8. 進(jìn)程間的聯(lián)系有兩種,一種是雙向的,即link;一種是單向的,即monitor。
前者建立的聯(lián)系是永久的,后者是臨時(shí)的。前者只能給存在的進(jìn)程建立聯(lián)系,后者可以監(jiān)視不存在的進(jìn)程(當(dāng)然會(huì)立即收到一個(gè){'DOWN'...,noproc}消息)。
顯然后者適合用在不對(duì)稱關(guān)系的進(jìn)程中,例如client-server
9. 解除對(duì)進(jìn)程的監(jiān)視最好調(diào)用erlang:demonitor(Reference, [flush]),因?yàn)閐emonitor調(diào)用之前監(jiān)視的進(jìn)程可能就DOWN掉了。
10. 任一進(jìn)程非正常退出,會(huì)給其link的進(jìn)程集發(fā)出exit信號(hào),exit信號(hào)將像多米諾骨牌一樣傳遞出去(每張牌就是一個(gè)進(jìn)程,倒掉代表進(jìn)程被結(jié)束)。
可以理解成:調(diào)用process_flag(trap_exit,true)后,進(jìn)程將收到的其它進(jìn)程exit信息轉(zhuǎn)換成{'EXIT', Pid, Reason}消息,從而制止了多米諾骨牌的繼續(xù)倒掉;
11. 進(jìn)程的正常結(jié)束不會(huì)引發(fā)關(guān)注:進(jìn)程正常退出時(shí),也會(huì)給它的直接link set發(fā)送exit信號(hào),但這個(gè)正常退出信號(hào)不會(huì)進(jìn)一步的傳播下去,也就是說(shuō)正常退出信號(hào)不會(huì)引發(fā)多米諾骨牌的倒塌。
(設(shè)置了trap_exit標(biāo)志的進(jìn)程會(huì)將這個(gè)exit信號(hào)轉(zhuǎn)換成消息{'EXIT',Pid,normal})。
12. 兩個(gè)在不同計(jì)算機(jī)上的link進(jìn)程,如果它們之間的網(wǎng)絡(luò)連接斷掉了,會(huì)收到{'EXIT', Pid, noconnection}的消息
13. 大型的Erlang系統(tǒng)中不應(yīng)該有孤兒進(jìn)程,也就是說(shuō)所有的進(jìn)程都要連接在一棵巨大的supervision樹上。
孤兒進(jìn)程有兩個(gè)問(wèn)題,首先不容易發(fā)現(xiàn)bug:當(dāng)這些進(jìn)程因bug當(dāng)?shù)魰r(shí),根本無(wú)從知曉。另一個(gè)問(wèn)題是“進(jìn)程泄漏”,孤兒進(jìn)程因?yàn)槟撤N原因掛了起來(lái),它會(huì)一直掛著,隨著越來(lái)越多的進(jìn)程掛起,這些不斷積累的孤兒進(jìn)程終將耗盡內(nèi)存。
14. supervisor進(jìn)程的唯一任務(wù)就是啟動(dòng)子進(jìn)程并監(jiān)視之。supervisor設(shè)置成trap_exit,并link到所有子進(jìn)程。
15. Erlang的在線升級(jí),分兩種情況。
第一種情況是模塊A在進(jìn)程中運(yùn)行,A會(huì)調(diào)用模塊B的函數(shù),運(yùn)行A模塊的進(jìn)程會(huì)維持一個(gè)到模塊B的最新版本的鏈接(link),在模塊B重載后,進(jìn)程中模塊B的鏈接(link)會(huì)切換到最新版本,這樣,模塊A以后會(huì)自動(dòng)調(diào)用更新后的函數(shù)。
第二種情況是模塊A本身的升級(jí),這種正在進(jìn)程中運(yùn)行的模塊的升級(jí)要復(fù)雜一些,取決于模塊中函數(shù)的調(diào)用方式:是直接調(diào)用,還是fully qualified function call調(diào)用(指B:fun1()這樣的調(diào)用),如果是直接調(diào)用,在模塊重載后,還是維持舊版本的模塊,而 fully qualified函數(shù)調(diào)用將會(huì)立即切換到最新版本的函數(shù)。
16. Erlang運(yùn)行時(shí)只維持兩個(gè)版本的模塊代碼,因此在第2次模塊升級(jí)后,最老版本的模塊會(huì)被移除,如果有進(jìn)程仍然運(yùn)行最老版本的模塊,這些進(jìn)程將隨著最老版本模塊的移除而被終止(killed)。
17. 有三種裝載模塊的方法。
第一種是直接調(diào)用模塊中的函數(shù),此時(shí)一個(gè)叫code server的進(jìn)程(它是Erlang kernel的一部分)將會(huì)搜索相應(yīng)的beam文件,然后裝載之;
第二種是編譯該模塊(相應(yīng)的函數(shù)是compile:file(Module))后會(huì)自動(dòng)裝載編譯好的模塊,在shell中是通過(guò)命令c(Module);
第三種方式是顯式的裝載模塊,通過(guò)調(diào)用code:load_file(Module)轉(zhuǎn)載指定的模塊,在本機(jī)上可以通過(guò)命令l(Module)裝載模塊,在網(wǎng)絡(luò)中可以通過(guò)命令nl(Module)將模塊裝載到各個(gè)節(jié)點(diǎn)上。
18. Erlang運(yùn)行時(shí),同一個(gè)模塊至多維持有兩個(gè):舊的和當(dāng)前的。當(dāng)又有新的版本裝載進(jìn)來(lái),舊的那個(gè)會(huì)被清除,當(dāng)前的變成舊的,剛裝載上的成為當(dāng)前的。
其中舊的、當(dāng)前的模塊與該模塊實(shí)際版本無(wú)關(guān),而與裝載的時(shí)間順序有關(guān)(可能先裝載一個(gè)最新版本的模塊,之后又裝載老版本的模塊,這種情況下先裝載的模塊是舊的,后裝載的模塊是當(dāng)前的)。
19. shell中按tab鍵會(huì)顯示所有已裝載的模塊。
20. 調(diào)用code:is_loaded(Module)判斷模塊是否已裝載。shell中通過(guò)tab鍵補(bǔ)全特性判斷模塊是否已裝載。
21. code server的主要任務(wù)是動(dòng)態(tài)的裝載和清除模塊。通過(guò)code模塊中的函數(shù)可以操作code server,進(jìn)而對(duì)系統(tǒng)代碼庫(kù)進(jìn)行管理和配置。
22. code search path是code server裝載模塊是的搜索路徑,缺省包括當(dāng)前路徑,以及所有庫(kù)應(yīng)用的路徑。通過(guò)code:get_path()查看。
23. Erlang根目錄:即Erlang安裝目錄,所有庫(kù)應(yīng)用都在根目錄的lib目錄下,通過(guò)code:root_dir()可以查看根目錄位置。
24. 熱升級(jí)面臨的幾個(gè)問(wèn)題:升級(jí)步驟原子化;向后兼容以備升級(jí)失敗;分布式環(huán)境中升級(jí)的同步化。SASL應(yīng)用庫(kù)提供了一些熱升級(jí)的工具。
25. 最簡(jiǎn)單的熱升級(jí)是重載模塊即可。前提條件是升級(jí)不會(huì)修改已存在的loop data。
26. 既然函數(shù)也是一種數(shù)據(jù),那么顯然,它也可以是tuple的一部分、record的一部分,也可以作為消息進(jìn)行發(fā)送。當(dāng)然,作為其它函數(shù)的返回值也就沒(méi)什么奇怪的,這樣就可以在運(yùn)行時(shí)動(dòng)態(tài)的創(chuàng)建函數(shù)了。
27. reference數(shù)據(jù):在分布式環(huán)境中reference數(shù)據(jù)提供了一個(gè)跨進(jìn)程的唯一標(biāo)識(shí)(tag),它主要用于進(jìn)行比較,多于消息傳遞有關(guān)。
28. 用變量綁定已定義在模塊中的函數(shù):Fun1 = fun Module:Function/Arity
29. 將函數(shù)傳遞給遠(yuǎn)程節(jié)點(diǎn)時(shí),顯然,函數(shù)中調(diào)用的那些模塊必須也在遠(yuǎn)程節(jié)點(diǎn)的code search path中。
30. 一個(gè)binary是一塊無(wú)類型的內(nèi)存的引用。最初被Erlang用來(lái)通過(guò)網(wǎng)絡(luò)加載代碼,隨后就應(yīng)用在基于socket的通訊中。
31. ets的match操作有可能會(huì)損害Erlang系統(tǒng)的實(shí)時(shí)性:這是因?yàn)樗械膍atch操作都是作為BIF實(shí)現(xiàn)的,而BIF的執(zhí)行具有原子性,當(dāng)對(duì)較大的ets表進(jìn)行match操作時(shí)要遍歷完整個(gè)ets表,這就會(huì)堵塞其它進(jìn)程。要避免此類問(wèn)題最好用first、next遍歷ets表,這樣做也許會(huì)更慢,但至少不會(huì)損害系統(tǒng)的實(shí)時(shí)性。
32. 用ets存儲(chǔ)record數(shù)據(jù)要指定key位置,因?yàn)樽鳛閞ecord的tuple第一個(gè)元素總是相同的。
33. 一個(gè)Erlang節(jié)點(diǎn)是指運(yùn)行中的Erlang運(yùn)行時(shí)系統(tǒng)。一個(gè)alive的Erlang節(jié)點(diǎn)是指“能夠”與其它節(jié)點(diǎn)通訊的節(jié)點(diǎn),alive節(jié)點(diǎn)必須有名字。
調(diào)用erlang:is_alive()判斷當(dāng)前節(jié)點(diǎn)是否alive。net_kernel模塊提供了控制Erlang節(jié)點(diǎn)alive的函數(shù)。
34. alive的Erlang節(jié)點(diǎn)名字有兩種:短名(short name)和長(zhǎng)名(long name),短名節(jié)點(diǎn)只能與短名節(jié)點(diǎn)通訊,長(zhǎng)名節(jié)點(diǎn)只能與長(zhǎng)名節(jié)點(diǎn)通訊。
35. Erlang系統(tǒng)的安全理念是:要么完全信任你,要么完全不信任你。因此互聯(lián)的遠(yuǎn)程Erlang節(jié)點(diǎn)擁有本地節(jié)點(diǎn)的所有訪問(wèn)權(quán)限。對(duì)于互聯(lián)網(wǎng)上分布的Erlang節(jié)點(diǎn),可以通過(guò)SSL加強(qiáng)安全性。
36. 節(jié)點(diǎn)間的安全是通過(guò)cookie控制的,每個(gè)節(jié)點(diǎn)持有一個(gè)被稱為secret cookie的atom,持相同cookie的節(jié)點(diǎn)間才能進(jìn)行通信。
(home目錄下有個(gè)“.erlang.cookie”文件,其內(nèi)容為缺省cookie值。)
另外,通過(guò)臨時(shí)設(shè)置cookie可以讓擁有不同cookie的節(jié)點(diǎn)間互通。
37. 分布式節(jié)點(diǎn)間的互聯(lián)是通過(guò)每個(gè)節(jié)點(diǎn)上的net_kernel進(jìn)程實(shí)現(xiàn)的,進(jìn)程的遠(yuǎn)程啟動(dòng)也是net_kernel負(fù)責(zé)。
net_kernel進(jìn)程通過(guò)cookie進(jìn)行安全授權(quán)。因此用戶可以通過(guò)修改net_kernel定制自己的安全授權(quán)機(jī)制。
38. 對(duì)于有太多Erlang節(jié)點(diǎn)的分布式系統(tǒng),一個(gè)問(wèn)題是會(huì)有太多的TCP/IP連接,如果有N個(gè)節(jié)點(diǎn),這些階段彼此聯(lián)通,會(huì)有N * (N - 1) / 2個(gè)TCP/IP連接。解決辦法是hidden node。
39. 通過(guò)node(hidden)或node(connected)查看hidden nodes
40. hidden node的一個(gè)用法是作為“網(wǎng)關(guān)”將許多小的分布式機(jī)群連接起來(lái)。另一個(gè)用法是用來(lái)做維護(hù),它不會(huì)影響流量。
41. 通用的消息發(fā)送格式是Pid ! Message,給遠(yuǎn)程注冊(cè)進(jìn)程發(fā)消息是:{register_name, node} ! Message
42. receive的timeout一個(gè)麻煩的地方是可能超時(shí)后消息又到了,這時(shí)消息就會(huì)堆積在接收進(jìn)程的mailbox中,在該進(jìn)程又一次進(jìn)入消息接收時(shí),可能處理的是這些超時(shí)后堆積的消息,因此進(jìn)行消息接收之前最好flush一下進(jìn)程的mailbox。
43. monitor_node(RemoteNode, true)用于監(jiān)控遠(yuǎn)程節(jié)點(diǎn),當(dāng)被監(jiān)控的遠(yuǎn)程節(jié)點(diǎn)當(dāng)?shù)魰r(shí)監(jiān)控進(jìn)程會(huì)收到{nodedown, RemoteNode}消息。
44. 查詢某個(gè)進(jìn)程(Pid)、某個(gè)引用(Reference)或者某個(gè)端口(Port)在哪個(gè)節(jié)點(diǎn)上,可以使用BIF函數(shù)node(Arg)。
45. epmd是Erlang port mapper deamon的縮寫,這是一個(gè)操作系統(tǒng)級(jí)的守護(hù)進(jìn)程,是Erlang運(yùn)行時(shí)系統(tǒng)的一部分。
不管運(yùn)行了多少Erlang節(jié)點(diǎn),每個(gè)計(jì)算機(jī)只運(yùn)行一個(gè)epmd,它隨Erlang節(jié)點(diǎn)的第一次啟動(dòng)而啟動(dòng),不隨Erlang節(jié)點(diǎn)的結(jié)束而結(jié)束。
epmd負(fù)責(zé)監(jiān)聽(tīng)4369端口上的連接請(qǐng)求,然后將其映射給相應(yīng)節(jié)點(diǎn)的監(jiān)聽(tīng)端口。
46. epmd可以作為shell命令單獨(dú)啟動(dòng),該命令還帶若干參數(shù),可以通過(guò) epmd -help查看。例如可以查看所有erlang節(jié)點(diǎn)的占用端口。
47. epmd的一個(gè)重要用處是通過(guò)參數(shù)delay_accept和delay_write可以模擬網(wǎng)絡(luò)繁忙的情況,便于測(cè)試。
48. 程序員編寫的OTP應(yīng)用(OTP application)是構(gòu)成Erlang系統(tǒng)的磚石,它在運(yùn)行時(shí)的進(jìn)程組成一個(gè)supervision樹。OTP應(yīng)用本身是一種OTP behavior。
posted on 2014-06-18 20:10
小王 閱讀(1674)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
Erlang