是否有办法实时通知系统用户系统正在部署过程中(发布到生产)?目的是防止他们开始执行原子操作?该系统是一个基于ASP.NET的系统,它已经具有SignalR Dlls,但我不知道如何在我知道系统正在部署的应用程序中找到“源”。
发布于 2022-03-31 07:56:12
这在很大程度上取决于您的部署过程,但我在以下方面实现了类似的目标:
我在一个控制器中创建了一个名为AnnounceUpdate的方法
[HttpPost("announce-update")]
public async Task<IActionResult> AnnounceUpdate([FromQuery] int secondsUntilUpdate, string updateToken)
{
await _tenantService.AnnounceUpdate(secondsUntilUpdate, updateToken);
return Ok();
}控制器方法在更新前的秒数,以及一个秘密令牌,以确保不只是任何人都可以调用这个端点。
我们的想法是,我们将在部署之前调用此控制器,以宣布挂起的部署。我使用Azure进行部署,因此我能够创建一个发布任务,该任务自动运行以下PowerShell代码来调用我的端点:
$domain = $env:LOCALURL;
$updateToken = $env:UPDATETOKEN;
$minutesTillUpdate = 5;
$secondsUntilUpdate = $minutesTillUpdate * 60;
$len = $secondsUntilUpdate / 10;
#notify users every 10 seconds about update
for($num =1; $num -le $len; $num++)
{
$url = "$domain/api/v1/Tenant/announce-update?secondsUntilUpdate=$secondsUntilUpdate&updateToken=$updateToken";
$r = Invoke-WebRequest $url -Method Post -UseBasicParsing;
$minsLeft = [math]::Floor($secondsUntilUpdate/60);
$secsLeft = $secondsUntilUpdate - $minsLeft * 60;
$timeLeft;
if($minsLeft -eq 0){
$timeLeft = "$secsLeft seconds";
}else{
if($secsLeft -eq 0){
$timeLeft = "$minsLeft minute(s)";
}else{
$timeLeft = "$minsLeft minute(s) $secsLeft seconds";
}
};
$code = $r.StatusCode;
Write-Output "";
Write-Output "Notified users $num/$len times.";
Write-Output "Response: $code.";
Write-Output "$timeLeft remaining."
Write-Output "_________________________________"
Start-Sleep -Seconds 10;
$secondsUntilUpdate = $secondsUntilUpdate - 10;
}
Write-Output "Allowing users to log out.";
Write-Output "";
Start-Sleep -Seconds 1;
Write-Output "Users notfied! Proceeding with update.";正如您所看到的,在脚本上,我已经设置了更新的时间是5分钟。然后,在5分钟的时间内,每10秒调用我的AnnounceUpdate端点。我这样做是因为如果我宣布一个5分钟后将发生的更新,然后2分钟后有人连接,他们将不会看到更新消息。在客户端,当客户端收到更新通知时,我将一个名为updatePending的变量设置为true,这样他们就不会继续每10秒收到一条消息。只有尚未看到更新消息的客户端才会收到更新消息。
在租户服务中,我有以下代码:
public async Task AnnounceUpdate(int secondsUntilUpdate, string updateToken)
{
if (updateToken != _apiSettings.UpdateToken) throw new ApiException("Invalid update token");
await _realTimeHubWrapper.AnnouncePendingUpdate(secondsUntilUpdate);
}我只需检查令牌是否有效,然后通过conitnue调用集线器包装器。
集线器包装器是signalR的集线器上下文的实现,它允许在代码中调用signalR方法。更多信息可以阅读https://learn.microsoft.com/en-us/aspnet/core/signalr/hubcontext?view=aspnetcore-6.0#:%7E:text=The%20SignalR%20hub%20is%20the%20core%20abstraction%20for,send%20notifications%20to%20clients%20from%20outside%20a%20hub.。
在集线器包装器中,我有以下方法:
public Task AnnouncePendingUpdate(int secondsUntilUpdate) =>
_hubContext.Clients.All.SendAsync("UpdatePending", secondsUntilUpdate);在客户端,我设置了这个处理程序:
// When an update is on the way, clients will be notified every 10 seconds.
private listenForUpdateAnnouncements() {
this.hubConnection.on(
'PendingUpdate', (secondsUntilUpdate: number) => {
if (!this.updatePending) {
const updateTime = currentTimeString(true, secondsUntilUpdate);
const msToUpdate = secondsUntilUpdate * 1000;
const message =
secondsUntilUpdate < 60
? `The LMS will update in ${secondsUntilUpdate} seconds.
\n\nPlease save your work and close this page to avoid any loss of data.`
: `The LMS is ready for an update.
\n\nThe update will start at ${updateTime}.
\n\nPlease save your work and close this page to avoid any loss of data.`;
this.toastService.showWarning(message, msToUpdate);
this.updatePending = true;
setTimeout(() => {
this.authService.logout(true, null, true);
this.stopConnection();
}, msToUpdate);
}
}
);
}我向客户端显示了一条祝酒词,通知他们更新的消息。然后,我设置了一个超时(使用secondsUntilUpdate__的值),它将记录用户退出并停止连接。这是专门为我的用例。现在你可以做你想做的任何事
总之,逻辑流程是:
PowerShell脚本->控制器->服务->集线器包装器->客户端
主要的方法是,我们仍然需要触发对端点的调用来宣布更新。我很幸运能够在我的发布过程中自动运行它。如果您正在手动发布和复制已发布的代码,那么您可以手动运行PowerShell脚本,然后在完成后进行部署?
https://stackoverflow.com/questions/71677714
复制相似问题