OK, if it is a development kit, I want to know whether it is really a runtime? Because eventually, whether debugging is friendly or not, rely on this.
Sheng Wu 吴晟 Twitter, wusheng1108 Daming <[email protected]> 于2021年4月27日周二 上午9:57写道: > PDK stands for Plugin Development Kit. > It is a good choice to build on spring-boot in the initial stage. > Because it is very friendly and easy to get started for Java > developers(plugins developers). > > > Sheng Wu <[email protected]> 于2021年4月27日周二 上午9:31写道: > > > > I can't see the detail from the graph. > > But if we are speaking of Java and Spring gateway ecosystem, you should > > know, that is not just interfaces. > > Spring boot, annotation system, IoC, AOP are all going to be there. So, > > basically, I would recommend you to boot the codes as all Spring-based > > applications did. > > BTW, I am not sure what PDK means. > > > > And about debugging, once your APISIX process could access the JVM > through > > a socket with manual localhost:port, it is fine for the Java developer to > > start this sidecar in the IDEA. > > > > Sheng Wu 吴晟 > > Twitter, wusheng1108 > > > > > > ZhengSong Tu <[email protected]> 于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 <[email protected]> 于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 <[email protected]> 于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 > > >> > > > >
