Instance lifecycle hooks

更新时间:
复制 MD 格式

After you implement and configure an instance lifecycle hook, Function Compute invokes it when the corresponding lifecycle event occurs. This topic describes how to implement instance lifecycle hooks in a custom image.

Background

A function instance's lifecycle includes Initializer and PreStop hooks. The Initializer hook has two types: invoke code and execute instruction. Currently, only GPU-accelerated functions support the execute instruction type of Initializer hook. For more information, see Configure instance lifecycle.

Instance lifecycle hooks follow the same billing rules as regular invocation requests. However, you can view their execution logs only in Real-time Log, Function Logs, or Advanced Logs. The Invocation Request List does not show hook logs. For more information, see View instance lifecycle hook logs.

Note

Currently, logs generated by execute instruction hooks cannot be written to Function Log.

Implementing hook methods

A function instance's lifecycle in Function Compute includes Initializer and PreStop hooks. You can configure an Initializer hook as either invoke code or execute instruction, but not both.

Invoke code

After you configure a hook of the invoke code type, the system sends a POST /initialize or GET /pre-stop HTTP request to your function when a function instance starts or stops. You need to respond to this request in your business code.

Path

Request

Expected response

(Optional) POST /initialize

The value returned by the Initializer hook.

Status code

  • 2xx: Success.

  • Non-2xx: Failure.

Note

When the Initializer hook times out or fails, the server always returns an HTTP 200 status code. You must check the X-Fc-Error-Type:InitializationError response header or the errorMessage field in the response body to determine whether the initialization failed.

(Optional) GET /pre-stop

The value returned by the PreStop hook.

Status code

  • 2xx: Success.

  • Non-2xx: Failure.

To use an Initializer hook in your custom image, you must implement the logic for the /initialize path and POST method in your HTTP server. The same principle applies to the PreStop hook. The following example shows a sample program for a Python 3.10 custom runtime.

Note

If you do not set an Initializer for a function, you do not need to implement the /initialize path. In this case, even if your HTTP server implements the /initialize path, its logic is not invoked. The same principle applies to the PreStop hook.

import os
from flask import Flask
from flask import request
app = Flask(__name__)
@app.route('/initialize', methods=['POST'])
def init_invoke():
    rid = request.headers.get('x-fc-request-id')
    print("FC Initialize Start RequestId: " + rid)
    # do your things
    print("FC Initialize End RequestId: " + rid)
    return "OK"
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE'])
def hello_world(path):
    rid = request.headers.get('x-fc-request-id')
    print("FC invoke Start RequestId: " + rid)
    # do your things
    print("FC invoke End RequestId: " + rid)
    return "Hello, World!", 200, [('Function-Name', os.getenv('FC_FUNCTION_NAME'))]
@app.route('/pre-stop', methods=['GET'])
def prestop_invoke():
    rid = request.headers.get('x-fc-request-id')
    print("FC PreStop Start RequestId: " + rid)
    # do your things
    print("FC PreStop End RequestId: " + rid)
    return "OK"
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=9000)

In addition to the preceding working example, the following /initialize examples show error scenarios in Python.

@app.route('/initialize', methods=['POST'])
def init():
    raise Exception("hahaha")
    return "OK", 200, []
@app.route('/initialize', methods=['POST'])
def init():
    return "OK", 404, []

Execute instruction

You can configure an execute instruction hook to run an initialization script when a function instance starts. You can use any shell implementation, such as /bin/bash, /bin/sh, /bin/csh, or /bin/zsh, as long as it is supported by the function's runtime environment.

The Function Compute console provides /bin/bash and /bin/sh as preset options. The following example uses /bin/sh.

#!/bin/sh
URL="http://localhost:7860"
REQUEST_PATH="sdapi/v1/txt2img"
JSON_DATA='{
	"prompt": "",
	"steps": 1,
	"height": 8,
	"width": 8
}'
temp_file=$(mktemp)
trap 'rm -f "$temp_file"' EXIT
if ! http_code=$(curl -s -w "%{http_code}" \
	-H "Content-Type: application/json" \
	-d "$JSON_DATA" \
	-o "$temp_file" \
	-X POST "$URL"/"$REQUEST_PATH"); then
	echo "{\"status\": \"curl_error\", \"code\": $curl_exit_code}" \
	| jq . >&2
	exit 1
