All Products
Search
Document Center

:Introduction to cloud-terminal joint debugging

Last Updated:Jan 23, 2024

Cloud-terminal joint debugging applies to function debugging, during which you can run the s proxied command to connect on-premises and cloud environments by invoking functions on on-premises terminals and cloud services. This improves your development efficiency. This topic describes the basic principles of cloud-terminal joint debugging and uses examples to describe how to implement cloud-terminal joint debugging and breakpoint debugging. In this topic, ApsaraDB RDS for MySQL and Apsara File Storage NAS (NAS) are used as examples.

Usage notes

The cloud-terminal joint debugging feature supports only the x86_64 architecture and does not support the Arm64 architecture.

Principles

In the serverless field, debugging has always been a pain point for developers. Some cloud vendors have provided tools to resolve the pain point. However, these tools focus on simulating on-premises execution environments and parameters but cannot connect on-premises environments and online environments. Serverless Devs provides the cloud-terminal joint debugging feature, which enables the connection between on-premises and online environments.

image

In the figure, Serverless Devs uses information, such as VPC configurations and NAS configurations, specified by the ServiceConfig parameter in an s.yaml file to create a helper function (C) that has the same configurations and network environment as the function that you want to debug. When the channel of cloud-terminal joint debugging is established, you can perform the following operations:

  • Access the resources of Alibaba Cloud public cloud from the container environment in which the on-premises function is invoked. For example, you can access the following environments:

    • VPC endpoints, such as the VPC endpoints of NAS, ApsaraDB RDS, or Message Queue for Apache Kafka

    • Internal networks, such as the internal endpoint of Object Storage Service (OSS)

  • Generate inbound traffic, such as the information about the context and event parameters. The inbound traffic is the actual traffic from cloud services.

    You can directly use an SDK or a trigger to invoke the helper function (C). For example, you can use an SDK to run the invocation commands of cloud-terminal joint debugging. The request traffic is returned to the on-premises debugging instance (A). This instance provides the container environment in which on-premises functions can be executed. In this case, the inbound traffic is the actual traffic from the cloud.

Note

A, B, and C in the preceding figure are all encapsulated in Serverless Devs. You need to only configure resources in the code and s.yaml file based on your business requirements. The configurations of the code and the s.yaml file must meet the following requirements:

  • You must attach the code to an on-premises environment (A). This environment is the container environment, in which on-premise functions are executed.

  • You can use the --debug-port parameter to implement port mapping between the integrated development environment and on-premises environment (A).

Sample code

This section provides examples to describe how to configure your function code and the s.yaml file. In this section, Python 3 is used. The examples are suitable for scenarios in which your code needs to access ApsaraDB RDS for MySQL and NAS over a private network.

Sample code

Sample s.yaml

# -*- coding: utf-8 -*-
import logging
import os
import pymysql
import pymysql.cursors

def handler(event, context):
    print("\n***test fc internal endpoint***")
    os.system("curl --connect-timeout 3 1.cn-hangzhou-internal.fc.aliyuncs.com")

    print("\n***test db internal addr ***")
    test_mysql()

    print("\n***test nas ***")
    os.system("ls -lh/mns/auto")

def test_mysql():
    # The private IP address of an ApsaraDB RDS for MySQL instance in the VPC. 
    connection = pymysql.connect(host='rm-xxxxxxx.mysql.rds.aliyuncs.com',
                                 user='userName',
                                 password='userPwd',
                                 db='testDB',
                                 port=3306,
                                 charset='utf8')
    try:
        with connection.cursor() as cursor:
            sql = "select * from users"
            cout = cursor.execute(sql)
            print("total:"+str(cout))

            for row in cursor.fetchall():
                print("ID:"+str(row[0])+'  Name:'+row[1])
            connection.commit()

    finally:
        connection.close()                
edition: 1.0.0          #  The version of the YAML specification. The version complies with the semantic versioning specification.
name: fcDeployApp       #  The name of the project.
access: "default"  #  The alias of the key.

