Prosty serwer pod websockety - alternatywa do Springa

0

Cześć,
potrzebuję dorobić sobie backend do prostej gierki (API oparte o websockety). Wszystko czego potrzebuję to:

  • łatwa obsługa websocketów
  • szybkie uruchamianie
  • najchętniej na JVM
  • późniejsze wpięcie Mongo
  • wsparcie Kotlina

Nie potrzebuję nawet kontenera IoC czy innych bajerów springowych. Może coś podobnego do Flaska?
Macie jakieś fajne propozycje? Czego mógłbym spróbować?

3

Jeśli w Javie to chyba nadal Ratpack daje radę. Mój stary projekcik - są websockety https://github.com/javaFunAgain/ratpong
W kotlinie to będzie działać nawet lepiej.
Jest też kotlin ktor, ale czasem mnie wkurza i nie sprawdziłem go dobrze.

1
jarekr000000 napisał(a):

Jeśli w Javie to chyba nadal Ratpack daje radę. Mój stary projekcik - są websockety https://github.com/javaFunAgain/ratpong
W kotlinie to będzie działać nawet lepiej.
Jest też kotlin ktor, ale czasem mnie wkurza i nie sprawdziłem go dobrze.

Dzięki, to jest prawdopodobnie to czego szukałem :) Projekt z websocketami na wagę złota. Zastanawiam się jak to jest z progiem wejścia? Od dwóch lat piszę tylko i wyłącznie w dosyć podstawowym Springu. Czy wejście w ratpacka będzie wymagało dużo cierpliwości czy powinno pójść gładko? (biorąc pod uwagę np. myślenie Promisami).

0

Zmiana paradygmatu, więc próg wejścia będzie relatywnie wyższy. Dodatkowo, programowanie asynchroniczne, współbieżne, reaktywne uchodzi powszechnie za trudne.

2
Charles_Ray napisał(a):

Zmiana paradygmatu, więc próg wejścia będzie relatywnie wyższy. Dodatkowo, programowanie asynchroniczne, współbieżne, reaktywne uchodzi powszechnie za trudne.

Nie no nie straszmy aż tak, Ratpack wcale taki trudny nie jest :)
Może być troszkę bardziej skomplikowany bo koniec końców jest małą biblioteką, a nie frameworkiem jak Spring i gdzieniegdzie pewnie będzie wrażenie, że trzeba robić tyyyyle, a w Springu to jedną adnotacją da się opękać. Paradygmatu samego w sobie też się nie zmienia, Java funkcyjna to nigdy nie będzie, co najwyżej mogą występować różne "wstawki".
Tak czy siak, użycie takiej biblioteczki to na pewno fajny pomysł - może pokazać, że nie wszystko musi stać na Springu, a i jeszcze może jakieś zalety dodatkowe się odkryje ;)

0

Jeżeli potrzebny jest naprawdę totalny minimalizm (obsługa jedynie websocketów, bez klasycznego HTTP) to można użyć czystego Netty (wszystkie Ratpacki czy inne Vertexy się na tym opierają):

import io.netty.bootstrap.ServerBootstrap
import io.netty.channel.ChannelHandler
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.ChannelInitializer
import io.netty.channel.SimpleChannelInboundHandler
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioServerSocketChannel
import io.netty.handler.codec.http.HttpObjectAggregator
import io.netty.handler.codec.http.HttpServerCodec
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler

// connect with ws://localhost:8080/ws

fun main() {
    val startTime = System.currentTimeMillis()
    ServerBootstrap()
        .group(NioEventLoopGroup())
        .channel(NioServerSocketChannel::class.java)
        .childHandler(object : ChannelInitializer<SocketChannel>() {
            override fun initChannel(connection: SocketChannel) {
                connection.pipeline()
                    .addLast(HttpServerCodec())
                    .addLast(HttpObjectAggregator(Short.MAX_VALUE.toInt()))
                    .addLast(WebSocketServerProtocolHandler("/ws"))
                    .addLast(WebsocketRequestHandler)
            }
        })
        .bind(8080)
        .sync()
        .channel().apply {
            println("Startup time: ${System.currentTimeMillis() - startTime}ms")
            closeFuture().sync()
        }
}


@ChannelHandler.Sharable
object WebsocketRequestHandler : SimpleChannelInboundHandler<TextWebSocketFrame>() {

    override fun channelRead0(context: ChannelHandlerContext, frame: TextWebSocketFrame) {
        val text = frame.text()
        println("Received text: $text")
        context.channel()
            .writeAndFlush(TextWebSocketFrame("Echo: $text"));
    }
}

Wystarczy jedna dependencja:
compile group: 'io.netty', name: 'netty-all', version: '4.1.48.Final'

Żeby zakodzić jednak coś poważniejszego na samym Netty, to próg wejścia rośnie znacząco bo to dość niskopoziomowa biblioteka mimo wszystko.

1 użytkowników online, w tym zalogowanych: 0, gości: 1