微服务开发文档

微服务使用JS脚本实现,支持模块化管理、高并发访问、数据库访问,主要用于扩展后端服务,或者创建其他独立的业务逻辑。 可用于实现移动端和服务端访问请求,以及通用的业务处理和数据查询服务,一个视频看懂微服务点击这里查看实战demo。架构图如下所示:

主要应用场景

  1. 扩展冰狐SaaS功能。一般SaaS系统都是通用的,但有时客户根据自己的业务特点可能有少部分功能无法完全满足需求,此时用户就可以通过编写微服务并注入到冰狐SaaS系统中,来满足自己的特殊业务需求。
  2. 实现自己的独立后端需求。有些业务我们必须要使用后端服务,如果用户独立开发一套后端系统,金钱和时间成本会比较高。此时可以直接使用微服务,编写js代码来搞定,不需要单独购买和维护各种服务器,不需要掌握各种复杂的开发和部署工具。

移动端接口

开发者可以在app脚本中通过callMicroService函数来调用微服务。移动端接口可以指定脚本和函数名(默认函数名为main),params直接透传给微服务脚本相应的函数,函数的返回值即为接口返回值。
典型应用场景:当移动端脚本开发者需要调用自定义的后端服务功能时使用callMicroService,比如访问数据库、获取用户和设备相关信息等。

移动端脚本demo

// 调用接口call_demo,参数分别为'name'和123,返回值为ret
function main() {
    var ret = callMicroService('call_demo', ['name', 123]);
    console.log('ret:' + ret);
}
                                        

服务端脚本demo

// 接口call_demo对应的脚本, name和value为移动端传入的参数
function main(name = '', value = 1) {
    console.log('name:' + name + '  value:' + value);
    return name + value;
}
                                        

服务端接口

第三方服务端可以调用open api:/api/call_micro_service来调用微服务。服务端接口可以指定脚本和函数名(默认函数名为main),query参数params直接透传给微服务脚本相应的函数,函数返回值为接口返回值。
典型应用场景:当开发者需要让第三方调用开发者自定义的后端服务功能时使用该接口。

第三方调用demo

// 调用服务端接口call_demo,参数为["name", 123],clientKey和accessToken请替换成自己的鉴权参数
                                        https://aznfz.com/api/call_micro_service?clientKey=xxxxx&accessToken=yyyyy&name=call_demo&isDev=true& params=%5B%22name%22%2C%20123%5D
                                        

服务端脚本demo

// 接口call_demo对应的脚本, name和value为移动端传入的参数
function main(name = '', value = 1) {
    console.log('name:' + name + '  value:' + value);
    return name + value;
}
                                        

业务处理服务

若需要让用户在网页端点击界面执行某个业务,则可以创建业务处理服务,可以让用户输入参数,然后触发云端的微服务(服务参数直接透传给微服务脚本),微服务可以控制所有手机执行任务。
例:录入数据业务就可以通过创建业务处理服务解决,首先用户输入数据并透传给微服务,微服务规则化数据后存入数据库。
支持的参数类型:整数、浮点数、布尔、字符串、文件、选项和设备。选项类型参数支持两种格式默认数据:1.用,分割多个item,每个item用:分割name和value,例:微信:1,支付宝:2。2.请求后端接口获取数据,用json对象表示,例:{"scriptName":"common", "functionName":"getDevice"},系统会自动执行common脚本的getDevice函数并返回结果作为选项的数据项。
典型应用场景:当用户需要从外部录入数据或者需要在网页端触发某个行为时可以使用业务处理服务,实际处理过程由微服务脚本完成,比如上传用户资料,触发设备调度任务等。

业务处理demo

业务参数元数据:
[{"name":"param","id":"p","type":"int","defaultValue":12,"description":"测试"}]

// 业务对应的脚本如下:(注意,函数参数必须与业务参数一致)
function main(p=1) {
    console.log('param:' + p);

    var users = userList();
    console.log('users:' + users);
    for (var u of users) {
        console.log('u:' + u);
        var devices = deviceList(u.openId);
        console.log('用户:' + u.username + ' 设备:' + devices);
    }

    // 获取管理员的设备
    var devices = deviceList('');
    console.log('管理员设备:' + devices);
}
                                            

数据查询服务

若用户需查询数据,则可以创建数据查询服务,以表格的形式显示数据。
数据查询处理函数原型:function main(fetchCountOnly, conditions, startIndex, itemCount){},fetchCountOnly表示是否仅仅获取符合查询条件的数据个数,conditions为用户输入的查询条件,startIndex和itemCount分别表示获取数据的起始游标位置和数据条数;返回数据为对象数组,例:[{"key","value"},{"key","value"}],key与列的id相对应,表格显示key对应的value值
查询参数:指查询数据时用户指定的参数,支持text和select,当执行服务时会让用户输入具体查询参数。text类型:返回的数据对应项包含text才返回,select类型:返回数据对应项等于选择值才返回;
列:指显示数据时的表格列,注意列id要与数据查询处理函数返回数据对象的key一致,否则无法显示;
数据操作:指对数据item的操作,比如删除等。每个数据操作可以指定脚本和函数用于具体处理,处理函数原型为 function main(item){},item为当前操作的数据。
典型应用场景:当用户需要查看系统内部数据时(可以类比于数据报表功能),可以使用数据查询模块来实现,比如查询所有上传的用户资料等。

