API网关之函数开发


前言

本文介绍了一种网关函数API的实现方式,核心为使用JDK自带的脚本引擎nashorn,驱动和执行用户自己开发的JS函数脚本,并把函数封装成一个API,发布到API网关上,像网关其他的API一样,对外提供服务。


一、函数API介绍

网关基本的功能是路由,就是将已知的外部接口再次包装后发布到网关,南向和北向应用使用网关发布的接口,可以通过一些规则路由到那些外部接口。
函数API实质是一个用户自定义的函数,这个函数是一个脚本,可以是JS、JAVA、C#等语言编写的,通过一致的函数入参和出参,以及传输协议包装之后,就成为一个可以被调用的接口,如果要被南向和北向系统调用,还要将它发布到网关。
函数是FaaS、PaaS等这些比较流行的ServerLess架构系统中比较重要的元素,当然这里将要介绍的函数和FaaS还不是一个概念,但是原理及用法有相似之处,比如这里是将函数作为一个API执行,这个和FaaS是一致的。

二、原理及实现

1、函数API实现方案:

1)第一种是利用freemark等模板引擎,将脚本直接生成接口代码,然后用javax.tools下面的工具动态编译成字节码,或者采用其他的动态编译工具都可以,这样就可以动态创建一个接口;
2)第二种无需动态生成接口,只需要使用一个脚本引擎,传入接口的上下文之后,利		用脚本引擎去调度脚本并返回执行结果就可以了。

方案优缺点分析:
1、方案一需要集成模板引擎生成代码,还要动态编译,例如js脚本,得利用脚本引擎JavaScript将js转成java,需要在工程里面生成代码,并编译成字节码,这就有个问题,将来的接口会非常的多,几千几万是很正常的,要生成如此之多的接口,工程慢慢会越来越臃肿,接口调用性能上也是很差的,而且多实例部署还要接口同步,脚本修改也要将上述过程再来一遍,所以这种方式显然不好。
2、方案二就简单多了,函数脚本统一存放在RDB,或者存放在redis、csv等数据库都可以,增加修改一个函数无需生成代码、编译、同步,也不会增加工程存储及接口io占用,利用java的脚本引擎做脚本的统一调度,拿到上下文执行脚本并返回处理结果就行了,这里介绍的就是这种方式。

2、函数API实现原理:

采用JDK最新的脚本引擎nashorn,脚本采用JavaScript编写,支持java、js混合编程
在这里插入图片描述

3、函数API实现过程

1)编写js脚本,持久化到数据库,这里是一个简单实例,脚本发起一个http求,调用一个接口

importClass(com.icss.cig.spms.integration.service.apiis.design.client.HttpClient);

function execute(request) {
    // 设置函数返回值
    var result = new Response();
    // 获取请求上下文
    var header = request.headers; // Head参数
    var parameter = request.parameters; // Harameter参数
    var body = request.body;
    var host = 'http://spms-integration-service-system';
    var url = '/rpc/pass/system/app/getToken';
    var req = Request.getInstance(header, parameter, body);
    var response = HttpClient.doPost(host, url, req);
    if (response.header.status == 200) {
        // 请求成功,设置返回值,自己封装返回值结构
        result = response;
    } else {
        // 请求失败,设置异常信息,自己封装返回异常信息
        result.header.code = response.header.status;
        result.header.message = response.header.message;
        result.header.error = response.header.error;
    }
    return result;
}

2)函数包装成一个接口wzf0616,这个接口为发布到网关的接口,对外定义调用方式
在这里插入图片描述
3)开发一个脚本调度接口,用来处理函数调用的不同请求,此接口暴露在注册中心

	@ApiOperation(value = "脚本执行调度", tags = {"API设计"})
    @PostMapping(value = "/rpc/pass/integration/apiis/design/redirectLocalInterface")
    Mono<SPMSRsp<Object>> redirectLocalInterfacePost(ServerWebExchange exchange);

4)将接口wzf0616发布到API网关,通过注册中心路由到接口redirectLocalInterface
5)函数API调用,用户通过网关接口wzf0616就可以调用定义的函数excute了
6)脚本引擎调度函数

ScriptEngine scriptEngine = ScriptManager.createScriptEngine();
scriptEngine.eval(scriptEntity.getScript());
Invocable invocable = (Invocable) scriptEngine;
Object result = invocable.invokeFunction("execute", scriptRequest);
public static ScriptEngine createScriptEngine() throws IOException, ScriptException {
        ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
        ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("nashorn");
        jsScriptEngine = scriptEngine;
        // 加载公共js
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        org.springframework.core.io.Resource[] resources =
                resolver.getResources("templates/freemark" + File.separator + "common.js");
        org.springframework.core.io.Resource resource = resources[0];
        InputStream  inputStream = resource.getInputStream();
        Reader reader = new InputStreamReader(inputStream, "utf-8");
        scriptEngine.eval(reader);
        return scriptEngine;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值