热更新部署


1. 背景

当 ASP.NET Core 应用在 Windows 上运行时,二进制文件被锁定,因此无法对其进行修改或替换。每次发布API都需要停止站点或者关闭程序池。不是很方便,好在.net提供了解决方案: ShadowCopy允许在应用运行时通过复制程序集来更新应用程序集。解决.netCore IIS站点发布时提示文件占用

1. 什么是 Shadow Copy?

Shadow Copy 是一种技术,用于创建文件或应用程序的副本,而不影响其原始版本。在 .NET 中,它允许应用程序在运行时加载程序集的副本,从而避免锁定原始文件。这在开发和部署场景中非常有用,因为它允许对程序集进行更新而不影响正在运行的应用程序实例。

 

2. Shadow Copy 的应用场景

  1. 热更新: 允许在不重启应用程序的情况下更新程序集。
  2. 单元测试: 在测试环境中加载程序集副本,避免测试代码影响生产代码。
  3. 插件系统: 在插件系统中加载独立的插件程序集,防止插件更新或卸载时影响主应用程序。

3. .net core 7中启用 ShadowCopy

ShadowCopy是通过自定义 web.config 中的 ANCM 处理程序设置来启用的:

XML 全选
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <remove name="aspNetCore"/>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified"/>
    </handlers>
    <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".logsstdout">
      <handlerSettings>
        <handlerSetting name="enableShadowCopy" value="true" />
        <!-- Ensure that the IIS ApplicationPool identity has permission to this directory -->
        <handlerSetting name="shadowCopyDirectory" value="../ShadowCopyDirectory/" />
      </handlerSettings>
    </aspNetCore>
  </system.webServer>
</configuration>

processPath arguments 这两个参数要替换掉, 否则站点启动不了:

processPath="dotnet" arguments="JOCAPI.Start.dll"

arguments 这个参数要替换成自己的项目启动项。

参考:https://learn.microsoft.com/zh-cn/aspnet/core/host-and-deploy/iis/advanced?view=aspnetcore-7.0#shadow-copy

 

JOCAPI的web.config配置信息如下,直接复制即可:

C# 全选
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath=".\JOCAPI.Start.exe" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" >
     <handlerSettings>
        <handlerSetting name="enableShadowCopy" value="true" />
        <!-- Ensure that the IIS ApplicationPool identity has permission to this directory -->
        <handlerSetting name="shadowCopyDirectory" value="../ShadowCopyDirectory/" />
      </handlerSettings>
    </aspNetCore>
    </system.webServer>
  </location>
</configuration>
<!--ProjectGuid: 55982b09-7bd9-4c40-bb4d-b7257229f14f-->

 

4. 效果

配置完成后,当需要发布API后,无需再手动停止站点或程序池,直接替换dll文件即可,不会再提示文件占用了

目录中会自动生成一个文件夹:ShadowCopyDirectory

热更新部署

自动生成站点更新备份

 

其他参考

https://www.jianshu.com/p/ba86836caeeb

 

EF报错

如果把 {app}.deps.json 文件删掉之后, 执行带有 EF 查询的方法, 报了这么一个异常:

PowerShell 全选
System.PlatformNotSupportedException: Strings.PlatformNotSupported_DataSqlClient
   at Microsoft.Data.SqlClient.SqlConnectionStringBuilder..ctor(String connectionString)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.<>c.<get_IsMultipleActiveResultSetsEnabled>b__7_0(String cs)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.get_IsMultipleActiveResultSetsEnabled()
   at Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerCompiledQueryCacheKeyGenerator.GenerateCacheKey(Expression query, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, Expression expression, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.FirstOrDefaultAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)

为解决这个问题, 把发布选项的目标运行时 从 可移植 改为 win-x64, 然后发布, EF 执行正常了..

 

日志文件

日志文件也被复制到了 ShadowCopy 文件夹中去了...
要解决这个问题,只能把所有日志目录指定站点文件外了。
不然真成扫地机器人扫狗屎,糊一地了。。。

 

 

 

 

 

 

 

版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
张国生
评论列表

发表评论

评论内容
昵称:
关联文章

更新部署
YARP+AgileConfig 5分钟实现一个支持配置更新的代理网关
asp.net core mvc修改cshtml试图加载动态更新
Nginx部署
YESWEB项目 生产环境部署
部署服务器的要求清单
window server部署open VPN
.NET Core 项目windows server中部署
《步步入门》 .NET 6 部署到Linux
CentOS7部署OpenVPN服务端
20210913 更新日志
.net Core项目 IIS部署运行异常信息输出
agGrid更新数据applyTransaction无效
YES-CMS 内容管理系统 快速发布与部署
GZDBHelper中Update方法,更新【模型】
npm更新安装包,重新安装
SQL Update更新表数据关联表
局域网共享文件自动更新办法
.NET6中一些常用组件的配置及使用记录,持续更新中。。。
GZDBHelper中Update方法,更新表格数据到数据库