接口注册程序
接口注册程序读取 $JUSTEP_HOME/model/service 下所有目录中的 app.m(定义平台中的接口),把它们注册到网关中
Kong 中的几个概念
- service
- 服务,由服务确定上游的访问地址
- route
- 路由,由路由确定使用哪个服务,从而确定上游访问地址
- plugin
- 插件,加在服务或路由上的插件,当访问到指定的服务或路由时,插件会被执行
- 在平台中,插件被限制只能加到路由上
- upstream
- 上游,service 通过 hostname 与上游的 name 匹配,用于多目标的负载均衡
- target
- 上游的地址,每个地址可以指定不同的权重,用于负载均衡的计算
- customer
- 用户,用于权限验证,指定在 plugin 中
app.m 中的几个概念
app.m 根据它的内容,分为静态和动态两种
- 静态 app.m 是指它的内容是固定的,不需要上下文去计算
- 一个 app.m 只生成一个对象
- 动态 app.m 是指它内容需要计算得到
- 一个 app.m 可能会生成多个对象
- service 节点上有 loop、when 等发生
- 下面的 app.m 示例中的第一个 app.m 就是一个动态的 app.m
app.m 示例
<?xml version="1.0" encoding="UTF-8" ?>
<service order="100" target="kong2" tags="registerServices" loop="{{@getRegisteredServices()@}}">
<name>{{@getItemData(serviceName)@}}</name>
<request_path>/{{@getItemData(serviceName)@}}</request_path>
<preserve_host>false</preserve_host>
<strip_request_path>true</strip_request_path>
<upstream_url>{{@getItemServiceUrl(serviceName)@}}</upstream_url>
<plugin name="authentication" enabled="true">
<app_key>{{.Env.API_KEY}}</app_key>
<app_secret>{{.Env.API_SECRET}}</app_secret>
<expire>600</expire>
<admin_users>system</admin_users>
<silent_mode>true</silent_mode>
<auto_refresh_session>true</auto_refresh_session>
</plugin>
</service>
<?xml version="1.0" encoding="UTF-8" ?>
<upstream>
<name>aaa-vip.xcaas.com</name>
<target weight="200">192.168.0.11:8098</target>
<target weight="100">192.168.0.12:8098</target>
</upstream>
<?xml version="1.0" encoding="UTF-8" ?>
<consumer>
<name>consumer1</name>
</consumer>
app.m 中根节点有三种类型
- service
- 用于定义服务和插件
- upstream
- 用于定义上游
- consumer
- 用于定义用户
service节点上的属性
- target
- 指明接口注册到哪个网关上,它的值只有两个:kong, kong2
- 只有门户(entry)服务上有 kong2
- 如果未指定,缺省值是 kong
- 指明接口注册到哪个网关上,它的值只有两个:kong, kong2
- order
- app.m 被注册的顺序,数值小的先注册
- 名字相同的接口会被后注册的覆盖
- loop
- 值是一个 JSONArray,JSONArray 中的每个 JSONObject 会被注册成一个对象
- when
- 值是一个布尔值,使用 when 指定的函数,对平台中所有的 app.m 进行计算,如果结果为真,则用它的内容注册一个对象
- enabled
- 值是一个布尔值,如果计算结果是假,则忽略它
- renew
- 值是一个布尔值,如果计算结果是真,先删除前面注册的插件,再添加这里定义的插件
- request_path
- 定义请求路径,可以是一个字符串,也可以是一个正则表达式;可以有多个值,多个值之间用逗号分隔
- 示例:/druid,~/[0-9]+.[0-9]+.[0-9]+.[0-9]+/druid
- /druid, /192.168.0.11/druid 的请求都会匹配到
- preserve_host
- 请求到上游时,是否保留主机名
- strip_request_path
- 生成上游的请求地址是,是否将 request_path 的值去除
- upstream_url
- 请求的上游地址
- plugin
- 定义一个插件,名字在节点 name 属性指定
- 插件的内容根据不同的插件是不同的,需要查看插件的 schema
- strip_request_path 含义示例
request_path: /myPath
upstream_url: http://192.168.0.11:8080
请求:/myPath/abcd
当 strip_request_path=true 时,到上游的请求为:http://192.168.0.11:8080/abcd
当 strip_request_path=false 时,到上游的请求为:http://192.168.0.11:8080/myPath/abcd
app.m 中的环境变量与函数
在 app.m 中,可以使用服务中定义的环境变量,它的表达方式是:{{.Env.XXXX}};其中 XXXX 是环境变量的名字。 app.m 中也可以使用函数,它的表达方式是:{{@XXXX(YYYY)@}};其中 XXXX 是函数的名字,YYYY 是参数的值。函数可以没有参数。 不管是环境变量还是函数,都不支持嵌套
app.m 中可用的函数列表
- JSONArray getExternalServices()
- 返回租户中服务类型(manager_service 表中的 type 字段)为 external 的所有服务
- String getServiceDomainName(serviceName)
- 返回租户中服务的内网域名
- String getItemServiceUrl(key, defaultValue)
- 返回循环对象中 key 所指向的服务的地址
- 如果循环对象中没有 key 的值,返回 defaultValue
- defaultValue 参数可选
- String getItemData(key, defaultValue)
- 返回循环对象中 key 的值
- 如果循环对象中没有 key 的值,返回 defaultValue
- defaultValue 参数可选
- String getMetaData(key, defaultValue)
- 返回 app.m 所在目录的服务的 meta 文件中 key 的值
- 如果循环对象中没有 key 的值,返回 defaultValue
- defaultValue 参数可选
- String hasMetaData(key)
- 返回 app.m 所在目录的服务的 meta 文件中是否存在 key 的值
- String getServiceName()
- app.m 所在目录的名字的最后一段
- 如:/usr/local/x5/model/service/comp/xxx,返回 xxx
- String getServiceNameFromPath()
- 根据 app.m 所在目录的名字的返回服务的目录名
- 如:/usr/local/x5/model/service/comp/xxx,返回 comp_xxx
- String getServicePath()
- 根据 app.m 所在目录的名字的返回服务的目录名
- 如:/usr/local/x5/model/service/comp/xxx,返回 /comp/xxx
- String getServicePath2()
- 根据 app.m 所在目录的名字的返回服务的目录名
- 如:/usr/local/x5/model/service/comp/xxx,返回 comp/xxx
- String isMain()
- 是否是 main 服务
- 在 /usr/local/x5/model/service/main 下的服务返回 true,其它返回 false
- String hasDataTable()
- app.m 所在的服务下面是否有 xxx.data.m 数据集定义
- String hasTag(tag)
- 服务上是否有指定的标签
- String getApiName()
- API 名字
- String getApiHosts()
- API 域名
- String getApiRequestPath()
- API 请求路径
- String getApiServiceAddress()
- 服务的 XXX_SERVICEADDRESS 环境变量的值
- String getApiServicePort()
- 服务的 XXX_PORT 环境变量的值
- String getApiUpstreamUrl()
- API 的上游地址
- String getApiStripRequestPath()
- API 的 strip_request_path 的值
- String getApiPreserveHost()
- API 的 preserve_host 的值
- String hasApp(appName)
- 租户中是否有指定的服务
- String serviceExists(serviceName)
- 在注册的服务中是否有指定的服务
- String getRegisteredServices()
- 返回注册的服务
- String getRegisteredServicesForRegExp()
- 返回注册的服务网关匹配字符串,如:[(entry)(wf)]
- String getTenantCode()
- 返回租户名
- String isTenantApp()
- 服务是否是一个租户服务
- String getSubServices()
- 返回租户中的由门户代理的子服务
- String getContextServiceName()
- 返回当前服务
- String isDefined(env, defaultValue)
- 环境变量是否定义
- 如果未定义,返回 defaultValue
- defaultValue 参数可选
- String isNotDefined(env, defaultValue)
- 环境变量是否未定义
- 如果未定义,返回 defaultValue
- defaultValue 参数可选
- String isFalseOrNotDefined(env)
- 环境变量未定义或者值是 false
- String isBlank(env)
- 环境变量值是否为空
- String isNotBlank(env)
- 环境变量值是否不为空
注册程序执行过程
- 找出 $JUSTEP_HOME/mode/service 下所有的 app.m
- 注册静态 app.m
- 注册动态 app.m
- 注册只有 plugin 的 app.m
- 如果网关是 off 模式使用新生成的 yml 文件重新加载配置,如果加载成功,将新生成的文件保存到备份目录,如果加载失败,使用之前成功的配置再次加载
- off 模式下文件的备份目录
- 开发时:/storage/data/gateway/dev/kong.yml
- 运行时:/storage/data/gateway/prod/kong.yml, /storage/data/gateway/prod/kong2.yml(只有 entry 有)
- off 模式下文件的备份目录
用户自己写 app.m 注意事项
- app.m 的存放目录
- 可以自己创建的目录
- 目录下必须要有 deploy 的信息,可参考 health-check 目录
- 如果放在一个已有的目录,注意目录中的 .meta 文件中是否有 health-check 的描述,如果有,会自动给接口加上 health-check 插件
- 如果用户想覆盖掉平台中一个已经有的接口
- 写一个接口名字相同的 app.m
- 把 order 设置一个比已经有的接口的 order 更大的值
- order 的缺省值是 0
- 如果要给一个接口加插件,首先查看平台的“应用/服务管理”的“更多-网关”功能中,是否已经有此插件,如果有,则从这个功能配置
- 注意这里加的插件是加在 kong2 上的
- 如果要加在 kong 上面,现在只支持写 app.m 的方法