helidon-io / helidon

Java libraries for writing microservices
https://helidon.io
Apache License 2.0
3.52k stars 564 forks source link

Prototype UDP support in Nima #5629

Open spericas opened 1 year ago

spericas commented 1 year ago

Scope of this task is to create a prototype that adds UDP support in Nima. For additional background information about this task see discussion in https://github.com/helidon-io/helidon/issues/5066

spericas commented 1 year ago

Overview of UDP Prototype

The Nima webserver was extended with a new listener that handles UDP traffic. Any port in a Helidon application can be marked as a UDP port. UDP ports have a single UdpEndpoint instance and no routers (no request URIs). The UDP listener uses a platform thread to handle message arrivals, and creates a new virtual thread to call onMessage.

A message can be mapped to ByteBuffer, byte[], InputStream or any other type handled by MediaSupport in Helidon such as JSON, etc. The @ServerTest annotation is extended with a new flag to mark the default port as UDP (other ports can be marked in a similar manner using the webserver's builder and @SetUpServer).

Unit Tests

Simplified unit test:

@ServerTest(udp = true)
class UdpSimpleTest extends UdpBaseTest {

    private final InetSocketAddress address;

    public UdpSimpleTest(WebServer webServer) {
        this.address = new InetSocketAddress("localhost", webServer.port());
    }

    @SetUpServer
    static void setUp(WebServer.Builder builder) {
        builder.udpEndpoint(new EchoService());
    }

    @Test
    void testEndpoint() throws Exception {
        echoMessage("hello", address);
    }

    static class EchoService implements UdpEndpoint {
        @Override
        public void onMessage(UdpMessage message) {
            try {
                String str = message.as(String.class);
                message.udpClient().sendMessage(str);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

Additional unit tests here:

Performance Testing

There are no standard load testers for UDP that I could find, partly because there is typically a need to implement some simple flow control to avoid overloading the server. I've created a simple, multi-thread UDP load generator and corresponding service to test raw performance that implements a trivial flow control protocol that simply sends an "ack" message periodically to throttle client messages. The service only reads all the bytes received but does not do any real processing. For more information see:

TODO: Use this load generator to compare performance with other frameworks.

The Simple UDP API

https://github.com/spericas/helidon/tree/udp-prototype/nima/udp/udp/src/main/java/io/helidon/nima/udp

spericas commented 1 year ago

@denismakogon