全部产品
存储与CDN 数据库 安全 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网

应用示例3 - 图像处理

更新时间:2017-11-10 17:55:31

本文介绍如何利用nodejs jimp图像处理库完成图像缩放功能。通过示例,您将了解:

  • 如何打包第三方依赖库
  • 如何开启和查看函数运行日志

本示例假定函数代码存放于code目录,源图片和结果图片存放于data目录,函数计算上已经存在名为“demo”的服务。如果您不了解创建服务等相关背景,请参阅hello world 应用示例

首先请执行 fcli shell 进入交互模式。

安装第三方依赖库

nodejs版本

由于函数依赖第三方图像处理库jimp,需要将它安装到code目录,和函数源代码一起打包上传。fcli为您提供了一个本地的沙盒环境,和函数计算服务中的函数运行环境保持一致。在沙盒环境中,您可以方便的安装第三方库,进行本地调试等操作。

  1. 执行sbox -d code -t nodejs6,其中 -d参数指定代码所在目录,它将被挂载到沙盒环境的”/code”位置;-t参数指定语言类型。

  2. 进入沙盒环境后,先运行 npm init -f生成package.json(nodejs6需要),再运行npm install jimp安装依赖库。

  3. 完成后执行exit退出沙盒环境。此时jimp库已经安装到了code目录下。

    注意

    1. sbox命令要求您的机器上已安装docker。docker的具体安装步骤,请参阅相关文档

    2. sbox用到的镜像存储在docker官方镜像库上,国内用户访问速度较慢。建议您使用阿里云镜像加速服务,具体设置请参阅相关文档

    3. 在 linux 下使用docker,要求有 root 权限。所以您需要使用 sudo fcli shell 的方式启动命令行工具;或者您可以参照相关文档设置,以非 root 用户管理 docker。

    4. 这边推荐您总是在沙盒环境中打包第三方库,测试函数和调查问题,这样能避免由于开发环境和运行环境不一致所引起的一些问题。特别是当您的函数依赖二进制文件时,请在沙盒环境中编译相关依赖。

      1. >>> sbox -d code -t nodejs6
      2. Entering the container. Your code is in the /code direcotry.
      3. root@df9fc6428140:/code# npm init -f
      4. npm info it worked if it ends with ok
      5. npm info using npm@3.10.10
      6. npm info using node@v6.10.3
      7. npm WARN using --force I sure hope you know what you are doing.
      8. Wrote to /code/package.json:
      9. {
      10. "name": "code",
      11. "version": "1.0.0",
      12. "description": "",
      13. "main": "index.js",
      14. "dependencies": {
      15. "jimp": "^0.2.28"
      16. },
      17. "devDependencies": {},
      18. "scripts": {
      19. "test": "echo \"Error: no test specified\" && exit 1"
      20. },
      21. "keywords": [],
      22. "author": "",
      23. "license": "ISC"
      24. }
      25. npm info init written successfully
      26. npm info ok
      27. root@df9fc6428140:/code# npm install jimp
      28. npm info it worked if it ends with ok
      29. ...
      30. npm info lifecycle jimp@0.2.28~postinstall: jimp@0.2.28
      31. code@1.0.0 /code
      32. -- jimp@0.2.28
      33. npm WARN code@1.0.0 No description
      34. npm WARN code@1.0.0 No repository field.
      35. npm info ok
      36. root@df9fc6428140:/code# exit
      37. exit

Python版本:

在python 版本中,这边的示例使用的是wand图像处理库,目前函数计算的python 运行环境中已经包含了wand这个模块, 所以这边不需要使用沙盒环境打包第三方库。想了解函数计算的Python运行环境中具体包含了哪些常用模块,请戳这里python_编程指南

注意: 如果有遇到问题,可以去该页面的最后一行点击进入完整demo shell 操作视频查看。

编写代码

在code目录下,创建 image_process.js 文件,实现名为 resize 的函数,其中源图片作为event参数传入。

  1. 'use strict';
  2. var jimp = require("jimp");
  3. var fs = require("fs")
  4. module.exports.resize = function(event, context, callback) {
  5. // 传入的event是png格式的图片,将其写入到tmp目录下。
  6. fs.writeFileSync("/tmp/serverless.png", event)
  7. // 读取/tmp目录下的png图片,调用jimp库完成resize,将结果图片写入到/tmp目录。
  8. jimp.read("/tmp/serverless.png", function(err, image) {
  9. if (err) {
  10. console.error("failed to read image");
  11. callback(err)
  12. return
  13. }
  14. image.resize(128, 128)
  15. .write("/tmp/serverless_128.png", function(err) {
  16. if (err) {
  17. console.error("failed to write image");
  18. callback(err)
  19. return
  20. }
  21. // 从/tmp目录读取结果图片,并作为response返回。
  22. callback(null, fs.readFileSync("/tmp/serverless_128.png"))
  23. })
  24. });
  25. };
  1. # -*- coding: utf-8 -*-
  2. from wand.image import Image
  3. def resize(event, context):
  4. with Image(blob=event) as img:
  5. with img.clone() as i:
  6. i.resize(128, 128)
  7. return i.make_blob()

创建SLS日志库

函数计算会将函数运行日志存储到您指定的日志库中。执行mkl -p fc -s demo在日志服务中创建名为 fc 的log project,和名为 demo 的log store。