查询脚本demo

/*
[{
	"id": 1,
	"name": "a",
	"value": "postman"
}, {
	"id": 2,
	"name": "ab",
	"value": "freeman"
}, {
	"id": 3,
	"name": "b",
	"value": "policeman"
}, {
	"id": 4,
	"name": "c",
	"value": "bad guy"
}]
*/
// 用于获取需要显示的表格数据,查询脚本的参数必须是如下格式:fetchCountOnly表示是否仅获取数据总数,conditions表示json数组格式的查询条件,startIndex表示游标值,itemCount表示一页的最大个数
function main(fetchCountOnly, conditions, startIndex, itemCount) {
	var jsonConditions = JSON.parse(conditions);
	var data = JSON.parse(getCustomData('query_data'));
	var ret = data;
	if (jsonConditions && jsonConditions.length > 0) {
		ret = [];
		for (var item of jsonConditions) {
			if (item.name == 'name') {
				for (var d of data) {
					if (d.name.includes(item.value)) {
						ret.push(d);
					}
				}
			}
		}
	}

	if (fetchCountOnly) {
		// 返回符合条件的数据个数
		return ret.length;
	} else {
		// 返回符合条件的格式化数据
		return ret;
	}
}

// 删除数据操作脚本, 脚本的参数必须如下所示,item表示选中后将要操作的数据项
function deleteItem(item) {
	var data = JSON.parse(getCustomData('query_data'));
	var index = 0;
	for (var d of data) {
		if (d.id == item.id) {
			break;
		}
		++index;
	}
	data.splice(index, 1);
	return setCustomData('query_data', data + '');
}                                            

实战demo

需求:
假设我们有100台手机做任务,需求如下:
  1. 按顺序来启动每台手机任务,移动端脚本名为:test。
  2. 两次启动之间需要加一个随机的间隔时间。
  3. 将自定义的参数传给每个启动的手机任务,自定义参数类型:string,参数名:url。

需求分析:
  1. 以上需求本质上是做100台手机的调度功能,仅依靠前端的js脚本是无法实现的,所以必须使用微服务。
  2. 由于需要输入参数url,所以我们可以使用「业务处理」服务来实现,添加一个url参数。
  3. 两手机任务启动间隔时间也可以做成参数,让用户自己选择间隔的范围。所以可以添加为minInterval和maxInterval两个参数分别表示最小和最大间隔时间(毫秒)。

实现:
根据上述分析,我们可以先建立「业务处理」服务,然后再编写对应的「微服务脚本」来实现调度功能。
  1. 新建业务处理服务。在网页端选择【微服务】/【业务处理】,点击右上角的"+服务"按钮,新建一个名为demo的业务处理服务。
  2. 添加参数。点击"参数"按钮,添加三个参数,分别为:【名称:url,类型:字符串】;【名称:minInterval,类型:整型】;【名称:maxInterval,类型:整型】。
  3. 新建微服务脚本。在网页端选择【微服务】/【微服务脚本】,点击右上角的"+脚本"按钮,新建一个名为demo的脚本。
  4. 关联脚本和业务处理服务。在网页端选择【微服务】/【业务处理】,点击"编辑"按钮,选择刚创建的"demo"为脚本。
  5. 实现微服务脚本。脚本的核心功能为:接收参数,根据参数和调度要求来启动每个手机任务。
    // url、minInterval,maxInterval为业务处理服务透传过来的参数
    function main(url, minInterval, maxInterval) {
        var devices = deviceList();
        for (var device of devices) {
            // 仅调度在线手机
            if (device.onlineState == 1) {
                // 在手机上执行移动端名为"test"的脚本,这里的url参数会直接透传给移动端脚本的main函数参数。
                scriptExe('test', device.uuid, [url], true);
    
                // 在minInterval和maxInterval之间随机延时一段时间
                sleep(Math.random() * (maxInterval - minInterval) + minInterval);
            }
        }
    }                        
  6. 执行服务。在网页端【微服务】/【业务处理】,选择刚创建的"demo"服务,然后点击"执行"按钮,填充相关参数,点击"执行"即可执行代码。
  7. 如果您还没有手机端脚本(移动端脚本),可以参考下面的代码:
    // url参数的值,是上面的微服务脚本通过调用scriptExe函数透传过来的。
    function main(url) {
        console.log('url:' + url);
    }