All Products
Search
Document Center

Initializer entry function

Last Updated: Jun 04, 2019

Different from a handler, which handles requests, an initializer processes initialization tasks. If an initializer is configured, Function Compute (FC) first runs the initializer for function initialization and then runs the handler to handle requests.

Scenarios

Function Compute runs user-defined functions in the following steps:

  1. Allocates compute resources to functions.
  2. Downloads the code of the functions.
  3. Starts the container and loads the function code.
  4. Invokes the initialization functions.
  5. Handles requests and returns results.

Steps 1 through 3 handle tasks required for a system layer cold start. This architecture allows Function Compute to apply various optimizations to minimize the performance impact brought by a spike of workload. Step 4 handles initialization tasks for a business layer cold start. For example, the initialization tasks can be loading large models for deep learning, building database connection pools, or loading dependent libraries. To minimize the effect caused by business layer cold start on the delay in handling requests, Function Compute introduces the initializer interface. The initializer locates the initialization logic in the user functions and optimizes scheduling.

Benefits

The initializer interface has the following benefits:

  • Initialization is separated from request handling, which makes it easier for users to write programs with clearer logic, better structures, and better performance.

  • Function code is smoothly updated and performance loss caused by business layer cold start is avoided. When a function instance starts, the system performs initialization before handling requests.

  • If more function instances are required because of heavy business load, the system estimates the overhead of business layer cold start. Then, it precisely calculates the timing for resource scaling and the amount of resources needed. This process minimizes the delay in handling requests.

  • Even if you keep your functions running without updating them, Function Compute may still release or replace a container in use. Even though a system layer cold start is not necessary, a business layer cold start is triggered. In this case, you can use the initializer to minimize the impact of the business layer cold start.

Features of the initializer interface

Initializers in different runtime environments share the following features:

  • No custom parameters

    Users cannot set custom parameters in the initializer. The initializer can only handle logic using properties of the context parameter provided by Function Compute. For more information, see context.

  • No return value

    Users cannot get return values for the initializer from the invocation request. If the initialization fails, you can learn the error type from the X-Fc-Error-Type and the body in the response. We recommend that you enable logging to locate the error more easily.

  • Custom timeout

    Users can set the initializer timeout, which is independent from the timeout of the handler. However, the initializer timeout must not exceed 300s.

  • Run timing

    The process of running a function is a function instance. A function instance is run in a container. The function instance is scaled based on the workload. Once a new function instance is created, the initializer is invoked. The handler is invoked after the initialization is complete.

  • Only one successful initialization

    If initialization is completed for a function instance, Function Compute does not invoke the initializer for this instance again during the instance life cycle. If the initialization for an instance fails, Function Compute invokes the initializer next time it receives a request to invoke this function instance. Once the initialization is successful, Function Compute directly invokes the handler when it receives an invoke request.

  • Conventions for naming the initializer entry point

    Conventions for naming the initializer entry point in runtime environments, except for Java, are the same as the conventions for naming the handler entry point. The format is [filename].[initializer name]. The initializer name is customizable. In Java, a class must be defined to implement the initializer interface provided by Function Compute.

  • Pay-As-You-Go

    You only pay for the run time of the initializer and the Internet traffic it generates. For more information, see Billing methods.

The initializer entry point

Function Compute supports the following programming languages. This section describes the definitions of the initializer entry point and related parameters in each supported runtime environment.

Node.js

Function Compute supports the following Node.js versions:

  • Node.js 6.1 (set runtime to Nodejs6)
  • Node.js 8.9 (set runtime to Nodejs8)

Initializer entry point: index.initializer

The initializer entry point is named in the following format: [file name].[initializer name]. For example, if you specify index.initializer as the initializer when implementing the initializer interface, Function Compute loads the initializer function defined in the index.js file.

To implement the initializer using Node.js in Function Compute, you must define a Node.js function as the initializer entry point. For example:

  1. exports.initializer = function(context, callback) {
  2. callback(null, '');
  3. };

If you want to use the initializer in the HTTP trigger, the HTTP trigger and the initializer must be identical in structure. For more information, see Node.js handler.

  • The function name

    exports.initializer corresponds to the name of the initializer. For example, if you specify the index.initializer as the initializer entry point when creating functions, Function Compute loads the initializer function defined in the index.js file.

  • The context parameter

    The context parameter contains the information generated when the function runs. This information includes request id, temporary AK, and function metadata. The data type of the context parameter is object. For more information about the structure and usage of the context parameter, see Node.js guide.

  • The callback parameter

    The callback parameter specifies the result returned after the function is invoked. The signature of the callback is function(err, data). The err and data parameters in the signature indicate the error and data respectively, which is the same as the callback parameter that is commonly used in Node.js. When the callback is invoked, if err is not null, return HandledInitializationError. The return value of the initialization function is blocked. Therefore, the value of the data parameter is invalid. You can set the data parameter to null as shown in the preceding example.

Python

Function Compute supports the following Python versions:

  • Python 2.7 (set runtime to python2.7)
  • Python 3.6 (set runtime to python3)

Initializer entry: main.my_initializer

`The initializer entry point is named in the following format: [文件名].[initializer 名]. For example, if you specify themain.my_initializeras theinitializer entry point` when implementing the initializer interface, Function Compute loads the my_initializer function in the main.py file.

To implement the initializer using Python in Function Compute, you must define a Python function as the initializer entry point. For example:

  1. def my_initializer(context):
  2. print("hello world!")

If you want to use the initializer in an HTTP trigger, the HTTP trigger and the initializer must be identical in structure. For more information, see Python handler.

  • The function name

    my_initializer corresponds to the initializer on the names. For example, if you specify the main.my_initializer as the initializer entry point when implementing the initializer function, Function Compute loads the my_initializer function defined in the main.py.

  • The context parameter

    The context parameter contains the information generated when the function runs. This information includes request id, temporary AK, and function metadata. The type of the context parameter is FCContext. For more information about the structure and usage of the context parameter, see Python guide.

