【Asp.net Core】在 Linux 子系统中安装 nginx 并配置反向代理

时间:2023-03-08 20:21:17

上一篇鸟文中,老周已经介绍过在 Ubuntu 子系统中安装 dotnet-sdk 的方法,本文老周给大伙伴们说说安装 nginx 服务,并配置反向代理。同样,老周假设你从来没有用过 Linux,所以老周会讲得很细。可能因为这样,博客园每次都把老周的文章撤下首页。不管他,他撤他的,我推我的,Who 怕 Who。

其实,你可以选择 nginx 或 Apache,不过老周更喜欢 nginx 一些,总觉得 Apache 有些别扭。当然了,asp.net core 应用是可以独立运行,所以,你确实可以直接公开指向应用程序的 url,而不使用反向代理。不过,官方推荐使用服务器组件来反向代理。

所谓反向代理,说白了就是这样的:客户端发送 HTTP 请求,首先由 nginx 服务收到请求,然后把 HTTP 请求转发给 ASP.NET Core 应用程序,请求处理完后,回应消息也是沿原路返回,从.net 程序发回 nginx,再由 nginx 服务发回客户端。

好,少说 P 话,咱们开始吧。

安装 nginx 服务

在上一篇中,老周说过把软件包更新源(sources.list)更改为国内的源,因为国外的源有时候很慢,而且经常会挂掉。上次老周演示的是使用网易的开源镜像,速度挺快的。现在,咱们执行一下这条命令,这是个好习惯,每次安装软件前,update 一下软件源。

sudo apt update

这条命令仅仅更新软件源,就是你在 sources.list 或 sources.list.d 中配置的源,并不是真正更新软件,要执行软件包更新,可以执行:

sudo apt upgrade

现在,咱们安装一下 nginx。

sudo apt install nginx

【Asp.net Core】在 Linux 子系统中安装 nginx 并配置反向代理

想运行 nginx ,输入以下命令。

sudo nginx

然后,在浏览器中访问 http://localhost,如果看到以下内容,说明你的 nginx 没问题了。

【Asp.net Core】在 Linux 子系统中安装 nginx 并配置反向代理

请你要严重注意,nginx 默认用的是 80 端口,请保证当前没有其他占用 80 端口服务运行,包括 IIS 也不行,如果是 Linux 子系统,它是共用 Windows 的资源的。

配置反向代理

我们要配置的文件在  /etc/nginx/sites-enabled 目录下,有一个 default 文件,我们只要修改它就可以了。

为了避免权限问题,可以先切换到 root 上下文。

su

然后输入你设置的 root 密码就行了。

定位到 /etc/nginx/sites-enabled 目录。

cd /etc/nginx/sites-enabled

然后你可以 ls 一下,你会看到有个叫 default 的文件。

【Asp.net Core】在 Linux 子系统中安装 nginx 并配置反向代理

如果你不放心,可以用 cp default def.bak 备份一下,这里我就不备份了,直接 X 掉它的所有内容。

echo '' > default

上面这条命令老周前面介绍过,这样做可以把文件的内容清空,随后我们用 nano 工具编辑。

nano default

在里面输入以下内容:

server{
listen ;
location /{
proxy_pass http://localhost:15000;
proxy_set_header Host $host;
proxy_http_version 1.1;
}
}

【Asp.net Core】在 Linux 子系统中安装 nginx 并配置反向代理

nginx 可以按照不同的模块进行配置,此处我们需要配置反向代理,即 ngx_http_proxy_module 模块,该模块的字段你不用去记,在 nginx 官方网站可以查到完整文档的。

老周先给你说 nginx 配置的文件模型吧。其实它的格式很像一个 C 风格的类:

<块名称>
{
字段名1 字段值1;
字段名2 字段值2;
字段名3 字段值3;
……
字段名f
{
字段名1 字段值1;
字段名2 字段值2;
……
}
}

首先你要放一个 server 节点。

server{
.......
}

listen 字段表示监听的端口,这个就是 80 了,一般不用改。

接着我们需要一个对路径的配置,即 location,反向代理就是用于转发,所以这个路径咱们就用 / ,表示根目录。

location /{
......
}

然后就是为 location 节点配置几个字段,全部都是以 proxy 开头的。

proxy_pass:这个就是填上咱们 asp.net Core 应用监听的端口,默认是 5000,主机名你直接写 localhost 就可以了,因为由 nginx 反向代理了,dotnet 应用是不对外公开的,所以你不用填网站的域名,客户端发送的请求是先到 nginx 再转发给 dotnet 应用。因此,你只需要让 nginx 服务器对外公开就行了。

proxy_set_header:这个字段是配置当 nginx 收到客户端请求后,把消息转发到 asp.net core 应用时添加的 HTTP 头,这个你可以按实际情况设置,如果你觉得没什么标头有用的,可以不配置。此处我转传了 Host 头,值是变量 $host ,这是一个局部变量,运行时会由 nginx 服务填充具体的主机名。

proxy_http_version:这个是版本号,你也可以忽略的。

说到底,整个配置最关键的是 proxy_pass 字段,只有给它分配了值,nginx 服务才会知道你的 ASP.NET Core 应用在哪监听,才能顺利转发。

输入完后,按 ctrl + o 保存,然后按 ctrl + x 退出。

接着执行一下 -t 参数验证一下上面的配置是否正确。

nginx -t

【Asp.net Core】在 Linux 子系统中安装 nginx 并配置反向代理

如果看到“test is successful”说明配置无误。

随后还要让 nginx 重新加载一下配置,这样才会使之生效。

