Hi,
I have some questions about this proposal.

1. If using similar C/S mode, whether the encoding and decoding process
will affect the performance.

2.Can we use protobuf, a more popular encoding and decoding toolkit?


Thanks!

*发件人: *Zexuan Luo <spacewan...@apache.org>
*发送时间: *2021年4月16日 14:52
*收件人: *dev@apisix.apache.org
*主题: *[Proposal] support using other languages to write plugin for APISIX



1. Background



APISIX currently only supports writing plugins in Lua. If other

languages are supported, it will greatly broaden the APISIX ecosystem

and user base.



2. Solution



Since WASM is not yet mature, we consider implementing it through local IPC.



For the sake of discussion, the following will assume that the plugin

is written in Java. However, in practice, our solution can be

interfaced with other languages.



2.1 Terminology



Several terms are defined here.



Plugin Runner: The service that runs the plugin, written in the same

language as the plugin. In the first version, we assume that there

will be only one Plugin Runner.



2.2 Plugin Runner lifecycle



To simplify user operation and reduce the difficulty of upgrading,

Plugin Runner is managed by APISIX.



APISIX starts the Plugin Runner when it starts and ends it when it

ends. if the Plugin Runner quits in the middle, APISIX will restart it

automatically.



2.3 Timing of APISIX communication with Plugin Runner



```

Router ----> Global Plugin (written in Lua) ---> Ext Plugin

(ext-plugin-pre-req) ----> Lua Plugin (Router)

---> Ext plugin (ext-plugin-post-req) ---> Upstream

```



Running the Ext Plugin in the Global Plugin is not supported at this

time, as the global logic can be executed uniformly in the Plugin

Runner.



Running Ext Plugin after getting an upstream response is not supported

at this time. We can support it later with a buffering response.



ext-plugin-pre runs before all non-global Lua plugins, and

ext-plugin-post runs after all non-global Lua plugins.



2.4 How APISIX communicates with Plugin Runner



APISIX communicates with Plugin Runner through a unix socket. The

communication protocol is as follows.



2.4.1 Communication format



```

1 byte of type + 3 bytes of length + data

```



The type can be 0 ~ 7, and the length can be [0, 8M). data length is

determined by length.

Since Ext Plugin usually does not exchange too much data, 8M should be

enough. The reason for taking 4 bytes is to keep the header small

enough to be read efficiently.



The current type takes the following values.



0 means error

1 means prepare_conf

2 means http_req_call



The data is serialized in capnproto, a binary serialization format.



capnproto is supported by many programming languages:

https://capnproto.org/otherlang.html



The advantages of choosing capnproto are.

1. focus on serialization performance

2. partial deserialization support, so that decode can be done only

when it is needed



2.4.2 Communication steps



Each ext plugin will have the following configuration.



```

{

    "conf": [

        {

            "name": "configuration name",

            "value": "configuration value"

        }

    ],

    "extra_info": [

                ...

    ]

}

```



conf can be used to set the execution configuration of the

plugin-related requests inside Plugin Runner.



The default data sent to Plugin Runner is only the most common

information. If you want additional information, you need to declare

it in extra_info beforehand.



To save communication costs, conf is sent separately.



1. APISIX will check if conf has a corresponding token in the local cache.

2. If not, APISIX sends a prepare_conf request to ask Plugin Runner

to cache the conf and return a token.

(Note that Plugin Runner's cache time needs to be longer than APISIX's

cache time.)

3. APISIX sends an http_req_call request to Plugin Runner.

4. Plugin Runner executes the request and returns a response to APISIX.

5. APISIX processes the request based on the response



2.4.3 proto



Refer to https://capnproto.org/language.html



The following is the proto for error



response

```

enum ErrorCode {

    BAD_REQUEST @0; # Plugin Runner can't understand APISIX

    SERVICE_UNAVAILABLE @1; # Plugin Runner can't handle the request

    CONF_TOKEN_NOT_FOUND @2;

}

struct ErrorResp {

    Code @0 :ErrorCode;

}

```



The following is the proto of prepare_conf



request

```

struct PrepareConfReq {

    conf @0 :List(Pair);

}

```



Response

```

struct PrepareConfResp {

    conf_token @0 :UInt32;

}

```



Here is the proto for http_req_call



request

```

struct Pair {

    name @0 :Text;

    value @1 :Text;

}

struct PairData {

    name @0 :Text;

    value @1 :Data;

}

enum Method {

        GET @0;

        ...

}



struct HTTPReqCallReq {

    id @0 :UInt32;

    src_ip @1 :Data;



    method @2 :Method;



    path @3 :Text;

    args @4 :List(Pair);

    headers @5 :List(Pair);



    conf_token @6 :UInt32;



    extra_info @7 :List(PairData);

}

```



Response

```

struct HTTPReqCallResp {

    id @0 :UInt32;



    struct Stop {

        status @0 :UInt16;

        headers @1 :List(Pair);

        body @2 :Data;

    }

    struct Rewrite {

        path @0 :Text;

        headers @1 :List(Pair);

        # Note that args are modified in full.

        # Either empty, meaning no args need to be moved

        # or the entire modified args, not the incrementally changed parts

        args @2 :List(Pair);

    }



    # What needs to be done when the response is received action

    action :union {

        # Do nothing

        continue @1 :Void;

        # Equivalent to core.response.exit(status, body), allowing

additional headers to be set

        stop @2 :Stop;

        # Rewrite the request

        rewrite @3 :Rewrite;

    }

}

```



2.4.4 Error handling



Logging and returning 503 error codes



2.4.5 Environment variables



APISIX configures the Plugin Runner with a number of environment

variables when it is started.



APISIX_LISTEN_ADDRESS: the address that the Plugin Runner needs to listen to

APISIX_CONF_EXPIRE_TIME: Plugin Runner needs to cache conf for longer than
this

Reply via email to