PHP

Function Compute supports the following Python version:

  • PHP 7.2 ( set runtime to Php7.2)

Initializer entry point: main.my_initializer

The initializer entry point is named in the following format: [文件名].[initializer 名]. For example, if you specify the main.my_initializer as the initializer entry point when implementing the initializer interface, Function Compute loads the my_initializer function in the main.php.

To implement the initializer interface using PHP in Function Compute, you must define a PHP function as the initializer entry point. For example:

  1. <? php
  2. function my_initializer($context) {
  3. echo 'hello world' . PHP_EOL;
  4. }
  5. ? >

If you want to use the initializer in the HTTP trigger, the HTTP trigger and the initializer must be identical in structure. For more information, see Python handler.

  • The function name

    my_initializer corresponds to the name of the initializer. For example, if you specify the main.my_initializer as the initializer entry point when implementing the initializer interface, Function Compute loads the my_initializer function defined in the main.php file.

  • The context parameter

    The context parameter contains the information generated when the function runs. This information includes request id, temporary AK, and function metadata. The type of the context parameter is FCContext. For more information about the structure and usage of the context parameter, see PHP guide.

Java

Function Compute supports the following Java version:

  • OpenJDK 1.8.0 (set runtime to java8)

Initializer entry point: example.HelloFC::initialize

Initializer is named in the following format: {package}.{class}::{method}. For example, if the package name is example and the class name is HelloFC, specify the example.HelloFC::initialize as the initializer entry point when the initializer interface is implemented.

To implement the initializer using Java in Function Compute, you must define a class that implements the pre-defined interface in FS. For example:

  1. package example;
  2. import com.aliyun.fc.runtime.Context;
  3. import com.aliyun.fc.runtime.FunctionComputeLogger;
  4. import com.aliyun.fc.runtime.FunctionInitializer;
  5. import java.io.IOException;
  6. public class HelloFC implements FunctionInitializer {
  7. @Override
  8. public void initialize(Context context) throws IOException {
  9. FunctionComputeLogger logger = context.getLogger();
  10. logger.debug(String.format("RequestID is %s %n", context.getRequestId()));
  11. }
  12. }
  • Package name and class name

    The package name and the class name can be customized. However, they must correspond to the initializer name. In the preceding example, the package name is example and the class name is HelloFC. In this case, the initializer name must be example.HelloFC::initialize, and the handler name must be {package}.{class}::{method}.

  • Interface implementation

    You must implement the interface that is pre-defined in FS. In the preceding example, the FunctionInitializer is implemented. The function interface does not involve input parameters and output parameters. For more information about the handler, see Java handler.

  • The context parameter

    The context parameter contains the information generated when the function runs. This information includes request id, temporary AK, and function metadata. The type of the context parameter is com.aliyun.fc.runtime.Context. For more information about the structure and usage of the context parameter, see Java guide.

The usages of the initializer and the handler are the same. For more information, see the Java runtime section in Function entry point definition.

Initializer, a better initialization solution than using the global variable

In the following examples, the initilization process refers to connecting a database and the request handling process is to query the database. The initializer and the global variable are used.

Using the initializer:

  1. import pymysql.cursors
  2. connection = None
  3. # my_initializer: initializer function
  4. def my_initializer(context):
  5. global connection
  6. connection = pymysql.connect(host='localhost',
  7. user='user',
  8. password='passwd',
  9. db='db',
  10. charset='utf8mb4',
  11. cursorclass=pymysql.cursors.DictCursor)
  12. def my_handler(event, context):
  13. global connection
  14. with connection.cursor() as cursor:
  15. # Read a single record
  16. sql = "SELECT count(*) FROM `users`"
  17. cursor.execute(sql)
  18. result = cursor.fetchone()
  19. return result

Using the global variable:

  1. import pymysql.cursors
  2. initialized = False
  3. def my_handler(event, context):
  4. global initialized
  5. if not initialized:
  6. connection = pymysql.connect(host='localhost',
  7. user='user',
  8. password='passwd',
  9. db='db',
  10. charset='utf8mb4',
  11. cursorclass=pymysql.cursors.DictCursor)
  12. initialized = True
  13. with connection.cursor() as cursor:
  14. # Read a single record
  15. sql = "SELECT count(*) FROM `users`"
  16. cursor.execute(sql)
  17. result = cursor.fetchone()
  18. return result

In most scenarios, the function logic includes the initialization logic and the request handling logic. The initialization logic can be loading large models for deep learning, building database connection pools, or loading dependent libraries. Both the initializer interface and the global variable guarantee that the initialization is performed only once. However, the two methods make a difference in the following scenarios:

  • A new function instance is created after the run request is triggered in Function Compute or more instances are created when the load rises: If you use the initializer, the initialization logic is performed before the system receives an invocation request. In this case, the functionality and the performance are not affected by the business layer cold start. If you use the global variable, the initialization logic and the request handling logic are performed sequentially after the system receives an invocation request. The initialization logic is handled first, which often delays the request handling logic.

  • The function is updated: Function code is smoothly updated and performance loss caused by business layer cold start is avoided. When a function instance starts, the system performs initialization before handling requests. If you use the global variable, the business layer cold start is not avoided when the new function instance starts.

  • Function Compute releases or updates containers in use periodically: Even if you keep your functions running without updating them, Function Compute may still release or replace a container in use. Even though a system layer cold start is not necessary, a business layer cold start is triggered. In this case, you can use the initializer to minimize the impact of the business layer cold start. Such cases cannot be avoided by using the global variable.