ASP.NET Core系统的部署

1. ASP.NET Core网站的发布

我们在开发环境中运行的项目所加载的程序集是为了方便开发工具调试而生成的调试版程序集,运行效率并不高。

因此我们不能直接把项目文件夹下bin/Debug中的程序集部署到生产环境的服务器上。

我们应该创建网站的发布版,创建网站发布版的过程简称为”发布”。

2. 网站部署需要注意的问题

网站发布后生成的程序是可以运行的。

比如我们发布生成以Windows服务器为目标的独立部署模式的程序,然后直接运行生成目录下的WebApplication1.exe,会发现程序能够正常运行。

因为ASP.NET Core内置的Kestrel就是一个跨平台、功能丰富、性能强大的Web服务器。

所以我们使用ASP.NET Core开发的网站不需要像.NET Framework的那样必须部署到IIS服务器下。

ASP.NET Core这样独立部署、自带Web服务器的优势使得它更适合如今的项目开发的需求。

我们也可以发布运行在Linx服务器上的独立部署模式的程序,把生成的程序复制到Linux服务器上,然后在终端上运行程序生成目录下

尽管Kestrel已经强大到足以作为一个独立的Web服务器使用了,但是在比较复杂的项目中,我们仍然不会让Kestrel直接面对终端用户的请求,而是在应用程序和用户之间部署负载均衡服务器。

用户的请求直接到达负载均衡服务器,然后负载均衡服务器再把用户的请求转发给应用程序中的Kestrel。

因为Kestrel中很多操作都需要编写代码来完成,比如配置域名证书、记录日志、URL重写等。

而在Nginx、IIS等服务器中,这些工作不需要我们编写代码,我们只要修改配置文件即可完成这些任务,所以Kestrel对运维工作并不友好。

更重要的是,为了提高系统的可用性,网站目前都是多服务器部署,同样一个网站部署到多台Web服务器上,由负载均衡服务器决定把用户请求转发到哪台服务器。

一个ASP.NET Core网站有很多部署方式。

在Windows下,我们既可以把网站用”进程内托管模型”方式插入IIS管道中运行,以获得更好的性能、更高的操控性,也可以用”进程外托管模型”方式把IIS当成反向代理服务器使用。

当然,在Windows下,我们也可以不使用IIS,而让应用程序的Kestrel直接处理用户请求或处理外部负载均衡服务器转发过来的请求。

在Linux服务器下,我们既可以把Nginx等当成反向代理服务器使用,也可以把应用程序部署、运行到容器中,把负载均衡服务器收到的请求转发给容器中的应用程序中的Kestrel来处理。

下面我们讲几个网站部署的重要问题:
问题一:

推荐的部署方式。如果公司有比较好的运维能力,并且系统的复杂度比较高,那么本书作者建议采用Linux作为服务器的操作系统,并且采用容器化部署,让应用程序运行在容器中,用Kubernetes进行容器的管理,这种做法是目前行业的推荐做法,也符合.NET Core的设计初衷。

如果公司没有对容器化研究深入的技术人员,但有技术能力支撑使用Linux服务器,那么可以采用Linux服务器部署网站,然后把外部负载均衡服务器的请求转发到应用程序的Kestrel中。

如果公司没有足够的Linux技术能力,那么可以使用Windows服务器,推荐用进程内托管模型方式来让网站以托管的方式运行在IIS中,因为这样性能更好,而且可以避免编写Windows服务让网站应用程序”随操作系统启动”。

问题二:

HTTPS证书等配置在哪里。

由于HTTPS具有避免运营商劫持、保护通信过程不被窃听等优点,因此现在大部分网站都已经启用HTTPS,微信小程序、IphoneApp等更是要求应用程序的网络接口必须采用HTTPS

对于采用了负载均衡服务器的部署方式来讲,我们一般把证书配置在负载均衡服务器上。

