查看: 92|回复: 0

.NET 微服务实践(6)-SQL SERVER

[复制链接]

2

主题

4

帖子

7

积分

新手上路

Rank: 1

积分
7
发表于 2022-9-20 13:19:22 | 显示全部楼层 |阅读模式
文章声明:本文系油管上的一个系列(.NET Microservices – Full Course)教程的学习记录的第五章。不涉及营销,有兴趣看可以原视频[1]。本文分成四部分:持久化卷申领、Kubernetes 密钥配置、部署SQL Server到Kubernetes、更新平台服务。
Kubetnetes持久化

Persistent Volumes Claim xxx

Persistent Volumn xxx

Storage Class xxx

创建持久卷申领

配置yaml文件
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mssql-claim
spec:
  resources:
    requests:
      storage: 100Mi
  accessModes:
    - ReadWriteOnce然后基于yaml文件创建申领卷
>>kubectl apply -f local.pvc.yaml检查结果


默认创建的申领持久卷在xxx
Kubenetes密钥创建

此处将为之后的SQL Server创建账号以及密码。
>>kubectl create secret generic mssql --from-literal=SA_PASSWORD="pa55wOrd!"这里的要点是

  • Secret的名称是mssql
  • Key是SA_PASSWORD
  • Key的Value是pa55w0rd!
在创建SQL Server的yaml文件时会运用到以上的信息
在Kubenetes中创建SQL Server

首先来看下加入SQL Server之后整个微服务的架构



考虑SQL Server之后的整体架构

创建SQL Server的yaml文件

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mssql-depl
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mssql
  template:
    metadata:
      labels:
        app: mssql
    spec:
      containers:
        - name: mssql
          image: mcr.microsoft.com/mssql/server:2017-latest
          ports:
            - containerPort: 1433
          env:
            - name: MSSQL_PID
              value: "Express"
            - name: ACCEPT_EULA
              value: "Y"
            - name: SA_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mssql
                  key: SA_PASSWORD
          volumeMounts:
            - mountPath: /var/opt/mssql/data
              name: mssqldb
      volumes:
        - name: mssqldb
          persistentVolumeClaim:
            claimName: mssql-claim注意事项:

  • deployment的名字时mssql-depl,之后通过kubectl get deployments查看到的就是这个名字
  • 整个deployment会去选择名为mssql的模板(selector app),同时创建了名为mssql的模板(template pp)
  • 名为mssql的模板将创建名为mssql的容器(container name),该容器的镜像地址为http://mcr.microsoft.com/mssql/server:2017-latest,并且配有标签(2017-latest)
  • 容器对外暴露的端口号是1433
  • 容器的环境变量(配置)如下。MSSQL_PID的值为Express,ACCEPT_EULA的值为Y,SA_PASSWORD的值取自名为mssql的secret中的key为SA_PASSWORD的值
  • SQL Server的卷挂载地址为容器所在环境内的地址。这里SQL Server将运行在Linux系统中,所以配置了一个Linux地址。
  • SQL Server使用的持久卷名为mssqldb、和挂载的名字一致(实际上,应该是先设置好持久卷名,然后配置容器的持久卷挂载地址、并确定挂载的卷名)。持久卷申领的名字为mssql-claim、即为之前申领的名字
为SQL Server配置Cluster IP

在加入SQL Server后,为了让其它服务能够访问到SQL Server,需要配置一个Cluster IP。
apiVersion: v1
kind: Service
metadata:
  name: mssql-clusterip-svc
spec:
  type: ClusterIP
  selector:
    app: mssql
  ports:
  - name: mssql
    protocol: TCP
    port: 1433
    targetPort: 1433注意事项:

  • 这里选择的app是mssql、即要创建的mssql容器。
  • Port和Target Port都和容器端口一致。
为SQL Server配置负载均衡

负载均衡 xxx
配置的yaml脚本
apiVersion: v1
kind: Service
metadata:
  name: mssql-loadbalancer
spec:
  type: LoadBalancer
  selector:
    app: mssql
  ports:
  - name: mssql
    protocol: TCP
    port: 1433
    targetPort: 1433部署SQL Server

执行命令
>>kubectl apply -f mssql-depl.yaml


部署SQL Server及关联服务



检查SQL Server关联服务



检查Pods


Docker中也显示SQL Server已经部署完成(app名为mssql,部署名为mssql-depl)
此时,可以通过数据库管理软件(如SSMS)进行登录查看


可以在其中创建一个数据库、并向从中添加一些数据。如果此时删除容器,再打开数据库,数据仍然存在。这是因为数据持久化在主机中、不会被容器或者Pods的生命周期影响。
更新平台服务、连接SQL Server

配置数据库连接字符串

在appsettings.Production.json中,配置数据库的连接字符串
{
  "CommandService": "http://commands-clusterip-svc:80",
  "ConnectionStrings": {
    "PlatformsConn": "Server=mssql-clusterip-svc,1433;Initial Catalog=platformsdb;User ID=sa;Password=pa55w0rd!"
  }
}这里的Server地址就是Cluster IP——使用这个地址是因为一旦平台服务部署好之后,它会同SQL Server一样都在Kubernetes的Node里面。
注入并使用SQL Server

之前平台服务统一使用内存数据库,现在将更新配置,使得在生产环境下使用SQL Server。
首先要引入环境变量,区分开发与生产环境
using Microsoft.Extensions.Hosting;

