When you debug a function in an on-premises environment, you can run the s proxied command to implement interconnection between on-premises and cloud applications. This helps you improve development efficiency. This topic describes the basic principles of interconnection between on-premises and cloud applications. This topic also describes how to implement interconnection between on-premises and cloud applications to access ApsaraDB RDS for MySQL and Apsara File Storage NAS, and implement breakpoint debugging during interconnection between on-premises and cloud applications.

Basic principles

In the Serverless field, debugging has always been a pain point for developers. Although some cloud service providers provide some tools to resolve this problem, interconnection between the on-premises execution environment and the cloud environment cannot be implemented because these tools focus on simulating the on-premises execution environment and parameter stage. Therefore, to implement interconnection between the on-premises execution environment and the cloud environment, Serverless Devs allows you to configure interconnection between on-premises and cloud applications.

fcserverlessdevsduanyunliantiao
Serverless Devs uses the service configurations, such as the Virtual Private Cloud (VPC) configuration and NAS configuration, specified by the ServiceConfig parameter in the s.yaml file to create a helper function, as shown in the preceding figure. This way, the service configurations and network environment of the helper function (C) are the same as those of a function to be debugged. The following requirements can be met after the tunnel for interconnection between on-premises and cloud applications is created:
  • The container in which functions are executed in the on-premises environment can access Alibaba Cloud services. For example, the container can use the following types of endpoints to access Alibaba Cloud services:
    • VPC endpoint, such as the VPC endpoint of NAS, ApsaraDB RDS, or Message Queue for Apache Kafka
    • Internal endpoint, such as the internal endpoint of OSS
  • Execution inbound traffic, such as context and event parameter information, is real traffic from the cloud.

    You can use triggers or use SDKs to run the s proxied command to invoke helper functions (C). The request traffic is returned to the on-premises debugging instance (A), which is the container in which functions are executed in the on-premises environment. In this case, the execution inbound traffic is real traffic from the cloud.

Note A, B, and C in the preceding figure are all encapsulated at the tool level. You need only to configure resources in the code and s.yaml file as required. The resource configuration in the code and s.yaml file must meet the following requirements:
  • The code must be mounted to the container in which functions are executed in the on-premises environment (A).
  • You can use the --debug-port parameter to specify the port mapping between the integrated development environment (IDE) and the container in which functions are executed in the on-premises environment.

Sample code

The sample code provided in this section is Python 3 code. The following table describes the function code and the content of the s.yaml file if your code needs to access ApsaraDB RDS for MySQL and NAS over a VPC.
Sample code Sample s.yaml file content
# -*- 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 VPC endpoint of ApsaraDB RDS for MySQL. 
    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 syntax. 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 properties 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 you run the s proxied setup command to prepare helper resources and an on-premises environment for interconnection between on-premises and cloud applications, the tunnel for interconnection between on-premises and cloud applications is created. Then, you can debug functions in the on-premises environment, and your code can access ApsaraDB RDS for MySQL and NAS over a VPC.

Prerequisites

The following operations are complete:

Procedure

  1. Run one of the following commands in the project directory as required to prepare helper resources and an on-premises environment for interconnection between on-premises and cloud applications.
    • If the s.yaml file contains only one project, or the s.yaml file contains multiple projects and you do not need to prepare helper resources and an on-premises environment for interconnection between on-premises and cloud applications for a specified project, run the following command:
      s proxied setup
    • If the s.yaml file contains multiple projects and you need to prepare helper resources and an on-premises environment for interconnection between on-premises and cloud applications for a specified project, run the following command:
      s <projectName> proxied setup
    Sample command 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 provison and 0 elasticity.// The container in Function Compute (C) 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 s proxied setup command is run, the project is blocked here and waits to be invoked. The execution environment is an HTTP server.
  2. Invoke functions in the on-premises environment.
    • HTTP function
      • If your function is an anonymous function for which an HTTP trigger is configured, you can use cURL or Postman to call the generated temporary domain name to implement on-premises debugging. In the following example, cURL is used:
        curl -v http://http-trigger-py36.fc-deploy-service.188077086902****.cn-hangzhou.fc.devsapp.net
      • If the value of the authType parameter for the HTTP trigger is function, perform the following steps to debug the HTTP function:
        1. Open a new terminal.
        2. Run the relevant command to go to the project directory.
        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 function for which a trigger is configured
        In this example, perform the following steps to invoke an event function for which an Object Storage Service (OSS) trigger is configured:
        1. Check the type of trigger used to trigger the execution of your function, such as the OSS event trigger or Alibaba Cloud CDN event trigger.
        2. Log on to the Function Compute console.
        3. Find the helper function and create a trigger for the function. For more information about how to create an OSS event trigger in this example, see Create a trigger.
        4. Log on to the OSS console. When a specified event such as object upload or download is triggered, the execution environment of Function Compute in the on-premises environment is invoked.
      • Event function for which no trigger is configured
        Perform the following steps to invoke an event function for which no trigger is configured:
        1. Open a new terminal.
        2. Run the relevant command to go to the project directory.
        3. Run the following command to invoke the function:
          s proxied invoke -e '{"key":"value"}'
        Notice If your function is an event function for which a trigger is configured, you can also use this method to invoke the function in the on-premises environment.
  3. Run the following command to clear the helper resources and on-premises environment required for interconnection between on-premises and cloud applications:
    s proxied cleanup
    Sample command 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 helper resources and on-premises environment are cleared, the blocking formed when the helper resources and on-premises environment for interconnection between on-premises and cloud applications are prepared is canceled.

Breakpoint debugging

The following sample Python 3 code describes how to implement breakpoint debugging during interconnection between on-premises and cloud applications:

  1. Run the following command in the project directory to prepare helper resources and an on-premises environment for interconnection between on-premises and cloud applications.
    s proxied setup --config vscode --debug-port 3000 

    Sample command 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 provison and 0 elasticity.// The container in Function Compute (C) 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 s proxied setup command is run, the project is blocked here and waits to be invoked. If you directly run the s proxied invoke command, an on-premises invocation in normal mode is implemented. If you require breakpoint debugging, insert a breakpoint (marked by ① in the figure) to the function code in the editor margin of VS Code and click the debugging icon (marked by ② in the figure).

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

    After you run the s proxied invoke command, you can return to VS Code. In this case, breakpoint debugging for the function has started.

  3. Run the following command to clear the helper resources, session, 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 project directory to install dependencies:
    s build --use-docker

    Sample command 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 an on-premises environment for interconnection between on-premises and cloud applications.
    s proxied setup --debug-port 3000 

    After the s proxied setup command is run, the project is blocked here and waits to be invoked. If you directly run the s proxied invoke command, an on-premises invocation in normal mode is implemented. 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 open the corresponding project directory. In the top navigation bar of IntelliJ IDEA, choose Run > Debug Configurations.
    2. In the Run/Debug Configurations dialog box, click the plus icon, select Remote, and then set the following parameters:
      • Name: the name of the custom debugger.
      • Port: Set the value of this parameter to 3000. If you use the --debug-port parameter to specify a different port when you prepare helper resources and an on-premises environment for interconnection between on-premises and cloud applications, you must set the Port parameter to the specified port.
    3. Click ok to complete the IntelliJ IDEA configuration.

  3. Insert a breakpoint (marked by ① in the figure) to the function code in the editor margin of IntelliJ IDEA and click the debugging icon (marked by ② in the figure).
  4. Open a new terminal and run the following command to invoke the function:
    s proxied invoke

    After you run the s proxied invoke command, you can return to IntelliJ IDEA. In this case, breakpoint debugging for the function has started.

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