1.Listener是什么
Listener實際上是一個 VirtualNetworkName,客戶端通過這個VNN來連接的具體的sqlserver實例 .Listener包含了DNS名稱,port和IPaddress。
當客戶端通過Listener進行連接時,Listener會將請求自動導向到PrimaryReplica或者SecondaryReplica了。
在SQL Server Management Studio對應的記錄
對應的VCO記錄
對應的DNS記錄
下面是一個ADO.NET的連接字符串Server=AgListener;Initial Catalog=agdb1;Integrated Security=SSPI;
在這個連接字符串中指定了要連接的Listener名稱,這樣客戶端就會自動連接到primaryreplica了。如果發生了failover,在新的primaryreplica上線后,listener會自動將連接導向到新的primaryreplica,無需人為的干預。
2.負載平衡
SecondaryReplica可以配置成readonly模式,這樣就可以將一些只讀的工作放置到secondaryreplica中進行(例如報表),這樣就可以實現一定程度的負載平衡。並且Listener可以將這些只讀的連接自動導向到SecondaryReplica。
要實現這一功能,需要在SQLServer端和客戶端同時進行一些配置。
SQL Server端
1)Secondary replica要配置成read-intent only或者Yes
2)設置READ_ONLY_ROUTING_URL
下面是一個的READ_ONLY_ROUTING_URL的例子。 語句里指定了每個replica使用的端口,這里的端口號需要根據實際instance使用的端口號進行相應調整
alter availability group ag modify replica on 'SQL108W2K8R21' with (secondary_role(read_only_routing_url='tcp://SQL108W2K8R21.259442DOM.COM:1433'))
alter availability group ag modify replica on 'SQL108W2K8R22' with (secondary_role(read_only_routing_url='tcp://SQL108W2K8R22.259442DOM.COM:1433'))
alter availability group ag modify replica on 'SQL108W2K8R23' with (secondary_role(read_only_routing_url='tcp://SQL108W2K8R23.259442DOM.COM:1433'))
3) READ_ONLY_ROUTING_LIST
為三個replica分別設置readonly routing的順序。以SQL108W2K8R21為例,當SQL108W2K8R21成為Primary replica時,readonly routing的順序依次為SQL108W2K8R22->SQL108W2K8R23-> SQL108W2K8R21. Listener會將客戶端的請求導向到SQL108W2K8R22,如果SQL108W2K8R22不可用,導向到SQL108W2K8R23,以此類推。
alter availability group ag MODIFY REPLICA ON N'SQL108W2K8R21' WITH (PRIMARY_ROLE(READ_ONLY_ROUTING_LIST=(N'SQL108W2K8R22', N'SQL108W2K8R23', N'SQL108W2K8R21')))
alter availability group ag MODIFY REPLICA ON N'SQL108W2K8R22' WITH (PRIMARY_ROLE(READ_ONLY_ROUTING_LIST=(N'SQL108W2K8R21', N'SQL108W2K8R23', N'SQL108W2K8R22')))
alter availability group ag MODIFY REPLICA ON N'SQL108W2K8R23' WITH (PRIMARY_ROLE(READ_ONLY_ROUTING_LIST=(N'SQL108W2K8R21', N'SQL108W2K8R22', N'SQL108W2K8R23')))
客戶端的設置
需要在連接字符串內指定ApplicationIntent=Readonly 並且將database指定為AG內的數據庫
例如:
Server=AgListener;database=agdb1;Integrated Security=SSPI;ApplicationIntent=Readonly
3.Multiple Listener
默認情況下,一個Ag只支持一個listener,當嘗試創建第二個listener時會返回19477錯誤:
The availability group '%.*ls' already has a listener with DNS name '%.*ls'. Availability groups can have only one listener. Use the existing listener, or drop the existing listener and create a new one.
但實際上我們可以通過下面的方式為AG創建多個Listener
1)打開Failover Cluster Manager,右鍵ag->Add a resource->Client Access Point
2)填寫Listener名稱
3)右鍵為其分配IPAddress
4) 右鍵ag resource property,設置dependency. 將agListener2添加到Dependencies
5)為Listener分配port,此時port為null
select *from sys.availability_group_listeners
執行下面的語句創建port
alter availability group [ag]
modify listener 'agListener2'
(port = 1433)
7)新的Listener就可以使用了,我們在SSMS里也可以找到相應的記錄
4.MultiSubnetFailover
SQLServer2012開始支持Multi Site SQL Cluster。 一般而言,多個數據中心分布在不同的地理位置,例如在上海和北京分別建立了數據中心,這樣當一個數據中心出現故障后(例如地震等災害),備用的數據中心可以繼續提供服務。
下面是一個多子網的Listener截圖
在多子網環境中,一個Listener下會注冊多個IP Address(之間為OR關系),但只有primary replica所在子網的IP是處於Online狀態的,其余的均為Offline。如果發生failover,這些IPAddress的狀態會依據對應的replica的角色發生變化。
那么多子網環境會對Listener有什么影響呢?
首先要介紹一下RegisterAllProvidersIP屬性。如果值為1,那么Listener對應的DNS就會出現同名的多條記錄,每個記錄地應一個IP Address。
如果RegisterAllProvidersIP的值為0,那么只會存在一條DNS記錄,也就是Primary replica所在子網的IP。
如果存在多條重名的DNS(RegisterAllProvidersIP=1)記錄,客戶端會依次請求這些IP Address,如果得到的IP是offline的,那么會繼續請求一下條記錄.這樣就增加了連接時間,您的應用也可能會出現連接問題。
為了解決這個問題,ADO.NET(.NET 3.5.1)引入了MultiSubnetFailover關鍵字,如果MultiSubnetFailover
為True,那么客戶端會同時嘗試連接所有子網的IPAddress,使用最先響應的那個IP地址來作為最終使用的地址,這樣就極大地縮短了連接時間.
如果RegisterAllProvidersIP=0,那只有PrimaryReplica子網下的IP會注冊到DNS,當failover發生時,新的primaryreplica子網下的listener的IP會代替之前的IP。這樣就避免的之前的情況。
但在實際環境中,我們還需要考慮DNS的TTL值(Time-To-Live),TTL默認值是1200秒。也就是說當failover發生后,失效的DNS記錄要在客戶端可能要保持20分鍾才會失效,在此期間,客戶端無法通過listener進行連接。
當然我們可以手工執行ipconfig /flushdns才更新記錄,但這樣畢竟需要人工介入。
或者縮短TTL,但TTL值越小,DNSServer的性能消耗就嚴重。需要權衡兩者。微軟的建議值是300秒(5分鍾).
1 OR 0
那么是什么時候應當將RegisterAllProvidersIP這是為1,而什么時候為0呢? 如果您的客戶端支持MultiSubnetFailover關鍵字,那么建議設置成1,並且在連接字符串將MultiSubnetFailover設置為true.
如果客戶端不支持MultiSubnetFailover關鍵字,那么就設置成0,並修改TTL為300秒
更多信息
===
如果Listener使用過T-SQL語句或者SSMS創建的,RegisterAllProvidersIP為1
如果是通過ClusterFailovermanager創建的, RegisterAllProvidersIP為0
可以通過powershell修改RegisterAllProvidersIP的值
Get-ClusterResource "SQL Network Name (SQLMULTISUBCLUS)" | Set-ClusterParameter RegisterAllProvidersIP 1/0
update 20190104
===
starting from SQL Server 2016, it supports loadbalance readonly feature
https://blogs.msdn.microsoft.com/alwaysonpro/2016/05/02/sql-server-2016-alwayson-availability-group-enhancements-load-balance-read-only-routing/
alter availability group pubag modify replica on 'liweiy744VM\sql17' with (secondary_role(read_only_routing_url='tcp://liweiy744VM.liweiyin1.lab:58896')) alter availability group pubag modify replica on 'liweiy745VM\sql17' with (secondary_role(read_only_routing_url='tcp://liweiy745VM.liweiyin1.lab:58896')) alter availability group pubag modify replica on 'liweiy746VM\sql17' with (secondary_role(read_only_routing_url='tcp://liweiy746VM.liweiyin1.lab:58896')) alter availability group pubag modify replica on 'liweiy747VM\sql17' with (secondary_role(read_only_routing_url='tcp://liweiy747VM.liweiyin1.lab:58896')) alter availability group pubag MODIFY REPLICA ON N'liweiy744VM\sql17' WITH (PRIMARY_ROLE(READ_ONLY_ROUTING_LIST=((N'liweiy745VM\sql17', N'liweiy746VM\sql17', N'liweiy747VM\sql17'),'liweiy744VM\sql17'))) alter availability group pubag MODIFY REPLICA ON N'liweiy745VM\sql17' WITH (PRIMARY_ROLE(READ_ONLY_ROUTING_LIST=((N'liweiy746VM\sql17', N'liweiy747VM\sql17',N'liweiy744VM\sql17'),'liweiy745VM\sql17'))) alter availability group pubag MODIFY REPLICA ON N'liweiy746VM\sql17' WITH (PRIMARY_ROLE(READ_ONLY_ROUTING_LIST=((N'liweiy744VM\sql17', N'liweiy745VM\sql17', N'liweiy747VM\sql17'),'liweiy746VM\sql17'))) alter availability group pubag MODIFY REPLICA ON N'liweiy747VM\sql17' WITH (PRIMARY_ROLE(READ_ONLY_ROUTING_LIST=((N'liweiy744VM\sql17', N'liweiy745VM\sql17', N'liweiy746VM\sql17'),'liweiy747VM\sql17')))