Simplify through use of grpc builder APIs
This commit is contained in:
@@ -15,6 +15,7 @@ import org.springframework.grpc.sample.proto.HelloRequest;
|
||||
import org.springframework.grpc.sample.proto.SimpleGrpc;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
|
||||
import io.grpc.Channel;
|
||||
import io.grpc.Grpc;
|
||||
import io.grpc.InsecureChannelCredentials;
|
||||
|
||||
@@ -45,11 +46,17 @@ public class GrpcServerApplicationTests {
|
||||
|
||||
@TestConfiguration
|
||||
static class ExtraConfiguration {
|
||||
|
||||
@Bean
|
||||
SimpleGrpc.SimpleBlockingStub stub() {
|
||||
var channel = Grpc.newChannelBuilderForAddress("0.0.0.0", 9090, InsecureChannelCredentials.create())
|
||||
.build();
|
||||
SimpleGrpc.SimpleBlockingStub stub(Channel channel) {
|
||||
return SimpleGrpc.newBlockingStub(channel);
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
Channel channel() {
|
||||
return Grpc.newChannelBuilderForAddress("0.0.0.0", 9090, InsecureChannelCredentials.create()).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2024-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.grpc.client;
|
||||
|
||||
import io.grpc.Channel;
|
||||
|
||||
public interface GrpcChannelFactory extends AutoCloseable {
|
||||
|
||||
Channel createChannel(String name);
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2024 the original author or authors.
|
||||
* Copyright 2024-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Partial copy from net.devh:grpc-spring-boot-starter.
|
||||
*/
|
||||
package org.springframework.grpc.server;
|
||||
|
||||
@@ -32,7 +31,7 @@ import io.grpc.Server;
|
||||
import io.grpc.ServerBuilder;
|
||||
import io.grpc.ServerServiceDefinition;
|
||||
|
||||
public abstract class AbstractGrpcServerFactory<T extends ServerBuilder<T>> implements GrpcServerFactory {
|
||||
public class DefaultGrpcServerFactory<T extends ServerBuilder<T>> implements GrpcServerFactory {
|
||||
|
||||
/** Logger available to subclasses. */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
@@ -45,7 +44,7 @@ public abstract class AbstractGrpcServerFactory<T extends ServerBuilder<T>> impl
|
||||
|
||||
private final int port;
|
||||
|
||||
protected AbstractGrpcServerFactory(String address, int port, final List<GrpcServerConfigurer> serverConfigurers) {
|
||||
public DefaultGrpcServerFactory(String address, int port, final List<GrpcServerConfigurer> serverConfigurers) {
|
||||
this.serverConfigurers = requireNonNull(serverConfigurers, "serverConfigurers");
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
@@ -70,7 +69,11 @@ public abstract class AbstractGrpcServerFactory<T extends ServerBuilder<T>> impl
|
||||
* Creates a new server builder.
|
||||
* @return The newly created server builder.
|
||||
*/
|
||||
protected abstract T newServerBuilder();
|
||||
@SuppressWarnings("unchecked")
|
||||
protected T newServerBuilder() {
|
||||
// TODO: Add support for address resolution
|
||||
return (T) ServerBuilder.forPort(getPort());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the given server builder. This method can be overwritten to add features
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Partial copy from net.devh:grpc-spring-boot-starter.
|
||||
*/
|
||||
|
||||
package org.springframework.grpc.server;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.grpc.util.GrpcUtils;
|
||||
|
||||
import com.google.common.net.InetAddresses;
|
||||
|
||||
import io.grpc.netty.NettyServerBuilder;
|
||||
import io.netty.channel.epoll.EpollEventLoopGroup;
|
||||
import io.netty.channel.epoll.EpollServerDomainSocketChannel;
|
||||
import io.netty.channel.unix.DomainSocketAddress;
|
||||
|
||||
/**
|
||||
* Factory for netty based grpc servers.
|
||||
*
|
||||
* @author Michael (yidongnan@gmail.com)
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class NettyGrpcServerFactory extends AbstractGrpcServerFactory<NettyServerBuilder> {
|
||||
|
||||
/**
|
||||
* Creates a new netty server factory with the given properties.
|
||||
* @param address The address to bind the server to.
|
||||
* @param port The port to bind the server to (0 for ephemeral port).
|
||||
* @param properties The properties used to configure the server.
|
||||
* @param serverConfigurers The server configurers to use. Can be empty.
|
||||
*/
|
||||
public NettyGrpcServerFactory(String address, int port, final List<GrpcServerConfigurer> serverConfigurers) {
|
||||
super(address, port, serverConfigurers);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NettyServerBuilder newServerBuilder() {
|
||||
if (getAddres().startsWith(GrpcUtils.DOMAIN_SOCKET_ADDRESS_PREFIX)) {
|
||||
final String path = GrpcUtils.extractDomainSocketAddressPath(getAddres());
|
||||
return NettyServerBuilder.forAddress(new DomainSocketAddress(path))
|
||||
.channelType(EpollServerDomainSocketChannel.class)
|
||||
.bossEventLoopGroup(new EpollEventLoopGroup(1))
|
||||
.workerEventLoopGroup(new EpollEventLoopGroup());
|
||||
}
|
||||
else if (GrpcUtils.ANY_IP_ADDRESS.equals(getAddres())) {
|
||||
return NettyServerBuilder.forPort(getPort());
|
||||
}
|
||||
else {
|
||||
return NettyServerBuilder
|
||||
.forAddress(new InetSocketAddress(InetAddresses.forString(getAddres()), getPort()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Partial copy from net.devh:grpc-spring-boot-starter.
|
||||
*/
|
||||
package org.springframework.grpc.util;
|
||||
|
||||
import io.grpc.MethodDescriptor;
|
||||
|
||||
/**
|
||||
* Utility class that contains methods to extract some information from grpc classes.
|
||||
*
|
||||
* @author Daniel Theuke (daniel.theuke@heuboe.de)
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public final class GrpcUtils {
|
||||
|
||||
/**
|
||||
* A constant that defines the scheme of a Unix domain socket address.
|
||||
*/
|
||||
public static final String DOMAIN_SOCKET_ADDRESS_SCHEME = "unix";
|
||||
|
||||
/**
|
||||
* A constant that defines the scheme prefix of a Unix domain socket address.
|
||||
*/
|
||||
public static final String DOMAIN_SOCKET_ADDRESS_PREFIX = DOMAIN_SOCKET_ADDRESS_SCHEME + ":";
|
||||
|
||||
/**
|
||||
* A constant that defines that the server should listen to any IPv4 and IPv6 address.
|
||||
*/
|
||||
public static final String ANY_IP_ADDRESS = "*";
|
||||
|
||||
/**
|
||||
* Extracts the domain socket address specific path from the given full address. The
|
||||
* address must fulfill the requirements as specified by
|
||||
* <a href="https://grpc.github.io/grpc/cpp/md_doc_naming.html">grpc</a>.
|
||||
* @param address The address to extract it from.
|
||||
* @return The extracted domain socket address specific path.
|
||||
* @throws IllegalArgumentException If the given address is not a valid address.
|
||||
*/
|
||||
public static String extractDomainSocketAddressPath(final String address) {
|
||||
if (!address.startsWith(DOMAIN_SOCKET_ADDRESS_PREFIX)) {
|
||||
throw new IllegalArgumentException(address + " is not a valid domain socket address.");
|
||||
}
|
||||
String path = address.substring(DOMAIN_SOCKET_ADDRESS_PREFIX.length());
|
||||
if (path.startsWith("//")) {
|
||||
path = path.substring(2);
|
||||
// We don't check this as there is no reliable way to check that it's an
|
||||
// absolute path, especially when Windows adds support for these in the future
|
||||
// if (!path.startsWith("/")) {
|
||||
// throw new IllegalArgumentException("If the path is prefixed with '//', then
|
||||
// the path must be absolute");
|
||||
// }
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the service name from the given method.
|
||||
* @param method The method to get the service name from.
|
||||
* @return The extracted service name.
|
||||
* @see MethodDescriptor#extractFullServiceName(String)
|
||||
* @see #extractMethodName(MethodDescriptor)
|
||||
*/
|
||||
public static String extractServiceName(final MethodDescriptor<?, ?> method) {
|
||||
return MethodDescriptor.extractFullServiceName(method.getFullMethodName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the method name from the given method.
|
||||
* @param method The method to get the method name from.
|
||||
* @return The extracted method name.
|
||||
* @see #extractServiceName(MethodDescriptor)
|
||||
*/
|
||||
public static String extractMethodName(final MethodDescriptor<?, ?> method) {
|
||||
// This method is the equivalent of MethodDescriptor.extractFullServiceName
|
||||
final String fullMethodName = method.getFullMethodName();
|
||||
final int index = fullMethodName.lastIndexOf('/');
|
||||
if (index == -1) {
|
||||
return fullMethodName;
|
||||
}
|
||||
return fullMethodName.substring(index + 1);
|
||||
}
|
||||
|
||||
private GrpcUtils() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2024-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.grpc.autoconfigure.client;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.grpc.server.GrpcServerFactory;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnBean(GrpcServerFactory.class)
|
||||
public class GrpcClientAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -17,17 +17,14 @@ package org.springframework.grpc.autoconfigure.server;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.grpc.server.DefaultGrpcServerFactory;
|
||||
import org.springframework.grpc.server.GrpcServerConfigurer;
|
||||
import org.springframework.grpc.server.GrpcServerFactory;
|
||||
import org.springframework.grpc.server.NettyGrpcServerFactory;
|
||||
|
||||
import io.grpc.ServerServiceDefinition;
|
||||
|
||||
@@ -37,17 +34,12 @@ import io.grpc.ServerServiceDefinition;
|
||||
@EnableConfigurationProperties(GrpcServerProperties.class)
|
||||
public class GrpcServerFactoryAutoConfiguration {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(GrpcServerFactoryAutoConfiguration.class);
|
||||
|
||||
@ConditionalOnMissingBean(GrpcServerFactory.class)
|
||||
@ConditionalOnClass(name = { "io.netty.channel.Channel", "io.grpc.netty.NettyServerBuilder" })
|
||||
@Bean
|
||||
public NettyGrpcServerFactory nettyGrpcServerFactory(final GrpcServerProperties properties,
|
||||
public DefaultGrpcServerFactory<?> defaultGrpcServerFactory(final GrpcServerProperties properties,
|
||||
final GrpcServiceDiscoverer serviceDiscoverer, final List<GrpcServerConfigurer> serverConfigurers) {
|
||||
|
||||
logger.info("Detected grpc-netty: Creating NettyGrpcServerFactory");
|
||||
final NettyGrpcServerFactory factory = new NettyGrpcServerFactory(properties.getAddress(), properties.getPort(),
|
||||
serverConfigurers);
|
||||
final DefaultGrpcServerFactory<?> factory = new DefaultGrpcServerFactory<>(properties.getAddress(),
|
||||
properties.getPort(), serverConfigurers);
|
||||
for (final ServerServiceDefinition service : serviceDiscoverer.findGrpcServices()) {
|
||||
factory.addService(service);
|
||||
}
|
||||
|
||||
@@ -20,12 +20,11 @@ import java.time.temporal.ChronoUnit;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.convert.DurationUnit;
|
||||
import org.springframework.grpc.util.GrpcUtils;
|
||||
|
||||
@ConfigurationProperties(prefix = "spring.grpc.server")
|
||||
public class GrpcServerProperties {
|
||||
|
||||
private String address = GrpcUtils.ANY_IP_ADDRESS;
|
||||
private String address = "*";
|
||||
|
||||
private int port = 9090;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class GrpcServiceAutoConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
@Bean
|
||||
public GrpcServiceDiscoverer defaultGrpcServiceDiscoverer(ApplicationContext applicationContext) {
|
||||
return new AnnotationGrpcServiceDiscoverer(applicationContext);
|
||||
return new DefaultGrpcServiceDiscoverer(applicationContext);
|
||||
}
|
||||
|
||||
@ConditionalOnMissingBean
|
||||
@@ -49,11 +49,11 @@ public class GrpcServiceAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
class AnnotationGrpcServiceDiscoverer implements GrpcServiceDiscoverer {
|
||||
class DefaultGrpcServiceDiscoverer implements GrpcServiceDiscoverer {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
public AnnotationGrpcServiceDiscoverer(ApplicationContext applicationContext) {
|
||||
public DefaultGrpcServiceDiscoverer(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user