Hi, ZhengSong,

You image is broken due to we could only use plain text in mailing list :)

Best Regards!
@ Zhiyuan Ju <https://github.com/juzhiyuan>


ZhengSong Tu <tzssanggl...@gmail.com> 于2021年4月26日周一 上午11:47写道:

> I have sketched the flow of the java side of the plugin runner
> [image: APISIX 运行 Java 插件.png]
>
> And I have some questions to clarify.
>
> 1. How does the plugin runner load the client's code?
>     It's up to each runner to figure it out according to its own
> language's ecology. Take java as an example,
> the user develops with the PDK provided by us, and packages the custom
> plugin code into a jar and puts it in the specified location. When the
> plugin runner starts, it loads the jar package in this location by means of
> a custom dynamic ClassLoader or something like that.
>
> 2. How do users develop?
>     Just provide the filter chain like Spring Cloud Gateway. Users can
> register their own filters. And the PDK is a jar, with some defined
> interfaces such as pre, post, etc., and some objects such as request,
> header, etc.
>
> 3. How to debug?
>     Option 1:  APISIX provides debugging mode for java plugins, this time
> it is not APISIX to start the plugin runner, but the user himself downloads
> the plugin runner code and runs the main method to start it, so as to
> construct a request to access APISIX, APISIX will pass the context of the
> request to the plugin runner, and then use it to debug java code.
>     Option 2:  java remote debug.
>
>
>
> Zexuan Luo <spacewan...@apache.org> 于2021年4月19日周一 下午6:18写道:
>
>> Here is the new flatbuffer schema:
>>
>> https://github.com/spacewander/incubator-apisix/blob/step1/apisix/plugins/ext-plugin/ext-plugin.fbs
>>
>> Zexuan Luo <spacewan...@apache.org> 于2021年4月16日周五 下午2:52写道:
>> >
>> > 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