Index
Serverless简介
Serverless最近非常流行,无服务器应用也让我们可以简单快速上线一些功能,而无需关心底层的基础架构。
那么今天也让我们来利用Serverless的思想在亚马逊云(AWS)上部署我们的程序吧。
课题
在AWS上部署一个钉钉和kintone的整合应用。可以让kintone随时同步钉钉的打卡数据。(钉钉上已有打卡记录)
流程
创建npm项目,编写代码 => 建立钉钉的应用 => 建立AWS的IAM账户 => 建立AWS的vpc => 建立AWS的API Gateway网关 => 建立Lambda =>kintone自定义开发
kintone设置
首先我们创建一个kintone app,在app里添加一个单行文本框字段以保存钉钉传过来的打卡地址。并且开启“API令牌”,设置访问权限,让这个应用可以通过API来添加数据。
服务端开发
创建一个npm项目,导入kintone的js sdk依赖包。
npm init npm install --save @kintone/kintone-js-sdk request request-promise
kintone/kintone-js-sdk是kintone的js sdk。具体的用法可以参见文档 https://github.com/kintone-labs/kintone-js-sdk/
关于钉钉的开发请参见另一篇文章 https://cybozudev.kf5.com/hc/kb/article/1295078
下面是具体的同步钉钉数据的代码,我们命名为index.js
const request = require('request-promise'); const kintone = require('@kintone/kintone-js-sdk'); const DOMAIN = 'https://oapi.dingtalk.com/gettoken?appkey='; const APP_KEY = 'xxxxxxxxxx'; const API_SECRET = 'xxxxxxxxxxxxx'; const KINTONE_DOMAIN = "xxxxx.cybozu.cn"; const MY_TOKEN = "xxxxxxxxxxxx"; const URL = DOMAIN + APP_KEY + '&appsecret=' + API_SECRET; exports.handler = async (event) => { let getAccessToken = function () { let options = { url: URL, method: 'GET' }; return request(options); }; let getCard = function (result) { let ppp = JSON.parse(result); var token = ppp.access_token; let options = { url: "https://oapi.dingtalk.com/attendance/listRecord?access_token=" + token, method: 'POST', body: { userIds: ["282306481325123890"], checkDateFrom: "2019-07-05 09:00:00", checkDateTo: "2019-07-05 12:00:00", isI18n: "false" }, json: true }; return request(options); }; let insertKintone = async (ding) => { let data = ding.recordresult[0].userAddress; let kintoneAuthWithAPIToken = (new kintone.Auth()).setApiToken(MY_TOKEN); let kintoneConnection = new kintone.Connection(KINTONE_DOMAIN, kintoneAuthWithAPIToken); let kintoneRecord = new kintone.Record(kintoneConnection); let appID = 1; let record = { ding: { value: data } }; try { let recordResult = await kintoneRecord.addRecord(appID, record); return recordResult; } catch (error) { return error; } }; return getAccessToken().then(getCard).then(insertKintone); };
请按照实际情况,设置APP_KEY,API_SECRET,KINTONE_DOMAIN,MY_TOKEN变量的值。
再建立一个test.js
const r = require("./index"); r.handler();
我们可以测试运行下node test.js,看下结果是否在kintone上已经同步了钉钉的打卡数据。
以下是kintone上同步钉钉的记录。
测试成功后,我们就可以把它部署到我们的AWS云上了。
AWS云服务器的部署
创建IAM账户
我们先建立一个AWS的IAM用户, 它能够安全地管理对AWS 服务和资源的访问。具体可参见AWS官方的介绍。我这边就不多做阐述了。
以下是我们建立的IAM账户,并赋予了它一定的权限。
建立VPC
为什么要建立vpc?
为了调用的安全性,很多的API调用是需要一个白名单的IP地址,只有这些IP可以调用它的API服务,但是如果你用一些云服务器,包括AWS的Lambda的时候,它并不会提供你一个固定的IP。这时候你可以使用aws的vpc服务,来解决这个问题。
详情请查看 如何解决Lambda里需要连接限制IP访问的应用
通过vpc获取到一个弹性IP后,这个IP就可以作为“服务器公网出口IP名单”填写到钉钉后台了。
AWS弹性IP:
钉钉应用小程序后台:
Lambda函数
Lambda是AWS提供的无服务器计算服务。
这边就以钉钉和kintone的整合作为例子。以Node.js作为语言来做一个demo。
创建函数
首先是创建函数,在Lambda画面,然后选择创建函数。输入函数名字,选好运行语言Node.js,然后选好角色权限。
设置参数
我们调整好基本设置的超时时间,设置好vpc网络的访问。
上传代码
我们可以将整个项目打成zip包,然后通过上传来部署到Lambda。
触发器API Gateway
API gateway一般用来作为多个微服务的路由,这里我们也可以简单的将它作为我们 Lambda函数运行的触发器。
新建一个API Gateway,选择REST。
点击“操作” > “创建方法”,创建一个GET方法,集成环境选择Lambda函数,然后选择我们之前创建的Lambda函数。
最后点击“部署 API”,设置部署的阶段名称。这样我们的API部署就完成了
此时点击“阶段”,点击GET方法,会显示 “调用URL”,访问该url就会触发之前我们创建的Lambda函数
kintone自定义开发
最后我们在kintone上自定义一段js代码,以便我们只要点击一下按钮即可同步钉钉的数据。
kintone_cum.js
(function () { "use strict"; kintone.events.on('app.record.index.show', function (event) { if (document.getElementById('my_index_button') !== null) { return; } var myIndexButton = document.createElement('button'); myIndexButton.id = 'my_index_button'; myIndexButton.innerText = '同步钉钉'; var url = "xxxxxxxxx"; //aws的api gateway的调用url myIndexButton.addEventListener('click', (e) => { $.ajax({ url: url, method: 'get' }).always( function () { window.location.reload(); } ) }) kintone.app.getHeaderMenuSpaceElement().appendChild(myIndexButton); }); })();
将上面的代码如下图上传到刚才创建的应用中。
点击同步钉钉后,程序会自动拉取钉钉的打卡记录,并刷新页面
后记
通过Lambda可以不用关心服务器的基础架构的部署,直接关注我们业务逻辑代码的开发就可以了,它提供很多开发语言,java,python,ruby等等。
vpc的建立也很好的解决了安全方面的一些问题,我们的kintone也可以放心的开通“IP地址限制”,这样从AWS过来的访问也可以安全的加入到白名单了。
注意事项
本示例代码不保证其运行。
我们不为本示例代码提供技术支持。