最近更新时间: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,但后台仍有任务异步执行)。函数服务根据请求量对后端实例进行动态扩缩容,无法保证后台进程、线程的存活性。
在 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")