掘金 后端 ( ) • 2024-05-07 10:41

theme: channing-cyan

梦琪1.jpg

背景

Flutter APP交付前,因为逐渐接入部分生产数据进行测试,开发与生成环境分离迫在眉睫。从访问限制、启动方式、配置差异等方面优雅分离环境。先后应用两个方案的实践,最终应用了侵入性最小的方案。

方案一(配置文件分离)

根据网上提供的方案,把main.dart配置文件拆分成两个,一个应用于开发环境、一个应用于生产环境。启动方式变更为:

  • flutter run --no-sound-null-safety --debug -t lib/main_dev.dart -v
  • flutter run --no-sound-null-safety -t lib/main.dart -v

这样的方式完成了分离需求。还可以再进一步简化输入指令。使用IDE的功能:如果你在使用如VSCode这样的IDE进行开发,你可以通过修改launch.json文件来指定在调试时使用的文件。例如,你可以将"args":["-t","lib/main_dev.dart"]添加到launch.json文件的configurations数组中,以便在调试时使用main_dev.dart文件。

使用一段时间后发现了一些问题。

  • 业务开发中配置改造需要同时修正main_dev.dart/main.dart两个文件,分离影响到业务开发
  • 即使简化过指令,和之前启动指令差距大,开发容易输错指令

能否精确区分出开发环境和生产环境配置上的差异,最小程度入侵业务。并且保持指令的简洁,维持开发人员固有习惯?方案二由此诞生 078D8523.png

方案二(精准配置分离)

启动文件main.dart中根据原生包foundation.dart提供的Flutter运行模式来区分环境。

运行模式包括 Debug、Release 和 Profile。其中,Release 模式对应的是优化后的应用程序版本,用于最终发布到用户设备上。

利用运行模式,将开发与生产环境的差异性配置精准分离。配置包含:

  • 日志等级
  • APP标题
  • APP Logo
  • 访问的环境域名
import 'package:flutter/foundation.dart';

  if (kReleaseMode) {
    loggerConfig = LoggerConfig(level: LoggerLevel.info, storageType: StorageType.internal, persistDays: 7);
    runApp(MultiProvider(
        providers: [ChangeNotifierProvider(create: (_) => LoadingProvider(false))],
        child: AppConfig(
            appName: 'xxx',
            apiBaseUrl: "https://wl.xxx.cn",
            wssBaseUrl: "wss://wl.xxx.cn",
            loggerConfig: loggerConfig,
            child: MyApp())));
  } else {
    loggerConfig = LoggerConfig(level: LoggerLevel.debug, storageType: StorageType.external, persistDays: 2);
    runApp(MultiProvider(
        providers: [ChangeNotifierProvider(create: (_) => LoadingProvider(false))],
        child: AppConfig(
            appName: 'xxx测试',
            apiBaseUrl: "https://wl-dev.xxx.cn",
            wssBaseUrl: "wss://wl-dev.xxx.cn",
            loggerConfig: loggerConfig,
            child: MyApp())));
  }

数据隔离

数据隔离采用最基础的域名隔离方式,把对接环境、数据库、配置文件隔离开。 DNS(Domain Name System)是域名系统,提前申请开发域名和生产域名,接入证书。

域名 平台 业务规划 openapi-dev.xxx.cn API开放平台 第三方系统接入 wl.xxx.cn 业务生产环境 wl-dev.xxx.cn 业务开发环境

利用nginx.conf中的include语法导入提前规划的.conf文件。隔离开二级域名、页面、API代理。

For Example (开放平台)

访问域名openapi-dev.xxx.cn,只提供部分开发API。没提供页面路由及私有API /conf/dev/confd/openapi.conf

server {
    listen       443 ssl;
    server_name  openapi-dev.xxx.cn;

    ssl_certificate      /usr/local/nginx/cert/xxx.cn.pem;
    ssl_certificate_key  /usr/local/nginx/cert/xxx.cn.key;

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

    location ~ ^/(openservice|cmpy|auth|admin|order|waybill|bill|message|captcha) {
      proxy_pass https://openservice;
    }
}

nginx.conf

集成/conf/dev/confd/openapi.conf

http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
	
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }
    
    # 集成/conf/dev/confd/openapi.conf
    include ../confd/*.conf;
}

根据系统访问限制,在多个二级域名上规划出各个系统访问入口。在功能、业务、部门等多个维度划分出产品。

数据克隆

数据克隆目的:将生产环境部分数据迁移到开发环境用于Bug复现、日志分析等。

因为环境完全隔离,数据库模型完全一致,只需要简单的SQL操作即可完成。

指令

根据启动方式的不同,优雅区分开启动的环境。

Run APP (默认模式->debug)

flutter run --no-sound-null-safety

打印日志

flutter run --no-sound-null-safety -v

Run (debug模式)

flutter run --no-sound-null-safety --debug

Run (release模式)

flutter run --no-sound-null-safety --release

Build Apk (默认模式->release)

flutter build apk --no-sound-null-safety --split-per-abi

Build Apk (debug模式)

flutter build apk --no-sound-null-safety --debug --split-per-abi

Build Apk (release模式)

flutter build apk --no-sound-null-safety --release --split-per-abi

后记

开发/生产环境分离其实核心旨在访问APIBaseUrl的分离,分离的方式、辐射面的不同对日常开发维护、业务升级、数据迁移等后续诸多场景都会造成或多或少的影响。系统性的考虑分离才能做到优雅分离。