期望通过光纤专用 WAN 连接的 SQL 服务器(相距 5000 公里)具有良好的性能是否合理。运营商告诉我们,该网络是“最佳”网络,并且保证延迟时间小于 50ms。
我们的数据库目前通过千兆以太网连接到同一数据中心内的其他机器。在两个数据中心之间建立 5000 公里的“LAN 扩展”对我们来说很有吸引力。但是当我们通过 Internet 和 VPN 连接时,我们发现在进行大量小额交易时性能非常慢。我们没有任何 WAN 经验,因此不确定大多数公司在这些情况下会怎么做。我们可以模拟 5000 公里的“延迟”吗?
答案1
光速下 5000 公里的延迟约为 17 毫秒。光纤下,延迟时间更可能是 25 毫秒。这是最佳情况下的服务器到服务器光纤,没有媒体转换、交换、路由、服务器响应等延迟。
最小值为 25ms,最大保证值为 50ms...
是的,有一些工具可以模拟慢速链接,例如
http://jagt.github.io/clumsy/- 一个用于改变网络流量的 Windows 程序
http://wanem.sourceforge.net/- 用于 WAN 仿真的 Linux LiveCD
以及很多建议https://stackoverflow.com/questions/130354/how-do-i-simulate-a-low-bandwidth-high-latency-environment和https://stackoverflow.com/questions/1094760/network-tools-that-simulate-slow-network-connection
答案2
比较模拟高网络延迟期间和相同正常网络延迟期间(对于相同的客户端负载和相同的数据库统计数据)的 sys.dm_os_wait_stats 轮询。例如,以下脚本可用于比较“ASYNC_NETWORK_IO”[wait_type] 的 [wait_rate (ms/Sec)]。以 X 到低 XX % 测量的差异可能受到背景噪音的影响(即它们毫无意义)。以 XXX% 测量的差异可能相关。为了让您定性地了解 wait_rates 的相对重要性,您将看到:如果您的 SQL Server 有 500 个活动工作线程,并且如果所有这 500 个线程都在等待一个 wait_type(在给定的一段时间内),那么那个 [wait_type] 的 [wait_rate (ms/Sec)] 将为 500,000 毫秒/秒。我通常会忽略小于 1000 毫秒/秒的 [wait_rate (毫秒/秒)]。
以下脚本用于收集 20 秒内的数据。您可以根据自己的测试需求进行调整。该脚本不会将 wait_types 聚合到各个类别中(例如,该脚本不会将所有 PAGEIO% 等待归为一类)。
DECLARE @hhmmssDelay CHAR(8) = '00:00:20'
SET NOCOUNT ON
CREATE TABLE
#ignored
(
wait_type NVARCHAR(60) PRIMARY KEY
)
INSERT
#ignored
SELECT 'BAD_PAGE_PROCESS'
UNION SELECT 'BROKER_EVENTHANDLER'
UNION SELECT 'BROKER_RECEIVE_WAITFOR'
UNION SELECT 'BROKER_TASK_STOP'
UNION SELECT 'BROKER_TO_FLUSH'
UNION SELECT 'BROKER_TRANSMITTER'
UNION SELECT 'CHECKPOINT_QUEUE'
UNION SELECT 'CLR_AUTO_EVENT'
UNION SELECT 'CLR_MANUAL_EVENT'
UNION SELECT 'DBMIRROR_EVENTS_QUEUE'
UNION SELECT 'DISPATCHER_QUEUE_SEMAPHORE'
UNION SELECT 'FT_IFTS_SCHEDULER_IDLE_WAIT'
UNION SELECT 'FT_IFTSHC_MUTEX'
UNION SELECT 'KSOURCE_WAKEUP'
UNION SELECT 'LAZYWRITER_SLEEP'
UNION SELECT 'LOGMGR_QUEUE'
UNION SELECT 'ONDEMAND_TASK_QUEUE'
UNION SELECT 'PREEMPTIVE_OS_AUTHENTICATIONOPS'
UNION SELECT 'PREEMPTIVE_OS_GETPROCADDRESS'
UNION SELECT 'REQUEST_FOR_DEADLOCK_SEARCH'
UNION SELECT 'RESOURCE_QUEUE'
UNION SELECT 'SLEEP_BPOOL_FLUSH'
UNION SELECT 'SLEEP_SYSTEMTASK'
UNION SELECT 'SLEEP_TASK'
UNION SELECT 'SQLTRACE_BUFFER_FLUSH'
UNION SELECT 'WAITFOR'
UNION SELECT 'XE_DISPATCHER_JOIN'
UNION SELECT 'XE_DISPATCHER_WAIT'
UNION SELECT 'XE_TIMER_EVENT'
UNION SELECT 'SQLTRACE_INCREMENTAL_FLUSH_SLEEP'
UNION SELECT 'DIRTY_PAGE_POLL'
UNION SELECT 'HADR_FILESTREAM_IOMGR_IOCOMPLETION' -- May be useful for AlwaysON (AKA Hadron)
SELECT
GETDATE() 'Poll'
, ows.*
INTO
#os_wait_stats
FROM
sys.dm_os_wait_stats ows
LEFT JOIN
#ignored i
ON
i.wait_type = ows.wait_type
WHERE
i.wait_type IS NULL
WAITFOR DELAY @hhmmssDelay
INSERT
#os_wait_stats
SELECT
GETDATE() 'Poll', ows.*
FROM
sys.dm_os_wait_stats ows
LEFT JOIN
#ignored i
ON
i.wait_type = ows.wait_type
WHERE
i.wait_type IS NULL
DECLARE @SecondsBetweenPolls INT
SELECT
@SecondsBetweenPolls=DATEDIFF(SECOND,MIN(Poll),MAX(Poll))
FROM
#os_wait_stats
DECLARE @SecondsSinceSQLServerStarted BIGINT
DECLARE @LastPoll DATETIME
SELECT
@LastPoll=MAX(Poll)
FROM
#os_wait_stats
SELECT
@SecondsSinceSQLServerStarted =DATEDIFF(SECOND, sqlserver_start_time, @LastPoll)
FROM sys.dm_os_sys_info
SELECT
CONVERT(NUMERIC(38,0),(Later.wait_time_ms-Earlier.wait_time_ms))/CONVERT(NUMERIC(38,0),@SecondsBetweenPolls) 'wait_rate (ms/Sec)'
,Later.wait_type
,Later.waiting_tasks_count-Earlier.waiting_tasks_count 'waiting_tasks_count'
,Later.signal_wait_time_ms-Earlier.signal_wait_time_ms 'signal_wait_time_ms'
,Later.wait_time_ms-Earlier.wait_time_ms 'wait_time_ms'
,CONVERT(NUMERIC(38,0),(Later.wait_time_ms))/CONVERT(NUMERIC(38,0),@SecondsSinceSQLServerStarted)'cumulative_wait_rate (ms/Sec)'
,Later.wait_time_ms 'cumulative_wait_time_ms'
,Earlier.Poll 'earlier_poll'
,Later.Poll 'later_poll'
,Earlier.max_wait_time_ms 'earlier_max_wait_time_ms'
,Later.max_wait_time_ms 'later_max_wait_time_ms'
FROM
#os_wait_stats Later
JOIN
(
SELECT
wait_type
,wait_time_ms
,waiting_tasks_count
,signal_wait_time_ms
,max_wait_time_ms
,Poll
FROM
#os_wait_stats
WHERE
Poll =
(
SELECT
MIN(Poll)
FROM
#os_wait_stats
)
) as Earlier
ON
Earlier.wait_type = Later.wait_type
WHERE
Later.wait_time_ms-Earlier.wait_time_ms > 0
ORDER BY
CONVERT(NUMERIC(38,0),(Later.wait_time_ms-Earlier.wait_time_ms))/CONVERT(NUMERIC(38,0),@SecondsBetweenPolls) -- 'wait_rate (ms/Sec)'
DESC
GO
DROP TABLE #os_wait_stats
GO
DROP TABLE #ignored