原網址:http://www.360doc.com/content/11/0412/10/6670178_109025796.shtml
Oracle 監聽器 Listener 是一個重要的數據庫服務器組件,在整個 Oracle 體系結構中,扮演着重要的作用。它負責管理 Oracle 數據庫和客戶端之間的通訊,它在一個特定的網卡端口(默認是TCP 1521端口)上監聽連接請求,並將連接轉發給數據庫,下面的部分,會從幾個方面對監聽器進行簡單介紹。
1.監聽器的功能
從當前的 Oracle 版本看,Listener 主要負責下面的幾方面功能:
- 監聽客戶端請求。監聽器運行在數據庫服務器之上,與 Oracle 實例(可為多個)相關關聯,是一個專門的進程 process,在 Windows 的服務項目或者 Linux 的運行進程列表中,都會看到對應的運行進程。Windows 上名為 TNSLSNR,Linux/Unix 平台上是 lsnrctl。監聽器守候在服務器制定端口(默認為:1521),監聽客戶端的請求。
- 為客戶端請求分配 Server Process。監聽器只負責接聽請求,之后將請求轉接給 Oracle Server Process。在 Oracle 的服務模式下,客戶端進程是不允許直接操作數據庫實例和數據,而是通過一個服務進程 Server Process(也稱為影子進程)作為代理。監聽器接受到請求之后,就向操作系統(或者 Dispatcher 組件)要求 fork(或分配)一個 Server Process 與客戶端相連。
- 注冊實例服務。本質上講,Listener 是建立實例和客戶端進程之間聯系的橋梁。Listener 與實例之間的聯系,就是通過注冊的過程來實現的。注冊的過程就是實例告訴監聽器,它的數據庫數據庫實例名稱 instance_name 和服務名 service_names。監聽器注冊上這樣的信息,對客戶端請求根據監聽注冊信息,找到正確的服務實例名稱。目前 Oracle 版本中,提供動態注冊和靜態注冊兩種方式。
- 錯誤轉移 failover。failover 是 RAC 容錯的一個重要方面功能,其功能是在數據庫實例崩潰的時候,可以自動將請求轉移到其他可用實例上的一種功能。可以提供很大程度上的可用性(Availability)功能。這個過程中,發現實例已經崩潰,並且將請求轉移到其他實例上,就屬於是 Listener 的功能。
- 負載均衡衡量。在 RAC 架構中,Oracle 實現了負載均衡。當一個客戶請求到來時,Oracle 會根據當前 RAC 集群環境中所有實例的負載情況,避開負載較高的實例,將請求轉移到負載較低的實例進行處理。在早期 RAC 版本中,負載輕重的衡量是根據監聽器當前維護連接數目來確定的,而不是實時查看多實例的負載。RAC 環境中的監聽器之間進行溝通通信。
2.監聽器的操作
監聽器在 Windows 和 Linux/Unix 平台上,都是可以直接操作的。下面以 Linux 平台操作為例,其他平台類似。
在命令行窗口(CMD),輸入 lsnrctl,就可以進入監聽器控制窗口。
[oracle@newtest ~]$ lsnrctl
LSNRCTL for Linux: Version 10.2.0.4.0 – Production on 06-APR-2011 14:31:46
Copyright (c) 1991, 2007, Oracle. All rights reserved.
Welcome to LSNRCTL, type “help” for information.LSNRCTL>
通過輸入命令 help,可以查看支持的監聽器操作。下面僅介紹常用的幾個:
查看當前監聽器狀態:
敲入 status,可以查看當前監聽器的狀態,對應操作日志信息和服務注冊信息等內容。如下:
LSNRCTL> status
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))
STATUS of the LISTENER
————————
Alias LISTENER
Version TNSLSNR for Linux: Version 10.2.0.4.0 – Production
Start Date 18-MAR-2011 18:03:56
Uptime 18 days 20 hr. 28 min. 37 sec
Trace Level off
Security ON: Local OS Authentication
SNMP OFFListener Parameter File /home/oracle/product/10.2.0/db_1/network/admin/listener.ora
Listener Log File /home/oracle/product/10.2.0/db_1/network/log/listener.log
Listening Endpoints Summary…
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521)))
Services Summary…
Service “Test” has 2 instance(s).
Instance “Test”, status UNKNOWN, has 1 handler(s) for this service…
Instance “Test”, status READY, has 1 handler(s) for this service…
Service “TestXDB” has 1 instance(s).
Instance “Test”, status READY, has 1 handler(s) for this service…
Service “Test_XPT” has 1 instance(s).
Instance “Test”, status READY, has 1 handler(s) for this service…
The command completed successfullyLSNRCTL>
需要額外注意的下面幾項內容。
監聽程序參數文件 /home/oracle/product/10.2.0/db_1/network/admin/listener.ora //使用的參數
監聽器啟動時依據參數文件的,當然沒有參數文件監聽器也是可以啟動,那時監聽器依據默認的行為操作。這個參數指定了監聽器參數文件的位置,listener.ora。這個文件是一個文本類型參數文件,描述了監聽器監聽端口,主機名稱和靜態注冊信息。Listener.ora是隨着數據庫實例的建立之后,建立監聽器的過程中動態配置的。
監聽程序日志文件 /home/oracle/product/10.2.0/db_1/network/log/listener.log //操作日志位置
監聽器日志,是一個記錄和描述監聽器工作和錯誤的信息庫。通過仔細研究日志內容,可以幫助我們發現當前的監聽器的問題、解決連接故障和深入理解監聽器工作原理。
上文中已經說明,監聽器有注冊功能,通過 status 命令(services命令同樣效果)。可以查看到當前有什么服務被注冊上,用來檢查連接服務失敗,是常用的工具。
開啟/關閉監聽器:
監聽器的行為受到參數文件的控制,我們有時候需要調整監聽器的參數。調整監聽參數的方法,可以通過 Oracle 提供的 GUI 界面完成,還可以通過手工修改 listener.ora 來完成。
因為參數文件 listener.ora 是一個文本文件。Oracle 對於文本類型的參數文件,大多數情況下是不支持熱加載的。pfile 和listener.ora 都是如此。
使用界面GUI,就是使用 Net Configuration Assistant 來配置。配置完成后,配置程序會自動重新啟動監聽器程序,來加載修改的參數文件。如果采用手工修改 listener.ora,就必須要手工的進行監聽程序關閉和啟動。
LSNRCTL> stop
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))
The command completed successfullyLSNRCTL> start
Starting /home/oracle/product/10.2.0/db_1/bin/tnslsnr: please wait…
TNSLSNR for Linux: Version 10.2.0.4.0 – Production
System parameter file is /home/oracle/product/10.2.0/db_1/network/admin/listener.ora
Log messages written to /home/oracle/product/10.2.0/db_1/network/log/listener.log
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521)))
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))STATUS of the LISTENER
————————
Alias LISTENER
Version TNSLSNR for Linux: Version 10.2.0.4.0 – Production
Start Date 06-APR-2011 14:35:27
Uptime 0 days 0 hr. 0 min. 0 sec
Trace Level off
Security ON: Local OS Authentication
SNMP OFF
Listener Parameter File /home/oracle/product/10.2.0/db_1/network/admin/listener.ora
Listener Log File /home/oracle/product/10.2.0/db_1/network/log/listener.log
Listening Endpoints Summary…(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521)))
Services Summary…
Service “Test” has 1 instance(s).
Instance “Test”, status UNKNOWN, has 1 handler(s) for this service…
The command completed successfullyLSNRCTL>
這里多說一句關於監聽器的參數配置。使用GUI可以滿足大部分的情況,而且可以避免拼寫錯誤引發的監聽器故障(監聽器不會檢查配置項目的正確與否)。但是,在一些比較復雜的情況下,比如一台機器綁定多個IP的情況,或者 RAC 的復雜功能配置上,還是傾向於使用手工編寫 listener.ora 的方法。
此外,lsnrctl 提示行還提供了 reload 命令,可以在 Listener 啟動的情況下,重新加載文件和 SID 信息。但是我還是比較喜歡 stop+start 的組合。
如果是在 Windows 平台下,啟動關閉監聽器還可以在系統服務項目列表中操作,效果是一樣的。
3.監聽器的工作過程
下面我們談談監聽器的工作過程。一般,監聽器作為一個獨立 process 在操作系統中運行,守候在特定網絡端口(默認為:1521),等待客戶端請求的到來。注意:我們在客戶端配置命名服務的時候,輸入的1521也就是為了與監聽器程序建立連接。
當一個請求“如期而至”,監聽器對照已經注冊的服務列表,查找對應的數據庫實例信息,獲取到指定實例的 ORACLE_HOME 路徑。相當於表明可以進行連接。
客戶端與實例的交互不是直接的,是通過 Server Process 作為代理中介來實現的。所有指令 SQL 都是客戶端通過 Server Process 發送到實例中,這種體系結構是 Oracle 對於實例和數據庫文件一種保護機制。
當監聽器獲得請求之后,要從 Oracle 實例中分配一個 Server Process 與之對應。這里不同的 Oracle 連接方式存在一些差別。
如果是專用連接模式,也就是一個客戶端連接對應一個 Server Process。監聽器就會向 OS 請求 fork(創造)出一個 Server Process,與監聽器嘗試交互。
如果是共享連接模式,也就是多個客戶端共享一個 Server Process(注意:這里還不是連接池)。監聽器就會向 Dispatcher 進程(管理共享模式連接的進程)請求一個 Server Process 與之交互。
Server Process 與監聽器的連接,實際上就是相互信息的交換。Server Process 將自身在 OS 中的進程編號、連接地址信息發給監聽器。監聽器將客戶端信息傳遞給 Server Process。
監聽器獲取到 Server Process 的信息之后,將其返回給客戶端連接程序。客戶端獲取到信息之后,進行重連接,根據返回的信息與 Server Process 在制定的服務器端口進行聯系。
直到這個時候,客戶端程序才將連接用戶名、密碼等信息發給 Server Process,進行登錄驗證等操作。監聽器的工作也就到此結束。
這里面有一個技術細節,就是 Server Process 與客戶端連接的時候,是允許不使用1521端口的。具體連接的端口,是帶有隨機因素的。在9i版本 Windows 平台下,如果安裝了防火牆,只允許1521端口通信,是會帶來一些連接問題。好在在其他平台上和之后的版本中,實現了一種端口共享技術,連接可以和監聽器一起使用1521端口。
4.監聽器的動/靜態注冊機制
介紹了監聽器工作原理,下面我們說說動靜態注冊的機制。在上面的內容中,我們已經初步了解了注冊的作用,注冊就是將數據庫作為一個服務注冊到監聽程序。客戶端不需要知道數據庫名和實例名,只需要知道該數據庫對外提供的服務名就可以申請連接到數據庫。這個服務名可能與實例名一樣,也有可能不一樣。在數據庫服務器啟動過程中,數據庫服務器會向監聽程序注冊相應的服務(無論何時啟動一個數據庫,默認地都有兩條信息注冊到監聽器中:數據庫服務器對應的實例和服務。)相當於是這樣:在數據庫服務器和客戶端之間有一監聽程序(Listener),在監聽程序中,會記錄相應數據庫對應的服務名(一個數據庫可能對應有多個服務名),當客戶端需要連接數據庫時,只需要提供服務名,就可以建立客戶端和服務器之間的連接。目前的 Oracle,支持靜態注冊和動態注冊兩種注冊方式。
靜態注冊顧名思義,就是顯示的指定出監聽器程序要為那個實例以哪個服務名做監聽。在啟動監聽器的時候,監聽程序是不知道所監聽實例服務是否存在。直到有客戶端請求指定的服務。
靜態注冊就是實例啟動時讀取 listener.ora 文件的配置,將實例和服務注冊到監聽程序。無論何時啟動一個數據庫,默認地都有兩條信息注冊到監聽器中:數據庫服務器對應的實例和服務。
靜態注冊時,listener.ora 文件中的 GLOBAL_DBNAME 向外提供服務名,listener.ora 文件中的 SID_NAME 提供注冊的實例名。下面是一個典型參數文件的結構:
# listener.ora Network Configuration File: /home/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 = /home/oracle/product/10.2.0/db_1)
(PROGRAM = extproc)
)(SID_DESC =
(GLOBAL_DBNAME = Test)
(ORACLE_HOME = /home/oracle/product/10.2.0/db_1)
(SID_NAME = Test)
)
)LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
)
)
其中,SID_LIST 配置節點中的 SID_DESC 就是配置靜態注冊的節點項目。SID_LIST 里用來配置當前監聽器注冊的服務項目,通過多個 SID_DESC 進行配置,每個 SID_DESC 基本上就是一個配置項目。默認是動態注冊的時候,只有 PLSExtProc 項目。
默認安裝時,會安裝一個 PL/SQL 外部程序(ExtProc)條目在 listener.ora 中,是 Oracle 為調用外部程序默認配置的監聽,它的名字通常是 ExtProc 或 PLSExtProc,但一般不會使用它,可以直接從 listener.ora 中將這項移除,因為對 ExtProc 已經有多種攻擊手段了,在不使用外部程序時,Oracle 也是建議刪除的。PLSExtProc 是 PL/SQL external procdure 的意思,就是在 PL/SQL 中調用外部語句,如 C,Java 寫的過程。現在,Oracle 已經全面支持 Java 了,這東西也就過時了,之所以繼續保留是考慮到兼容以前老版本的數據庫實例。有時可能會在多個數據庫實例之間拷貝 listener.ora,請檢查拷貝來的文件中是否含有不需要的服務,確保只留下的確需要的服務項目,減少監聽器受攻擊的面。其實 Oracle DBA 應該特別重視監聽器的安全性,因為黑客可以輕易的侵入沒有進行安全配置監聽器的 Oracle 數據庫實例。如果你想了解 Oracle 監聽器安全配置方面的知識。
靜態配置項目中,通過 GLOBAL_NAME 配置服務項目,通過 SID_NAME 指定數據庫實例的名稱,通過 ORACLE_HOME 配置 Oracle 數據庫軟件安裝的基本目錄。
動態注冊是與靜態注冊相對應的一種注冊方法。同樣也是通過 listener.ora 進行配置。下面是一個典型的配置參數文件:
# listener.ora Network Configuration File: /home/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 = /home/oracle/product/10.2.0/db_1)
(PROGRAM = extproc)
)
)LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
)
)
對比上面的靜態注冊文件,可以發現顯示指定服務名稱和數據庫實例名的項目不見了。只有本地地址和監聽器端口信息。
動態注冊的動作是監聽器所在主機上數據庫實例完成。動態注冊是 Oracle 上一個不能關閉的功能。實例的 background process PMON,每隔一段時間(一到兩分鍾)就會將實例的參數信息注冊到監聽器上,實現動態注冊。
注冊的信息是數據庫參數 service_name 和 instance_name。可以通過 Show Parameter 命令查看。
SQL> show parameter instance_name;
NAME TYPE VALUE
———————————— ———– ——————————
instance_name string TestSQL> show parameter service_names;
NAME TYPE VALUE
———————————— ———– ——————————
service_names string Test
一般數據庫在建立的時候,這兩個參數都是已經設置好的,不會輕易的發生變化。
如果 instance_name 參數沒有設置,則系統會選取參數 db_name 作為實例名稱返回。如果 service_names 沒有設置,則會將 db_name 和 db_domain 兩個參數組合成服務名實現注冊。
值得注意的一個問題是,service_names 參數是一個可以指定多個服務名稱的參數,以逗號分隔。也就是說,一個 Oracle 實例時可以同時作為多個服務名向外提供服務的。service_name 是 Oracle 在新近版本中提出,替代 SID_NAME 的概念。使用 Service 的指定方式,多個 Oracle 實例就可以統一提供一致的數據訪問服務(也就是 RAC)。
通常,對 instance_name 和 service_name 兩個參數,還是建議設置上。因為會在一定程度上影響到動態注冊的效果。
如果沒有顯示的指定這兩個參數,那么只有在數據庫實例啟動在監聽器實例之后的時候,才會一次動態注冊。一旦之后監聽器重新啟動,動態注冊的信息就不會存在,而且很難再次注冊上。所以,我們是推薦將這兩個參數設置上的。
只有顯示設置兩個值的情況下,PMON 才會周期性的將注冊信息加以注冊。通過命令行,也可以強迫 PMON 立即執行一次注冊操作。
SQL> alter system register ;
System altered
最后,我們聊一聊動態注冊的作用,支持錯誤轉移 failover。注冊操作的發動方是 PMON 后台進程,PMON 是 Oracle 實例最重要的后台進程,很多資料和 DBA 都是以該進程的狀態確定數據庫實例的狀態。PMON 負責動態注冊,如果不能進行動態注冊,說明 PMON 已經失去了工作能力,也就意味着監聽程序所服務的實例已經不能工作。
通過動態注冊的機制,監聽程序是可以知道所服務的服務器實例已經崩潰,對於客戶端的請求,可以實現錯誤轉移。
當然,我們這里談到的崩潰是實例的崩潰。如果監聽器程序崩潰了,情況又是另一種樣子了。
我們可以使用命令 lsnrctl status 來查看某服務是靜態注冊還是動態注冊。實例狀態為 UNKNOWN 值時表明此服務是靜態注冊的設置。這時監聽器用來表明它不知道關於該實例的任何信息,只有當客戶發出連接請求時,它才檢查該實例是否存在。動態注冊的數據庫通過狀態信息中的狀態 READY 或狀態 BLOCKED(對於一個備用數據庫)來指明。不管關閉何時數據庫,動態注冊的數據庫都會動態地從 監聽器注銷,而與之相關的信息將從狀態列表中消失。這樣,不管數據庫是在運行還是已經關閉,監聽器總是知道它的狀態。該信息將被用於連接請求的回退 (fallback)和負載平衡。