nginx -s reload

测试效果

下面咱们新建一个 ASP.NET Core 应用项目来测试一下,类型选择“空”就行了,老周喜欢空模板,灵活。

修改 Main 方法,让监听端口指向刚刚上面 nginx 配置中指定的 15000 端口号。

        public static void Main(string[] args)
{
BuildWebHost(args).Run();
} public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseUrls("http://localhost:15000")
.Build();

使用 UseUrls 方法可以指定监听的 URL,当然,你也可以用配置文件(.json)来设置,或者可以指定通配域名 http://*:15000。

然后修改 Startup 类。在 ConfigureServices 方法中,添加 MVC 服务功能。

        public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}

在 Configure 方法中启用 MVC 功能。

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseMvc();
}

注意这两个地方是不同的,前面 AddMvc 只是添加这个功能,并没有启用,所以你随后要通过 Use 方法启用功能,并把与 MVC 相关的中间件插入 HTTP 通信管道中,以处理 HTTP 请求。

咱们这个项目只用来测试人品的,所以老周就不遵守 MVC 的规范了,不建 Views 、Controllers等目录了,反正老周向来都是不按常规出牌的。直接在项目中新建一个类,名字你随便取,按照约定,应该叫 XXXController,当然你也可以不这样叫,叫 Cat,叫 Pig 都行,只要类是从 Controller 类继承,运行时也能认的。

    public class DemoController : Controller
{
[HttpGet("/")]
public IActionResult Start()
{
return View("~/Main.cshtml");
} [HttpPost("/setdata")]
public IActionResult Setdata([FromForm]int a, [FromForm]int b)
{
int r = a + b;
return View("~/Show.cshtml", r);
}
}

注意,类必须是公共的,类的成员也要公共的,不然后面没法用。第一个 action 方法叫 Start,我加了 HttpGet 特性,以 GET 方式访问,并指定了“/”模板,表明你从应用的根 URL 就能执行这个 Start 方法,即输入 http://localhost:15000/,就能访问到。第二个 action 方法名叫 Setdata,HttpPost 表示以 POST 方式访问,路径是 http://localhost:15000/setdata。

Setdata 方法有两个参数,a和b。我给它们加了 FromForm 特性,啥意思呢,就是说客户端页面的 <form> 元素 POST 上来的内容中,一定要包含叫 a 和 b 的两个字段,这样参数 a 和 b 就会自动获取到值了。比如,客户端 POST 上来的是 a=5&b=9,那么 Setdata 方法的参数就可以获得值 a = 5,b = 9。

由于这个示例没有建立 Views 文件夹,按照默认的搜规则是找不到视图的,所以这里一定要指定视图的完整文件名。在新建视图页前,先建个布局页,可以作为母板。文件名为 _Layout.cshtml,内容如下:

<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" charset="utf-8" />
<title>@ViewBag.Title</title>
</head>
<body>
<div>
@RenderBody()
</div>
</body>
</html>

RenderBody方法指定,其他视图页一旦套用这个母板页,就会用它的内容替换 RenderBody。

现在咱们新建一个视图页—— Main.cshtml。

@{
Layout = "~/_Layout.cshtml";
} <div>
<div>
<h3>请输入参数</h3>
</div>
<div>
<form method="post" action="/setdata">
<div>
<label for="a">第一个数:</label>
<input type="text" name="a"/>
</div>
<div>
<label for="b">
第二个数:
</label>
<input type="text" name="b"/>
</div>
<div>
<button type="submit">确定</button>
</div>
</form>
</div>
</div>

Layout 属性引用母板页。form 元素的 action 值指向 Setdata 方法,刚刚咱们用 HttpPost 特性定义了它的路径是 /setdata。

下面是第二个视图页—— Show.cshtml。

@{
Layout = "~/_Layout.cshtml";
} @model int <div >
<div >计算结果:</div>
<div>@Model</div>
</div>

使用 @model 指令指定作为当前视图的 Model 属性的类型,这里用的是 int ,为啥呢,还记得 Setdata 方法吗?

        public IActionResult Setdata([FromForm]int a, [FromForm]int b)
{
int r = a + b;
return View("~/Show.cshtml", r);
}

最后一句,在返回视图页的同时,把变量 r 的值也传递进去,它是 int 类型,因此,在 Show.cshtml 页面中应当以 int 类型界定 Model 属性。

在页面上,访问 Model 属性就可以得到传过来的计算结果了。

 <div>@Model</div>

好了,这个示例就完工了,先把这个示例运行起来,接着确保 nginx 已在 Linux 子系统中运行,如果不确定,可以输入

service nginx status

如果看到这个,表示 nginx 正在运行。

【Asp.net Core】在 Linux 子系统中安装 nginx 并配置反向代理

如果 not running 的话,最简单一招,直接输入 nginx 回车,就会运行了。

在浏览器中输入 http://localhost,回车,默认端口是 80,不用输端口号。

如果出现这个,请检查 asp.net core 应用运行了没有。

【Asp.net Core】在 Linux 子系统中安装 nginx 并配置反向代理

我们随便输入两个整数。

【Asp.net Core】在 Linux 子系统中安装 nginx 并配置反向代理

然后提交,就会看到两个整数相加的结果了。

【Asp.net Core】在 Linux 子系统中安装 nginx 并配置反向代理

如此,表明 nginx 已经成功将 HTTP 消息转发了,反向代理就顺利完成了。

好了,吃饭时间到了,今天煮的是牛肉,很久没吃牛肉了,赶紧开饭。

本文示例源码下载地址,请点击这里