检查服务器是否可用

12

我正在寻找一种检查服务器是否可用的方法。 我们有一个离线应用程序,可以将数据保存到服务器上,但是如果服务器连接中断(偶尔会发生),我们必须将数据保存到本地数据库而不是在线数据库。 因此,我们需要不断地检查服务器是否仍然可用。

我们在此应用程序中使用C#。

对于sqlconnection.open的检查并不是一个很好的选择,因为这需要大约20秒才能抛出错误,我们不能等待这么长时间+ 我也正在使用一些http服务。

7个回答

33

只需使用System.Net.NetworkInformation.Ping类。 如果您的服务器不响应ping(出于某种原因,您决定阻止ICMP Echo请求),则必须为此发明自己的服务。 就个人而言,我赞成不要阻止ICMP Echo请求,并认为这是正确的方法。ping命令已经被用来检查主机的可达性。

using System.Net.NetworkInformation;
var ping = new Ping();
var reply = ping.Send("google.com", 60 * 1000); // 1 minute time out (in ms)
// or...
reply = ping.Send(new IPAddress(new byte[]{127,0,0,1}), 3000);

这可能存在一个问题,即路由器/交换机回复ping请求,或者数据库服务本身已经崩溃。 - UnkwnTech
两者都似乎不太可能,服务不应该在服务器崩溃的情况下失败。网络必须设置为ping作为可靠的可达性测试。 - John Leidegren
如果ping失败,可能是防火墙问题(防火墙和NAT路由器丢弃ping请求并不罕见)。 如果ping成功,数据库服务仍然可能停止。 因此,ping不适用于测试服务的可用性。 - DonkeyMaster
如果ping测试失败,您仍然可以尝试打开连接,如果这也不起作用,则数据库肯定无法访问。但是,您仍然不知道这是由于网络故障还是服务器故障。 - John Leidegren
Ping不是一个好的测试选择。将RDS输入服务器,告诉它重新启动或使用命令行关机,您可以在整个关机和重启过程中通过ping进行测试,但不能将文件保存到目录或访问数据库。 - Lawrence Thurman
显示剩余4条评论

3
如果你所说的连接不可靠,我建议不要使用单独的检查,而是将保存数据到本地作为异常处理的一部分。
我的意思是,如果连接失败并抛出异常,您可以切换策略并将数据保存在本地。
如果你先进行检查,然后连接在实际保存数据时中断,那么你仍然会遇到需要处理的异常。因此,最初的检查是不必要的。只有在您可以假设成功检查后连接已经连接并保持连接时,检查才有用。

2
从您的问题中可以看出,连接服务器的目的是使用其数据库。您首要考虑的是检查是否能成功连接到数据库。无论您能否 PING 服务器或获取 HTTP 响应(如其他答案中所建议的),除非您成功建立到数据库的连接,否则您的进程将失败。您提到检查数据库连接需要太长时间,为什么不只需更改应用程序连接字符串中的 Connection Timeout 设置为更短的值,例如5秒 (Connection Timeout=5)?

这难道不会影响查询执行的时间吗?我们有一些需要10秒钟才能完成的脚本...如果超时时间设置为5秒,那么程序不就会崩溃了吗? - user29964
是的,你说得对,但我建议你仅在最初的“探测”中使用这个缩短的连接超时时间来检查服务器和数据库是否正常运行。之后,使用更为合理的超时时间进行连接。 - Chris Driver

1
如果这是一个 SQL Server,那么您可以尝试打开一个新的连接。如果 SqlConnection.Open 方法失败,则可以检查错误消息以确定服务器是否不可用。

1

你现在正在做的是:

  • 使用远程服务器
  • 如果远程服务器失败,则使用本地缓存

如何确定服务器是否可用?使用 catch 块。这是编码最简单的方法。


如果您实际上拥有一个本地数据库(而不是例如交易列表或等待插入的数据),我建议您改变设计方案:
  • 使用本地数据库
  • 定期同步本地数据库和远程数据库

我会让你自己判断与并发约束相关的其他应用程序问题,然后选择解决方案。


0

既然你想要确定数据库服务器是否存在,可以在尝试连接到数据库时捕获任何错误,或者使用套接字并尝试在某个服务上与服务器进行原始连接。我建议使用数据库作为资源。


0

.Net Core 7

你可以使用以下方法检查 ICMP 的结果:

if (reply.Status != IPStatus.Success)

例如,我需要检查LMS的服务器,并将此问题提到Hangfire上。
public async Task<OperationResult<bool>> CheckIsActive(List<Server> servers)
        {
            try
            {
                var ping = new Ping();
                foreach (var server in servers)
                {
                    var reply = ping.Send(server.ServerUrl, 60 * 1000);

                    if (reply.Status != IPStatus.Success)
                        await server.SetDownServer();
                }

                return OperationResult<bool>.OnSuccess(true);
            }
            catch (Exception exception)
            {
                return OperationResult<bool>.OnException(exception);
            }
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接