Skip to content

Latest commit

 

History

History
116 lines (84 loc) · 3.92 KB

the-internal-of-apisix-java-plugin-runner.md

File metadata and controls

116 lines (84 loc) · 3.92 KB
title
The internal of apisix java plugin runner

This article explains the internal design of apisix-java-plugin-runner.

Table of Contents

Overview

The apisix-java-plugin-runner designed as a TCP server built using netty, it provides a PluginFilter interface for users to implement.

Users only need to focus on their business logic, not on the details of how the apisix java plugin runner communicates with APISIX.

The inter-process communication between them is depicted by the following diagram.

the-internal-of-apisix-java-plugin-runner

Communication

apisix-java-plugin-runner and APISIX use the Unix Domain Socket for inter-process communication, so they need to be deployed in the same instance.

apisix-java-plugin-runner is managed by APISIX. APISIX starts the apisix-java-plugin-runner when it starts and ends it when it ends. if the apisix-java-plugin-runner quits in the middle, APISIX will restart it automatically.

Serialization

Refer to flatbuffers

FlatBuffers is a cross platform serialization library architected for maximum memory efficiency. It allows you to directly access serialized data without parsing/unpacking it first, while still having great forward/backward compatibility.

You can refer to the ext-plugin.fbs schema file to see how Lua and Java layout the serialized objects.

Codec

apisix-java-plugin-runner and APISIX use a private binary protocol for coding and decoding. The protocol format is

1 byte of type + 3 bytes of length + data

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

The current type takes the following values

  • 0 means error
  • 1 means prepare_conf
  • 2 means http_req_call

The binary data generated by the flatbuffer serialization is placed in the data segment.

Threading model

Apisix plugin runner will run your plugins directly onto the event loop.

While this empower the best performance possible, as a plugin developer you will have the responsibility never to block threads on the event loop. Doing so would result in catastrophic performance drop.

Hopefully one can write asynchronous plugins easily: just call the PluginFilterChain as a callback once you are done.

For instance:

@Component
public class AsyncResponseFilter implements PluginFilter {
    @Override
    public String name() {
        return "AyncResponseFilter";
    }

    @Override
    public void postFilter(PostRequest request, PostResponse response, PluginFilterChain chain) {
        callExternalService()
            .thenAccept(body -> {
                response.setBody(body);
                chain.postFilter(request, response);
            });
    }

    // This simulates calls to an external service
    CompletableFuture<String> callExternalService() {
        return CompletableFuture.completedFuture("response_body");
    }
}