You need to enable JavaScript to run this app.
导航

开发方法

最近更新时间2022.06.10 16:25:10

首次发布时间2022.06.10 16:25:10

针对 Native 运行时 ,您的程序是一个 HTTP 服务程序。函数服务冷启动 Native 运行时,会调用程序中的启动脚本run.sh 启动您定义的 HTTP 服务。之后,该 HTTP 服务将接管来自函数服务的所有请求。

服务规范

在本地开发 Native 函数需要遵循以下规范:

  • 服务本身必须是无状态的,如需状态可存储至远端 redis 或 mysql,服务启动不依赖本地内存 cache 或落盘的数据。

  • 服务必须通过环境变量_FAAS_RUNTIME_PORT获取监听端口,否则函数发布冷启动过程将会出现以下错误。

    {
        Status: "failed"
        StatusMessage: "Function cold start timeout, please check your log/code and then retry, or contact oncall"
    }
    
  • 服务需要提供一个启动脚本run.sh

    • run.sh需要置于服务的根目录下。

    • run.sh 必须具有可执行权限,否则发布服务时会出现 permission denied 报错。可通过以下命令给 Linux 系统所有的用户组添加run.sh的执行权限。

      chmod a+x run.sh
      
  • 对于 HTTP 服务,必须额外实现一个GET "/v1/ping" 接口,函数服务通过该接口状态是否返回 Status Code 200 判断服务存活性。

  • 不鼓励服务启动后台进程或线程(即请求已经返回了 Response,但后台仍有任务异步执行)。函数服务根据请求量对后端实例进行动态扩缩容,无法保证后台进程、线程的存活性。

HTTP 服务开发示例(以 Golang 语言为例)

在 Native 运行时中,函数服务会将请求 Method、Path、Body、Query 以及 Headers 转发给您的 HTTP 服务。您可以直接使用入参请求头(Headers)和请求体 (Body)来编写函数的业务逻辑。以下示例可作为您本地开发 HTTP 服务的参考。

服务端口

服务必须通过环境变量_FAAS_RUNTIME_PORT获取监听端口,示例代码如下。

func buildSimpleServer(s *SimpleServer) *http.Server {
   port := os.Getenv("_FAAS_RUNTIME_PORT")
   if port == "" {
      log.Fatal("failed to load _FAAS_RUNTIME_PORT")
   }

   return &http.Server{
      Addr:    ":" + port,
      Handler: s.buildHTTPHandler(),
   }
}

服务启停

服务必须提供启停方法,并在 main 函数中进行调用,示例代码如下。

func main() {
   ...

   // Start server.
   server := server.NewSimpleServer()
   server.Start()

   ...
   server.Stop()
}

// Start starts the server.
func (s *SimpleServer) Start() {
   log.Printf("start simple server, port: %s", s.httpServer.Addr)

   go func() {
      if err := s.httpServer.ListenAndServe(); err != http.ErrServerClosed {
         log.Fatalf("server listen error: %v", err)
      }
   }()

   return
}

// Stop stops the server.
func (s *SimpleServer) Stop() {
   log.Printf("stop simple server...")

   ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
   defer cancel()

   if err := s.httpServer.Shutdown(ctx); err != nil {
      log.Fatalf("failed to shutdown server, error: %v", err)
   }
}

请求处理程序

针对 Native 运行时的 HTTP 服务而言,由于您本身已经实现了一个 HTTP 服务,因此您可以在 HTTP 服务的逻辑中对您的请求处理程序进行自定义处理。例如:您可以通过编写 handler func 来实现您的 HTTP 服务请求处理逻辑,示例代码如下。

func (s *SimpleServer) buildHTTPHandler() http.Handler {
   r := mux.NewRouter()
   r.Path("/").Methods(http.MethodGet).HandlerFunc(helloHandler)

   // NOTE: GET v1/ping should be provided for liveness check by FaaS Platform.
   // Status Code OK denotes that the service is healthy.
   v1Router := r.PathPrefix("/v1").Subrouter()
   v1Router.Path("/ping").Methods(http.MethodGet).HandlerFunc(pingHandler)

   return r
}

// SimpleMessage contains a simple message for return.
type SimpleMessage struct {
   Message string `json:"Message"`
}

func pingHandler(w http.ResponseWriter, _ *http.Request) {
   _ = gores.JSON(w, http.StatusOK, SimpleMessage{Message: "All is well."})
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
   log.Printf("received new request, header: %+v", r.Header)

   _ = gores.JSON(w, http.StatusOK, SimpleMessage{Message: "Hello world from FaaS Native XD"})
}

说明

对于 HTTP 服务,必须额外实现一个GET "/v1/ping" 接口,函数服务通过该接口状态是否返回 Status Code 200 判断服务存活性。

函数调用说明

当 HTTP 服务的请求处理程序被调用时,和调用一个 Web API 方式一样,您可以直接使用 cURL、Postman 或浏览器等方式直接请求调用。函数服务会将用户的请求,包括 Method、Path、Body、Query 以及 Headers 转发给您的 HTTP 服务。

说明

您可以创建 API 网关触发器,通过自定义路由规则,为您的 HTTP 服务映射不同的访问路径 Path。

启动脚本

服务需要提供一个启动脚本run.sh,示例代码如下。

#!/bin/bash
set -ex
cd `dirname $0`

# A special check for CLI users (run.sh should be located at the 'root' dir)
if [ -d "output" ]; then
    exec ./output/main
else
    exec ./main
fi

使用环境变量

对于 Native 函数,您可以在控制台配置函数运行时所需的环境变量,并在代码中读取对应的环境变量,用于函数处理逻辑。对于所配置的环境变量,veFaaS 会将其注入到函数运行所在的容器中,程序可以通过语言的内置库进行读取。 例如:若您函数配置中环境变量的键(key)为 envKey,运行环境读取该环境变量的代码示例如下。

import "os"
envValue := os.Getenv("envKey")