fi
response=$(<"$temp_file")
echo "http code $http_code"
if [ "$http_code" -eq 200 ]; then
	echo "$response" | jq -r '.' || printf "%s\n" "$response"
	exit 0
else
	echo "$response_body" \
	| jq -c 'if type == "object" then . else {raw: .} end' 2>/dev/null \
	| jq -s '{status: "http_error", code: $code, response: .[0]}' \
		--arg code "$http_code" \
		>&2
	exit 1
fi

An exit code of 0 indicates success; any other value indicates failure. You can write error information to standard error (stderr) in your script to help identify the cause of errors. For example, the following code snippet shows that after a curl request fails, relevant error information is output and the exit code is set to 1.

if ! http_code=$(curl -s -w "%{http_code}" \
	-H "Content-Type: application/json" \
	-d "$JSON_DATA" \
	-o "$temp_file" \
	-X POST "$URL"/"$REQUEST_PATH"); then
	echo "{\"status\": \"curl_error\", \"code\": $curl_exit_code}" \
	| jq . >&2
	exit 1
fi

Hook error codes

Invoke code

Error code

Description

400

  • If an Initializer hook fails with a 400 or 404 status code, the system does not resend that specific request. However, it continues to attempt initialization with new invocation requests until one succeeds.

  • If a PreStop hook fails and returns a 400 or 404 status code, this does not affect the freezing or stopping of the function instance.

404

500

Function Compute restarts the instance.

Execute instruction

If the instruction returns a non-zero exit code, the system does not re-execute it and instead returns an error.

Configure lifecycle hooks

  1. Log on to the Function Compute console. In the left-side navigation pane, click Functions.

  2. In the top navigation bar, select a region. On the Functions page, click the function that you want to manage.

  3. On the function details page, click the Configuration tab. In the Instance Configuration section, click Modify.

  4. In the Instance Configuration panel, configure the Initializer hook and set the Initializer timeout.

    • invoke code

      Turn on the Initializer hook switch. Set the Initializer timeout to 300 seconds. For hook type, select invoke code or execute instruction. After the hook is enabled, Function Compute sends an HTTP POST /initialize request when an instance starts. Your code must handle this request and return a 200 status code. If a 4xx or 5xx status code is returned, Function Compute returns an error or restarts the instance.

    • execute instruction

      The console provides two preset shell implementations: /bin/bash and /bin/sh.

      Turn on the Initializer hook switch, set the Initializer timeout to 300 seconds, and select execute instruction as the hook type. For the command, select /bin/sh. In the code editor, write a health check script. For example, use curl to send a POST request to localhost:7860/sdapi/v1/txt2img with JSON parameters including prompt, steps, height, and width. Use mktemp to create a temporary file and trap to set up cleanup.

  5. In the Instance Configuration panel, configure the PreStop hook and its timeout, and then click Deploy.

    Turn on the PreStop hook switch and set the PreStop timeout to 3 seconds.

View instance lifecycle hook logs

Note

Currently, logs generated by execute instruction hooks cannot be written to Function Log.

You can view hook logs by using the Function Logs feature.

  1. Log on to the Function Compute console. In the left-side navigation pane, click Functions.

  2. In the top navigation bar, select a region. On the Functions page, click the function that you want to manage.

  3. On the function details page, click the Test tab, click Test Function, and then choose Logs > Function Logs.

    On the Function Logs tab, you can view the function's invocation logs and Initializer hook logs. The following is an example:

    2024-06-26 10:59:23FC Initialize Start RequestId: 529eab23-9b3a-4ffc-88c8-9a686*******
    2024-06-26 10:59:23FC Initialize End RequestId: 529eab23-9b3a-4ffc-88c8-9a686*******
    2024-06-26 10:59:25FC Invoke Start RequestId: 1-667b840c-15c49df0-b7dc1*******
    2024-06-26 10:59:25FC Invoke End RequestId: 1-667b840c-15c49df0-b7dc1*******

    Since function instances are cached and not immediately destroyed, PreStop hook logs are not available instantly. To quickly trigger the PreStop hook, you can update the function's configuration or code. After the update is complete, check Function Logs again to view the PreStop hook logs. The following is an example:

    2024-06-26 11:04:33FC PreStop Start RequestId: c4385899-f071-490e-a8b7-e33c5*******
    2024-06-26 11:04:33FC PreStop End RequestId: c4385899-f071-490e-a8b7-e33c5*******