由于HTTPS通信要进行加密和解密,因此启用HTTPS之后网站的内存、CPU压力会增大,如果负载均衡服务器到网站应用程序之间的通信是安全可信的,那么我们在网站应用程序中就不启用HTTPS了,也就是用户到负载均衡服务器是HTTPS通信,而负载均衡服务器到网站应用程序的Kestrel之间是HTTP通信。

如果我们配置了负载均衡服务器到网站应用程序之间采用HTTP通信,那么一定要删掉Program.cs中的UseHttpsRedirection,以避免程序把HTTP请求重定向到HTTPS请求。

问题三:

如何获取客户端的IP地址。

对于启用了负载均衡服务器的网站来讲,由于用户的请求由负载均衡服务器转发给网站应用程序。

因此在网站应用程序看来,请求是负载均衡服务器发出的。

我们在使用HttpContext.Connection.RemoteIpAddress获取客户端的IP地址的时候,获取的其实是负载均衡服务器地址,而非原始的用户IP地址。

大部分负载均衡服务器都支持开启把原始的用户IP地址放到名字为X-Forwarded-For的请求报文头中的设置。

在负载均衡服务器上开启这个设置后,我们只要为应用程序安装ForwardedHeadersMiddleware中间件,这样ASP.NET Core就会把请求报文头中的X-Forwarded-For值应用到HttpContext.Connection.RemoteIpAddress中,因此我们无论是否使用负载均衡服务器,都可以使用HttpContext.Connection.RemoteIpAddress获取客户端的IP地址。

当然,使用HttpContext.Connection.RemoteIpAddress获取用户IP地址的时候,一定要注意X-Forwarded-Fox造假的问题。

防范这种问题的手段有两点需要注意:

  • 如果网站应用程序直接面对用户请求,而没有使用负载均衡服务器的话,就不要启用ForwardedHeadersMiddleware中间件
  • 在面向最终用户的负载均衡服务器上,请设置忽略客户端请求报文头中的X-Forwarded-For
问题四:

程序的更新。

.NET 程序在运行时会锁定DLL等文件,因此如果我们有新版网站应用程序要替换在运行中的版本的时候,操作系统会提示”文件被占用”,从而无法完成替换。

如果网站部署在IIS中,有两种解决方法。

一种方法是我们编写一个内容包含”网站正在更新”的HTML文件,文件名是app_offline.htm,然后把这个文件放到网站的根目录下,当IIS检测到这个文件以后,就会关闭网站,我们就可以覆盖程序进行更新了。

在更新期间,对于新的请求,IIS会把app_offline.htm的内容返回给客户端,因此访问者看到的就是”网站正在更新”这样的提示信息。

当网站完成更新后,我们删除app_offline.htm即可,下一个请求到来后IIS将自动启动并应用。

这种方法比较适合企业内部应用等允许有下线时间的系统,对于互联网网站等不允许有下线时间的系统,我们可以使用.NET6新增的”影子拷贝”(shadow-copying),它允许我们在程序运行时替换程序集。

无论是app_offline.htm还是影子拷贝,它们都只能在IIS中部署网站时使用。

如果我们使用容器+负载均衡服务器的方式来部署网站,只要启动新版网站的容器,然后把旧版网站的容器停止就可以了。

如果我们用Kestrel+负载均衡服务器的方式部署网站,因为我们有多台应用服务器,所以我们可以分批更新,也就是先停止其中一批服务器,对它们的程序进行更新,然后重新启动这些服务器,再停止另一批服务器,对它们的程序进行更新,最后重启这些服务器。

由于我们不是一次性把所有服务器都停止,因此我们的更新操作不会影响用户的访问。

无论采用哪种方式更新网站,只要我们用负载均衡服务器把用户请求转发给多台网站服务器,就会存在新旧版网站同时运行的短暂时间,甚至有可能来自同一个用户的属于同一个业务流程的两个连续请求分别被新旧版两个程序处理。

因为我们在编写新系统的时候,要考虑规避这样的短时间内新旧版程序共存导致的逻辑混乱问题。

订阅评论
提醒
0 评论
最旧
最新 最多投票
内联反馈
查看所有评论
滚动至顶部