Instance lifecycle hooks
Instance lifecycle hooks run your custom logic when a function instance starts or stops. This topic describes how to implement and configure Initializer and PreStop hooks for functions that use custom images.
Background information
A function instance lifecycle involves Initializer and PreStop hooks. Function Compute invokes the corresponding hook when a related instance lifecycle event occurs.
An 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.
The billing rules for instance lifecycle hooks are the same as those for regular invocation requests.
For more information about hook logs, see View instance lifecycle hook logs.
Hook types
Initializer hooks support two implementation types. The following table compares them.
Hook type | Mechanism | Applicable scope |
invoke code | Function Compute sends an HTTP request to your function. Your business code responds to the request. | Initializer and PreStop hooks |
execute instruction | Function Compute runs a shell command or script that you configure. The exit code determines success or failure. | Initializer hooks for GPU-accelerated functions only |
You can configure only one of the two types for an Initializer hook.
Implement hooks
The following sections describe how to implement each hook type.
Invoke code
After you configure a hook of the invoke code type, Function Compute sends an HTTP request POST /initialize or GET /pre-stop to your function when a function instance starts or stops. You must respond to the request in your business code.
Path | Request | Expected response |
(Optional) POST | Request body: None. Request headers: common request headers. For more information, see Function Compute common request headers. | Response body: the value returned by the function Initializer. Status code: 2xx: success. Non-2xx: failure. When an Initializer hook times out or fails, the server always returns the HTTP 200 status code. Use the |
(Optional) GET | Request body: None. Request headers: common request headers. For more information, see Function Compute common request headers. | Response body: the value returned by the function PreStop.
|
The Path column is marked (Optional) because each hook is an optional configuration. If you do not set an Initializer for the function that you create, you do not need to implement /initialize. In this case, even if your HTTP server implements /initialize, the /initialize logic in your code is never invoked. The same applies to PreStop.
To use the Initializer hook method in a custom image, implement the logic for the /initialize path with the POST method in your HTTP server. The same applies to the PreStop hook method. The following sample program uses the Python 3.10 custom runtime as an example.
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)Your hook code can also fail at run time. The following /initialize samples show two typical failures and how Function Compute responds to each. For the system behavior of each error code, see Hook error codes.
In the following example, the handler raises an exception. Function Compute treats the failure as a 500 error and restarts the instance.
@app.route('/initialize', methods=['POST'])
def init():
raise Exception("hahaha")
return "OK", 200, []In the following example, the handler returns a 404 status code. Function Compute does not resend the request.
@app.route('/initialize', methods=['POST'])
def init():
return "OK", 404, []Execute instruction (GPU-accelerated functions only)
The execute instruction type is available only for GPU-accelerated functions.
With the execute instruction type, Function Compute runs the shell command or script that you configure after the function instance starts. An exit code of 0 indicates that the hook instruction ran successfully. Any other exit code indicates a failure.
You can use a custom shell implementation, such as /bin/bash, /bin/sh, /bin/csh, or /bin/zsh. Make sure that the function runtime environment supports the shell implementation that you use.
The Function Compute console provides /bin/bash and /bin/sh as preset options. The following example uses /bin/sh. The script performs an initialization health check: it uses curl to send a request to a local service and uses jq to format the output. Make sure that both tools are available in your runtime environment.
#!/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
fiWrite error information to standard error (stderr) in your script to help locate the cause of an error. For example, the following code snippet writes error information when the curl request fails and sets the exit code to 1. The same failure behavior applies: if the instruction returns a non-zero exit code, the instruction is not run again and the system returns the related error. For more information, see Hook error codes.
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
fiConfigure lifecycle hooks
Log on to the Function Compute console. In the left-side navigation pane, choose Function Management > Functions.
In the top navigation bar, select a region. On the Functions page, click the target function.
On the function details page, click the Configuration tab. In the Instance Configuration section, click Modify.
In the Instance Configuration panel, configure the Initializer hook. Turn on the Initializer hook switch, and then set Initializer timeout based on your business requirements. In this example, the timeout is set to
300seconds. For hook type, select one of the following types:invoke code
After the hook is enabled, Function Compute sends an HTTP POST
/initializerequest to the function when the instance starts. Your business code must respond to the request and return the 200 status code.execute instruction
The execute instruction type is available only for GPU-accelerated functions.
Select execute instruction as the hook type, and then select a shell instruction, such as /bin/sh. In the code editor, write the initialization script. For a complete example, see Execute instruction (GPU-accelerated functions only).
(Optional) Configure the PreStop hook. Turn on the PreStop hook switch, and then set PreStop timeout based on your business requirements. In this example, the timeout is set to
3seconds.Click Deploy.
Verify that the hooks take effect. Invoke the function, or update the function configuration or code, to trigger instance creation and destruction. Then check the hook logs by following the instructions in View instance lifecycle hook logs.
View instance lifecycle hook logs
You can query hook execution logs in Real-time Log, Function Logs, or Advanced Logs. The Invocation Request List does not display hook logs.
Logs generated by execute instruction hooks cannot be written to Function Logs.
You can view hook logs by using the Function Logs feature.
Log on to the Function Compute console. In the left-side navigation pane, choose Function Management > Functions.
In the top navigation bar, select a region. On the Functions page, click the target function.
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 invocation logs and Initializer hook logs of the function. The following example shows the logs.
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*******Each function instance is cached for a period of time and is not destroyed immediately, so PreStop hook logs are not available right away. To trigger the PreStop hook quickly, update the function configuration or the function code. After the update is complete, check Function Logs again to view the PreStop hook logs. The following example shows the logs.
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*******Hook error codes
Invoke code
Error code | Description |
400 | If a function Initializer hook fails and returns 400 or 404, the request is not resent, but the system keeps retrying until the invocation succeeds. If a function PreStop hook fails and returns 400 or 404, the freezing and stopping of the function instance are not affected. |
404 | |
500 | Function Compute restarts the instance. |
Execute instruction
If the instruction returns a non-zero exit code, the instruction is not run again and the system returns the related error. If your script writes error information to stderr, you can use that output to locate the cause of the failure.