开发一个Serverless应用

本文涉及的产品
简介: 当我们通过Serverless架构,建立了一个函数,并输出了Hello World之后,表明我们已经完成了Serverless架构的“初体验”,接下来,我们可以以其中一个云厂商为例(例如阿里云),进行基础的小工具开发和建设。

当我们通过Serverless架构,建立了一个函数,并输出了Hello World之后,表明我们已经完成了Serverless架构的“初体验”,接下来,我们可以以其中一个云厂商为例(例如阿里云),进行基础的小工具开发和建设。

在我们日常的生产中,需要获取客户端外网IP是一个非常常见的需求,但是在客户端直接获取外网IP实际上是一个比较困难的事情,这个时候就会有一个简单的方法:在服务端开一个接口来做这个事情,即当客户端请求该接口之后,该接口返回其IP地址。

如果我们选择用Python语言来开发这个项目,在传统的项目中,这个看似简单的应用,实际上并不简单,它通常需要我们有:

这里面包括Nginx,Python的环境,还要有我们所需要的Web Framework的框架(例如Django、Flask、Bottle、Web2py等),除此之外还要有我们的业务逻辑。在项目完成开发,上线之后,我们可能还需要对服务器的健康等进行持续关系和关注,必要时还要做一些高可用方案等。但是在Serverless架构下,这个过程将会变得非常简单:

在整个项目中,我们无需关注Nginx这些服务器软件,无需关注Python等环境的安装配置,更不用关心一些服务器的运维操作,在很多时候也无需关注高可用,我们关心的只是我们的函数代码,至于一些服务器软件全都交给云厂商来搞定,API网管等产品提供类似Nginx的能力,函数计算提供Python的运行环境,至于高可用、极致弹性则是函数计算所必备的“基础能力”。当然,让使用者更关注自身的业务逻辑,这也是Serverless的优势之一。

知识准备

为了更好的完成项目,以阿里云函数计算为例,在开始项目之前,需要进行一些概念的明确,基础知识的储备。

什么是Runtime

所谓的Runtime实际上就是所谓的运行时,可以认为是一种环境或者说是一种支持,例如阿里云函数计算提供了Python2.7的Runtime,可以认为你的Python2.7的应用是可以运行在这个环境下,针对不同的Runtime在文档中都会相关的描述,以Python相关的Runtime为例,在官网上,我们可以看到相关Runtime的描述信息,包括日志的输出方法,所支持的编程语言及版本,所运行的系统类型及版本,以及默认集成的工具/模块/依赖等。

什么是触发器

众所周知,函数计算是通过事件进行触发的,触发器是触发函数执行的方式。在事件驱动的计算模型中,事件源是事件的生产者,函数是事件的处理者,而触发器提供了一种集中、统一的方式来管理不同的事件源。在事件源中,当事件发生时,如果满足触发器定义的规则,事件源会自动调用触发器所对应的函数。

当然不同的事件源和函数进行一个事件的数据结构的规约,当事件源因为某些规则触发了函数,那么这个预先规约好的数据结构,将会作为参数之一传递给函数,例如阿里云对象存储与函数计算规约的事件数据结构:

{

 "events": [

   {

     "eventName": "ObjectCreated:PutObject",

     "eventSource": "acs:oss",

     "eventTime": "2017-04-21T12:46:37.000Z",

     "eventVersion": "1.0",

     "oss": {

       "bucket": {

         "arn": "acs:oss:cn-shanghai:123456789:bucketname",

         "name": "testbucket",

         "ownerIdentity": "123456789",

         "virtualBucket": ""

       },

       "object": {

         "deltaSize": 122539,

         "eTag": "688A7BF4F233DC9C88A80BF985AB7329",

         "key": "image/a.jpg",

         "size": 122539

       },

       "ossSchemaVersion": "1.0",

       "ruleId": "9adac8e253828f4f7c0466d941fa3db81161****"

     },

     "region": "cn-shanghai",

     "requestParameters": {

       "sourceIPAddress": "140.205.***.***"

     },

     "responseElements": {

       "requestId": "58F9FF2D3DF792092E12044C"

     },

     "userIdentity": {

       "principalId": "123456789"

     }

   }

 ]

}          

当用户的函数设置了OSS触发器,并绑定了某个对象存储的存储桶,当这个存储桶满足绑定操作时,即会生成一个事件,并触发函数。例如,我们可以为我们的函数计算设置一个OSS触发器,绑定存储桶“MyServerlessBook”(这个存储桶通常需要和用户的函数在同一个账号下,同一个地域下),设置了一个触发条件“oss:ObjectCreated:PutObject”(调用PutObject接口上传文件即会触发该函数),所以一旦该存储桶收到以PutObject接口上传的文件,就会按照之前规约好的数据结构生成一个事件,触发当前函数并将事件作为参数传递给函数的对方方法。

什么是函数入口

在我们学习C语言的时候,都会会知道一个叫main()的函数,main()函数称之为主函数,一个C程序总是从main()函数开始执行的,例如:

#include <stdio.h>

int main(void)

{

   printf("HelloWorld!\n");

   return 0;

}