services:
  fc-deploy-test: #  The name of the service.
    component: devsapp/fc  # The name of the component.
    props: #  The attribute value of the component.
      region: cn-hangzhou
      service:
        name: fc-deploy-service
        description: 'demo for proxied invoke'
        internetAccess: true
        vpcconfig:
            vpcId: vpc-bp1wv9al02opqahi****
            securityGroupId: sg-bp1h2swzeb5vgjfu****
            vswitchIds:
                - vsw-bp1kablus0jrcdeth****
        nasconfig:
            userId:10008
            groupId:10008
            mountPoints:
                - serverAddr: example.com
                nasDir: /
                fcDir: /mnt/auto
      function:
        name: event-function
        description: this is a test
        runtime: python3
        codeUri: .
        handler: index.handler
        memorySize: 128
        timeout: 60
Note

After the channel for cloud-terminal joint debugging is established, you can debug the function in your on-premises environment. This way, you can access the VPC of Apsara RDS for MySQL and NAS over a private network in the code.

Prerequisites

Before you start, make sure that the following operations are performed:

Procedure

  1. In the project directory, run the following commands based on your business requirements to prepare helper resources and on-premises environments for cloud-terminal joint debugging:

    • If one or more projects are contained in the s.yaml file and you do not want to specify a project for testing, run the following command:

      s proxied setup
    • If multiple projects are included in the s.yaml file and you want to specify a project for testing, run the following command:

      s <projectName> proxied setup

    Sample output:

    [2021-10-08T15:55:16.653] [INFO ] [S-CLI] - Start ...
      Session created, session id: S-d847ae28-767f-4532-a2f2-307ee2b99c5f.
    ......
    [2021-10-08T15:55:24.580] [INFO ] [FC-DEPLOY] - Checking Trigger httpTrigger exists
    [2021-10-08T15:55:24.807] [INFO ] [FC-DEPLOY] - Checking Trigger httpTrigger exists
      Make service SESSION-S-d847a success.//The helper service is deployed. 
      Make function SESSION-S-d847a/http-trigger-py36 success.//The helper function is deployed. 
      Make trigger SESSION-S-d847a/http-trigger-py36/httpTrigger success.//The helper trigger is deployed. 
    ......
    There is auto config in the service: SESSION-S-d847a
      Helper function is set to 1 provision and 0 elasticity.//The Function Compute (C) container is started. 
      Proxy container is running.//The code container in the on-premises environment (A) is started. 
      Session established!//The session is established. 
    [2021-10-08T15:56:13.251] [INFO ] [FC-PROXIED-INVOKE] - Pulling image registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-python3.6:1.9.19, you can also use 'docker pull registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-python3.6:1.9.19' to pull image by yourself.
    1.9.19: Pulling from aliyunfc/runtime-python3.6
    ......
    Digest: sha256:6a4da97962dba5f6cb00c5e8e83024c4758ec358e5bf884efff897b9826d9454
    Status: Downloaded newer image for registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-python3.6:1.9.19
    [2021-10-08T15:56:15.694] [INFO ] [FC-PROXIED-INVOKE] - Checking Server in function container is up. exists
    FunctionCompute python3 runtime inited.
    FC Invoke End RequestId: unknown_request_id, Error: Unhandled function error
    [2021-10-08T15:56:16.831] [INFO ] [FC-PROXIED-INVOKE] - Server in function container is up!//The execution environment of Function Compute in the on-premises environment (A) is started. 
    End of method: proxied
    Note

    After the command that you select is executed, the project is blocked and pending to be invoked. The execution environment is based on an HTTP server.

  2. Invoke functions in the on-premises environment.

    • HTTP function

      • If a function is an anonymous HTTP trigger function, you can use cURL or Postman to invoke the domain name that is temporally generated to implement on-premises debugging. cURL is used in this example.

        curl -v http://http-trigger-py36.SESSION-S-d847a.188077086902****.cn-hangzhou.fc.devsapp.net
      • If authType of the HTTP trigger is function, perform the following steps to implement debugging of the HTTP function:

        1. Start a new terminal.

        2. Run commands to switch to the directory of the project that you want to manage.

        3. Run the following command to invoke the function:

          s proxied invoke -e '{"body":123,"method":"GET","headers":{"key":"value"},"queries":{"key":"value"},"path":"string"}'
    • Event function

      • Event functions with triggers

        This example describe how to invoke a function in an on-premises environment. An OSS trigger is used in this example.

        1. Confirm the trigger that you want to use to trigger function execution. The trigger can be an OSS trigger or an Alibaba Cloud CDN (CDN) event trigger.

        2. Log on to the Function Compute console.

        3. Find the helper function and create a trigger for the helper function. For more information about how to create an OSS trigger, see Step 1: Create an OSS trigger.

        4. Log on to the OSS console and trigger an event. For example, you can upload or download files to trigger the execution of the function in the on-premises environment.

      • Event functions without triggers

        This example describes how to invoke an event function that is not equipped with a trigger. Perform the following steps:

        1. Start a new terminal.

        2. Run commands to switch to the directory of the project that you want to manage.

        3. Run the following command to invoke the function:

          s proxied invoke -e '{"key":"value"}'
        Important

        If your event function is equipped with a trigger, you can also use this method to invoke this function in the on-premises environment.

  3. Run the following command and clean the helper resources and on-premises environment:

    s proxied cleanup

    Sample output:

      Stop container succeed.
      Unset helper function provision and on-demand config done.
    [2021-10-08T16:41:19.960] [INFO ] [FC-DEPLOY] - Using region: cn-hangzhou
    [2021-10-08T16:41:19.988] [INFO ] [FC-DEPLOY] - Using access alias: default
    [2021-10-08T16:41:19.989] [INFO ] [FC-DEPLOY] - Using accessKeyID: LTAI4G4cwJkK4Rza6xd9****
    [2021-10-08T16:41:19.993] [INFO ] [FC-DEPLOY] - Using accessKeySecret: eCc0GxSpzfq1DVspnqqd6nmYNN****
    [2021-10-08T16:41:20.104] [INFO ] [FC-DEPLOY] - Checking Service SESSION-S-a9143 exists
    [2021-10-08T16:41:20.397] [INFO ] [FC-DEPLOY] - Service: SESSION-S-a9143 already exists online.
    [2021-10-08T16:41:20.400] [INFO ] [FC-DEPLOY] - Checking Function http-trigger-py36 exists
    [2021-10-08T16:41:20.583] [INFO ] [FC-DEPLOY] - Function: http-trigger-py36 already exists online.
    [2021-10-08T16:41:20.586] [INFO ] [FC-DEPLOY] - Checking Trigger httpTrigger exists
    [2021-10-08T16:41:20.820] [INFO ] [FC-DEPLOY] - Trigger: httpTrigger already exists online.
      Using fc deploy type: sdk, If you want to deploy with pulumi, you can [s cli fc-default set deploy-type pulumi] to switch.
      Delete trigger SESSION-S-a9143/http-trigger-py36/httpTrigger success.
      [TriggerNotFound], DELETE /services/SESSION-S-a9143/functions/http-trigger-py36/triggers/httpTrigger failed with 404. requestid: 9de742e1-d8f6-4db0-a4bd-02b10542147e, message: trigger 'httpTrigger' does not exist in service 'SESSION-S-a9143' and function 'http-trigger-py36'.
      Delete function SESSION-S-a9143/http-trigger-py36 success.
      Delete service SESSION-S-a9143 success.
      Delete session: S-a9143b1a-88ff-48bd-bd79-2f3755397fe2 done.
      Stop container succeed.
    End of method: proxied
    Note

    After the cleaning is complete, the blocking between the helper resources and the on-premises environment is removed.

