随着.NET Core 2.0的发布,微软拥有了通用、模块化、跨平台和开源的平台的下一个主要版本,该平台最初发布于2016年。.NET Core已经被创建为拥有很多在目前发布的.NET框架中可用的API。最初创建它的目的是为下一代ASP.NET解决方案提供支持,但是现在成为许多其他场景的基础,包括IoT、云以及下一代移动解决方案。在本系列文章中,我们将探讨.NET Core的优点以及它如何不仅仅有益于传统的.NET开发人员,还有益于所有需要把稳健、高性能和经济的解决方案带入市场的技术人员。
本文是《.NET Core》系列文章的其中之一。您可以通过RSS订阅以接收相关通知。
最感兴趣的.NET Core的特性之一是跨平台支持,无论是在开发期还是在运行期。对于.NET,您不再被限制于Windows。如今,您可以使用Linux和macOS进行开发和运行应用程序。还有,不再要求开发和运行平台相同,因此,您可以在Mac上开发您的.NET Core应用程序,然后部署到Windows和Linux服务器。
微软的云平台Azure
Azure是微软的云平台,能出色地匹配.NET Core应用程序,因为其拥有大量用于托管这些应用程序的基础设施和平台服务,以及广泛的跨平台支持。Azure有一套基础架构服务,提供计算、存储和网络功能,使客户能够像管理传统数据中心的基础架构一样部署虚拟服务器。 这种方法为客户提供对托管应用程序的基础架构和操作系统配置的强大控制。 Azure虚拟机支持多种版本的Windows Server和多种Linux版本,包括Red Hat、CentOS、Suse等。
在把您的.NET Core应用程序部署到Azure之前,您需要在Azure中设置应用程序主机或运行。在Azure中,您可以有很多方法来部署基础架构和服务。最简单容易的入门方法是使用Azure门户网站。从该门户网站,您可以在市场上找到所需的服务,并通过一系列询问向导来配置和部署这些服务。如果您正在配置虚拟机,只要虚拟机处于运行状态了,就可以进行远程管理和配置了,如果运行在Windows中,就使用远程桌面(Remote Desktop);而如果运行在Linux中,则使用SSH。
如果您跟我一样,是个DevOps的粉丝,也许喜欢自己尽可能地编写脚本,这样就可以做到可重复和精简的。Azure资源管理(Azure Resource Manager,简称ARM)模板允许您在Azure中自动部署服务。ARM模板只是简单的JSON文件,定义了您希望部署的资源以及它们之间的关系。这些ARM模板很受欢迎,并且有个GitHub repo,它含有数百个为许多服务、平台和配置准备的预置模板。您可以找到这些模板和这个GitHub repo。
除了部署和配置Azure服务,您还可以使用ARM模板来配置操作系统,以及使用虚拟机扩展来安装其他依赖项。例如,如果您在Ubuntu Linux上设置一个web服务器,您就需要部署Ubuntu Linux虚拟机,然后部署一个像Apache的web服务器。利用自定义脚本虚拟机扩展,您能够在虚拟机完成部署后执行自定义脚本。利用这些自定义脚本,您可以做很多事,像安装其他服务以及类似Apache及PHP的应用程序服务器。您可以在Azure Quickstart模板GitHub repo中看到一个例子,它是用Apache部署Ubuntu Linux服务器ARM模板。在GitHub上呈现的README.md文件中,您可以点击“Deploy to Azure”按钮,如图1所示,以开始把选定模板部署到您的Azure订阅的过程。一旦您拥有web服务器,就可以在Azure中部署和运行ASP.NET Core应用程序了。
图1 – 拥有Apache GitHub README.md的Ubuntu
创建一个ASP.NET Core应用程序
现在是时候创建一个我们可以部署到Azure的.NET Core应用程序了。利用Visual Studio 2017,我使用ASP.NET Core创建了一个简单的web API。由于那个新的Hello World!网络应用程序看起来是个待办事项列表,我就创建了一个待办事项列表API。
首先,我在Visual Studio中创建了一个新项目,选择了web类别和ASP.NET Core Web Application模板,如图2所示。
图2 – Visual Studio 2017 新ASP.NET Core Web Application
创建项目之后,我添加了一个定义属性为待办事项列表的模型类,代码如图3所示。我让它很简单,只创建了id的属性和待办事项列表项的名称,以及一个用于跟踪该项是否完成的布尔量。
public class TodoItem
{
public string Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
}
图3 – TodoItem.cs模型类
在创建数据访问类时,我喜欢使用仓储模式,因此,我为待办事项列表存储库创建了一个接口,如图4所示。这定义了所有我需要用于访问数据的方法,包括一个读取单个待办事项的get方法、一个返回所有待办事项列表项的get方法,还有用于添加、更新和删除待办事项列表项的方法。
public interface ITodoItemRepository
{
TodoItem Get(string id);
IList<TodoItem> Get();
void Add(TodoItem item);
void Update(TodoItem item);
void Delete(string id);
}
图4 – ITodoItemRepository.cs 待办事项列表仓储模式接口
然后,我用实体框架(Entity Framework,简称EF)创建了待办事项列表项目仓储接口的实现,如图5所示。这包括EF上下文类和使用该EF上下文的仓储类。
public class TodoContext : DbContext
{
public TodoContext(DbContextOptions<TodoContext> options)
: base(options)
{
}
public DbSet<TodoItem> TodoItems { get; set; }
}
public class TodoItemRepository : ITodoItemRepository
{
private readonly TodoContext _context;
public TodoItemRepository(TodoContext context)
{
_context = context;
if (!_context.TodoItems.Any())
{
_context.TodoItems.Add(new TodoItem { Name = "Item1" });
_context.SaveChanges();
}
}
public TodoItem Get(string id)
{
return _context.TodoItems.FirstOrDefault(t => t.Id == id);
}
public IList<TodoItem> Get()
{
return _context.TodoItems.ToList();
}
public void Add(TodoItem item)
{
_context.TodoItems.Add(item);
_context.SaveChanges();
图5 – TodoContext.cs和TodoListRepository.cs
最后,我用图6中所示的代码为待办事项列表web API创建了控制器。该控制器只是使用ITodoItemRepository并执行恰当的数据访问方法。
[Produces("application/json")]
[Route("api/Todo")]
public class TodoController : Controller
{
private ITodoItemRepository _repository;
public TodoController(ITodoItemRepository repository)
{
_repository = repository;
}
[HttpGet]
public IEnumerable<TodoItem> Get()
{
return _repository.Get();
}
[HttpGet("{id}", Name = "Get")]
public TodoItem Get(string id)
{
return _repository.Get(id);
}
[HttpPost]
public void Post([FromBody]TodoItem value)
{
_repository.Add(value);
}
[HttpPut("{id}")]
public void Put(int id, [FromBody]TodoItem value)
{
_repository.Update(value);
}
图6 – TodoController.cs Web API控制器
现在,我们已经完成了那些实现待办事项列表web API的类,接下来我们需要为我们的web API做些配置以让它工作。当我们创建web API控制器实现时,我提到我们在用ITodoItemRepository,但是在审查代码后,您也许想知道ITodoItemRepository字段是如何获取实现实体框架的TodoItemRepository实例的。ASP.NET Core具有内置依赖注入容器支持运行时注入实现,并且可以调用Startup.cs中的ISserviceCollection.Add*方法,如图7所示,我们可以把ITodoItemRepository接口与TodoItemRepository类关联起来,因此,无论何时需要一个ITodoItemRepository类型的字段,都可以用TodoItemRepository实现的实例对其进行初始化。在这种情况下,我们使用AddScoped()方法,为每个请求创建一个新实例,并推荐给实体框架。您可以阅读更多有关服务生命周期选项的信息。
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<TodoContext>(opt => opt.UseInMemoryDatabase("TodoList"));
services.AddScoped<ITodoItemRepository, TodoItemRepository>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
图7 – Starup.cs
另一方面,我们需要配置的是实体框架的数据存储。对于我们简单的Hello World!待办事项列表API,我选择使用内存数据库。在图7所示的Startup.cs中,调用IServiceCollection.AddDbContext为实体框架上下文配置内存数据库。
有了这个,您就能够按F5键在本地运行该应用程序了,并且可以使用Visual Studio进行调试。除了在Windows上运行外,您也可以在macOS或Linux OS上运行,然后,您也可以把它部署到Azure中的Windows或Linux 虚拟机。
部署到Azure PaaS
作为开发人员,我们不想操心部署、配置和管理服务器。相反,我们宁愿把时间和精力专注于开发我们的应用程序上。虽然我们可以用底层基础架构服务,但Azure提供了很多高级平台服务,让开发人员专注于其应用程序和数据,从而减少花在设置和配置基础架构上的时间。对于客户来说,也不必一直为操作系统和应用程序服务器打补丁和进行维护了。
Azure应用程序服务(Azure App Service)属于高级平台服务,可以把服务器和基础架构抽象并隐藏起来,只为我们提供一个部署我们网络应用程序的目标。在Visual Studio中,您可以在ASP.NET项目上单击右键,选择Publish选项,如图8所示,以启动把您的网络应用程序部署到Azure应用程序服务中的网络应用程序。
图8 – 高亮显示Publish选项的Visual Studio项目上下文菜单
选择Publish选项后,Visual Studio中的一个屏幕会显示将要提供的几个部署目标选项,其中Azure App Service是该列表上的第一个选项,如图9所示。
图9 – Visual Studio中的发布(Publish)屏幕
如果您选择Azure应用程序服务,可以选择是否要通过“Create New”选项来创建一个全新的网络应用服务,或者可以通过选择“Select Existing”选项,在您的Azure订阅中选择一个现有的网络应用程序。完成之后,可以点击“Publish”按钮以启动通过引导进行部署的流程。这将部署到默认的运行于Windows上的Azure应用程序服务,但是,现在您可以部署到运行于Linux上的Azure应用程序服务,甚至可以使用Docker容器。
在Visual Studio中,您可以轻松地启用Docker容器支持您的ASP.NET Core应用程序,只需要在您的ASP.NET Core项目上单击右键而已,在上下文菜单中选择Add,然后选择Docker Support,如图10所示。
图10 – 把Docker Support添加到ASP.NET Core Apps
然后,Visual Studio会显示一个对话框,让您来选择是否需要Windows或Linux Docker容器。在您选择了平台之后,Visual Studio在您的项目中添加一个Dockerfile,并在包含多个docke-rcompose.yml文件的解决方案资源管理器(Solution Explorer)中添加一个docker-compose节点。
现在,在项目上单击右键选择发布(Publish)时,您会看到一些不同的选择,包括微软Azure应用程序服务Linux和容器注册表(Container Registry),如图11所示。
图11 – 在Visual Studio中的发布(Publish)屏幕,用于Docker支持的ASP.NET Core web应用程序
当您选择微软Azure应用程序服务Linux时,它将引导您完成部署流程,该过程将创建一个运行于Linux上的Azure应用服务程序,并具有docker支持,您也可以选择创建或使用现有的docker容器注册表。
Azure是一个大型云平台,包含很多服务,我已经在本文中提到了像虚拟机这样的基础架构服务,以及像应用程序服务这样的平台服务,但是,在其他应用程序运行时,您还可以在Azure中运行的.NET Core应用程序,包括Azure Functions(无服务器)、Service Fabric(微服务)和Azure Container Service(docker容器)等等。如果您对这些服务感兴趣,可以访问http://www.azure.com以获得更多资讯。
结语
正如我在本文开头所提到的,我最喜欢的.NET Core的特性之一是广泛的平台支持,包括Windows、Linux和macOS。结合Azure,您不仅获得跨平台的开发平台,还可以获得云平台以托管和运行支持很多操作系统(包括Windows Server和多个版本的Linux)的应用程序,并且还有很多高级平台服务,像Azure应用程序服务、Docker容器和拥有Azure Functions的无服务器计算。这种能力令人非常兴奋,并通过提供广泛的生态系统支持和开放性提供了很多可能性。
作者简介
阅读英文原文:https://www.infoq.com/articles/azure-and-net-core