spring-cloud / spring-cloud/spring-cloud-gateway

Recycling ManagedChannel to prevent creation on every call in JsonToGrpcGatewayFilterFactory

Open
#3,120 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement in progress
Dominant language
Java
Stars
4.9k
Forks
3.5k
Avg merge
20h 57m
Merged PRs (30d)
8

Description

Is your feature request related to a problem? Please describe.
JsonToGrpcGatewayFilter which converts a json to a gRPC creates ManagedChannel on every call.

package org.springframework.cloud.gateway.filter.factory;

public class JsonToGrpcGatewayFilterFactory
        extends AbstractGatewayFilterFactory<JsonToGrpcGatewayFilterFactory.Config> {
    ... ...
    class GRPCResponseDecorator extends ServerHttpResponseDecorator {
    ... ...
        // We are creating this on every call, should optimize?
        private ManagedChannel createChannelChannel(String host, int port) {
	    NettyChannelBuilder nettyChannelBuilder = NettyChannelBuilder.forAddress(host, port);
	    try {
		return grpcSslConfigurer.configureSsl(nettyChannelBuilder);
	    }
	    catch (SSLException e) {
		throw new RuntimeException(e);
	    }
        }
    }
}

Furthermore, there's no logic that call shutdown() ManagedChannel.

2023-11-03T12:12:05.152+09:00 ERROR 6277 --- [ctor-http-nio-3] i.g.i.ManagedChannelOrphanWrapper        : 
    *~*~*~ Previous channel ManagedChannelImpl{logId=7, target=localhost:8081} was not shutdown properly!!! ~*~*~*
        Make sure to call shutdown()/shutdownNow() and wait until awaitTermination() returns true.

Describe the solution you'd like
So here below is my suggestion using ConcurrentHashMap to recycle ManagedChannels.
(or add something like lifecycle to manages all ManageChannels?)

Describe alternatives you've considered

package org.springframework.cloud.gateway.filter.factory;

public class JsonToGrpcGatewayFilterFactory
        extends AbstractGatewayFilterFactory<JsonToGrpcGatewayFilterFactory.Config> {
    // a container for ManagedChannel. key = host + ":" + port
    private final ConcurrentHashMap<String, ManagedChannel> ManagedChannelContainer = new ConcurrentHashMap<>();
    ... ...
    class GRPCResponseDecorator extends ServerHttpResponseDecorator {

    ... ...
        // get ManageChannel from ManageChannelContainer and if it exists, return that value(ManageChannel);
        // if it doesn't exist, create ManageChannel and put it in ManageChannelContainer and return it.
        private ManagedChannel createChannelChannel(String host, int port) {
	    String key = host + ":" + port;
            ManagedChannel managedChannel =  ManagedChannelContainer.get(key);

            if (managedChannel == null) {
                NettyChannelBuilder nettyChannelBuilder = NettyChannelBuilder.forAddress(host, port);
                try {
                    managedChannel = grpcSslConfigurer.configureSsl(nettyChannelBuilder);
                    ManagedChannelContainer.put(key, managedChannel);
                    return managedChannel;
                }
                catch (SSLException e) {
                    throw new RuntimeException(e);
                }
            } else {
                return managedChannel;
            }
        }
    }
}

Additional context
build.gradle

// includes spring-cloud-gateway-server:4.0.7
implementation 'org.springframework.cloud:spring-cloud-gateway-starter:4.0.7'

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading JsonToGrpcGatewayFilterFactory and tracing how GRPCResponseDecorator creates and uses ManagedChannel for each request. Define the channel ownership and lifecycle, including reuse, SSL configuration, and shutdown behavior; the work is done when channels are not recreated unnecessarily and are cleanly released.

Written by the indexing model from the issue text.

Assessment

Tech stack
grpc, java, spring
Domain
api, backend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.