简介

你好!我是Michał Niegrzybowski,我是一名.NET顾问。你可以在这个博客上看到我之前的文章,关于用.NET、Angular和MongoDB开发一个实时全栈应用程序。
你是否经常面临一个服务不工作的问题,而你又不知道为什么?有多少次是与一些外部服务、数据库等依赖关系或你正在使用的队列机制有关?当然,你可以不时地检查每个服务,你也可以针对服务运行一些烟雾测试,但如果 "服务不工作是因为与MSSQL的连接失败",它不会给你一个答案。
在.NET应用程序中,我们可以定义健康检查。顾名思义,就是对我们的服务进行检查。有很多开箱即用的检查,例如,针对SQL数据库、MongoDB、ElasticSearch等等。作为对ably-labs 仓库的贡献,我们发布了一个开源的Ably.Healthcheck库。
在这篇文章中,我们说明了每一个可用的健康检查,并希望得到 "Ably还活着吗 "这个问题的答案。
出错时该怎么做
让我们想象一下,你在浏览互联网时,突然每个页面都无法加载。你会怎么做?也许你试着按F5,但什么也没发生。于是你打开控制台,写道 ping [www.google.com](http://www.google.com):
好了。看起来一切都很好,你的浏览器配置出现了一些问题。
如果使用Aply的代码不工作,你也可以通过使用ping来检查是否是因为你或Aply的问题。你可以定期调用ping ,向Ably服务器发送一个心跳ping,当心跳ping请求从服务器回音时,返回以秒为单位的经过时间。

定期向Aply服务器发送一个心跳ping请求
这里有一个代码片段,这是你唯一需要添加到位于启动文件中ConfigureServices 方法中的健康检查配置中的东西:
services.AddHealthChecks()
.AddCheck(
"AblyPing",
AblyPingHealthCheck(
new AblyRealtime ("apiKey"), Timespan.FromSeconds 1.
)
)
值得注意的是最后一个参数,它说的是可以接受的ping延迟(1秒)。
值得一提的是,调用ping() 进行健康检查是免费的。与本文后面描述的其他两种健康检查相比,Ably不会向你收取ping 信息的费用。
ping有效,但我的信息没有通过信道传过来
发送ping是一个基本的检查,以确认你的Ably依赖性是否一切正常。如果你想更确定Aply服务是健康的,另一个选择是:ChannelHealthCheck 。
与PingHealthCheck 相比,它能给你什么?它使用一个真实的通道,发送一个消息,并等待一个消息传递状态。因此,你要验证你的具体通道,以及与之相关的一切配置是否正确。
这张图显示了ChannelHealthCheck 的工作方式。

的序列。ChannelHealthCheck
这是你需要添加到你的ConfigureServices 方法中的内容:
services.AddHealthChecks()
.AddCheck(
"AblyChannel",
AblyChannelHealthCheck(
new AblyRealtime ("apiKey"),
"ServiceName",
"ChannelName"
)
)
与PingHealthcheck 相比,我们需要传递两个额外的参数:
ServiceName是我们的消息主题的后缀,所以我们可以很容易地将它们与 "正常 "消息区分开来。ChannelName是我们要测试的频道的名称。默认情况下,我们使用的是 "健康检查 "频道。
Ping可以工作,频道可以工作,但有时我的信息到达得很慢
最后一个也是最彻底的可用健康检查被命名为Timer 。它不仅检查消息是否到达真正的信道,而且还检查消息中的时间戳,以及它与消息发送时的时间有多大差别。在配置这个健康检查时,你可以自己设置一个可接受的时间间隔,这样你就可以预先知道消息交换之间是否有 "滞后"。
这张图显示了TimerHealthCheck 的工作原理:

的顺序。TimerHealthCheck
这是你需要添加到ConfigureServices 方法中的内容:
services.AddHealthChecks()
.AddCheck(
"AblyChannel",
AblyTimerHealthCheck(
new AblyRealtime ("apiKey"),
"ServiceName",
"ChannelName",
TimeSpan.FromSeconds 1.,
TimeSpan.FromSeconds 1.
)
)
与之前的检查相比,有两个额外的参数。首先,timespan与你发送消息的时间和消息里面的消息属性之间可接受的时间差有关。而第二个参数则描述了通过Ably通道接收消息所需的等待时间。你需要记住,第一个参数应该总是小于第二个参数。
在.NET WebApp中配置Ably健康检查
正如介绍中提到的,前面展示的所有代码样本都使用了新的Ably.Healthcheck 库。这个库可以帮助你只用几行代码就可以开始使用Ably健康检查。让我们看看更完整的代码片断是怎样的。所以,让我们去看看我们用.NET编写的WebApp样本。我们需要将AddHealthChecks 在启动文件中:
...
member this.ConfigureServices(services: IServiceCollection) =
...
let ably = new AblyRealtime ("apiKey")
...
services.AddHealthChecks()
.AddCheck(
"AblyPing",
AblyPingHealthCheck(
Ably,
TimeSpan.FromSeconds 1.
)
)
.AddCheck(
"AblyChannel",
AblyChannelHealthCheck(
ably,
"ServiceName",
"ChannelName"
)
)
.AddCheck(
"AblyTimer",
AblyTimerHealthCheck(
ably,
"serviceName",
"ChannelName",
TimeSpan.FromSeconds1.,
TimeSpan.FromSeconds1.
)
)
|> ignore
...
...
用AddHealthCheckUI改进用户界面
我们还想添加一个漂亮的健康检查视图,所以我们在启动文件中把AddHealthCheckUI ,在ConfigureService :
member this.ConfigureServices(services: IServiceCollection) =
...
services
.AddHealthChecksUI(fun s ->
s
.SetEvaluationTimeInSeconds(60)
.AddHealthCheckEndpoint("Self", $"http://{Dns.GetHostName()}/health")
|> ignore)
.AddInMemoryStorage() |> ignore
...
member this.Configure(app: IApplicationBuilder, env: IWebHostEnvironment) =
...
...
app.UseEndpoints(fun endpoints ->
endpoints.MapControllers() |> ignore
endpoints.MapHealthChecksUI(fun setup ->
setup.UIPath <- "/ui-health"
setup.ApiPath <- "/api-ui-health"
) |> ignore
endpoints.MapHealthChecks(
"/health",
HealthCheckOptions(
Predicate = (fun _ -> true),
ResponseWriter = Func<HttpContext, HealthReport, Task>(fun (context) (c: HealthReport) -> UIResponseWriter.WriteHealthCheckUIResponse(context, c))
)
) |> ignore
) |> ignore
...
结果
下面是一个失败结果的例子(Ably Channel通过,Timer失败):

通道测试通过,但定时器失败
这里是一个成功的例子(Ably Channel和Timer通过):

通道和定时器的检查都通过了
我决定每60秒运行一次这些测试,而不是默认的10秒,这样就不会在Ably仪表盘上产生太多不必要的流量。
我希望你喜欢这篇文章。谢谢你的阅读!