阿里云函数计算限制了上传的项目文件必须在50M以内,但是spring boot项目依赖了大量的第三方包,轻轻松松打包出来大于50M。
具体解决的方案有两种:第一种是把项目改成war包,然后上传到oss上,函数计算单独作为一个项目入口。具体操作参考:https://yq.aliyun.com/articles/703125?spm=5176.11065265.1996646101.searchclickresult.2bd53ba6gCpgeY&aly_as=yag25Ia4
这个方案需要调整项目成为war,还需要另外建一个函数计算项目,当然函数计算项目基本上不会有什么内容和改动,只是提供一个入口文件和template.yml配置。
第二种方法的思路是把第三方包放到nas上,打包的时候不放到项目jar包里面去,在函数入口的地方调整classLoad方法,读取nas中的包,从而大幅减少jar包大小。好处就是修改代码功能后,如不涉及第三方包的新增修改,上传文件很小。
项目可以参考:hxtrip-serverless;具体操作步骤:
首先要看项目所在环境,如果使用vpc网络的话,可以设置nas:auto,函数计算会自动创建nas;我们公司是在专用VPC环境下,所以需要手动创建。
-
打开文件存储nas,https://nas.console.aliyun.com/?spm=5176.12818093.aliyun_sidebar.28.488716d0zhnPQE#/ofs/list;
-
新建一个文件系统,然后设置可用区的时候,一定要选择可用区E,因为函数计算只能访问到可用区E的资源。
-
增加挂载点,选择对应的VPC网络和交换机;创建交换机完成以后,在挂载命令中找到对应的ServerAddr,后续要用这个。
4、在template.yml中增加nas配置,具体参考如下
ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
#创建服务
hxtrip-serverless-service:
Type: 'Aliyun::Serverless::Service'
Properties:
#服务的描述
Description: 'hxtrip serverless demo'
NasConfig:
UserId: 10003
GroupId: 10003
MountPoints:
- ServerAddr: '367444a369-mgf1.cn-shanghai.nas.aliyuncs.com:/'
MountDir: '/mnt/auto'
主要看NasConfig这块配置,修改其中的ServerAddr为挂载点中的值即可,其他不用调整。
- 增加Entrypoint.class类,作为项目入口。具体可以参考hxtrip-serverless项目中的代码,也可以参考github上代码
https://github.com/vangie/oversize-java-example/blob/master/src/main/java/example/Entrypoint.java
6.再次调整template.yml中的函数的入口配置;具体如下
#创建函数方法
user-api:
Type: 'Aliyun::Serverless::Function'
Properties:
#初始化函数的调用入口
Initializer: com.hxtrip.serverless.Entrypoint::initialize
#处理函数的调用入口
Handler: com.hxtrip.serverless.Entrypoint::handleRequest
#运行时环境
Runtime: java8
#代码位置
CodeUri: './target/serverless-1.0.0.jar'
#每次函数执行分配的内存大小,单位是 MB
MemorySize: 256
#处理函数在被终止之前可以运行的最长时间,单位是秒
Timeout: 60
#初始化函数在被终止之前可以运行的最长时间,单位是秒
InitializationTimeout: 60
#函数配置环境变量
EnvironmentVariables:
'USER_CONTEXT_PATH': '/2016-08-15/proxy/hxtrip-serverless-service/user-api'
'APP_BASE_DIR': '/tmp'
'active': 'pro'
FUN_HANDLER: com.hxtrip.serverless.FcHandler::handleRequest
FUN_INITIALIZER: com.hxtrip.serverless.FcHandler::initialize
核心点是把入口的Handler和Initializer改成了Entrypoint类,原本的FcHandler类移动到环境变量里面,增加FUN_HANDLER和FUN_INITIALIZER两个参数。这两个参数在ENtrypoint类中使用。
- 在pom中增加plugin配置;
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/.fun/nas/367444a369-mgf1.cn-shanghai.nas.aliyuncs.com/lib</outputDirectory>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${project.java.version}</source>
<target>${project.java.version}</target>
</configuration>
</plugin>
</plugins>
其中outputDirectory中的配置值需要替换成自己的serverAddr。这个配置是指定第三方依赖的包所在目录位置。
8. 修改的地方都已经完成了。现在可以执行命令mvn clean package。可以看到项目文件夹下的.fun目录下会多出一个nas文件夹,可以看到所以依赖的jar包都到这个里面去了。
然后执行命令 fun nas sync 把这些文件上传到nas上去。完成之后执行fun deploy上传项目。
上传完成之后,可以去函数计算的控制台查看是否正确,可以看到入口和环境变量都已经改动正确了。
执行命令 fun nas ls -al nas:///mnt/auto/lib 可以排查nas上是否把文件都上传上去了。
另外注意的是如果template.yml中的函数配置CodeUri 如果写 ./,可以使用 fun build,如果写了 xxx.jar,那么就不需要了。运行fun build会覆盖配置,需要去.fun文件中把build文件夹删除。
参考文案:
阿里云函数计算控制台:https://fc.console.aliyun.com/fc/overview/cn-shanghai
阿里云函数计算帮助文档:https://help.aliyun.com/product/50980.html
Github参考项目:https://github.com/vangie/oversize-java-example