監(jiān)聽器工作過程
目前累計服務(wù)客戶上千,積累了豐富的產(chǎn)品開發(fā)及服務(wù)經(jīng)驗。以網(wǎng)站設(shè)計水平和技術(shù)實力,樹立企業(yè)形象,為客戶提供成都做網(wǎng)站、網(wǎng)站建設(shè)、網(wǎng)站策劃、網(wǎng)頁設(shè)計、網(wǎng)絡(luò)營銷、VI設(shè)計、網(wǎng)站改版、漏洞修補(bǔ)等服務(wù)。成都創(chuàng)新互聯(lián)始終以務(wù)實、誠信為根本,不斷創(chuàng)新和提高建站品質(zhì),通過對領(lǐng)先技術(shù)的掌握、對創(chuàng)意設(shè)計的研究、對客戶形象的視覺傳遞、對應(yīng)用系統(tǒng)的結(jié)合,為客戶提供更好的一站式互聯(lián)網(wǎng)解決方案,攜手廣大客戶,共同發(fā)展進(jìn)步。
下面我們談?wù)劚O(jiān)聽器的工作過程。一般,監(jiān)聽器作為一個獨立process在操作系統(tǒng)中運行,守候在特定網(wǎng)絡(luò)端口(默認(rèn)為:1521),等待客戶端請求的到來。注意:我們在客戶端配置命名服務(wù)的時候,輸入的1521也就是為了與監(jiān)聽器程序建立連接。
當(dāng)一個請求“如期而至”,監(jiān)聽器對照已經(jīng)注冊的服務(wù)列表,查找對應(yīng)的數(shù)據(jù)庫實例信息,獲取到指定實例的ORACLE_HOME路徑。相當(dāng)于表明可以進(jìn)行連接。
客戶端與實例的交互不是直接的,是通過Server Process作為代理中介來實現(xiàn)的。所有指令SQL都是客戶端通過Server Process發(fā)送到實例中,這種體系結(jié)構(gòu)是Oracle對于實例和數(shù)據(jù)庫文件一種保護(hù)機(jī)制。
當(dāng)監(jiān)聽器獲得請求之后,要從Oracle實例中分配一個Server Process與之對應(yīng)。這里不同的Oracle連接方式存在一些差別。
如果是專用連接模式,也就是一個客戶端連接對應(yīng)一個Server Process。監(jiān)聽器就會向OS請求fork(創(chuàng)造)出一個Server Process,與監(jiān)聽器嘗試交互。
如果是共享連接模式,也就是多個客戶端共享一個Server Process(注意:這里還不是連接池)。監(jiān)聽器就會向Dispatcher進(jìn)程(管理共享模式連接的進(jìn)程)請求一個Server Process與之交互。
Server Process與監(jiān)聽器的連接,實際上就是相互信息的交換。Server Process將自身在OS中的進(jìn)程編號、連接地址信息發(fā)給監(jiān)聽器。監(jiān)聽器將客戶端信息傳遞給Server Process。
監(jiān)聽器獲取到Server Process的信息之后,將其返回給客戶端連接程序??蛻舳双@取到信息之后,進(jìn)行重連接,根據(jù)返回的信息與Server Process在制定的服務(wù)器端口進(jìn)行聯(lián)系。
直到這個時候,客戶端程序才將連接用戶名、密碼等信息發(fā)給Server Process,進(jìn)行登錄驗證等操作。監(jiān)聽器的工作也就到此結(jié)束。
這里面有一個技術(shù)細(xì)節(jié),就是Server Process與客戶端連接的時候,是允許不使用1521端口的。具體連接的端口,是帶有隨機(jī)因素的。在9i版本Windows平臺下,如果安裝了防火墻,只允許1521端口通信,是會帶來一些連接問題。好在在其他平臺上和之后的版本中,實現(xiàn)了一種端口共享技術(shù),連接可以和監(jiān)聽器一起使用1521端口。
介紹了監(jiān)聽器工作原理,下面我們說說動靜態(tài)注冊的機(jī)制。
動靜態(tài)注冊機(jī)制
在上面的內(nèi)容中,我們已經(jīng)初步了解了注冊的作用,就是實現(xiàn)數(shù)據(jù)庫實例名和服務(wù)名注冊到運行的監(jiān)聽器程序中。目前的Oracle,支持靜態(tài)注冊和動態(tài)注冊兩種注冊方式。
靜態(tài)注冊顧名思義,就是顯示的指定出監(jiān)聽器程序要為那個實例以哪個服務(wù)名做監(jiān)聽。在啟動監(jiān)聽器的時候,監(jiān)聽程序是不知道所監(jiān)聽實例服務(wù)是否存在。直到有客戶端請求指定的服務(wù)。
指定靜態(tài)注冊的位置是在listener.ora參數(shù)文件,下面是一個典型參數(shù)文件的結(jié)構(gòu)。
# listener.ora Network Configuration File: D:\oracle\product\10.2.0\db_1\network\admin\listener.ora
# Generated by Oracle configuration tools.
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = D:\oracle)
(PROGRAM = extproc)
)
(SID_DESC =
(GLOBAL_DBNAME = orcl)
(ORACLE_HOME = D:\oracle)
(SID_NAME = orcl)
)
)
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
(ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
)
)
其中,SID_LIST配置節(jié)點中的SID_DESC就是配置靜態(tài)注冊的節(jié)點項目。SID_LIST里用來配置當(dāng)前監(jiān)聽器注冊的服務(wù)項目,通過多個SID_DESC進(jìn)行配置,每個SID_DESC基本上就是一個配置項目。默認(rèn)是動態(tài)注冊的時候,只有PLSExtProc項目。
靜態(tài)配置項目中,通過GLOBAL_NAME配置服務(wù)項目,通過SID_NAME指定數(shù)據(jù)庫實例的名稱,通過ORACLE_HOME配置Oracle數(shù)據(jù)庫軟件安裝的基本目錄。
動態(tài)注冊是與靜態(tài)注冊相對應(yīng)的一種注冊方法。同樣也是通過listener.ora進(jìn)行配置。下面是一個典型的配置參數(shù)文件。
# listener.ora Network Configuration File: D:\oracle\product\10.2.0\db_1\network\admin\listener.ora
# Generated by Oracle configuration tools.
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = D:\oracle)
(PROGRAM = extproc)
)
)
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = www-0e6111dff74)(PORT = 1521))
)
)
對比上面的靜態(tài)注冊文件,可以發(fā)現(xiàn)顯示指定服務(wù)名稱和數(shù)據(jù)庫實例名的項目不見了。只有本地地址和監(jiān)聽器端口信息。
動態(tài)注冊的動作是監(jiān)聽器所在主機(jī)上數(shù)據(jù)庫實例完成。動態(tài)注冊是Oracle上一個不能關(guān)閉的功能。實例的background process PMON,每隔一段時間(一到兩分鐘)就會將實例的參數(shù)信息注冊到監(jiān)聽器上,實現(xiàn)動態(tài)注冊。
注冊的信息是數(shù)據(jù)庫參數(shù)service_name和instance_name。可以通過Show Parameter命令查看。
SQL> show parameter instance_name;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
instance_name string orcl
SQL> show parameter service_names;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
service_names string orcl
一般數(shù)據(jù)庫在建立的時候,這兩個參數(shù)都是已經(jīng)設(shè)置好的,不會輕易的發(fā)生變化。
如果instance_name參數(shù)沒有設(shè)置,則系統(tǒng)會選取參數(shù)db_name作為實例名稱返回。如果service_names沒有設(shè)置,則會將db_name和db_domain兩個參數(shù)組合成服務(wù)名實現(xiàn)注冊。
值得注意的一個問題是,service_names參數(shù)是一個可以指定多個服務(wù)名稱的參數(shù),以逗號分隔。也就是說,一個Oracle實例時可以同時作為多個服務(wù)名向外提供服務(wù)的。Service_name是Oracle在新近版本中提出,替代SID_NAME的概念。使用Service的指定方式,多個Oracle實例就可以統(tǒng)一提供一致的數(shù)據(jù)訪問服務(wù)(也就是RAC)。
通常,對instance_name和service_name兩個參數(shù),還是建議設(shè)置上。因為會在一定程度上影響到動態(tài)注冊的效果。
如果沒有顯示的指定這兩個參數(shù),那么只有在數(shù)據(jù)庫實例啟動在監(jiān)聽器實例之后的時候,才會一次動態(tài)注冊。一旦之后監(jiān)聽器重新啟動,動態(tài)注冊的信息就不會存在,而且很難再次注冊上。所以,我們是推薦將這兩個參數(shù)設(shè)置上的。
只有顯示設(shè)置兩個值的情況下,PMON才會周期性的將注冊信息加以注冊。通過命令行,也可以強(qiáng)迫PMON立即執(zhí)行一次注冊操作。
SQL> alter system register
2 ;
System altered
最后,我們聊一聊動態(tài)注冊的作用,支持錯誤轉(zhuǎn)移failover。注冊操作的發(fā)動方是PMON后臺進(jìn)程,PMON是Oracle實例最重要的后臺進(jìn)程,很多資料和DBA都是以該進(jìn)程的狀態(tài)確定數(shù)據(jù)庫實例的狀態(tài)。PMON負(fù)責(zé)動態(tài)注冊,如果不能進(jìn)行動態(tài)注冊,說明PMON已經(jīng)失去了工作能力,也就意味著監(jiān)聽程序所服務(wù)的實例已經(jīng)不能工作。
通過動態(tài)注冊的機(jī)制,監(jiān)聽程序是可以知道所服務(wù)的服務(wù)器實例已經(jīng)崩潰,對于客戶端的請求,可以實現(xiàn)錯誤轉(zhuǎn)移。
當(dāng)然,我們這里談到的崩潰是實例的崩潰。如果監(jiān)聽器程序崩潰了,情況又是另一種樣子了。