ASP.NET Core在CentOS上的最小化部署实践

引言

本文从Linux小白的视角, 在CentOS服务器上搭建一个Nginx-Powered AspNet Core Web准生产应用。在开始之前,我们还是重温一下部署原理,正如你所常见的.Net Core 部署图:

在Linux上部署.Net Core App最好的方式是使用Kestrel 服务在端口5000上支撑web应用;然后设置Nginx作为反向代理服务器,将输入请求转发给Kestrel服务器, 这个模式称为 边缘代理服务器(edge-origin proxy)。

部署模型优势:

  • 可扩展性:反向代理服务器和Web服务器可以设置在一台或者不同的机器上,为伸缩部署提供可能, 可按需部署多个Web服务器,Nginx反向代理服务器本身可充当优秀的负载均衡器。

  • 数据安全性:edge-origin 模式隐藏了 Web服务器进程的细节,对外只暴露80端口,对外暴露的只有Nginx 反向代理服务器,减少了网络攻击的可能性。

  • 高性能:反向代理服务器可以为后端服务器配置 内容缓存,减少对后端服务器的请求,这是个很重要的性能提升,避免DDOS攻击和暴力恶意攻击。

  • 多功能性:本文虽然是在讲述Linux-only 部署, 这种模式允许你高效、透明地混合使用Linux和Windows服务器,以上Web服务器也可以是 IIS-Powered的Web服务器。

知识准备

首先明确dotnet程序是一个独立进程, 原本可不依赖反向代理服务器运行;
第二明确Nginx反向代理服务器的作用,  这里需要为.NetCore 程序添加必要的转发中间件