public Startup(
    IConfiguration configuration, IWebHostEnvironment env)
{
    Configuration = configuration;
    _env = env;
}

private readonly IWebHostEnvironment _env;
然后根据环境注入不同的数据库
public void ConfigureServices(IServiceCollection services)
{
    if (_env.IsDevelopment())
    {
        Console.WriteLine(">>>Using InMem Db");
        services.AddDbContext<ApplicationDbContext>(opt =>
            opt.UseInMemoryDatabase("InMemory"));
    }
    else if (_env.IsProduction())
    {
        Console.WriteLine(">>>Using SQL Server");
        services.AddDbContext<ApplicationDbContext>(opt =>
            opt.UseSqlServer(Configuration.GetConnectionString("PlatformsConn")));
    }
}
这里会从配置文件中读取数据库连接字符串PlatformConn
生成初始化的迁移脚本

一般来说,可以直接调用EF Core的脚本命令(Visual Studio)进行初始化
add-migration InitCreation但是因为在开发环境(默认环境)下使用内存数据库,migration会发生错误。因此,一方面需要在appsettings.Development.json中,配置数据库的连接字符串,另一方面需要在代码中做出临时的修改。
首先是配置文件
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "CommandService": "https://localhost:44345",
  "ConnectionStrings": {
    "PlatformsConn": "Server=localhost,1433;Initial Catalog=platformsdb;User ID=sa;Password=pa55w0rd!"
  }
}这里不同于生产环境的配置,因为对数据库的访问是主机访问Kubernetes,因此要使用localhost作为IP地址。
再是在代码中的临时修改
//if (_env.IsDevelopment())
//{
//    Console.WriteLine(">>>Using InMem Db");
//    services.AddDbContext<ApplicationDbContext>(opt =>
//        opt.UseInMemoryDatabase("InMemory"));
//}
//else if (_env.IsProduction())
//{
//    Console.WriteLine(">>>Using SQL Server");
//    services.AddDbContext<ApplicationDbContext>(opt =>
//        opt.UseSqlServer(Configuration.GetConnectionString("PlatformsConn")));
//}
services.AddDbContext<ApplicationDbContext>(opt =>
    opt.UseSqlServer(Configuration.GetConnectionString("PlatformsConn")));
这样就可以进行migration脚本的生成。
但是还遇到了其它的麻烦,报错内容为
Add-Migration : 无法将“Add-Migration”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。
该问题的解决思路可以参考这两篇文章[2][3]
完成之后,命令行截图如下


可以看到对于之前平台服务创建的模型[4]有对应的migration。
namespace PlatformService.Migrations
{
    public partial class InitialCreation : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "Platforms",
                columns: table => new
                {
                    PlatformId = table.Column<int>(type: "int", nullable: false)
                        .Annotation("SqlServer:Identity", "1, 1"),
                    Name = table.Column<string>(type: "nvarchar(max)", nullable: false),
                    Publisher = table.Column<string>(type: "nvarchar(max)", nullable: false),
                    Cost = table.Column<string>(type: "nvarchar(max)", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Platforms", x => x.PlatformId);
                });
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "Platforms");
        }
    }
}
一旦生成migration脚本之后,就可以取消之前的临时修改。
初始化数据库

在之前的环境中,是对内存数据库进行初始化的。现在同样也要对这部分进行环境的区分,使得在生产环境下,可以初始化SQL Server数据库。
传入环境变量
public static void MockPopulation(IApplicationBuilder app, bool isProduction)
{
    using (var serviceScope = app.ApplicationServices.CreateScope())
    {
        SeedData(serviceScope.ServiceProvider.GetService<ApplicationDbContext>(), isProduction);
    }
}

private static void SeedData(ApplicationDbContext context, bool isProduction)
{ }
外部调用代码为
MockInMemoryDatabase.MockPopulation(app, _env.IsProduction());
然后在SeedData中,针对环境进行初始化区分
if (isProduction)
{
    Console.WriteLine(">>>Attempting to apply migration...");
    try
    {
        context.Database.Migrate();
    }
    catch (Exception ex)
    {
        Console.WriteLine($">>>Cannot run migration: {ex.Message}");
    }
}
这里无须担心,每次初始化平台服务时,都会进行重复进行migration。这是因为migration时会用现有的migrate脚本名字和数据库(连接字符串对应的数据库)中一张名为__EFMigrationsHistory的表中的migrate脚本名字进行比对,如果数据库中不存在现有的migrate脚本,则将进行migration;反之则不会进行。
重新构建平台服务的镜像,并重新部署

该部分可以参考之前的内容[5]
测试平台服务与SQL Server的连接

查看初始化数据


然后在通过创建接口,插入一条新数据


查看全部数据,发现一共有4条数据读取到(中间为了演示,去除了两条数据、使得插入的数据自增长主键跳过4、5,直接为6)


参考


  • ^Youtube视频链接 https://www.youtube.com/watch?v=DgVjEo3OGBI&list=PLpSmZmoBaROZm0ucoQchgBJJ_SyTZWbC0&index=3&t=12301s
  • ^权限配置 https://www.cnblogs.com/pari-Zhong/p/5339028.html
  • ^EFCore模块注入 https://www.cnblogs.com/lbonet/p/9143686.html
  • ^创建平台服务 https://zhuanlan.zhihu.com/p/507220056
  • ^重新部署平台服务 https://zhuanlan.zhihu.com/p/508808719
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表