腾讯云无服务器云函数实践

从传统的服务器到近年风生水起的云服务器微服务架构,再到无服务器(Serverless)架构,开发者们的探索之路永不停歇!

现有的云函数有:

AWS Lambda(鼻祖)

微软Azure Functions

Google Cloud Functions

Apache OpenWhisk

阿里云函数计算

腾讯云无服务器云函数

虽然各家的名称都不一样,但总体来说都是基于FaaS(Function as a Service),所有的事情都是基于函数去做。

它可以结合API网关来调用,进而达到传统服务器的功能。

优点

不需要管理,优化服务器,什么弹性伸缩,负载均衡都不用自己去做。

相对安全,可靠,因为这些事情都由产商来完成。

可用度高,触发执行,有需要的时候才会执行,空闲0成本。

开发者可以只关注业务逻辑,其它的一概不管。

其实,好多云商都在推出自家的函数产品,有一个很奇怪的现象,国内的几家云巨头的网页都做得一模一样,让人傻傻分不清。

由于我买了腾讯的云服务器,顺带就试了一下如何创建腾讯分无服务器云函数。

支持的语言有:Python2.7, Python3.6, Nodejs6.10, Nodejs8.9, Java8, Php5.6, Php7.2, Golang1

另外,微信小程序也推出了云函数开发,当然了只支持Nodejs的,也有数据库和云存储的支持,这也是我选择腾讯的另一个原因吧!

开发步骤:

在无服务器云函数控制台新建函数服务。

上传自己的代码(jar或zip)。

测试

注意事项:

Java版本是8.0。

Java执行方法格式为:[package].[class]::[method],注意包名只能是一级,还不支持多级包名(好像有坑,)。

日志:System.out.print就可以,或者使用java.util.logging,由于无法联调,日志信息很重要。

Demo

public class Function {public String handle(Input input) {System.out.println("-----------------");System.out.println("Input: " + input);if (input == null || input.getName() == null) {return "发生错误";}String result = input.getName().toUpperCase();System.out.println("Result: " + result);return result;}}public class Input {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}测试模板:

{"name":"abcd"}日志:

START RequestId: f389b1c9-edff-11e8-b97c-525400c7c826Event RequestId: f389b1c9-edff-11e8-b97c-525400c7c826Event:{"name": "abcd"}-----------------Input: demo.Input@4de8b406Result: ABCDEND RequestId: f389b1c9-edff-11e8-b97c-525400c7c826Report RequestId: f389b1c9-edff-11e8-b97c-525400c7c826 Duration:854.408ms Memory:128MB MaxMemoryUsed:31.168MB说实话腾讯云的bug还真不少,网页控制台里面居然没有String类型的模板,非得用JSON,。 不过也好,像这样简单的例子实际中也不存在。

编写函数代码总结一,事件入参(函数中的第一个变量)

Java基础类型包括String

POJO类型,必须有公有getter和setter方法。

二,Context入参(函数中的第二个变量为Context类型)

import com.qcloud.scf.runtime.Context...public String handle(Input input, Context context) { //}Context是什么?每家的函数服务都会传一个Context参数进去,一般是这个函数相关的一些变量,如名称,内存配置等,有些也会直接传一个logger对象进去, 腾讯云的Context现在还比较鸡肋:

package com.qcloud.scf.runtime;public abstract interface Context {public abstract String getRequestId();public abstract int getTimeLimitInMs();public abstract int getMemoryLimitInMb();// public abstract String getFunctionName();// public abstract String getFunctionVersion();// public abstract String getMemoryLimitInMb();// public abstract String getTimeLimitInMs();// public abstract String getLogGroupName();// public abstract String getLogStreamName();}三,返回结果可以是Java基础类,String和POJO。

 

四,Maven打包,需要用shade插件将所有jar包打到一起

build plugins plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-shade-plugin/artifactId version2.3/version configuration createDependencyReducedPomfalse/createDependencyReducedPom /configuration executions execution phasepackage/phase goals goalshade/goal /goals /execution /executions /plugin /plugins/buildSDK的使用腾讯云SDK在Github上有源码开发,是已经封装好了的API,也可以通过Maven来引用:

dependencygroupIdcom.tencentcloudapi/groupIdartifactIdtencentcloud-sdk-java/artifactIdversion3.0.29/version/dependency首先:实例化认证对象,需要腾讯云账户secretId和secretKey

// 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKeyCredential credential = new Credential(secretId, secretKey);ClientProfile profile = new ClientProfile(ClientProfile.SIGN_SHA256);ScfClient scfClient = new ScfClient(credential, region, profile);然后通过:CreateFunctionRequest,DeleteFunctionRequest,ListFunctionsRequest等进行函数的创建,删除等操作。

CreateFunctionRequest createRequest = new CreateFunctionRequest();if (uploaded) { Code code = new Code(); code.setCosBucketName(function.getBucket().getName()); code.setCosBucketRegion(function.getBucket().getRegion()); code.setCosObjectName(functionName); createRequest.setCode(code);}createRequest.setDescription(function.getDescription());createRequest.setRuntime(RUNTIME);createRequest.setFunctionName(functionName);createRequest.setHandler(handler);try { scfClient.CreateFunction(createRequest);} catch (TencentCloudSDKException e) { throw e;}源码上传源码上传有2中方式:

直接将打好的jar包或zip包通过网页控制台上传。

通过COS(腾讯云对象存储)上传。 通过COS上传,首先要把你的jar包或zip包上传到对象存储,然后在控制台中进行关联就可以了

注意的一点: 通过SDK+COS上传代码的时候,COS的bucketName不要带后面的appid,一般情况下载对象存储中名称是有[name]-[appid]组成的。

上传的代码如下:

COSCredentials cred = new BasicCOSCredentials(function.getSecretId(), function.getSecretKey());ClientConfig clientConfig = new ClientConfig(new Region(bucketRegion));COSClient cosClient = new COSClient(cred, clientConfig);if (!cosClient.doesBucketExist(bucketName)) {CreateBucketRequest request = new CreateBucketRequest(bucketSimpleName);cosClient.createBucket(request);cosClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);} else {cosClient.putObject(bucketName, function.getName(), mavenProject.getArtifact().getFile());}cosClient.shutdown();注意:这里的bucketName一定要是全名:([name]-[appid])。

但是如果用SDK更新云函数:一定记得不要带[appid],只使用前面的[name]作为bucketName。

Credential credential = new Credential(secretId, secretKey);ClientProfile profile = new ClientProfile(ClientProfile.SIGN_SHA256);ScfClient scfClient = new ScfClient(credential, region, profile);UpdateFunctionCodeRequest updateCodeRequest = new UpdateFunctionCodeRequest();updateCodeRequest.setFunctionName(functionName);updateCodeRequest.setHandler(handler);updateCodeRequest.setCosBucketName(bucketName);updateCodeRequest.setCosBucketRegion(bucketRegion);updateCodeRequest.setCosObjectName(objectName);scfClient.UpdateFunctionCode(updateCodeRequest);曾经因为这个问题,提了工单进行了好多次的重试。切记!


腾讯云优惠活动博客,实时更新腾讯云最新优惠活动及提供腾讯云代金券的领取。