集成&自动化 - FaaS(云)连接器
注意:本文档涉及功能的使用需要使用者有一定的开发基础。
1. 功能介绍
- 宜搭FaaS(云)连接器以阿里云FaaS服务为依托,使开发人员只需关注业务处理代码的编写,无须关注服务器的部署运维扩容缩容,赋予开发者云开发能力。
- 通过开发人员在云IDE的代码编辑,使宜搭连接器更加贴合自身业务,灵活可定制。
- 秉承宜搭连接器初衷,更进一步推动打破低代码产品与三方应用间壁垒的进程。
说明:宜搭给每个组织赠送了 1000 次FaaS连接器调用次数 (超出后 1000元 100g 的附件容量送三万次)。
2. 创建FaaS(云)连接器
2.1 云连接器的创建
FaaS连接器作为宜搭自定义连接器类型之一,所以其创建也需通过连接器工厂进行操作。
操作路径:
- 连接器创建入口:宜搭官网>>设置(平台管理)>>连接器工厂>>连接器管理>>创建连接器>>FaaS自定义连接器>>填写连接器名称>>确定(操作如图2.1-1 所示)
图2.1-1 云连接器创建入口
- 填写连接器基本信息:可对连接器的名称、图标、介绍进行配置。(操作如图2.1-2 所示)
图2.1-2 填写云连接器基本信息
- 定义连接器参数信息:可对连接器出入参的名称、字段、描述等信息进行配置>>保存>>前往云IDE开发。(操作如图2.1-3 所示)
图2.1-3 定义连接器参数
「前往云IDE开发」按钮说明:
- 作用:点击该按钮,系统会对云资源进行校验,通过后,页面跳转至「阿里云云开发平台」,在这里开发者进行代码的编辑以达到定制的目的。
- 出现时机:连接器为新建时,进行连接器相关配置的保存后才出现;连接器已存在时,按钮会直接显示。
2.2 云IDE页面简介
扩展阅读:获取云IDE详细介绍,请移步:什么是云开发平台。
云IDE是云开发平台的在线IDE,云开发平台是一个拥有「0门槛全云端开发」、「统一的团队业务环境」、「一致的Serverless环境」、「本地化的IDE特性和体验」等极致特性的云上研发工作平台,助力研发团队实现工作的在线化(团队在线、环境在线、代码在线、协同在线)以及研发模式Serverless化,帮助研发团队实现对行业架构经验及架构服务的高效分享与传播,极致提升研发效率,极致降低研发成本。
2.3 云上的FaaS代码
备注: 目前接入了Java 语言、Python 语言和 NodeJS 语言的Faas模板。(新版连接器工厂可见新增的NodeJS和Python)
2.3.1 入口文件路径及作用
2.3.1.1 Java语言
文件路径:src/main/java/com/alibaba/work/faas/FaasEntry.java。(如图2.3-1 所示)
图2.3-1 入口文件所在路径
- 入口文件作用:用于自定义FaaS连接器相关逻辑,更加灵活。
2.3.1.2 NodeJS语言
文件路径 根目录>faasEntry.js
2.3.1.3 Python语言
文件路径 根目录>faasEntry.py
2.3.2 入口文件代码说明
备注: 目前接入了Java 语言 、 Python 语言和NodeJS 语言的Faas模板。(新版连接器工厂可见新增的NodeJS和Python) , 下面是以Java语言代码为例的代码说明(备注: NodeJS版Faas模板和Java版Faas模板做了全部功能的对齐,工具类和示例代码齐全。Python版Faas模板和Java版Faas模板做了部分功能对齐。
//入口文件 FaasEntry.java 初始化代码
package com.alibaba.work.faas;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.work.faas.common.AbstractEntry;
import com.alibaba.work.faas.common.FaasInputs;
import com.alibaba.work.faas.util.DingOpenApiUtil;
import com.alibaba.work.faas.util.YidaConnectorUtil;
import com.alibaba.work.faas.util.YidaConnectorUtil.ConnectorTypeEnum;
import com.alibaba.work.faas.util.YidaConnectorUtil.YidaResponse;
import com.aliyun.fc.runtime.Context;
/**
* @Description 宜搭Faas连接器函数入口,FC handler:com.alibaba.work.faas.FaasEntry::handleRequest
* @Version 2.0
* @Author bufan
**/
public class FaasEntry extends AbstractEntry {
@Override
public JSONObject execute(FaasInputs faasInputs, Context context) {
context.getLogger().info("faasInputs: " + JSON.toJSONString(faasInputs));
//填充宜搭工具类的上下文, 必须调用此方法!!! 请不要删除
initYidaUtil(faasInputs);
//登录态里的钉钉userId
String userId = (String) faasInputs.getYidaContext().get("userId");
//登录态里的钉钉corpId
String corpId = (String) faasInputs.getYidaContext().get("corpId");
//业务传的实际入参(如果您配置了参数映射(也就是点击了连接器工厂里的解析Body按钮并配置了各个参数描述和映射), 那么就是业务实际参数经过参数映射处理后的值)
Map<String,Object> input = faasInputs.getInputs();
/**
* 示例1, 在doYourBusiness方法里编写您的业务代码, 也可以将业务代码封装到其他Class源文件或方法里, cloudIDE和您的本地IDE基本无区别。
*/
// JSONObject result = new JSONObject();
// try {
// Object businessResult = doYourBusiness(input);
// result.put("success",true);
// result.put("result",businessResult);
// result.put("error","");
// return result;
// } catch (Exception e) {
// result.put("success",false);
// result.put("result",null);
// result.put("error",e.getMessage());
// return result;
// }
/**
*示例2, 调用宜搭连接器
*/
// JSONObject result = new JSONObject();
// try {
// Object connectorResult = invokeYidaConnector(faasInputs);
// result.put("success",true);
// result.put("result",connectorResult);
// result.put("error","");
// return result;
// } catch (Exception e) {
// result.put("success",false);
// result.put("result",null);
// result.put("error",e.getMessage());
// return result;
// }
/**
*示例3, 调用钉开放平台OpenAPI
*/
// JSONObject result = new JSONObject();
// try {
// List<String> formInstanceIdList = invokeDingOpenApi();
// result.put("success",true);
// result.put("result",formInstanceIdList);
// result.put("error","");
// return result;
// } catch (Exception e) {
// result.put("success",false);
// result.put("result",null);
// result.put("error",e.getMessage());
// return result;
// }
/**
* 返回的JSONObject并不是一定要带success、result、error, 下面的代码只是示例, 具体返回哪些key-value由您自己决定, 尽量与您在宜搭连接器工厂里配置的出参结构保持一致即可
*/
JSONObject result = new JSONObject();
result.put("success",true);
result.put("result","恭喜您, 成功调用宜搭FASS连接器!");
result.put("error","");
return result;
}
/**
* 将相关参数存到宜搭工具类里, 必须要调用此方法!!! 请不要删除!!!
*
* @param faasInputs
*/
private static final void initYidaUtil(FaasInputs faasInputs){
/**
* 用于调用钉钉开放平台OpenAPI的accessToken, 宜搭提供的, 仅申请了钉钉开放平台的部分OpenAPI的调用权限
* 如果此accessToken不满足您的需求,可在钉钉开放平台创建您自己的钉钉应用并获取appKey和APPSecret并使用com.alibaba.work.faas.util.DingOpenApiUtil获取您自己的customAccessToken
*
* @see com.alibaba.work.faas.util.DingOpenApiUtil#getCustomAccessTokenThenCache(String,String)
*/
String accessToken = (String) faasInputs.getYidaContext().get("accessToken");
// 设置钉开放平台访问token, 后续无需再设置
DingOpenApiUtil.setAccessToken(accessToken);
// try {
// //调用该方法就会自动存储customAccessToken, 之后请不要调用DingOpenApiUtil.setAccessToken(accessToken)将返回的customAccessToken覆盖宜搭传入的accessToken;
// DingOpenApiUtil.getCustomAccessTokenThenCache("您的钉钉应用appKey", "您的钉钉应用appSecret");
// } catch (Exception e) {
// System.out.println("getCustomAccessTokenThenCache error:"+e.getMessage());
// }
/**
*调用宜搭连接器依赖consumeCode
*/
String consumeCode = (String)faasInputs.getYidaContext().get("consumeCode");
//设置连接器消费码, 后续无需再设置
YidaConnectorUtil.setConsumeCode(consumeCode);
}
/**
* 可以将您的业务代码放在这里
*
* @param input
* @return
* @throws Exception
*/
private Object doYourBusiness(Map<String,Object> input) throws Exception{
//取实际的入参
String param1 = (String)input.get("参数1");
String param2 = (String)input.get("参数2");
String paramN = (String)input.get("参数N");
//业务处理
return null;
}
/**
* 示例 调用钉钉官方连接器(待办连接器, 创建待办)
*
* @param faasInputs
* @return
* @throws Exception
*/
private Object invokeYidaConnector(FaasInputs faasInputs) throws Exception {
Map<String,Object> input = faasInputs.getInputs();
String userId = (String)faasInputs.getYidaContext().get("userId");
String corpId = (String)faasInputs.getYidaContext().get("corpId");
JSONObject connectorActionInputs = new JSONObject();
//注意: http连接器的入参是body,query等, 钉钉官方连接器则不是, 请参考宜搭帮助文档 https://www.yuque.com/yida/support/stbfik
{
connectorActionInputs.put("unionId",Arrays.asList(userId));
connectorActionInputs.put("subject",(String)input.get("title"));
connectorActionInputs.put("creatorId",Arrays.asList(userId));
connectorActionInputs.put("description","Faas连接器里调用钉钉官方连接器创建待办");
connectorActionInputs.put("dueTime",System.currentTimeMillis()+600*1000);
connectorActionInputs.put("priority",10L);
}
//请确保调用前设置了consumeCode
//更多钉钉官方连接器ID和动作ID及出入参请参照 https://www.yuque.com/yida/support/stbfik#Mv0dK (如果目标段落不存在, 请访问 https://www.yuque.com/yida/support/stbfik)
YidaResponse response = YidaConnectorUtil.invokeService("G-CONN-1016B8AEBED50B01B8D00009","G-ACT-1016B8B1911A0B01B8D0000I", ConnectorTypeEnum.DING_INNER_CONNECTOR,null,connectorActionInputs);
if (Objects.nonNull(response) && response.isSuccess()){
try {
return YidaConnectorUtil.extractYidaConnectorExecutionResult(response);
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}else {
throw new Exception(Objects.isNull(response)?"执行宜搭连接器失败":response.getErrorCode() +" "+response.getErrorMsg());
}
}
/**
* 示例 批量创建宜搭表单实例
*
* @return
* @throws Exception
*/
private List<String> invokeDingOpenApi() throws Exception {
BatchSaveFormDataRequest request = new BatchSaveFormDataRequest();
request.setAsynchronousExecution(true);
request.setKeepRunningAfterException(true);
request.setNoExecuteExpression(true);
request.setAppType("宜搭应用编码");
request.setUserId("钉钉userId");
request.setSystemToken("宜搭应用systemToken");
request.setFormUuid("表单编码");
JSONObject formData = new JSONObject();
formData.put("表单组件1的ID", "表单组件1的值");
formData.put("表单组件2的ID", "表单组件2的值");
//批量创建200条
request.setFormDataJsonList(Collections.nCopies(200,formData.toJSONString()));
return DingOpenApiUtil.batchSaveFormData(request);
}
}
上述代码拆解:
execute()
为入口函数,用于承载FaaS连接器逻辑的编辑。有两个入参,分别为 FaasInputs(需重点关注)及 Context 。FaasInputs
参数有两个属性,分别为
yidaContext
:用于获取宜搭服务端上下文内容以及附加内容。目前能获得4个上下文变量(以下简称变量。后续会根据需要带出更多相关的上下文变量):
变量userId
用于获取当前登录人的钉钉用户ID;
变量corpId
用于获取当前登录人所在企业在钉钉的唯一标识;
变量 accessToken 用于调用钉钉开放平台OpenAPI;
备注:Faas代码模板里提供了便捷调用钉钉开放平台OpenAPI的工具类, 您也可以用工具类编写代码获取您自己的accessToken来调用钉钉开放平台OpenAPI。
变量 consumeCode 用于在Faas连接器里调用宜搭连接器(钉钉一方连接器、钉钉三方连接器、自定义HTTP连接器)和宜搭平台接口;
备注:Faas代码模板提供了便捷调用宜搭连接器的工具类。
inputs
:传入FC函数的实际入参:
备注:
如果您在连接器工厂里配置了Faas连接器入参的参数映射, 那么实际取到的入参是您调用Faas连接器传的入参对象经过参数映射处理后得到的对象。
如果您没有在连接器工厂里配置Faas连接器入参的参数映射,那么宜搭会将您调用Faas连接器传的入参直接传入FC函数。
- 业务逻辑编写区域:您不必非得在execute()函数内编写业务逻辑,您可以在已有的类里添加新的方法,可以创建新类,可以在maven pom.xml里引入您需要的依赖,您只需要将业务结果在execute函数内返回即可。
返回结果类型为JSONObject:用于存放业务执行结果。
2.3.3 断点调试
目前宜搭FaaS连接器提供的Faas代码模板可选Java、NodeJS、Python开发语言, 全部支持断点debug
,具体操作在云IDE里有提示。Java语言也可以在类里添加main
函数并在云IDE里执行main函数并在云IDE控制台观察输出结果。
Java断点调试
下图是Java环境下的断点Debug示例(备注: NodeJS、Python的断点调试和Java类似,区别在于NodeJS和Python的断点是由IDE自动生成调试配置文件,Java无需自动生成调试配置文件)
NodeJS断点调试
- 先按照工程根目录下的README.md安装Node依赖,如下图所示。
- 切换到调试面板添加调试配置文件(首次点击三角形那个“启动调试”按钮会自动新建调试配置文件(选择NodeJS配置),无需自己填写调试配置。
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}/test/tpl.test.js"
}
]
}
(() => {
handler(JSON.stringify({
"body": JSON.stringify({
"inputs": {
},
"yidaContext": {
"accessToken": "17f5033ce3d733fbb0c63fed5f24d9cb",
"consumeCode": "193F27DDD0AD40186D7E4707C12DB4D44CBC2B89E8D4813708ED88D0E7BDF86FF1226683194967A585E53BE531E2A3FA5110FEEFB2363906F055C25B78F3F2EE93EB5B067E0171B5E1C9A18958A43658E3F7289C5FF8A42FE48E288364F14BD661C36AC5F2B459F9DA95ADDB94AB65D6",
"corpId": "您的钉钉corpId",
"userId": "您的钉钉userId"
}
})
}), {}, (error, response) => {
console.info(error ? ("error:" + JSON.stringify(error) + " " + error.name + " " + error.message) : "", "\n\nresponse:", JSON.stringify(response));
})
})();
- 打断点,也可以自己新增执行语句并打断点。
- 切到调试面板,点击启动调试按钮进入debug状态。
Python断点调试
略,请参考NodeJS断点调试。
2.3.4 代码的保存、提交与推送
- 保存修改的源码(快捷键: Mac是command + s , Windows是ctrl + s)(手动保存不是非必须的,因为commit时CloudIDE会询问是否要自动保存全部打开编辑过未保存的文件,选择是则自动保存修改过的文件)
- 在CloudIDE左侧边栏切到git面板(如下图所示),点击提交代码按钮(图标是✔️)并在弹出的输入框里填写commit信息后按回车,然后点击菜单(图标是三个点号)选择“推送”就会推送到远端代码仓库。
也可以通过git命令操作:云平台同各位熟知的IDE一样内置了Git命令,在完成自身业务逻辑代码编写后,也可以通过git的各种命令实现代码的保存、提交及推送操作。
- 保存:
git add .
- 提交:
git commit
- 推送:
git push
2.3.5 部署
代码推送到远程仓库后,点击侧边栏部署按键>>选择线上环境>>点击部署。(操作如图2.3-2 所示)
图2.3-2 应用部署
注意:宜搭目前仅开放了调用部署在线上环境的FaaS代码(宜搭后续会在连接器工厂开放测试Faas连接器,即调用Faas预发环境),故而,请选择线上环境进行部署。
代码部署成功,表示连接器的创建工作已经完成,接下来就可以在宜搭中进行使用了。
2.3.6 打印和查看运行日志
2.3.6.1 如何打印运行日志
宜搭非常推荐用户增加日志,便于问题的排查定位。打印日志的方式有多种:
- 可以从入口函数的第二个入参Context对象里取得Logger对象并打印日志,即:context.getLogger().info("您的日志"),或者context.getLogger().warn("您的日志"),或者context.getLogger().error("您的日志")。
- 使用编程语言自己的日志打印方法
- Java语言可以使用
System.out.print
或者 System.out.println 方法来打日志。(请给日志添加关键词,并且用空格将关键词与其前后的字符串隔开,否则检索日志时可能不会匹配) - NodeJS语言可以使用console.info来打印日志。(请给日志添加关键词,并且用空格将关键词与其前后的字符串隔开,否则检索日志时可能不会匹配)
- Python语言可以使用logging模块内的logger来打印日志(Python版Faas模板内已经提供)(请给日志添加关键词,并且用空格将关键词与其前后的字符串隔开,否则检索日志时可能不会匹配)
如下图所示(Java示例):
2.3.6.2 如何查看打印的运行日志:
- 进入到连接器编辑模式:连接器工厂>>找到对应连接器>>点击「前往云IDE开发」。(操作如图2.3-3 所示)
图2.3-3 进入连接器编辑模式
- 跳转到应用列表:「应用管理」>>「云原生应用」。(操作如图2.3-4 所示)
图2.3-4 进入应用列表
- 选择对应连接器进入日志管理页:选择应用>>运维监控>>日志管理页。(操作如图2.3-5 所示)
图2.3-5 进入日志管理
- 环境选择「线上环境」>>日志查询选择带有release字样的选项,比如下图选择了
wblogrelease-fc-2022012501607003
>>输入关键字>>进行日志查询(操作如图2.3-6 所示)
图2.3-6 查看日志
2.4 FaaS连接器的使用
2.4.1 在连接器数据源中使用
拓展阅读:获取宜搭连接器数据源功能相关详细介绍,请移步:远程数据源调用自定义连接器
2.4.2 在集成&自动化和审批流中使用
拓展阅读:获取宜搭集成&自动化功能相关详细介绍,请移步:集成&自动化-连接器
2.4.3 在Faas代码里调用宜搭连接器
调用宜搭连接器: (请查看faas代码获取更详细的说明)
com.alibaba.work.faas.util.YidaConnectorUtil#invokeService(String connectorId,String actionId, ConnectorTypeEnum connectorTypeEnum, Long connection,JSONObject inputs)
2.4.4 在Faas代码里调用宜搭平台接口
宜搭平台接口参考: 宜搭平台接口
调用宜搭平台接口: (请查看faas代码获取更详细的说明)
com.alibaba.work.faas.util.YidaConnectorUtil
getYidaApi(String path,Map<String,String> headers, Map<String,String> queries)
postYidaApi(String path,Map<String,String> headers, Map<String,String> queries, Map<String,String> bodies)