.NET Core部署到linux(CentOS)最全解决方案,进阶篇(Supervisor+Nginx)
<blockquote><p>在.NET Core部署到linux(CentOS)最全解决方案,常规篇一文,我们详细讲解了传统的.NET Core部署到Linux服务器的方法,学到了Linux在虚拟机下的安装、Xshell,Xftp的使用方法、git在linux下的交互使用以及.net core在linux下的发布与运行全过程。本文讲讲解通过使用Supervisor+Nginx的组合来实现.net core的高效部署。</p>
</blockquote>
<h2 id="1supervisor">1、Supervisor</h2>
<h3 id="11supervisor介绍">1.1、Supervisor介绍</h3>
<p>官网:http://supervisord.org,源码位置:https://github.com/Supervisor/supervisor</p>
<p>Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。</p>
<p>它是通过fork/exec的方式把这些被管理的进程当作supervisor的子进程来启动,这样只要在supervisor的配置文件中,把要管理的进程的可执行文件的路径写进去即可。也实现当子进程挂掉的时候,父进程可以准确获取子进程挂掉的信息的,可以选择是否自己启动和报警。supervisor还提供了一个功能,可以为supervisord或者每个子进程,设置一个非root的user,这个user就可以管理它对应的进程。</p>
<h3 id="12为什么要用supervisor">1.2、为什么要用Supervisor</h3>
<p>在linux或者unix操作系统中,守护进程(Daemon)是一种运行在后台的特殊进程,它独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。由于在linux中,每个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端被称为这些进程的控制终端,当控制终端被关闭的时候,相应的进程都会自动关闭。但是守护进程却能突破这种限制,它脱离于终端并且在后台运行,并且它脱离终端的目的是为了避免进程在运行的过程中的信息在任何终端中显示并且进程也不会被任何终端所产生的终端信息所打断。它从被执行的时候开始运转,直到整个系统关闭才退出。</p>
<p>此处的创建守护进程,是指发布在Linux上 asp.net core 程序的dotnet xxx.dll命令的宿主进程创建一个守护进程。在 Linux 上有很多可以管理进程的工具,我们使用 Supervisor 来做这个事情。</p>
<p>原因有两点:</p>
<blockquote>
<p>①、它是微软官方文档推荐的,降低学习成本。<br>
②、它并不一定是最好的,但一定是文档最全的。</p>
</blockquote>
<h3 id="13supervisor4大组件">1.3、Supervisor4大组件</h3>
<ul>
<li>supervisord</li>
</ul>
<blockquote>
<p>主进程,负责管理进程的server,它会根据配置文件创建指定数量的应用程序的子进程,管理子进程的整个生命周期,对crash的进程重启,对进程变化发送事件通知等。同时内置web server和XML-RPC Interface,轻松实现进程管理。。该服务的配置文件在/etc/supervisor/supervisord.conf。</p>
</blockquote>
<ul>
<li>supervisorctl</li>
</ul>
<blockquote>
<p>客户端的命令行工具,提供一个类似shell的操作接口,通过它你可以连接到不同的supervisord进程上来管理它们各自的子程序,命令通过UNIX socket或者TCP来和服务通讯。用户通过命令行发送消息给supervisord,可以查看进程状态,加载配置文件,启停进程,查看进程标准输出和错误输出,远程操作等。服务端也可以要求客户端提供身份验证之后才能进行操作。</p>
</blockquote>
<ul>
<li>Web Server</li>
</ul>
<blockquote>
<p>superviosr提供了web server功能,可通过web控制进程(需要设置配置项)</p>
</blockquote>
<ul>
<li>XML-R- #supervisor</li>
</ul>
<blockquote>
<p>一个Linux/Unix系统上的进程监控工具<br>
一个Python开发的通用的进程管理程序<br>
可以管理和监控Linux上面的进程<br>
能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启<br>
不过同daemontools一样,它不能监控daemon进程</p>
</blockquote>
<h3 id="14安装supervisor">1.4、安装Supervisor</h3>
<p>相应安装建议以管理员方式登录系统,非管理员请以sudo命令安装。</p>
<blockquote>
<p>Linux sudo命令以系统管理者的身份执行指令,也就是说,经由 sudo 所执行的指令就好像是 root 亲自执行。</p>
</blockquote>
<p>1、安装EPEL源的命令如下:</p>
<pre><code class="language-shell">sudo yum -y install epel-release
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118112731096-1456082263.png" alt="安装EPEL源" loading="lazy"></p>
<p>2、执行如下命令安装supervisor:</p>
<pre><code class="language-shell">sudo yum -y install supervisor
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118112752777-708856376.png" alt="" loading="lazy"></p>
<p>3、设置开机启动:</p>
<pre><code class="language-shell">systemctl enable supervisord
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118112807369-1747072090.png" alt="" loading="lazy"></p>
<p>4、启动supervisord</p>
<pre><code class="language-shell">systemctl start supervisord
</code></pre>
<p>5、查看supervisord状态</p>
<pre><code class="language-shell">systemctl status supervisord
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118112818446-456680501.png" alt="" loading="lazy"></p>
<h3 id="15supervisor配置及使用">1.5、Supervisor配置及使用</h3>
<p>通过vi命令或者xftp修改配置文件开启web界面访问,如下图所示,分别取消inet_http_server等四个配置的注释:</p>
<pre><code class="language-shell">vi /etc/supervisord.conf
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118112906372-1385810183.png" alt="" loading="lazy"></p>
<p>执行如下命令,重新加载配置文件:</p>
<pre><code class="language-shell">supervisorctl reload
</code></pre>
<p>然后在浏览器打开http://你的ip:9001,输入上面我们设置的用户名:user1,密码:123456后,如图所示:</p>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118112939683-616822709.png" alt="" loading="lazy"><br>
<img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118112949323-1448546450.png" alt="" loading="lazy"></p>
<p>看到上图这个界面,就表示supervisor安装完成了。</p>
<p>切换到/etc/supervisord.d目录,在此目录创建名称为:core50test.ini的ini文件,内容如下:</p>
<pre><code class="language-ini">#表示程序名称,用于在supervisor中显示,无特殊意义。
# 输入执行命令,这里表示执行的是dotnet Core50Test.dll
command=/bin/bash -c "dotnet Core50Test.dll"
# 应用程序根目录
directory=/root/app_data/core50test/publish
# 是否自动启动,当 supervisor 加载该配置文件的时候立即启动它
autostart=true
# 是否自动重启, 程序异常退出后自动重启
autorestart=true
# 该配置文件输出单个日志文件的大小,默认50M
logfile_maxbytes=50MB
# 日志备份个数
logfile_backups=10
# 记录日志级别
loglevel=info
# 指定标准输出日志文件
stdout_logfile=/root/app_data/data/logs/core50test/core50test.out.log
# 环境变量
environment=ASPNETCORE_ENVIRONMENT=Production
# 启动服务的用户
user=root
# 把stderr重定向到stdout,默认 false
redirect_stderr=true
</code></pre>
<p>上述代码包含了注释信息,参考精減版配置如下:</p>
<pre><code class="language-ini">
command=/bin/bash -c "dotnet Core50Test.dll"
directory=/root/app_data/core50test/publish
autostart=true
autorestart=true
logfile_maxbytes=50MB
logfile_backups=10
loglevel=info
stdout_logfile=/root/app_data/data/logs/core50test/core50test.out.log
environment=ASPNETCORE_ENVIRONMENT=Production
user=root
redirect_stderr=true
</code></pre>
<p><strong>注意</strong>:stdout_logfile指向的文件夹一定要先创建,否则无法启动,上述配置文件中的内容需要根据用户实际情况修改,如我当前登录的用户是:<strong>yonghu</strong>,你们是其他的就做相应的修改即可。</p>
<p>然后执行如下命令来重新加载配置:</p>
<pre><code class="language-shell">supervisorctl reload
</code></pre>
<p>命令执行成功后, 刷新浏览器,可以看到如下界面:</p>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113008563-577318012.png" alt="supervisor正在运行的应用" loading="lazy"></p>
<p>当界面显示running时,则表示我们我们刚刚配置的.net core应用运行起来了。</p>
<p>如下图所示。</p>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113025525-246560634.png" alt="" loading="lazy"></p>
<p>我们可以方便的通过supervisor提供的web管理界面对我们的应用进行启动与停止,查看日志等操作,非常的方便,丝般润滑般的爽呀。</p>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113041841-782062475.png" alt="Supervisor启动与停止应用" loading="lazy"></p>
<p>查看日志:</p>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113056535-44862685.png" alt="" loading="lazy"></p>
<h3 id="16supervisor常用命令">1.6、Supervisor常用命令</h3>
<pre><code class="language-shell">### 查看supervisorctl支持的命令
# supervisorctl help
default commands (type help <topic>):
=====================================
add exit openreloadrestart start tail
availfg pid removeshutdownstatusupdate
clearmaintailquitrereadsignal stop version
### 查看当前运行的进程列表
# supervisorctl status
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113113069-1982285436.png" alt="" loading="lazy"></p>
<ul>
<li>
<p>update 更新新的配置到supervisord(不会重启原来已运行的程序)</p>
</li>
<li>
<p>reload,载入所有配置文件,并按新的配置启动、管理所有进程(会重启原来已运行的程序)</p>
</li>
<li>
<p>start xxx: 启动某个进程</p>
</li>
<li>
<p>restart xxx: 重启某个进程</p>
</li>
<li>
<p>stop xxx: 停止某一个进程(xxx),xxx为里配置的值</p>
</li>
<li>
<p>stop groupworker: 重启所有属于名为groupworker这个分组的进程(start,restart同理)</p>
</li>
<li>
<p>stop all,停止全部进程,注:start、restart、stop都不会载入最新的配置文</p>
</li>
<li>
<p>reread,当一个服务由自动启动修改为手动启动时执行一下就ok</p>
</li>
</ul>
<p>最常用的几个命令为:</p>
<pre><code class="language-shell">#启动所有
supervisorctl start all
# 重启所有
supervisorctl restart all
# 停止所有
supervisorctl stop all
#PS:要操作某个服务,把all换成服务名即可
#查看服务状态
supervisorctl status
</code></pre>
<h2 id="2使用nginx">2、使用Nginx</h2>
<p>在前面文章中,我们已经可以非常方便的对web应用进行部署与管理了,但还存在一个问题,我们的应用程序默认是绑定的5000端口,如果要指定80端口或者配置域名该怎么处理呢?下面就该nginx登场了。</p>
<h3 id="21nginx介绍">2.1、Nginx介绍</h3>
<p>Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。</p>
<h3 id="22nginx安装">2.2、Nginx安装</h3>
<p>安装方式参考:http://nginx.org/en/linux_packages.html#RHEL-CentOS</p>
<p>安装先决条件:</p>
<pre><code> sudo yum install -y yum-utils
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113137664-58436559.png" alt="" loading="lazy"></p>
<p>设置yum存储库,先创建一下内容的文件:/etc/yum.repos.d/nginx.repo</p>
<pre><code class="language-shell">
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113151275-1876837436.png" alt="" loading="lazy"></p>
<p>默认情况下,使用稳定 nginx 包的存储库。如果要使用主线 nginx 包,请运行以下命令:</p>
<pre><code class="language-shell"> yum-config-manager --enable nginx-mainline
</code></pre>
<p>运行如下命令安装nginx:</p>
<pre><code class="language-shell"> sudo yum install -y nginx
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113201372-895008167.png" alt="" loading="lazy"></p>
<p>设置开机启动:</p>
<pre><code class="language-shell">systemctl enable nginx
</code></pre>
<p>启动nginx:</p>
<pre><code class="language-shell"> systemctl start nginx
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113223514-124050883.png" alt="" loading="lazy"></p>
<p>此时,就可以在浏览器通过ip访问了:http://你的ip,界面如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113235056-1714793727.png" alt="" loading="lazy"></p>
<h3 id="23nginx部署">2.3、Nginx部署</h3>
<p>nginx安装完成后,切换到/etc/nginx/conf.d目录,修改default.conf文件内容,如下所示:</p>
<pre><code>server {
listen 80;
server_namelocalhost;
location / {
proxy_pass http://0.0.0.0:5000;
}
error_page 500 502 503 504/50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
</code></pre>
<p>保存后,执行如下命令,重新加载配置:</p>
<pre><code>nginx -s reload
</code></pre>
<p>然后再次访问http://你的ip,一切正常的话应该可以看到如下的界面,表示我们的.NET Core程序已经完美运行在linux系统了。</p>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113251394-1332694153.png" alt="" loading="lazy"></p>
<p>如果部署后遇到类型下面这样的错误</p>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113303472-1704853412.png" alt="" loading="lazy"></p>
<p>出现这样的问题,有可能的是因为SeLinux的限制,执行如下命令之后,再刷新页面:</p>
<pre><code>setenforce 0
</code></pre>
<blockquote>
<p>selinux(security enhanced linux)安全增强型linux系统,它是一个linux内核模块,也是linux的一个安全子系统。</p>
<p>selinux的主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则)</p>
</blockquote>
<p>如果设置后还是不能解决,可以查看nginx的日志了,默认的日志路径为:/var/log/nginx</p>
<p>通过<strong>setenforce 0</strong>命令,只是临时实效,重启后会失效。</p>
<p>可以通过修改/etc/selinux/config 文件,将<strong>SELINUX=enforcing改为SELINUX=disabled</strong>,然后重启,即可永久生效。</p>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113340201-356613393.png" alt="" loading="lazy"></p>
<p>通过近两篇文章的介绍,我们需要更新应用,只需要将代码提交到git仓库,然后在服务器中执行git pull和dotnet publish即可。</p>
<p>如果熟悉shell的话,可以通过编写shell命令一键执行应用程序的更新,代码示例:</p>
<pre><code class="language-shell"># !/bin/bash
cd /root/app_data/source/core50test
git pull
dotnet publish -o /root/app_data/core50test/publish
supervisorctl restart core50test
</code></pre>
<p>将上述的代码保存为sh文件,上传到服务器,并设置权限。如下图所示:</p>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113354657-1968485182.png" alt="" loading="lazy"></p>
<p>代码提交到git仓库后,执行如下命令:</p>
<pre><code>./build.sh
</code></pre>
<p>执行结果如下图所示:</p>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113406846-288575783.png" alt="" loading="lazy"></p>
<p>更新后重新运行,已经更新。</p>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113429424-1536716996.png" alt="" loading="lazy"></p>
<p>这儿可能有的小伙伴会遇到一个小小的坑要注意,shell脚本写得没有问题,执行会报类似这样的错误</p>
<pre><code class="language-shell">$'\r':command not found
</code></pre>
<p>出现这种问题是因为windows下的文件换行用的是\r\n,而linux系统用的是\n,如果在win下的文档上传到linux,就有可能出现这样的问题,只需用vi打开shell脚本文件,然后使用命令:set ff=unix,保存文件即可。</p>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210118113503981-1709677708.png" alt="" loading="lazy"></p>
<p>supervisor一个作为守护线程,用于维护应用程序的生命周期的,nginx则是作为反向代理使用,配置shell可以做到高效部署,非常的方便。</p>
<hr>
<p>一路走来数个年头,感谢RDIFramework.NET框架的支持者与使用者,大家可以通过下面的地址了解详情。</p>
<p>RDIFramework.NET官方网站:http://www.rdiframework.net/</p>
<p>RDIFramework.NET官方博客:http://blog.rdiframework.net/</p>
<p>特别说明,框架相关的技术文章请以官方网站为准,欢迎大家收藏!</p>
<p>RDIFramework.NET框架由海南国思软件科技有限公司专业团队长期打造、一直在更新、一直在升级,请放心使用!</p>
<p>欢迎关注RDIFramework.NET框架官方微信公众号(微信号:<strong>guosisoft</strong>),及时了解最新动态。</p>
<p>使用微信扫描二维码立即关注</p>
<p><img src="https://img2020.cnblogs.com/blog/157572/202101/157572-20210111113503341-2082613464.png" alt="微信号:**guosisoft**" loading="lazy"></p>
</div>
<div id="MySignature" role="contentinfo">
<span style="font-size:10pt;">
</span>
<p>
<br />
</p>
<p style="background-color:#f8f8ee;font-family:微软雅黑;font-size:12px;" id="mySignature">
<span style="font-size:10pt;">作者:</span>
<strong>
<span style="color:red;font-size:12px;">
<span>
<span style="font-size:10pt;">RDIF</span>
</span>
</span>
</strong>
<br />
<span style="font-size:10pt;">出处:</span>
<span style="font-size:10pt;">http://www.cnblogs.com/huyong/</span>
<br />
<span style="font-size:10pt;">Email:</span>
<span style="font-size:10pt;">406590790@qq.com</span>
<br />
<span style="font-size:10pt;">QQ:</span>
<span style="font-size:10pt;">406590790</span>
<br />
<span style="font-size:10pt;">微信:</span>
<span style="font-size:10pt;">13005007127(同手机号)</span>
<br />
<span style="font-size:10pt;">框架官网:</span>
<span style="font-size:10pt;">http://www.guosisoft.com/</span>
<span style="font-size:10pt;">http://www.rdiframework.net/</span>
<br />
<span style="font-size:10pt;">框架其他博客:</span>
<span style="font-size:10pt;">http://blog.csdn.net/chinahuyong</span>
<br />
<span style="font-size:10pt;">http://www.cnblogs.com/huyong</span>
<br />
<span style="font-size:10pt;">国思RDIF开发框架</span>
,
<span style="font-size:10pt;color:#FFFFFF;background-color:#009900;">给用户和开发者最佳的.Net框架平台方案,为企业快速构建跨平台、企业级的应用提供强大支持。</span>
<br />
<span style="font-size:10pt;">关于作者:系统架构师、信息系统项目管理师、DBA。专注于微软平台项目架构、管理和企业解决方案,多年项目开发与管理经验,曾多次组织并开发多个大型项目,在面向对象、面向服务以及数据库领域有一定的造诣。现主要从事基于</span>
<span style="font-size:10pt;">RDIF</span>
<span style="font-size:10pt;">框架的技术开发、咨询工作,主要服务于金融、医疗卫生、铁路、电信、物流、物联网、制造、零售等行业。</span>
<br />
<span style="font-size:10pt;">如有问题或建议,请多多赐教!</span>
<br />
<span style="font-size:10pt;">本文版权归作者和CNBLOGS博客共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,如有问题,可以通过微信、邮箱、QQ等联系我,非常感谢。</span>
</p><br><br>
来源:https://www.cnblogs.com/huyong/p/14291930.html
頁:
[1]