Breakpoint debugging

This section describes how to implement breakpoint debugging during cloud-terminal joint debugging. In this section, Python 3 is used as an example.

  1. Run the following command in the project directory to prepare the helper resources and on-premises environment that is required for cloud-terminal joint debugging.
    s proxied setup --config vscode --debug-port 3000 

    Sample output:

    [2021-10-08T15:55:16.653] [INFO ] [S-CLI] - Start ...
      Session created, session id: S-d847ae28-767f-4532-a2f2-307ee2b99c5f.
    [2021-10-08T15:55:18.395] [INFO ] [FC-PROXIED-INVOKE] - Deploying helper function...
    [2021-10-08T15:55:18.397] [INFO ] [FC-PROXIED-INVOKE] - Creating cleaner service...
    [2021-10-08T15:55:22.021] [INFO ] [FC-DEPLOY] - Using region: cn-hangzhou
    [2021-10-08T15:55:22.022] [INFO ] [FC-DEPLOY] - Using access alias: default
    [2021-10-08T15:55:22.022] [INFO ] [FC-DEPLOY] - Using accessKeyID: LTAI4G4cwJkK4Rza6xd9****
    [2021-10-08T15:55:22.022] [INFO ] [FC-DEPLOY] - Using accessKeySecret: eCc0GxSpzfq1DVspnqqd6nmYNN****
     Using fc deploy type: sdk, If you want to deploy with pulumi, you can [s cli fc-default set deploy-type pulumi] to switch.
    [2021-10-08T15:55:22.971] [INFO ] [FC-DEPLOY] - Checking Service SESSION-S-d847a exists
    [2021-10-08T15:55:23.293] [INFO ] [FC-DEPLOY] - Setting role: AliyunFCDefaultRole
    [2021-10-08T15:55:23.886] [INFO ] [RAM] - Checking Role AliyunFCDefaultRole exists
    [2021-10-08T15:55:24.099] [INFO ] [RAM] - Updating role: AliyunFCDefaultRole
    [2021-10-08T15:55:24.191] [INFO ] [RAM] - Checking Plicy AliyunFCDefaultRolePolicy exists
    [2021-10-08T15:55:24.300] [INFO ] [FC-DEPLOY] - Checking Function http-trigger-py36 exists
    [2021-10-08T15:55:24.577] [WARN ] [FC-DEPLOY] - Image registry.cn-hangzhou.aliyuncs.com/aliyunfc/ts-remote:v0.1.1 dose not exist locally.
    Maybe you need to run 's build' first if it dose not exist remotely.
    [2021-10-08T15:55:24.580] [INFO ] [FC-DEPLOY] - Checking Trigger httpTrigger exists
    [2021-10-08T15:55:24.807] [INFO ] [FC-DEPLOY] - Checking Trigger httpTrigger exists
      Make service SESSION-S-d847a success.//The helper service is deployed. 
      Make function SESSION-S-d847a/http-trigger-py36 success.//The helper function is deployed. 
      Make trigger SESSION-S-d847a/http-trigger-py36/httpTrigger success.//The helper trigger is deployed. 
    [2021-10-08T15:55:26.129] [INFO ] [FC-DEPLOY] - Checking Service SESSION-S-d847a exists
    [2021-10-08T15:55:26.568] [INFO ] [FC-DEPLOY] - Checking Function http-trigger-py36 exists
    [2021-10-08T15:55:26.922] [INFO ] [FC-DEPLOY] - Checking Trigger httpTrigger exists
    [2021-10-08T15:55:27.542] [INFO ] [FC-DEPLOY] - Using customDomain: auto: fc will try to generate related custom domain resources automatically
      End of request
      Deployed.
      End of request
    [2021-10-08T15:55:35.499] [INFO ] [FC-DEPLOY] - Generated auto custom domain: http-trigger-py36.session-s-d847a.188077086902****.cn-hangzhou.fc.devsapp.net
    [2021-10-08T15:55:35.499] [INFO ] [FC-DEPLOY] - Creating custom domain: http-trigger-py36.session-s-d847a.188077086902****.cn-hangzhou.fc.devsapp.net
    [2021-10-08T15:55:35.679] [INFO ] [FC-DOMAIN] - Creating custom domain: http-trigger-py36.session-s-d847a.188077086902****.cn-hangzhou.fc.devsapp.net
    
    There is auto config in the service: SESSION-S-d847a
      Helper function is set to 1 provision and 0 elasticity.//The Function Compute (C) container is started. 
      Proxy container is running.//The code container in the on-premises environment (A) is started. 
      Session established!//The session is established. 
    [2021-10-08T15:56:13.251] [INFO ] [FC-PROXIED-INVOKE] - Pulling image registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-python3.6:1.9.19, you can also use 'docker pull registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-python3.6:1.9.19' to pull image by yourself.
    1.9.19: Pulling from aliyunfc/runtime-python3.6
    ......
    Digest: sha256:6a4da97962dba5f6cb00c5e8e83024c4758ec358e5bf884efff897b9826d9454
    Status: Downloaded newer image for registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-python3.6:1.9.19
    [2021-10-08T15:56:15.694] [INFO ] [FC-PROXIED-INVOKE] - Checking Server in function container is up. exists
    FunctionCompute python3 runtime inited.
    FC Invoke End RequestId: unknown_request_id, Error: Unhandled function error
    [2021-10-08T15:56:16.831] [INFO ] [FC-PROXIED-INVOKE] - Server in function container is up!//The execution environment of Function Compute in the on-premises environment (A) is started. 
    End of method: proxied

    After the command is executed, the project is blocked and pending to be invoked. If you directly run the invocation command, the function is invoked in an on-premises environment. If breakpoint debugging is required, add a breakpoint (1) to the code of a function in the sidebar of the VS Code editor and click the debugging icon (2).

  2. Start a new terminal and run the following command to invoke the function.
    s proxied invoke

    After you run the debugging command, go back to the VS Code UI. Breakpoint debugging is started for the function.

  3. Run the following command to clean the helper resources, sessions, and on-premises debugging container:
    s proxied clean