注意:

  1. 如果没有开通日志服务请先开通(开通了的请先查看下是否欠费)。

  2. 如果您已经有log store,这一步可跳过。

  3. 如果您复制上述命令执行,您可能会收到下述错误。这是由于日志服务的 project 名称要求全局唯一,您需要将 fc 改名。详见日志服务文档

    1. Error: {
    2. "errorCode": "ProjectAlreadyExist",
    3. "errorMessage": "Project fc already exist",
    4. ...
    5. }
  4. 您需要为使用的日志资源单独付费。特别注意,日志服务会对资源收取一定的预留费用,这意味着即使您不写任何日志,也会付费,最低¥0.04/每天。计费细节请参阅相关文档

  5. 由于日志是调试和问题诊断的重要信息,强烈建议您开通日志服务来保存函数运行日志。

    1. songluo@demo $ ./fcli shell
    2. Welcome to the function compute world. Have fun!
    3. >>> mkl --help
    4. mkl: create the log project/store
    5. flags:
    6. --help
    7. -p, --project string the log project
    8. --shard int the shard count of the log store (default 1)
    9. -s, --store string the log store
    10. --ttl int the ttl of the log store, in days (default 30)
    11. >>> mkl -p fc -s demo
    12. Note: you have to pay at least 0.04 RMB/day for the log store resource. For the detail billing info please refer to:
    13. https://www.aliyun.com/price/product#/sls/detail
    14. Do you want to create the log store? [y/n]
    15. y
    16. >>>

授权函数计算日志库写权限

由于日志是用户的资源,函数计算需要获得用户的显式授权才能写入日志。执行grant demo命令,根据提示信息,授予函数计算将 demo 下的函数运行日志写到指定的日志库中。函数计算的权限管理基于阿里云资源访问控制服务(RAM),细节请参阅相关文档

注意:如果您当前使用的账户是 RAM 子用户,则执行 grant 命令时可能会收到如下错误。这是由于您的账户没有 create policy 等权限。您需要主账户为您授予相关权限。

  1. Error: failed to create policy write-fc-logs due to {
  2. "HttpStatus": 404,
  3. "HostId": "ram.aliyuncs.com",
  4. "Code": "Inactive",
  5. "Message": "Account is inactive to this service"
  6. }
  1. songluo@demo $ ./fcli shell
  2. Welcome to the function compute world. Have fun!
  3. >>> grant demo
  4. Please input the role name:
  5. fc-logs
  6. Please input the policy name:
  7. write-demo-logs
  8. Permission grant scenarios:
  9. 1. Allow FC write function logs to your log store.
  10. 2. Allow FC copy code from your OSS location.
  11. Please input your choice [1-2]:
  12. 1
  13. Please input the log project: fc
  14. Please input the log store: demo
  15. ...grant success
  16. >>> info /ram/roles/fc-logs
  17. Role:
  18. {
  19. "RoleId": "338942517712635876",
  20. "RoleName": "fc-logs",
  21. "Arn": "acs:ram::1186202104331798:role/fc-logs",
  22. "Description": "create the role fc-logs",
  23. "AssumeRolePolicyDocument": "{\n \"Statement\": [{\n \"Action\": \"sts:AssumeRole\",\n \"Effect\": \"Allow\",\n \"Principal\": {\"Service\": [\"fc.aliyuncs.com\"]}}],\n \"Version\": \"1\"}",
  24. "CreateDate": "2017-09-19T09:12:12Z"
  25. }
  26. Attached policies:
  27. [{write-demo-logs Custom create the policy write-demo-logs v5 0} {fc-copy-code-all Custom create the policy fc-copy-code-all v1 0} {fc-oss-rw Custom create the policy fc-oss-rw v1 0}]

创建并调用函数

执行mkf demo/resize -t nodejs6 -h image_process.resize -d code,在函数计算上创建名为 resize 的函数,属于 demo 服务。[ 注:python版本把runtime设置为python2.7 ]。

  1. songluo@demo $ ./fcli shell
  2. Welcome to the function compute world. Have fun!
  3. >>> mkf demo/resize -t nodejs6 -h image_process.resize -d code

调用函数并查看日志

假定源图片在 data 目录下,名为 serverless.png ,执行invk demo/resize -f data/serverless.png -o data/serverless_128.png,完成图片的缩放。

执行logs demo查看整个 demo 服务的日志,执行logs demo/resize查看指定函数的日志。

  1. songluo@demo $ ls
  2. code data fcli
  3. songluo@demo $ cd code
  4. songluo@code $ ls
  5. hello_world.js image_process.js node_modules
  6. songluo@demo $ fcli shell
  7. Welcome to the function compute world. Have fun!
  8. >>> ls demo
  9. resize
  10. world
  11. >>> invk demo/resize -f data/serverless.png -o data/serverless_128.png
  12. >>> logs demo/resize
  13. 2017-09-28T15:54:35+08:00 serviceName:demo functionName:resize message:2017-09-28T07:54:35.426Z [info] FunctionCompute nodejs runtime inited.
  14. 2017-09-28T15:54:35+08:00 serviceName:demo functionName:resize message:FC Invoke Start RequestId: c3c4b57d-847b-42c3-daf0-4f3a8cc278e4
  15. 2017-09-28T15:54:35+08:00 serviceName:demo functionName:resize message:FC Invoke End RequestId: c3c4b57d-847b-42c3-daf0-4f3a8cc278e4

示例3 完整demo操作视频,请点击 image_process

本文导读目录