一、云函数的概述
1、什么是云函数
- 官方解释
云函数是一项Serverless计算服务,提供FaaS(Function as a Service)能力,一方面云函数将开发测试的对象聚焦到函数级别,可以帮助您大幅简化应用开发与运维相关的事务,另一方面您可以通过在应用中集成云函数SDK,便捷操作云数据库、云存储等,提升业务功能构建的便利性。云函数可以根据函数的实际流量对函数进行弹性伸缩,您无需对服务器资源进行管理,解决了开发者运维管理的难题。
- 通俗理解
云函数是一种无需管理服务器的计算服务,可以让你只专注于编写函数代码,不需要处理服务器的复杂管理。通过云函数,你可以轻松连接云数据库和云存储,方便地构建应用功能。而且,它会根据你应用的访问量自动调整资源,不用你手动管理服务器资源,让你更专注于开发应用本身。
补充:什么是Serverless?
Serverless 是一种无需管理服务器和运行环境的计算服务。你可以把它想象成一种按需的云计算资源,就像打开水龙头就有水一样,你只需要调用API,云服务就会为你分配所需的计算资源,而无需提前准备服务器或部署应用。Serverless服务实现了计算资源的按需分配,简化了应用的部署和维护,使得开发者可以更加专注于业务逻辑的开发。
2、云函数作用
-
简化开发与运维
云函数提供了高效可靠的函数开发与运行框架,替开发者完全解决传统应用开发与运维中的诸多复杂事务(如服务器配置与管理、代码部署、负载均衡、弹性伸缩、高可用保证等等),您只需聚焦业务逻辑、开发并上传函数代码,即可构建高可用、可伸缩的Serverless应用。
-
扩展周边服务
云函数作为Serverless的核心与枢纽,支持方便连接和扩展周边云服务能力,您可以像拼搭积木一样自由便捷地组织各项服务来实现业务逻辑。
3、云函数工作原理
该图片展示了鸿蒙端云一体化的工作原理。从左到右,上到下,我们可以看到以下主要组件和它们之间的关系:
-
开发云函数:这表示开发者可以在本地或云端环境中编写和部署函数。这些函数可以通过SDK(软件开发工具包)被集成到各种应用程序中,如移动端、桌面端等。
-
函数仓库:这是一个存储和管理函数的地方,开发者可以将他们编写的函数上传到这里。
-
触发器类型:当特定事件发生时,会触发函数的执行。例如,可以通过HTTP请求、消息队列、定时器等方式触发函数。
-
云函数:这是运行在云端的服务,可以自动伸缩以应对高并发请求。开发者发布的函数会被部署到云函数上,供全球用户访问。
-
函数运行平台:这是一个为函数提供运行环境的平台,包括认证服务、云数据库和HTTP网关等功能。
-
函数A、B、C:这些都是开发者发布的具体函数,每个函数都可以有自己的功能和用途。
-
HTTP网关:这是一个对外接口,允许外部客户端通过HTTP协议调用函数。
整个流程如下:开发者首先在本地或云端环境中开发函数,然后将其上传到函数仓库。之后,这些函数可以通过不同的触发器类型被触发,并在云函数上执行。执行结果可以通过函数运行平台的API返回给调用者。
鸿蒙端云一体化的这种架构使得开发者可以更专注于函数的开发,而无需关心底层的基础设施。同时,它也提供了高度的可扩展性和灵活性,使应用能够轻松应对各种业务需求的变化。
二、云函数开发准备
1、创建项目(如果已创建直接进入第二步)
1)登录,点击“我的项目”。
AGC平台地址
如果大家第一次点击我的项目,会出现以下同意协议,后续出现类似的,同意或者确定。
2)在项目页面中点击“添加项目”。
3)在“创建项目”页面中输入项目名称后 ,点击“创建并继续”。
说明:
点击“创建并继续”后,如果系统提示“您所在团队创建的项目数已经达到上限,请清理不需要的项目”,请进入“我的项目”,点击需要删除的项目卡片,点击“项目设置”页面下方的“删除项目”清理多余的项目。
2、添加应用(已经添加直接进入第三步)
如果已经创建了项目,可以使用已经创建的项目,如果不想使用已经创建的项目,则可以自己重新按照上一个小节创建AGC项目
-
若项目中没有应用,在“项目设置”页面中点击“添加应用”。
若项目中已有应用,展开顶部应用列表框,点击“添加应用”。
添加应用页面设置参数
第一步:选择APP(HarmonyOS)
第2步:选择APPID进行参数设置,点击下一步
下一步选择,项目,这里是默认的就好,因为我是通过项目来创建应用的,直接点击确认
说明:
如果提示“包名已存在,请更换包名”,您需要检查下您是否已经创建相同包名的应用,如果有,请勿重复创建。如果您未创建,请联系华为技术支持人员进行处理。
3、开通服务
- 登录AppGallery Connect,点击“我的项目”。
- 在项目列表中点击需要开通云函数的项目。
3. 在左侧导航栏选择“云开发(Serverless)> 云函数”,进入云函数页面,点击“立即开通”。
三、开发云函数(服务端编写+客户端调用)
1、案例01:简单计算案例
需求:实现用于计算两个数的值 之和的云函数
实现思路
1、服务器端创建云函数
2、服务器端测试云函数是否正常运行通过
3、编写客户端的代码来调用云函数
4、运行测试
实现步骤
第一步:服务器端创建云函数
新建一个函数名名为fun0901的函数名
点击创建
函数配置、点击下一步
触发器的选择,这里默认就够了
编辑函数代码
放大以后,编写代码,默认模版,我们可以在里面进行编辑,圈红的地方都不要动
编辑函数代码,函数的功能就是获取两个数,然后再进行相加,然后将相加的结果返回,代码编辑好了以后,缩小编辑区域,进入下一步
第二步:测试
完成以后,点击测试,运行函数
第三步:客户端调用
(1)创建项目
注意bundle name要和云侧项目的包名一致
(2)下载sdk配置文件 agconnect-services.json
将下载的json文件复制到src/main/resources/rawfile目录中
(3)配置oh-package.json5
entry\oh-package.json5
鸿蒙操作系统中的oh-package.json5
文件是用于配置鸿蒙应用的元数据文件,类似于Node.js中的package.json
。这个文件定义了鸿蒙应用的名称、版本、描述、主要入口文件、作者、许可证以及依赖关系等信息。json5
是JSON的一个扩展,它允许在文件中使用注释和更为宽松的语法。记得点sync
"dependencies": {"@hw-agconnect/crypto-ohos": "^1.0.10","@hw-agconnect/function-ohos": "^1.0.10","@hw-agconnect/auth-ohos": "^1.0.10","@hw-agconnect/cloudstorage-ohos": "^1.0.10","@hw-agconnect/api-ohos": "^1.0.10","@hw-agconnect/base-ohos": "^1.0.10","@hw-agconnect/core-ohos": "^1.0.10","@hw-agconnect/credential-ohos": "^1.0.10","@ohos/agconnect-auth-component": "^1.0.5","@hw-agconnect/auth-component": "^1.0.0","@hw-agconnect/cloud": "^1.0.0","@hw-agconnect/hmcore": "^1.0.0","long": "5.2.1"}
(4)加入网络权限
src/main/module.json5
"requestPermissions": [{"name": 'ohos.permission.INTERNET'}],
(5)修改.so文件的加载顺序
entry/build-profile.json5
...
"buildOption": {//配置筛选har依赖.so资源文件的过滤规则"napiLibFilterOption": {//按照.so文件的优先级顺序,打包最高优先级的.so文件"pickFirsts": ["**/1.so"],//按照.so文件的优先级顺序,打包最低优先级的.so 文件"pickLasts": ["**/2.so"],//排除的.so文件"excludes": ["**/3.so"],//允许当.so重名冲突时,使用高优先级的.so文件覆盖低优先级的.so文件"enableOverride": true,}}
...
(6)entryAbility初始化
import { initialize } from '@hw-agconnect/hmcore';
import json from '../../resources/rawfile/agconnect-services.json'
...async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {try {await initialize(this.context, json);console.info('hmlog-->','AGConnectSuccessed!')} catch (e) {console.error('hmlog-->','AGConnectError', JSON.stringify(e))}}
(7) 客户端调用
import cloud from '@hw-agconnect/cloud'
import { FunctionResult } from '@hw-agconnect/function-ohos'@Entry
@Component
struct Demo01 {@State a:number=0 //加数1@State b:number=0 //加数2@State c:number=0 //结果build() {Column({space:30}){Text("客户端调用云函数(案例一:简单案例)")Row({space:15}){TextInput({text:""+this.a}).width(80).onChange(val=>this.a=parseInt(val))Text("+")TextInput({text:""+this.b}).width(80).onChange(val=>this.b=parseInt(val))Text("=")Text(this.c+"")}.width("100%")Button("计算").width("60%").onClick(()=>{this.callFun()})}.width("100%").padding(30)}//点击计算按钮的的时候调用云函数async callFun(){//一般情况下肯定是需要看看输入是否为空,格式对不对//以上我们假设做过了//调用云函数//函数名//version 函数的版本 默认版本就是$latestlet res:FunctionResult=await cloud.callFunction({name:"fun0901",version:'$latest',params:{"num1":this.a,"num2":this.b}})// this.c = res.getValue()// console.log(JSON.stringify(res.getValue())) //{"result":121}this.c = res.getValue().resultconsole.log(this.c+"<====")}
}
2、案例02:根据输入的年,获取这个年的生肖
实现思路
1、服务器端创建云函数
2、服务器端测试云函数是否正常运行通过
3、编写客户端的代码来调用云函数
4、运行测试
实现步骤
第一步:服务器端创建云函数
新建一个函数名名为fun0902的函数名,其他操作和上面案例01一致(参考上面),函数内容如下
// handler.js is a demo for handler function.
let myHandler = function(event, context, callback, logger) {let res = new context.HTTPResponse({"simple": "example"}, {"res-type": "simple example","faas-content-type": "json"}, "application/json", "200");//声明一个变量year,用于接受传递过来的参数let year;//如果body中有数据,那就是客户端调用传递过来的参数if(event.body){//获取传递过来的参数year = JSON.parse(event.body).year}else{//如果是服务端调用当前的函数,那就直接通过event.year获取year = event.year}//将year对12求余//function isNumber(input){logger.info(parseInt(input).toString())if(parseInt(input).toString()=='NaN'){return false}else{return true}}//自己封装的方法function animal(inputyear){let shengxiao ="" //这个变量用于保存具体的生效if(!isNumber(inputyear)){shengxiao="please input a number"}else{let yu=year%12switch(yu){case 0: shengxiao='猴'breakcase 1: shengxiao='鸡'breakcase 2: shengxiao='狗'breakcase 3: shengxiao='猪'breakcase 4: shengxiao='鼠'breakcase 5: shengxiao='牛'breakcase 6: shengxiao='虎'breakcase 7: shengxiao='兔'breakcase 8: shengxiao='龙'breakcase 9: shengxiao='蛇'breakcase 10: shengxiao='马'breakcase 11: shengxiao='羊'break}}return shengxiao;}//给调用者响应res.body = {result:animal(year)}// send responsecallback(res);
};module.exports.myHandler = myHandler;
客户端调用
import cloud from '@hw-agconnect/cloud'@Entry
@Component
struct Demo02 {//用于存放年@State num:number=0@State shengxiao:string = "" //用于查询生效的结果build() {Column({space:15}){Text("客户端调用云函数(案例二:复杂点的示例)")TextInput().onChange(val=>this.num=Number(val))Button("查询生效").width("100%").onClick(()=>{this.getShengXiao()})Text("生肖:"+this.shengxiao)}.width("100%").height("100%").padding(30)}async getShengXiao(){try {let rs = await cloud.callFunction({name:"fun0902",version:"$latest",params:{year:this.num}})this.shengxiao = rs.getValue().result}catch (e) {console.log("====>error:",JSON.stringify(e))}}
}
四、开发云函数(使用端云一体化的方式)
案例01:简单的计算案例
1、创建项目、选择CloudDev,然后点击下一步
云侧项目,找到云函数(cloudfunctions)右击,new Cloud Function
创建好了的默认内容
右击函数,执行run
dev中,将函数测试好了没有问题,后续再传到云端
到此云侧函数创建好了,但是还没有实现具体的功能,要实现具体的功能,写代码调试,最后再上传到 云侧就可以
在dev中书写的云侧的代码,并测试成功
let myHandler = async function (event, context, callback, logger) {logger.info(event);// do something herelet num1:number = 0let num2:number = 0//如果是客户端调用if(event.body){let _body = JSON.parse(event.body)num1 = _body.num1num2 = _body.num2}else{//如果是服务器端调用就执行这个num1 = event.num1num2 = event.num2}let sum = num1+num2callback({code: 0,desc: "Success.",body:{result:sum}});
};export { myHandler };
下一步就将我们的在一体化项目中创建的云函数发布的云服务上去
上传到云函数成功了。
客户端,调用云函数
客户端可以使用这个端云一体化的项目(端侧)调用云函数,端侧项目没有rawfile目录,需要自己创建。另外还需配置依赖so文件加载顺序。。。。都需要再做
节约时间,我个人直接使用原来的不是端云一体化的项目进行访问了,这个功能和前面一样。
import cloud from '@hw-agconnect/cloud'
import { FunctionResult } from '@hw-agconnect/function-ohos'@Entry
@Component
struct Demo03 {@State a:number=0 //加数1@State b:number=0 //加数2@State c:number=0 //结果build() {Column({space:30}){Text("客户端调用云函数(端云一体化创建的云函数)")Row({space:15}){TextInput({text:""+this.a}).width(80).onChange(val=>{this.a=Number(val) //针对""转换为0 但是parseInt 针对空字符转成NaN})Text("+")TextInput({text:""+this.b}).width(80).onChange(val=>this.b=Number(val))Text("=")Text(this.c+"")}.width("100%")Button("计算").width("60%").onClick(()=>{this.callFun()})}.width("100%").padding(30)}//点击计算按钮的的时候调用云函数async callFun(){//一般情况下肯定是需要看看输入是否为空,格式对不对//以上我们假设做过了//调用云函数//函数名//version 函数的版本 默认版本就是$latestlet res:FunctionResult=await cloud.callFunction({name:"fun0903",version:'$latest',params:{"num1":this.a,"num2":this.b}})// this.c = res.getValue()// console.log(JSON.stringify(res.getValue())) //{"result":121}console.log("====>",JSON.stringify(res.getValue())) //注意端云一体化云函数返回的内容this.c = res.getValue().body.result}
}
案例02:输入数值获取生效案例
1、云开发本地开发云函数
let myHandler = async function (event, context, callback, logger) {/*** 根据输入的一个年份 获取生效* @param input 输入的年份*/function getZodiac(input){let mo:number = input%12let zodiac=""switch (mo){case 0:zodiac="猴"breakcase 1:zodiac="鸡"breakcase 2:zodiac="狗"breakcase 3:zodiac="猪"breakcase 4:zodiac="鼠"breakcase 5:zodiac="牛"breakcase 6:zodiac="虎"breakcase 7:zodiac="兔"breakcase 8:zodiac="龙"breakcase 9:zodiac="蛇"breakcase 10:zodiac="马"breakcase 11:zodiac="羊"breakdefault :zodiac="请输入数值"break}return zodiac}let yearif(event.body){year=JSON.parse(event.body).year}else{year=event.year}//如果year的类型是字符串类型的话 返回请输入数字if(typeof(year)=='string'){callback({result:"对不起请输入数字"});}else{//否则就正常返回生肖的内容callback({result:getZodiac(year)})}
};export { myHandler };
2、端侧调用发布到云侧的代码
import cloud from '@hw-agconnect/cloud'@Entry
@Component
struct Demo04 {//用于存放年@State num:number=0@State shengxiao:string = "" //用于查询生效的结果build() {Column({space:15}){Text("客户端调用云函数2(端云一体化上传的)")TextInput().onChange(val=>{if(Number(val).toString()=="NaN"){this.num = -1}else{this.num = Number(val)}})Button("查询生效").width("100%").onClick(()=>{this.getShengXiao()})Text("生肖:"+this.shengxiao)}.width("100%").height("100%").padding(30)}async getShengXiao(){try {let rs = await cloud.callFunction({name:"fun0904",version:"$latest",params:{year:this.num}})this.shengxiao = rs.getValue().result}catch (e) {console.log("====>error:",JSON.stringify(e))}}
}