使用Serverless Devs部署事件函数(阿里云)

环境配置

需要提前安装 Serverless Devs并配置好密钥

代码编写

  1. 导入依赖

    <dependency>
        <groupId>com.aliyun.fc.runtime</groupId>
        <artifactId>fc-java-core</artifactId>
        <version>1.3.0</version>
    </dependency>
    <dependency>
        <groupId>com.aliyun.fc.runtime</groupId>
        <artifactId>fc-java-common</artifactId>
        <version>2.2.0</version>
    </dependency>
    
  2. 配置maven插件,可以使用Apache Maven Shade插件或Apache Maven Assembly插件,推荐使用shade插件,目前实践使用Assembly打包部署会出现问题

     <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>3.2.1</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>shade</goal>
                            </goals>
                            <configuration>
                                <filters>
                                    <filter>
                                        <artifact>*:*</artifact>
                                        <excludes>
                                            <exclude>META-INF/*.SF</exclude>
                                            <exclude>META-INF/*.DSA</exclude>
                                            <exclude>META-INF/*.RSA</exclude>
                                        </excludes>
                                    </filter>
                                </filters>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
    
  3. 编写初始化方法和函数执行入口

    import com.aliyun.fc.runtime.*;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import javax.servlet.ReadListener;
    import javax.servlet.ServletInputStream;
    import java.io.*;
    /**
     * Hello world!
     *
     */
    
    public class FunctionApp implements StreamRequestHandler, FunctionInitializer {
        Logger logger = LoggerFactory.getLogger(getClass());
    
        private AppLoader fcAppLoader = new FcAppLoader();
    
    
        // Request url web path
        // 1. Without custom domain: /2016-08-15/proxy/${YourServiceName}/${YourFunctionName}
        // 2. With custom domain: your mapping settings path
        private String userContextPath = System.getenv("USER_CONTEXT_PATH");
    
        // Webapp home directory after inited
        private String appBaseDir = System.getenv("APP_BASE_DIR");
    
        //初始化方法,可以初始化spring容器,让多实例去共享一个spring容器
        @Override
        public void initialize(Context context) throws IOException {
            FunctionComputeLogger fcLogger = context.getLogger();
    
            // Config FcAppLoader
            fcAppLoader.setFCContext(context);
            if (appBaseDir != null) {
                fcAppLoader.setBaseDir(appBaseDir);
            }
    
            // Load code from /code
            fcLogger.info("Begin load code");
            fcAppLoader.loadCodeFromLocalProject("");
            fcLogger.info("End load code");
    
            // Init webapp from code
            long timeBegin = System.currentTimeMillis();
            fcLogger.info("Begin load webapp");
            boolean initSuccess = fcAppLoader.initApp(userContextPath, FunctionApp.class.getClassLoader());
            if(!initSuccess) {
                throw new IOException("Init web app failed");
            }
            fcLogger.info("End load webapp, elapsed: " + (System.currentTimeMillis() - timeBegin) + "ms");
        }
    
        @Override
        public void handleRequest(
                InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
            outputStream.write(new String("hello world").getBytes());
        }
    
    }
    
  4. 编写s.yaml文件

    edition: 1.0.0
    name: granwin_mns_demo
    # access 是当前应用所需要的密钥信息配置:
    # 密钥配置可以参考:https://www.serverless-devs.com/serverless-devs/command/config
    # 密钥使用顺序可以参考:https://www.serverless-devs.com/serverless-devs/tool#密钥使用顺序与规范
    access: 'xxx' #在cmd提前配好的密钥别名
    
    vars: # 全局变量
      region: 'cn-shenzhen'
      service:
        name: 'mns-demo2'
        description: 'mns-demo2'
        role: 'acs:ram::xxx:role/aliyunfcfullaccess'
        internetAccess: true
        logConfig: auto
        vpcConfig: # VPC配置, 配置后function可以访问指定VPC
          vpcId: vpc-xxx              # VPC ID
          securityGroupId: sg-xxx    # 安全组ID
          vswitchIds: # 交换机 ID 列表
            - vsw-xxx
    
    
    services:
      framework: # 业务名称/模块名称
        # 如果只想针对 framework 下面的业务进行相关操作,可以在命令行中加上 framework,例如:
        # 只对framework进行构建:s framework build
        # 如果不带有 framework ,而是直接执行 s build,工具则会对当前Yaml下,所有和 framework 平级的业务模块(如有其他平级的模块,例如下面注释的next-function),按照一定顺序进行 build 操作
        component: fc # 组件名称,Serverless Devs 工具本身类似于一种游戏机,不具备具体的业务能力,组件类似于游戏卡,用户通过向游戏机中插入不同的游戏卡实现不同的功能,即通过使用不同的组件实现不同的具体业务能力
        actions: # 自定义执行逻辑,关于actions 的使用,可以参考:https://www.serverless-devs.com/serverless-devs/yaml#行为描述
          pre-deploy: # 在deploy之前运行
            - run: mvn package -DskipTests # 要执行的系统命令,类似于一种钩子的形式
              path: ./ # 执行系统命令/钩子的路径
        #        - component: fc build --use-docker               # 要运行的组件,格式为【component: 组件名 命令 参数】(可以通过s cli registry search --type Component 获取组件列表)
        #        - plugin: myplugin                               # 与运行的插件 (可以通过s cli registry search --type Plugin 获取组件列表)
        #          args:                                          # 插件的参数信息
        #            testKey: testValue
        #      post-deploy: # 在deploy之后运行
        #        - component: fc versions publish # 要运行的命令行
        props: # 组件的属性值
          region: ${vars.region} # 关于变量的使用方法,可以参考:https://www.serverless-devs.com/serverless-devs/yaml#变量赋值
          service: ${vars.service}
          function:
            name: 'mns-demo2'
            description: 'mns-demo2'
            codeUri: ./target/mns_demo-jar-with-dependencies.jar #生成jar的位置
            handler: com.granwin.mns_demo.FunctionApp::handleRequest #执行入口
            initializer: com.granwin.mns_demo.FunctionApp::initiazlize       # 初始化方法
            initializationTimeout: 10 #初始化超时时间 单位 s
            environmentVariables: # 环境变量
              USER_CONTEXT_PATH: '/2016-08-15/proxy/mns-demo2/mns-demo2'
              APP_BASE_DIR: '/tmp'
            runtime: java8
            memorySize: 512
            timeout: 30
            instanceConcurrency: 1        # 单实例多并发
    #      triggers:
    #        - name: mnsTrigger            # 触发器名称
    #          type: mns_topic             # 触发器类型
    #          qualifier: 'LATEST'              # 触发服务的版本
    #          config: # 触发器配置,包括OSS触发器, Log触发器, Log触发器, Timer触发器, Http触发器, MNS触发器, CDN触发器
    #            topicName: mns-demo           # mns topic的名字
    #            notifyContentFormat: 'JSON'     # 推送给函数入参 event 的格式,可选值:STREAM, JSON
    #            notifyStrategy: 'BACKOFF_RETRY' # 调用函数的重试策略,可选值:BACKOFF_RETRY, EXPONENTIAL_DECAY_RETRY
    #            filterTag: abc                  # 描述了该订阅中消息过滤的标签(标签一致的消息才会被推送),不超过 16 个字符的字符串,默认不进行消息过滤,即默认不填写该字段
    
  5. 进入项目的目录,使用s deploy进行部署

    image-20221111163752573

6.在控制台进行测试,成功返回结果

image-20221111164005203