Azure App Service 多容器部署实例

概要

1. 项目结构
2. 构建以及部署
3. 相关链接

项目结构

一个简单的Web应用 – Switches

应用实现了一个可变长度的布尔数组修改存储,并在前端以switch的形式展示。点击switch时发送请求修改数组中某元素值,修改成功后重新获取数组值。
项目使用Angular, .Net Core, Redis, 前后端分离结构。后端连接redis以实现简单存储的功能。

在一个App Service中实现

App Service实例中只需要运行两个容器即.Net Core App以及Redis, 前端打包后的js以静态文件的形式host在Net Core的默认目录下。
核心是Docker Compose的使用,并为.Net Core App,redis两者之间建立连接。

为什么要需要Scaling

AutoScale在应用负载时让适当数量的资源运行。 当负载增加时,添加资源来处理增加的负载;当资源空闲时,删除资源以节省资金。
App Service中存在两种Scaling即Scale Up以及Scale Out。

Scale Up即对整个实例进行扩大,得到更强计算能力的同时也意味着需要付出更多的成本。
Scale Out即对实例的数量进行调整,即时每个实例的大小相同,但处理工作的能力自然随着数量增加而提高

AutoScale只支持Scale out,并能制定复杂的规则自动化调整,对于用户数量不多但并发较高的应用更加友好。

为什么要需要多容器运行

发挥多实例即Scale Out的优势。Scale Out后拥有多个后端实例,多个redis实例。为高并发提供保障。

App Service的Scaling功能以实例为单位,故多容器运行的实例在Scaling时容器运行数量会成倍增长。而且由于自动创建销毁的特性,App Service不适用于存储功能的应用,但我们可以在实例中使用缓存服务来提高应用的响应速度。
例如WordPress的Redis应用。每个实例第一次访问数据库后将数据存储在Redis,下一次获取数据时先检索redis获取,由此减少对数据库的访问。

当然也可以对Redis做持久化的存储,在容器重启时不丢失数据。

构建以及部署

构建.Net Core App

工程简单分为API以及Data两个工程,Data中的RedisService类包含连接Redis,操作Redis的方法。
在StartUp时注册为一个singleton service,注入至Controller实现调用。
API中存在两个接口,获取当前布尔数组值,修改当前数组值。

[HttpGet]
public async Task<string> Get()
{
    return await _redisService.Get(_switchKey);
}

异步调用RedisService中方法并返回结果。

构建Angular App

工程简单分为Service,Components两个部分,Service中使用Anglar HttpClient发送请求,Component中存在一个组件使用多个Switch的状态展示当前数组值。OnChange时获取所有Switch状态作为参数通过注入的Service发起修改请求。
这里修改了build prod时的输出目录为.Net Core App开启静态文件支持后默认的wwwroot目录,即以静态文件的形式serve。

  "scripts": {
    "build:prod": "ng build --prod --output-path=../Switches/wwwroot/",
  }
构建Dock Compose

App service中多容器运行的核心即Dock Compose,
这里首先声明所有需要的容器即.Net Core App以及Redis。
由于.Net Core App在启动时首先尝试连接Redis,但若此时Redis仍未启动,将导致无法连接从而无法正完成startUp。如何解决?使用depends_on字段,使得Redis容器能够先于.Net Core App启动。

version: "3"

services:
  switches:
    container_name: APIServer
    image: "ymhvic/switches"
    depends_on:
      - redis
    restart: always
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "80:80"
      - "443:443"

  redis:
    container_name: redis
    image: "redis:latest"
    restart: always
    ports:
      - "6379:6379"

以此模板启动,宿主机的80以及443端口将映射到.Net Core App容器对应端口,6379映射至Redis。

由于App Service不支持networks字段,这里无法使用内网ip连接
.Net Core App的redis连接字符串如下:

{
    "RedisConnectionString": "redis:6379"
}

可以在下文的git仓库中找到使用networks的Docker compose。
这里附上App Service不支持的Docker compose字段。https://docs.microsoft.com/en-us/azure/app-service/containers/configure-custom-container#configure-multi-container-apps

迭代更新流程

前端修改后build prod输出至wwwroot,后端修改后重新生成镜像push至仓库。
重启app service下载最新镜像即完成新版本的更新。

相关链接

App Service实例
https://switches.azurewebsites.net

ymhvic/Switches镜像仓库
https://hub.docker.com/repository/docker/ymhvic/switches

.Net Core App代码仓库
https://github.com/VictorYMH/Switches