其实在函数计算中也是这样,在我们创建函数的时候,我们也需要告知系统,我们的入口方法是什么。通常情况下,函数入口的格式为[文件名].[函数名]。以Python为例,创建函数时指定的Handler为index.handler,那么函数计算会去加载index.py中定义的handler函数。通常情况下一个函数计算的入口方法会有两个参数:

def handler(event, context):

   return 'hello world'

一个是event,一个是context:

event: 是用户自定义的函数入参,以字节流的形式传给函数,数据结构由您自行定义,它可以是一个简单的字符串 、一个JSON对象、一张图片(二进制数据)。函数计算不对event参数的内容进行任何解释。

对于不同的函数触发情况,event参数的值会有以下区别:

  • 事件源服务触发函数时,事件源服务会将事件以一种平台预定义的格式作为event参数传给函数,您可以根据此格式编写代码并从event参数中获取信息。例如使用OSS触发器触发函数时会将Bucket及文件的具体信息以JSON格式传递给event参数。
  • 函数通过SDK直接调用时,您可以在调用方和函数代码之间自定义event参数。调用方按照定义好的格式传入数据,函数代码按格式获取数据。例如定义一个JSON类型的数据结构{"key":"val"}作为event,当调用方传入数据{"key":"val"}时,函数代码先将字节流转换成JSON,再通过event["key"]来获得值val

context: context参数是函数计算平台定义的函数入参,它的数据结构由函数计算设计,包含函数运行时的信息,使用场景通常有两种,一种是用户的临时密钥信息可以通过context.credentials获取,通过context中的临时密钥去访问阿里云的其他服务(使用示例中以访问OSS为例),避免了在代码中使用密钥硬编码。另一种是在context中可以获取本次执行的基本信息,例如requestId、serviceName、functionName、qualifier等。在阿里云函数计算中,关于context的结构基本如下

{  

  requestId: '9cda63c3-1ac9-45ba-8a59-2593bb9bc101',  

  credentials: {    

     accessKeyId: 'xxx',    

     accessKeySecret: 'xxx',    

     securityToken: 'xxx'  

  },  

  function: {    

     name: 'xxx',    

     handler: 'index.handler',    

     memory: 512,    

     timeout: 60,    

     initializer: 'index.initializer',    

     initializationTimeout: 10  

  },  

  service: {    

     name: 'xxx',    

     logProject: 'xxx',    

     logStore: 'xxx',    

     qualifier: 'xxx',    

     versionId: 'xxx'  

  },  

  region: 'xxx',  

  accountId: 'xxx'

}


当然,在上一章中,细心的读者应该已经发现,阿里云的函数计算相对于其他云厂商的函数计算,在创建函数的时候多了一个选项:除了事件函数,还有一个选择叫HTTP函数。与普通的事件函数不同的是,HTTP函数更适合快速构建Web服务等场景。HTTP触发器支持HEAD、POST、PUT、GET和DELETE方式触发函数,同时与普通的事件函数不同的是,HTTP函数的入参和Response也略微不同,以官方例子为例:

# -*- coding: utf-8 -*-

import json

HELLO_WORLD = b"Hello world!\n"

def handler(environ, start_response):

   request_uri = environ['fc.request_uri']

   response_body = {

     'uri':environ['fc.request_uri'],

     'method':environ['REQUEST_METHOD']

   }

   # do something here

   status = '200 OK'

   response_headers = [('Content-type', 'text/json')]

   start_response(status, response_headers)

   # Python2

   return [json.dumps(response_body)]

   # Python3 tips: When using Python3, the str and bytes types cannot be mixed.

   # Use str.encode() to go from str to bytes

   # return [json.dumps(response_body).encode()]

当然,HTTP函数的一个优势是更加容易与传统的Web框架进行结合,以Python的轻量级Web框架Flask为例:

# index.py

from flask import Flask

app = Flask(__name__)

@app.route('/')

def hello_world():

   return 'Hello, World!'

此时,我们只需要将函数的入口方法设置为:index.app即可实现一个Flask项目运行在函数计算上。这个过程相对于很多在函数计算层面将JSON对象转换成Request对象的方案要方便得多。当然除了这一点之外,HTTP函数的优势还有:

  • 简化了开发人员的学习成本和调试过程,帮助开发人员快速使用函数计算搭建Web service和API。
  • 支持选择熟悉的HTTP测试工具验证函数计算侧的功能和性能。
  • 减少请求处理环节,HTTP触发器支持更高效的请求、响应格式,不需要编码或解码成JSON格式,性能更优。
  • 方便对接其他支持Webhook回调的服务,例如CDN回源、MNS等。

项目开发

原生FaaS开发

想要获得用户的IP地址,那么我们就要根据函数计算的特性,寻找到事件的数据结构,在这个数据结构中找到客户端IP的字段。我们可以先创建一个HTTP函数,输出environ:

# -*- coding: utf-8 -*-

import json

def handler(environ, start_response):

   print(environ)

   response_body = {}

   response_headers = [('Content-type', 'text/json')]

   start_response('200 OK', response_headers)

   return [json.dumps(response_body).encode()]