The following sample Java 8 code describes how to use IntelliJ IDEA to implement breakpoint debugging:

  1. Run the following command in the directory of the project that you want to manage to install dependencies:
    s build --use-docker

    Sample output:

    [2021-10-09T15:28:39.391] [INFO ] [S-CLI] - Start ...
    [2021-10-09T15:28:40.520] [INFO ] [FC-BUILD] - Build artifact start...
    [2021-10-09T15:28:40.548] [INFO ] [FC-BUILD] - Use docker for building.
    [2021-10-09T15:28:40.867] [INFO ] [FC-BUILD] - Build function using image: registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-java8:build-1.9.21
    [2021-10-09T15:28:41.411] [INFO ] [FC-BUILD] - begin pulling image registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-java8:build-1.9.21, you can also use docker pull registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-java8:build-1.9.21 to pull image by yourself.
    build-1.9.21: Pulling from aliyunfc/runtime-java8
    ......
    Digest: sha256:35eb46f6235729dbcb1fa48f4ce4ae7b213b967a0f1b9c625e464dbba58af22d
    Status: Downloaded newer image for registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-java8:build-1.9.21
    [2021-10-09T15:30:52.690] [INFO ] [FC-BUILD] - Build artifact successfully.
    
    Tips for next step
    ======================
    * Invoke Event Function: s local invoke
    * Invoke Http Function: s local start
    * Deploy Resources: s deploy
    End of method: build

  2. Run the following command to prepare helper resources and the on-premises environment for cloud-terminal joint debugging.
    s proxied setup --debug-port 3000 

    After you run the command, the project is blocked and pending to be invoked. If you directly run the invocation command, the function is invoked in an on-premises environment. If you require breakpoint debugging, you must configure IntelliJ IDEA when you perform breakpoint debugging for the first time.

    1. Open IntelliJ IDEA and then the corresponding directory of the project that you want to manage. In the top navigation bar of IntelliJ IDEA, choose Run > Debug Configurations....
    2. In the Run/Debug Configurations dialog box, click the plus icon and select Remote, and then configure parameters as prompted:
      • Name: the name of the custom debugger.
      • Port: the port number. Set the value to 3000. If you set --debug-port to another port number for cloud-terminal joint debugging, set Port to the same port number as that of --debug-port.
    3. Click ok. The IntelliJ IDEA configurations are complete.

  3. Add a breakpoint for the code of a function in the sidebar of the IntelliJ IDEA editor (1) and click the debug icon (2).
  4. Start a new terminal and run the following command to invoke the function.
    s proxied invoke

    After you run the debugging command, go back to the IntelliJ IDEA UI. Breakpoint debugging is started for the function.

  5. Run the following command to clean the helper resources, sessions, and on-premises debugging container:
    s proxied clean