Avba
Avba

Reputation: 15296

How to create a GRPC service over a local socket rather then inet in scala/java

My GRPC service is only accessible to applications on the local machine.

I assume it would perform faster if the clients would connect over Unix domain socket, rather then localhost:port

I'm tyring to understand how to create the grpc service in this case, it should be able to run on CentOS as well as on Mac

Currently creating the server like this:

val server: Server = ServerBuilder.forPort(port).addService(GreeterGrpc.bindService(new GrpcServer, ec)).build().start()

I also tried configuration like this:

val server: Server = io.grpc.netty.NettyServerBuilder.forPort(port).addService(ProtoReflectionService.newInstance()).addService(GreeterGrpc.bindService(new GrpcServer, ec)).build().start()

but couldn't figure out how to bind to local socket rather then localhost

Upvotes: 6

Views: 14041

Answers (2)

Ulf Adams
Ulf Adams

Reputation: 1329

For future readers: Java 16 added support for UDS. Netty issue tracking Java 16-related changes is https://github.com/netty/netty/issues/10991.

Upvotes: 2

Eric Anderson
Eric Anderson

Reputation: 26464

localhost:port should be basically as fast as a Unix Domain Socket (UDS). The main use case of UDS is for better control of permissions and security, as Unix file permissions apply.

Java does not support UDS. So to get grpc-java using UDS you must use a JNI component like netty-transport-epoll or netty-transport-kqueue.

grpc-java does not provide out-of-the-box support for UDS, but you can combine the pieces together yourself:

// You are responsible for shutting down 'elg' and 'boss'. You
// may want to provide a ThreadFactory to use daemon threads.
EventLoopGroup elg = new EpollEventLoopGroup();

ManagedChannel chan = NettyChannelBuilder
    .forAddress(new DomainSocketAddress("filename"))
    .eventLoopGroup(elg)
    .channelType(EpollDomainSocketChannel.class)
    .build();

EventLoopGroup boss = new EpollEventLoopGroup(1);
Server serv = NettyServerBuilder
    .forAddress(new DomainSocketAddress("filename"))
    .bossEventLoopGroup(boss)
    .workerEventLoopGroup(elg)
    .channelType(EpollServerDomainSocketChannel.class)
    .build();

The "boss" event loop group's only job is to accept() new connections. If the rate of new connections is low, you can use elg for bossEventLoopGroup().

You should share elg as much as possible across Channels and Servers.

Epoll isn't available on OS X, so you would need to use kqueue instead. For kqueue use KQueueEventLoop, KQueueDomainSocketChannel, and KQueueServerDomainSocketChannel instead of their epoll counterparts.

Upvotes: 10

Related Questions