完成之后,我们执行该函数,可以看到输出的日志中有REMOTE_ADDR字段,存放的是客户端的IP地址:

所以此刻,我们可以通过environ['REMOTE_ADDR']来获得这个IP地址:

# -*- coding: utf-8 -*-

import json

def handler(environ, start_response):

   response_body = {

     'IP':environ['REMOTE_ADDR']

   }

   response_headers = [('Content-type', 'text/json')]

   start_response('200 OK', response_headers)

   return [json.dumps(response_body).encode()]

测试代码,可以看到已经正确输出我们的IP地址:

通过函数计算为我们生成的地址:

在客户端用命令行工具测试:

基于Web框架开发

首先在本地创建项目一个Flask项目,并且新建文件index.py:

from flask import Flask, request


app = Flask(__name__)



@app.route('/')

def index():

   return {"IP": request.remote_addr}



if __name__ == '__main__':

   app.run(

       host="0.0.0.0",

       port=int("8001")

   )


安装项目所需要的依赖到当前项目下,例如本项目只需要一个flask即可:

pip3 install flask -t ./

安装完成之后,我们可以本地启动该项目进行基本测试:

此时,我们在阿里云函数计算上创建一个HTTP函数,选择我们刚才的项目文件夹上传,同时函数入口要改成index.app:    

然后可以点击“新建”按钮,进行函数创建,创建完成之后,我们可以在控制台点击一下“测试”按钮,可以看到,已经成功输出我们的IP地址:

当然,我们也可以使用默认生成URL,在本地进行测试:

此时结果:


举一反三

AWS Lambda

上文是以阿里云函数计算为例,当然在其他云厂商中实现该服务的方法也是类似的,例如在AWS的Lambda中,代码可以为:

import json


def lambda_handler(event, context):

   return {

       'statusCode': 200,

       'body': json.dumps({"IP": event['requestContext']['http']['sourceIp']})

   }


腾讯云云函数

腾讯云云函数中,代码为:

# -*- coding: utf8 -*-

import json

def main_handler(event, context):

   response_body = {

     'IP': event['requestContext']['sourceIp']

   }

   return response_body

华为云函数工作流

华为云的可以是:

# -*- coding:utf-8 -*-

import json

def handler (event, context):

   return {

       "statusCode": 200,

       "isBase64Encoded": False,

       "body": json.dumps({"IP": event['headers']['x-real-ip']}),

       "headers": {

           "Content-Type": "application/json"

       }

   }


至此我们完成了一个简单的查询客户端IP的API服务的开发。相对于传统的自建服务器,安装各种软件,后期不断运维而言,Serverless架构的优势非常明显,它让我们仅关注自身的业务代码即可,无论是运行环境还是API网关等,都交给云厂商来统一管理和维护,这对研发效率的提升,人力资源投入的降低,是有巨大帮助和推进作用的。除此之外,传统云主机情况下,我们需要让我们的机器一直在运行,哪怕很长一段时间没有流量也要持续运行,而只要运行就会有费用的产生,就会有成本的产生,但是在Serverless架构下,我们即便开发、测试完项目,他也会处于一个静默状态,只有当请求到来的时候,函数被触发的时候,系统才会进行计费,也就是说只有使用才有费用,不使用无费用产生,这对于整个资源成本的压缩,具有极大的帮助和促进作用。

相关实践学习
基于函数计算一键部署掌上游戏机
本场景介绍如何使用阿里云计算服务命令快速搭建一个掌上游戏机。
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
目录
相关文章
|
1天前
|
运维 前端开发 Serverless
函数计算产品使用问题之wordpress应用模板在什么地方
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
17天前
|
运维 中间件 Serverless
Serverless 应用引擎产品使用合集之是否可以去掉Access-Control-Expose-Headers
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
17天前
|
消息中间件 Serverless PyTorch
Serverless 应用引擎产品使用合集之FC内网访问VPC内的资源不通是什么导致的
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
17天前
|
NoSQL Java Serverless
Serverless 应用引擎产品使用合集之Java如何使用ScheduledExecutorService来实现定时触发
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
17天前
|
算法 前端开发 Serverless
Serverless 应用引擎产品使用合集之启动函数的命令可以如何实现
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
21小时前
|
运维 Serverless 数据处理
函数计算产品使用问题之应用每次重新部署,里面的函数之前配好的“运行时”和“层”都会恢复初始状态,该怎么办
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
17天前
|
消息中间件 Serverless 文件存储
Serverless 应用引擎产品使用合集之在NAS中下载torch和diffusers依赖包,如何加载
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
17天前
|
运维 Serverless PHP
Serverless 应用引擎产品使用合集之官方Stable Diffusion模板采用的是什么方式
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
17天前
|
缓存 运维 Serverless
Serverless 应用引擎产品使用合集之基于django应用模板创建的FC,如何配置数据库
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
17天前
|
存储 运维 Kubernetes
Serverless 应用引擎产品使用合集之部署Stable Diffusion启动失败一般是什么导致的
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。

热门文章

最新文章

相关产品

  • 函数计算