服务模块规范

服务模块概述

  • 每个微服务应用中可以包含多个服务模块。
  • 每个微服务应用的资源根目录是 model ,在 model/service 目录中包含了当前微服务应用的所有服务模块,服务模块目录不允许嵌套。

服务模块基本组成

目录和文件 类型 说明
model/service/{serviceName} dir 服务主目录
model/service/{serviceName}/deploy.m file 服务目录标识文件
model/service/{serviceName}/app.m file 服务网关注册文件
model/service/{serviceName}/deploy dir 服务定义目录
model/service/{serviceName}/deploy/*.def.xml file 服务定义文件
model/service/{serviceName}/deploy/*.sh file 自定义脚本文件
model/service/{serviceName}/dist dir 服务资源目录,例如:war、jar

服务目录标识文件 deploy.m

deploy.m 文件用于标识当前目录是服务模块目录,例如:model/service/app1/deploy.m 表示需要部署一个服务名为 app1 的服务,缺省的 deploy.m 文件是一个空文件。

服务网关注册文件 app.m

app.m 用于配置代理网关,每个 app.m 对应在网关上配置的一个接口.根据需要可以通过子目录创建多个 app.m 来实现在网关上配置多个接口,目录名不限,例如:

  • model/service/{serviceName}/app.m
  • model/service/{serviceName}/root/app.m
  • model/service/{serviceName}/…/app.m
<?xml version="1.0" encoding="UTF-8" ?>
<service>
    <!-- 接口名 -->
    <name>davinci</name>
    <!-- 接口路由配置 -->
    <request_path>/davinci</request_path>
    <preserve_host>true</preserve_host>
    <strip_request_path>false</strip_request_path>
    <upstream_url>http://localhost:8787</upstream_url>
    <!-- 接口插件配置 -->
    <plugin name="authentication" enabled="false">
        <app_key>{{.Env.API_KEY}}</app_key>
        <app_secret>{{.Env.API_SECRET}}</app_secret>
    </plugin>
    <plugin name="health-check" enabled="true">
        <health_url>/davinci</health_url>
    </plugin>
</service>

服务定义文件 *.def.xml

服务在开发调试环境部署运行环境下有不同的服务定义文件,分别对应架构设计工具中的开发架构运行架构(kube或pool)。 一般服务环境定义文件有以下几个:

文件 说明
dev.def.xml 开发调试环境定义文件
production.def.xml 默认的部署运行环境服务定义
production.kube.def.xml 部署运行环境 kube 部署的服务定义,如果此文件存在,优先级高于默认的 production.def.xml
production.pool.def.xml 部署运行环境 pool 部署的服务定义,如果此文件存在,优先级高于默认的 production.def.xml

服务定义文件 *.def.xml 包含: properties 服务属性定义、uses 服务引用定义 和 spec 服务部署定义 三个部分。

<service>
  <!-- 服务属性定义 -->
  <properties>
    <property name="serviceAddress" value="${appsvc.serviceAddress}" readonly="true">
      <label label = "服务地址"/>
    </property>
    <property name="port" value="${appsvc.port}" readonly="true">
      <label label = "端口(port)"/>
        </property>
    <property name="dbType" value="${db.dbType}" readonly="true">
      <label label = "数据库类型"/>
    </property>
    <property name="dbHost" value="${db.dbHost}" readonly="true">
      <label label = "数据库服务地址"/>
    </property>
    <property name="dbPort" value="${db.dbPort}" readonly="true">
      <label label = "数据库端口"/>
    </property>
    <property name="dbUser" value="${db.dbUser}" readonly="true">
      <label label = "数据库用户名"/>
    </property>
    <property name="dbPasswd" value="${db.dbPasswd}" readonly="true">
      <label label = "数据库密码"/>
    </property>
    <property name="dbName" value="${db.dbName}" readonly="true">
      <label label = "数据库名称"/>
    </property>
    <property name="dbSchema" value="${db.dbSchema}" readonly="true">
      <label label = "dbSchema"/>
    </property>
    <property name="dbProperties" value="${db.dbProperties}" readonly="true">
      <label label = "dbProperties"/>
    </property>
    <property optional="true" name="dbextSharding" value="${db.dbextSharding}" readonly="true">
      <label label = "sharding"/>
    </property>
  </properties>
  <!-- 服务引用定义 -->
  <uses>
    <use name="db" instance="database"></use>
    <use name="minio" instance="minio"></use>
  </uses>
  <!-- 服务部署定义 -->
  <spec platform="app-container">
    <option name="name" value="appsvc" />
    <option name="instance" value="tomcat" />
  </spec>
</service>

服务属性定义 properties

服务属性使用 properties/property 定义,用于定义服务的配置属性和环境变量,例如: 地址、端口、用户名、密码、数据连接等。 每个 property 定义默认生成 ${serviceName}_${propertyName} 的环境变量(全大写,减号替换为下划线),可以在 property 上通过 env 属性控制环境变量的命名,env="-" 表示不产生环境变量。 说明:这里的环境变量就是服务运行时的环境变量,在 java 中可以通过 System.getenv 函数获取。

property 的属性关键字 说明
name 属性名
value 属性值
readonly true / false(默认值),是否只读属性,指在架构设计工具中属性值是否只读
optional true / false(默认值),是否可选属性,可选属性的属性值如果无效则不生成环境变量,代码中可以通过判断环境变量是否存在执行不同的逻辑
env 指定环境变量名称,- 表示不产生环境变量
output true / false(默认值),是否自动输出属性,自动输出属性会在引用的服务中自动生成对应的属性定义
tag 标签,用于定义和区分同一类的属性

property / value 可以使用的系统变量 说明 适用服务
@serviceName@ 服务逻辑名称 所有服务
@serviceAddress@ 容器内部的服务访问地址 定义了yaml的服务
@containerName@ 容器名称 定义了yaml的服务
@justepHomeDir@ justep home 目录 所有服务
@appId@ 应用ID 所有服务
@apiKey@ apiKey 所有服务
@apiSecret@ apiSecret 所有服务
@domainPrefix@ 应用域名前缀 所有服务
@baseDomain@ 应用域名 所有服务
@indexUrl@ app.conf中定义的 index_url 所有服务
@pcindexUrl@ app.conf中定义的 pc_index_url 所有服务
@mindexUrl@ app.conf中定义的 m_index_url 所有服务
@adminUrl@ app.conf中定义的 admin_url 所有服务
@tenantId@ 租户ID 所有服务
@appHttpPort@ 应用http端口 所有服务
@appHttpsPort@ 应用https端口 所有服务

property / value 可以使用的系统函数 说明 适用服务
@systemAdminUser()@ 系统管理用户名 所有服务
@systemAdminPasswd()@ 系统管理密码 所有服务
@jdbcDriver(\'dbName\' )@ 从数据库定义生成 jdbc driver 所有服务
@jdbcUrl(\'dbName\' )@ 从数据库定义生成 jdbc url 所有服务
@env(\'envName\' )@ 访问环境变量 所有服务
@redisAllocKey(\'name\' )@ 生成redis分配键 所有服务

服务引用定义 uses

服务引用使用 uses/use 定义,用于定义服务之间的引用关系。 服务引用后,在服务的属性定义中就可以通过 ${serviceInstance.property} 引用其他服务的属性来配置当前服务的属性值.

use 的属性关键字 说明
name 引用后的别名
instance 引用的服务实例
optional true / false(默认值),是否可选引用
可选服务引用和可选属性

在某些应用场景下,服务A对服务B的引用关系不是强制要求的,B是否存在,不影响A的正常运行,仅影响到A的执行逻辑。针对这种场景,服务定义允许定义可选的服务引用和属性。

<!-- 可选引用 -->
<uses>
  <use optional="true" name="dbproxy" instance="comp.dbproxy"></use>
</uses>

对于所有声明的可选服务引用 {name} ,有一个系统属性 @{name}Exists@ 用于获取目标服务是否存在的值, true/false。这个系统属性可用于定义引用端的property。

<!-- 可选属性 -->
<property name="dbproxyExists" value="@dbproxyExists@"  readonly="true">
  <label label = "dbproxy 是否存在"/>
</property>

应用运行时可读取 Exists 环境变量,根据环境变量的值分别处理目标服务存在和不存在的逻辑。 关于可选引用的 property,有以下特殊规则:

  1. 通过可选引用引入的服务定义的 property,具备可选特性
  2. 可选 property 具备传递性,一个 property 如果引用了可选 property,也具备可选特性,例如 A.a 引用了 B.b,如果 B.b 具备可选特性,那么 A.a 也具备可选特性
  3. 具备可选特性的 property,如果服务不存在,该 property 在模型解析时被忽略,也不会生成环境变量。
  4. 由于容器的 yaml 定义不具备条件判断的能力,所以具有可选特性的 property,不允许用于容器的yaml中。 除了上述4点外,其它特性与普通的 property 一致。

服务部署定义 spec

服务部署使用 spec 定义,用于定义服务的部署方式。

  • <spec platform="docker-compose"/> 说明这是一个通过容器镜像部署的服务
  • <spec platform="app-container"> 说明这是一个部署到运行容器的服务

服务部署定义的参数通过 option 子节点定义:

option name option value
name 运行容器的别名,在属性定义中可以通过别名引用容器实例的属性值
value 运行容器实例,tomcat、nginx、java-runtime、node-runtime...
container 运行容器类型,java、nginx、nodejs...
deploy true(默认值)/ false,是否部署 dist 资源
<!-- 容器镜像 -->
<spec platform="docker-compose" />
<!-- Java Tomcat -->
<spec platform="app-container">
  <option name="name" value="appsvc" />
  <option name="instance" value="tomcat" />
  <option name="container" value="java" />
  <option name="deploy" value="true" />
</spec>
<!-- Nginx -->
<spec platform="app-container">
  <option name="name" value="appsvc" />
  <option name="instance" value="nginx-runtime" />
  <option name="container" value="nginx" />
  <option name="deploy" value="true" />
</spec>
<!-- Java Spring Boot -->
<spec platform="app-container">
  <option name="name" value="appsvc" />
  <option name="instance" value="java-runtime" />
  <option name="container" value="java" />
  <option name="deploy" value="true" />
</spec>

自定义脚本文件与服务模块的运行生命周期

服务模块可以看成是一个标准服务,有初始化、启动、停止。初始化属于部署后需要执行的逻辑,在新部署、升级部署、关联模版变更时候执行;启动和停止是在每次池绑定或者解绑时执行。

服务模块的运行生命周期包含以下几个阶段:

顺序 阶段 说明
1 install 安装依赖,例如 maven 的 jar,或者自定义安装某些软件(如果是容器型组件,在容器里面执行,否则在app-init里面执行),install 可看成 init0 的细分阶段
2 init0 start 之前执行的初始化,例如:数据库初始化等
3 start 启动服务,注意: java-runtime、node-runtime 等运行时的服务需要写自己的 start.sh 用于启动服务,而 tomcat 或 nginx 的运行时 start 是整个 tomcat 或 nginx 的启动,服务单独写 start.sh 也将被忽略
4 init start之后执行的初始化,依赖服务运行
5 inited 所有服务就绪后(网关放行)
6 stop 停止服务,不用单独写stop.sh,停止服务由系统默认提供(基于supervisor对start启动的进程和子进程进行管理)

对于用户自定义的服务模块,可以通过自定义脚本文件,在相应的服务运行阶段执行 shell 脚本。自定义脚本文件的命名规范:

  • 文件路径:model/service/{serviceName}/deploy/*.sh
  • 默认文件名:${阶段}.sh,install.sh,init0.sh,start.sh,init.sh,inited.sh, stop.sh 。
  • 按部署类型区分:${部署类型}.${阶段}.sh,部署类型的取值范围:dev、production、kube.production、pool.production,例如:如果对于 kube 和 pool 的生产部署需要有不同的 start 脚本,可以分别定义 kube.production.start.sh 和 pool.production.start.sh 。

results matching ""

    No results matching ""