This is why we choose capnproto rather than protobuf. The encode/decode performance is important, so we choose capnproto which has a better performance than protobuf.
bzp2010 <bzp2...@apache.org> 于2021年4月16日周五 下午4:44写道: > > 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