It is an easier way to support more languages through out-of-process RPC
network communication.

Nice proposal, I think we can make a try.

^_^


On Sat, Apr 17, 2021 at 11:52 AM Zexuan Luo <[email protected]> wrote:

> I am glad to hear that there is another option.
> We can use flatbuffers as the codec instead of capnproto.
>
> > as you are not using a standard RPC protocol, no
> possibility of internal tracing
>
> The protocol is extendable and tracing support can be added.
>
> Currently, I focus on performance most because performance is a good
> selling point.
>
> People will say, "APISIX + Java sidecar is faster than Spring Cloud
> Gateway, let's adopt it!".
> It is possible as Nginx is faster than Spring Cloud Gateway.
>
> People won't say, "APISIX + Java sidecar has better observability than
> Spring Cloud Gateway, let's adopt it!".
> As there are two processes than one, it is impossible to have better
> observability.
>
> If people don't even buy, there is no chance to compare observability.
>
> There is a trade-off between performance & observability. I want to
> improve the performance as much as we can, attract people to use it,
> then we can have a chance to improve the observability.
>
> Sheng Wu <[email protected]> 于2021年4月16日周五 下午8:22写道:
> >
> > I want to remind you, as you are not using a standard RPC protocol, no
> > possibility of internal tracing. So how should we collect
> > metrics/performance-data of this cross-processes communication?
> > And it is Java lib(maybe others have the same issue),
> > https://github.com/capnproto/capnproto-java/graphs/contributors, has
> > very little activities. I am not sure how healthy their community is.
> >
> > Have you taken a look at this? https://google.github.io/flatbuffers/
> > It is used in Istio, and SkyWalking used this in mesh scenarios. This
> > protocol has a very good performance especially when some fields are
> > not required to deserialize, which from my understanding, is a very
> > case when running the sidecar process.
> >
> > Sheng Wu 吴晟
> > Twitter, wusheng1108
> >
> > Zexuan Luo <[email protected]> 于2021年4月16日周五 下午6:19写道:
> > >
> > > It will hold long connections.
> > >
> > > Need to clarify that the "long connection" doesn't conflict with the
> > > "request / response mode". For example, gRPC's unary mode can work on
> > > a long connection.
> > >
> > > bzp2010 <[email protected]> 于2021年4月16日周五 下午6:04写道:
> > > >
> > > > Oh, I get it.
> > > > Will it use a long connection based on UNIX socket to transfer data?
> Or is
> > > > it a request / response mode similar to HTTP?
> > > >
> > > > Zexuan Luo <[email protected]> 于2021年4月16日周五 下午5:53写道:
> > > >
> > > > > 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 <[email protected]> 于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 <[email protected]>
> > > > > > *发送时间: *2021年4月16日 14:52
> > > > > > *收件人: *[email protected]
> > > > > > *主题: *[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
> > > > >
>


-- 

*MembPhis*
My GitHub: https://github.com/membphis
Apache APISIX: https://github.com/apache/apisix

Reply via email to