// Invoke the UseForwardedHeaders middleware and configure it to forward the X-Forwarded-For and X-Forwarded-Proto headers.
// NOTE: This must be put BEFORE calling UseAuthentication or similar authentication scheme middlewares.
// ref.: https://www.ryadel.com/en/asp-net-core-2-publish-deploy-web-application-linux-centos-tutorial-guide-nginx
app.UseForwardedHeaders(new ForwardedHeadersOptions
{ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

第三明确 dotnet程序需要在Linux系统中以守护进程的方式运行,可使用 supervisor、systemd等管控工具。

CentOS部署

1. 安装环境

sudo rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm
-- rpm是一种软件包管理方式,这里的微软软件包仓库以rpm包的形式提供,包含仓库配置和供发行版认证软件包的公钥,你可以理解为添加了一个nuget包仓库sudo yum update
sudo yum install aspnetcore-runtime-2.2                                
-- yum基于rpm包管理,能够从指定服务器自动下载rpm包并且安装,可自动处理依赖关系,并一次安装所有依赖软件包。

2. dotnet程序发布、测试

  • 使用VS项目右键发布到指定目录

  • 使用zip方式打包

  • 使用scp、SFTP工具上传到Linux服务器, 一般情况下拷贝到var目录

scp D:\production\eqidproxyServer.zip root@10.201.80.126:/var/www   --以下命令将zip包拷贝到 /var/www目录下
  • 在CentOS服务器上解压

unzip -d eqidproxyServer eqidproxyServer.zip
  • 执行dotnet EqidProxyServer.dll

3. 使用systemd将dotnet进程设置成Linux守护进程

完成以上步骤,dotnet程序并不能在后台作为服务运行,Nginx虽然能作为反向代理服务器转发请求到dotnet进程, 但是并不具备管理dotnet进程的能力。

下面使用 systemd来将dotnet进程设定为系统服务。

systemd是一个Linux的系统服务管理器,其作用是提供系统服务依赖管理 、实现系统初始化时服务的并行启动。

① 创建服务文件:vim /etc/systemd/system/kestrel-eqidproxyserver.service

[Unit]
Description=EqidProxyServer deploy on centos[Service]
WorkingDirectory=/var/www/eqidproxyserver/eqidproxyServer
ExecStart=/usr/bin/dotnet /var/www/eqidproxyserver/eqidproxyServer/EqidProxyServer.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
TimeoutStopSec=90
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=root
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false[Install]
WantedBy=multi-user.target

红色背景行是需要你注意配置的,这里我们使用root来执行dll, 一般情况下需要创建一个web账户,并给予项目文件夹owner权限。
下面在root用户组下创建www-data用户,并给予owner权限

 sudo useradd -m -g root www-datasudo chown www-data var/www/eqidproxyserver

注意:Linux 是大小写敏感的文件系统,设定ASPNETCORE_ENVIRONMENT=Production 会在配置文件中搜索如下配置文件:appsettings.Production.json, 故配置和文件名需要留意匹配。

② 启用、启动服务

sudo systemctl enable kestrel-eqidproxyserver.service       // 启用服务
sudo systemctl start kestrel-eqidproxyserver.service        // 指定服务名启动
sudo systemctl status kestrel-eqidproxyserver.service       // 验证服务状态

以下是验证服务状态的输出:

● kestrel-eqidproxyserver.service - EqidProxyServer deploy on centosLoaded: loaded (/etc/systemd/system/kestrel-eqidproxyserver.service; enabled; vendor preset: disabled)Active: active (running) since Thu 2019-02-28 18:04:20 CST; 3min 2s agoMain PID: 52859 (dotnet)Memory: 46.3MCGroup: /system.slice/kestrel-eqidproxyserver.service└─52859 /usr/bin/dotnet /var/www/eqidproxyserver/eqidproxyServer/EqidProxyServer.dllFeb 28 18:06:18 gs-server-5809 dotnet-eqidproxyserver[52859]: info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Feb 28 18:06:18 gs-server-5809 dotnet-eqidproxyserver[52859]: Request finished in 136.6715ms 200
Feb 28 18:06:23 gs-server-5809 dotnet-eqidproxyserver[52859]: info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Feb 28 18:06:23 gs-server-5809 dotnet-eqidproxyserver[52859]: Request starting HTTP/1.1 GET http://127.0.0.1/
Feb 28 18:06:23 gs-server-5809 dotnet-eqidproxyserver[52859]: info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Feb 28 18:06:23 gs-server-5809 dotnet-eqidproxyserver[52859]: Request finished in 3.5599ms 200
Feb 28 18:06:32 gs-server-5809 dotnet-eqidproxyserver[52859]: info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Feb 28 18:06:32 gs-server-5809 dotnet-eqidproxyserver[52859]: Request starting HTTP/1.1 GET http://10.201.80.126/
Feb 28 18:06:32 gs-server-5809 dotnet-eqidproxyserver[52859]: info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Feb 28 18:06:32 gs-server-5809 dotnet-eqidproxyserver[52859]: Request finished in 1.3498ms 200

4. 搭配Nginx部署web程序

① 安装Nginx, 在终端使用curl localhost测试nginx

  sudo yum install nginx      【首次安装需要显式启动:sudo service nginx start】

CentOS安装的nginx并没有作为守护进程运行,执行sudo systemctl enable nginx 启用nginx守护进程

② 配置Nginx作为反向代理服务器

  • 修改/etc/nginx/nginx.conf 文件:sudo vi /etc/nginx/nginx.conf

  • 将80端口请求转发到Kestrel服务(localhost:5000)

server {listen       80;server_name  default_website;root         /usr/share/nginx/html;# Load configuration files for the default server block.include /etc/nginx/default.d/*.conf;location / {proxy_pass         http://localhost:5000;proxy_http_version 1.1;proxy_set_header   Upgrade $http_upgrade;proxy_set_header   Connection keep-alive;proxy_set_header   Host $host;proxy_cache_bypass $http_upgrade;proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header   X-Forwarded-Proto $scheme;}error_page 404 /404.html;location = /40x.html {}error_page 500 502 503 504 /50x.html;location = /50x.html {}}

一旦nginx配置完成,可以使用sudo nginx -t 测试配置文件;
如果配置文件合法,重启nginx (sudo nginx -s reload)
完成以上步骤之后,现在已经可以从127.0.0.1、127.0.0.1:5000、 服务器IP访问web程序。

5.查看进程日志

使用systemd方式管理进程,所有事件和进程都会记录到某个集中日志,该集中日志包含所有被systend管理的服务和进程的日志。(这个日志功能相当于windows服务器中的事件查看器)

查看刚才建立的服务日志, 可使用下面的命令:

sudo journalctl -fu kestrel-eqidproxysever.service
// 时间过滤:
sudo journalctl -fu kestrel-eqidproxysever.service --since "2018-11-18" --until "2019-03-28 04:00"
  • rpm包源:https://docs.microsoft.com/en-us/windows-server/administration/linux-package-repository-for-microsoft-software

  • rpm/yum区别:https://zhuanlan.zhihu.com/p/27724520

  • Linux进程管理:https://linux.cn/article-3801-1.html

关注我们
更多干货及潮流技术

请关注Dotnet Plus公众号

“阅读全文,体验更佳”

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310151.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pearls POJ - 1260(区间记忆化搜索)

题意: n件物品,给出数量和价格,(注意数量和价格都是升序给出的这个是能DP的关键),要买掉所以商品 对于每类物品,所需要的价格是(a[i]10)*p[i] ,即要多买10件,也可以把价格…

[PAT乙级]1006 换个格式输出整数

让我们用字母 B 来表示“百”、字母 S 表示“十”&#xff0c;用 12…n 来表示不为零的个位数字 n&#xff08;<10&#xff09;&#xff0c;换个格式来输出任一个不超过 3 位的正整数。例如 234 应该被输出为 BBSSS1234&#xff0c;因为它有 2 个“百”、3 个“十”、以及个…

bigdecimal 平均数_MapReduce实例-必须用Combine--求平均数

本身求平均数很简单的&#xff0c;必须用到combine的话我在两个地方废了很多时间&#xff0c;一是combine的输入不仅仅是map的输出&#xff0c;还有可能是combine的输出&#xff0c;所以对value的处理得分两种情况吧&#xff1b;二是结果要保留4位有效数字。。。噗&#xff0c;…

面试官:你不懂六大设计原则,回去等通知吧!

一、前言不知道大家是否有这样的体会&#xff0c;就是在学习设计模式的时候&#xff0c;看了很多书籍&#xff0c;也照着很多示例把每个模式挨个敲了几遍&#xff0c;但过了一段时间后&#xff0c;就会忘了一大半。或者有的朋友尝试在业务编码中使用&#xff0c;却越用越复杂&a…

Dollar Dayz POJ - 3181(动态规划+大数高低位分离输出)

题意&#xff1a;就是给出二个数N&#xff0c;和k&#xff0c;有1~k种钱币&#xff0c;每种都 是无限个&#xff0c;用这些种类的钱币可以组合成总钱N有多少种方式。 解题&#xff1a;这就是一个完全背包&#xff0c;把N看成容量&#xff0c;钱币的类型值为 花费和价值。与记录…

[PAT乙级]1007 素数对猜想

让我们定义d​n​​为&#xff1a;d​n​​p​n1​​−p​n​​&#xff0c;其中p​i​​是第i个素数。显然有d​1​​1&#xff0c;且对于n>1有d​n​​是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。 现给定任意正整数N(<10​5​​)&#xff0c;请计…

is this mysql server_Mysql:is not allowed to connect to this MySQL server

如果你想连接你的mysql的时候发生这个错误&#xff1a;ERROR 1130: Host 192.168.1.3 is not allowed to connect to this MySQL server解决方法&#xff1a;1。 改表法。可能是你的帐号不允许从远程登陆&#xff0c;只能在localhost。这个时候只要在localhost的那台电脑&#…

Asp.Net Core Filter 深入浅出的那些事-AOP

一、前言在分享ASP.NET Core Filter 使用之前&#xff0c;先来谈谈AOP,什么是AOP 呢&#xff1f;AOP全称Aspect Oriented Programming意为面向切面编程&#xff0c;也叫做面向方法编程&#xff0c;是通过预编译方式和运行期动态代理的方式实现不修改源代码的情况下给程序动态统…

C++函数模板和普通函数的调用规则

C函数模板和普通函数的调用规则: 普通函数可以进行自动类型转换。 函数模板必须严格类型匹配。 C编译器优先考虑普通函数。 如果函数模板可以产生一个更好的匹配&#xff0c;那么选择模板。 可以通过空模板实参列表的语法限定编译器只能通过模板匹配。 代码如下&#xff…

A Mini Locomotive POJ - 1976(动态规划+思维)

题意&#xff1a;有三个火车头&#xff0c;n个车厢&#xff0c;每个车厢里面对应的有一定的人数。规定每个火车头最多 拉m个连续的车厢而且他们拉的车厢一定是从左到右连续的&#xff0c;问它能够拉的最多的人数&#xff1b; 思路&#xff1a;类似01背包的解法&#xff0c;首先…

mysql如何管理innodb元数据_MySQL 8 InnoDB 集群管理

使用 dba.checkInstanceConfiguration()在添加实例到集群中前&#xff0c;使用该方法检查实例配置是否满足InnoDB 集群要求。使用 dba.configureLocalInstance() 配置实例在MySQL Server版本不支持持久化功能的实例上&#xff0c;需要使用该方法添加修改配置信息到本地实例的选…

c编译过程概述

index.cpp是如何变成index.exe&#xff1f; 过程如下: #mermaid-svg-TCJ1Rm4qFgAObpkX .label{font-family:trebuchet ms, verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-TCJ1Rm4qFgAObpkX .label text{fill:#333}#mermaid-svg-T…

.NET Core技术研究-通过Roslyn代码分析技术规范提升代码质量

随着团队越来越多&#xff0c;越来越大&#xff0c;需求更迭越来越快&#xff0c;每天提交的代码变更由原先的2位数&#xff0c;暴涨到3位数&#xff0c;每天几百次代码Check In&#xff0c;补丁提交&#xff0c;大量的代码审查消耗了大量的资源投入。如何确保提交代码的质量和…

FATE HDU - 2159(二维完全背包)

限制条件&#xff1a; 1.忍耐度 m 2.杀怪个数 s 构造&#xff1a; dp[m][s] 得到的经验值 Time limit 1000 ms Memory limit 32768 kB OS Windows Source 2008信息工程学院集训队——选拔赛 最近xhd正在玩一款叫做FATE的游戏&#xff0c;为了…

mysql数据库check命令_利用mysqlcheck命令快速修复mysql数据库

表索引异常,修复msql表索引(表引擎:myisam)myisamchk --safe-recover /usr/local/mysql/data/ename_news/dede_arccacherepair table customerquestion;Error infos: Table ./ename_news/dede_arccache is marked as crashed and should be repairedmyisamchk -r data/ename_ne…

python中类变量的访问方式_在Python中,如何访问类方法中的“静态”类变量

就像所有的好例子一样&#xff0c;你简化了你实际想要做的事情。这很好&#xff0c;但值得注意的是&#xff0c;python在类和实例变量方面有很大的灵活性。方法也是如此。为了获得很好的可能性&#xff0c;我建议阅读Michael Ftsch new-style classes introduction&#xff0c;…

[PAT乙级]1009 说反话

给定一句英语&#xff0c;要求你编写程序&#xff0c;将句中所有单词的顺序颠倒输出。 输入格式&#xff1a; 测试输入包含一个测试用例&#xff0c;在一行内给出总长度不超过 80 的字符串。字符串由若干单词和若干空格组成&#xff0c;其中单词是由英文字母&#xff08;大小写…

Cheapest Palindrome POJ - 3280(动态规划*)

题意&#xff1a; 给出一个字符串&#xff0c;要求将其修改成一个回文字符串&#xff0c;给出修改某种字母&#xff08;添加或删除&#xff09;的价值&#xff0c;求最小使其成为回文字符串的价值。 题解&#xff1a; 感觉是求最长回文子序列的变形&#xff0c;然而刚开始想着…

Blazor Blazor Blazor

Blazor 项目现在可以说是整个 .NET 社区最火的项目&#xff0c;但是它的起源却非常有趣&#xff0c;也可以说是见证了 .NET 社区的发展。2017年4月&#xff0c;一位英国光头小哥哥开始思考在 WebAssembly 下运行 .NET 的方法&#xff0c;这时他碰巧发现一个之前从未见过的 .NET…

C++函数模板机制结论

函数模板机制结论: 编译器并不是把函数模板处理成能够处理任何类型的函数函数模板通过具体类型产生不同的函数编译器会对函数模板进行两次编译&#xff0c;在声明的地方对模板代码本身进行编译&#xff0c;在调用的地方对参数替换后的代码进行编译。