├── .gitignore ├── .travis.yml ├── README.md ├── grpc-eureka-java-starter ├── META-INF │ └── spring.factories ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── exampledriven │ └── grpc │ └── eureka │ └── GrpcEurekaConfiguration.java ├── grpc-eureka-java ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── exampledriven │ └── grpc │ └── eureka │ ├── EurekaNameResolver.java │ └── EurekaNameResolverProvider.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | *.iml 3 | .idea -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: oraclejdk8 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.exampledriven/grpc-eureka-java/badge.svg)](https://maven-badges.herokuapp.com/com.github.exampledriven/grpc-eureka-java/rsql-parser) 2 | 3 | [![Build Status](https://travis-ci.org/ExampleDriven/grpc-eureka-java.svg?branch=master)](https://travis-ci.org/ExampleDriven/grpc-eureka-java) 4 | 5 | # GRPC, Eureka integration in Java 6 | 7 | This project integrates GRPC with Eureka, the best way to understand how it works is to look at the [example code](https://github.com/ExampleDriven/spring-boot-grpc-example) 8 | 9 | ## Server setup 10 | The server does not need any special setup, it should just start GRPC the usual way and register itself to Eureka the usual way 11 | 12 | ## Client setup 13 | 14 | ### Using the Spring Boot Starter 15 | 16 | 1. Add the starter dependency to your project 17 | ```xml 18 | 19 | com.github.exampledriven 20 | grpc-eureka-java-starter 21 | version 22 | 23 | ``` 24 | 25 | 26 | 2. Set the `grpc.eureka.service-id` property to the service id of your server 27 | 28 | 3. A default instance of ManagedChannel is auto created for you. You can use it like this 29 | 30 | ```Java 31 | 32 | @Autowired 33 | ManagedChannel managedChannel; 34 | 35 | @PostConstruct 36 | private void initializeClient() { 37 | 38 | bookServiceBlockingStub = BookServiceGrpc.newBlockingStub(managedChannel); 39 | 40 | } 41 | 42 | ``` 43 | 44 | ## Without using Spring Boot Starter 45 | 46 | 1. Add the following dependency 47 | 48 | ```xml 49 | 50 | com.github.exampledriven 51 | grpc-eureka-java 52 | version 53 | 54 | ``` 55 | 56 | 2. You have to manually create an instance of ManagedChannel like this 57 | 58 | ```Java 59 | return ManagedChannelBuilder 60 | .forTarget("eureka://" + eurekaServiceId) 61 | .nameResolverFactory(new EurekaNameResolverProvider(eurekaClientConfig, "grpc.port")) 62 | .loadBalancerFactory(RoundRobinLoadBalancerFactory.getInstance()) 63 | .usePlaintext(true) 64 | .build(); 65 | ``` -------------------------------------------------------------------------------- /grpc-eureka-java-starter/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.exampledriven.grpc.eureka.GrpcEurekaConfiguration -------------------------------------------------------------------------------- /grpc-eureka-java-starter/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | com.github.exampledriven 7 | grpc-eureka-java-parent 8 | 1.0.0-SNAPSHOT 9 | 10 | 11 | grpc-eureka-java-starter 12 | jar 13 | 14 | GRPC Eureka Java integration Starter 15 | 16 | https://github.com/ExampleDriven/ 17 | 18 | Spring Boot Starter for Eureka integration with GRPC 19 | 20 | 21 | Exampledriven 22 | exampledriven.wordpress.com 23 | 24 | 25 | 26 | Apache License, Version 2.0 27 | http://www.apache.org/licenses/LICENSE-2.0 28 | 29 | 30 | 31 | 32 | 33 | szantop 34 | Peter Szanto 35 | Exampledriven 36 | exampledriven.wordpress.com 37 | 38 | Project lead 39 | 40 | 41 | 42 | 43 | 44 | 45 | UTF-8 46 | 1.8 47 | 1.8 48 | 0.15.0 49 | 50 | 51 | 52 | 53 | 54 | com.github.exampledriven 55 | grpc-eureka-java 56 | 1.0.0-SNAPSHOT 57 | 58 | 59 | 60 | org.springframework 61 | spring-context 62 | 4.3.3.RELEASE 63 | provided 64 | 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-autoconfigure 69 | 1.4.1.RELEASE 70 | provided 71 | 72 | 73 | 74 | io.grpc 75 | grpc-stub 76 | provided 77 | 78 | 79 | 80 | com.netflix.eureka 81 | eureka-client 82 | provided 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /grpc-eureka-java-starter/src/main/java/org/exampledriven/grpc/eureka/GrpcEurekaConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.exampledriven.grpc.eureka; 2 | 3 | import com.netflix.discovery.EurekaClientConfig; 4 | import io.grpc.ManagedChannel; 5 | import io.grpc.ManagedChannelBuilder; 6 | import io.grpc.util.RoundRobinLoadBalancerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | 13 | @Configuration 14 | public class GrpcEurekaConfiguration { 15 | 16 | @Value("${grpc.eureka.service-id}") 17 | private String eurekaServiceId; 18 | 19 | @Autowired 20 | EurekaClientConfig eurekaClientConfig; 21 | 22 | @Bean 23 | @ConditionalOnMissingBean(ManagedChannel.class) 24 | public ManagedChannel defaultManagedChannel() { 25 | 26 | return ManagedChannelBuilder 27 | .forTarget("eureka://" + eurekaServiceId) 28 | .nameResolverFactory(new EurekaNameResolverProvider(eurekaClientConfig, "grpc.port")) 29 | .loadBalancerFactory(RoundRobinLoadBalancerFactory.getInstance()) 30 | .usePlaintext(true) 31 | .build(); 32 | 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /grpc-eureka-java/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | com.github.exampledriven 7 | grpc-eureka-java-parent 8 | 1.0.0-SNAPSHOT 9 | 10 | 11 | grpc-eureka-java 12 | jar 13 | 14 | GRPC Eureka Java integration 15 | 16 | https://github.com/ExampleDriven/ 17 | 18 | Eureka integration with GRPC 19 | 20 | 21 | Exampledriven 22 | exampledriven.wordpress.com 23 | 24 | 25 | 26 | Apache License, Version 2.0 27 | http://www.apache.org/licenses/LICENSE-2.0 28 | 29 | 30 | 31 | 32 | 33 | szantop 34 | Peter Szanto 35 | Exampledriven 36 | exampledriven.wordpress.com 37 | 38 | Project lead 39 | 40 | 41 | 42 | 43 | 44 | 45 | UTF-8 46 | 1.8 47 | 1.8 48 | 49 | 50 | 51 | 52 | 53 | com.google.inject 54 | guice 55 | 4.1.0 56 | 57 | 58 | 59 | com.netflix.eureka 60 | eureka-client 61 | 1.4.11 62 | provided 63 | 64 | 65 | 66 | io.grpc 67 | grpc-netty 68 | provided 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | org.apache.maven.plugins 79 | maven-release-plugin 80 | 2.5.3 81 | 82 | true 83 | false 84 | release 85 | deploy 86 | 87 | 88 | 89 | 90 | org.apache.maven.plugins 91 | maven-compiler-plugin 92 | 3.7.0 93 | 94 | 1.8 95 | 1.8 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /grpc-eureka-java/src/main/java/org/exampledriven/grpc/eureka/EurekaNameResolver.java: -------------------------------------------------------------------------------- 1 | package org.exampledriven.grpc.eureka; 2 | 3 | import com.netflix.appinfo.ApplicationInfoManager; 4 | import com.netflix.appinfo.EurekaInstanceConfig; 5 | import com.netflix.appinfo.InstanceInfo; 6 | import com.netflix.appinfo.MyDataCenterInstanceConfig; 7 | import com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider; 8 | import com.netflix.discovery.DiscoveryClient; 9 | import com.netflix.discovery.EurekaClient; 10 | import com.netflix.discovery.EurekaClientConfig; 11 | import com.netflix.discovery.shared.Application; 12 | import io.grpc.Attributes; 13 | import io.grpc.NameResolver; 14 | import io.grpc.ResolvedServerInfo; 15 | 16 | import java.net.InetSocketAddress; 17 | import java.net.URI; 18 | import java.util.Collections; 19 | import java.util.List; 20 | import java.util.stream.Collectors; 21 | 22 | public class EurekaNameResolver extends NameResolver { 23 | 24 | private final String serviceName; 25 | private final String portMetaData; 26 | private final EurekaClient eurekaClient; 27 | 28 | public EurekaNameResolver(EurekaClientConfig clientConfig, URI targetUri, String portMetaData) { 29 | this.portMetaData = portMetaData; 30 | serviceName = targetUri.getAuthority(); 31 | 32 | MyDataCenterInstanceConfig instanceConfig = new MyDataCenterInstanceConfig(); 33 | 34 | ApplicationInfoManager applicationInfoManager = initializeApplicationInfoManager(instanceConfig); 35 | 36 | eurekaClient = new DiscoveryClient(applicationInfoManager, clientConfig); 37 | } 38 | 39 | private static synchronized ApplicationInfoManager initializeApplicationInfoManager(EurekaInstanceConfig instanceConfig) { 40 | InstanceInfo instanceInfo = new EurekaConfigBasedInstanceInfoProvider(instanceConfig).get(); 41 | return new ApplicationInfoManager(instanceConfig, instanceInfo); 42 | } 43 | 44 | @Override 45 | public String getServiceAuthority() { 46 | return serviceName; 47 | } 48 | 49 | @Override 50 | public void start(Listener listener) { 51 | 52 | update(listener); 53 | 54 | } 55 | 56 | private void update(Listener listener) { 57 | Application application = eurekaClient.getApplication(serviceName); 58 | 59 | List resolvedServerInfos = application.getInstances().stream().map(instanceInfo -> { 60 | int port; 61 | if (portMetaData != null) { 62 | String s = instanceInfo.getMetadata().get(portMetaData); 63 | port = Integer.parseInt(instanceInfo.getMetadata().get(portMetaData)); 64 | } else { 65 | port = instanceInfo.getPort(); 66 | } 67 | return new ResolvedServerInfo(new InetSocketAddress(instanceInfo.getHostName(), port), Attributes.EMPTY); 68 | }).collect(Collectors.toList()); 69 | 70 | listener.onUpdate(Collections.singletonList(resolvedServerInfos), Attributes.EMPTY); 71 | } 72 | 73 | @Override 74 | public void shutdown() { 75 | 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /grpc-eureka-java/src/main/java/org/exampledriven/grpc/eureka/EurekaNameResolverProvider.java: -------------------------------------------------------------------------------- 1 | package org.exampledriven.grpc.eureka; 2 | 3 | import com.netflix.discovery.EurekaClientConfig; 4 | import io.grpc.Attributes; 5 | import io.grpc.NameResolver; 6 | import io.grpc.NameResolverProvider; 7 | import javax.annotation.Nullable; 8 | import java.net.URI; 9 | 10 | public class EurekaNameResolverProvider extends NameResolverProvider { 11 | 12 | protected static final String EUREKA = "eureka"; 13 | private EurekaClientConfig eurekaClientConfig; 14 | private final String portMetaData; 15 | 16 | public EurekaNameResolverProvider(EurekaClientConfig eurekaClientConfig) { 17 | this(eurekaClientConfig, null); 18 | } 19 | 20 | public EurekaNameResolverProvider(EurekaClientConfig eurekaClientConfig, String portMetaData) { 21 | this.eurekaClientConfig = eurekaClientConfig; 22 | this.portMetaData = portMetaData; 23 | } 24 | 25 | @Override 26 | protected boolean isAvailable() { 27 | return true; 28 | } 29 | 30 | @Override 31 | protected int priority() { 32 | return 6; 33 | } 34 | 35 | @Nullable 36 | @Override 37 | public NameResolver newNameResolver(URI targetUri, Attributes params) { 38 | return new EurekaNameResolver(eurekaClientConfig, targetUri, portMetaData); 39 | } 40 | 41 | @Override 42 | public String getDefaultScheme() { 43 | return EUREKA; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.github.exampledriven 6 | grpc-eureka-java-parent 7 | 1.0.0-SNAPSHOT 8 | pom 9 | 10 | GRPC Eureka Java integration parent 11 | 12 | https://github.com/ExampleDriven/ 13 | 14 | Eureka integration with GRPC 15 | 16 | 17 | Exampledriven 18 | exampledriven.wordpress.com 19 | 20 | 21 | 22 | Apache License, Version 2.0 23 | http://www.apache.org/licenses/LICENSE-2.0 24 | 25 | 26 | 27 | 28 | scm:git:git://github.com/ExampleDriven/grpc-eureka-java.git 29 | scm:git:git@github.com:ExampleDriven/grpc-eureka-java.git 30 | https://github.com/ExampleDriven/grpc-eureka-java 31 | 32 | 33 | 34 | 35 | szantop 36 | Peter Szanto 37 | Exampledriven 38 | exampledriven.wordpress.com 39 | 40 | Project lead 41 | 42 | 43 | 44 | 45 | 46 | 47 | UTF-8 48 | 1.8 49 | 1.8 50 | 0.15.0 51 | 52 | 53 | 54 | 55 | 56 | io.grpc 57 | grpc-netty 58 | ${grpc.verson} 59 | 60 | 61 | 62 | io.grpc 63 | grpc-stub 64 | ${grpc.verson} 65 | 66 | 67 | 68 | com.netflix.eureka 69 | eureka-client 70 | 1.4.11 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | org.apache.maven.plugins 81 | maven-release-plugin 82 | 2.5.3 83 | 84 | true 85 | false 86 | release 87 | deploy 88 | 89 | 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-compiler-plugin 94 | 3.7.0 95 | 96 | 1.8 97 | 1.8 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | grpc-eureka-java 106 | grpc-eureka-java-starter 107 | 108 | 109 | 110 | 111 | oss.sonatype.org 112 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 113 | 114 | 115 | oss.sonatype.org 116 | https://oss.sonatype.org/content/repositories/snapshots 117 | 118 | 119 | 120 | 121 | 122 | run-its 123 | 124 | 125 | 126 | 127 | org.apache.maven.plugins 128 | maven-invoker-plugin 129 | 2.0.0 130 | 131 | true 132 | ${project.build.directory}/it 133 | 134 | */pom.xml 135 | 136 | verify 137 | ${project.build.directory}/local-repo 138 | src/it/srunettings.xml 139 | 140 | clean 141 | test-compile 142 | 143 | 144 | 145 | 146 | integration-test 147 | 148 | install 149 | integration-test 150 | verify 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | release 162 | 163 | 164 | performRelease 165 | true 166 | 167 | 168 | 169 | 170 | 171 | org.apache.maven.plugins 172 | maven-source-plugin 173 | 174 | 175 | attach-sources 176 | 177 | jar-no-fork 178 | 179 | 180 | 181 | 182 | jar 183 | 184 | 185 | 186 | 187 | 188 | org.apache.maven.plugins 189 | maven-gpg-plugin 190 | 1.5 191 | 192 | 193 | sign-artifacts 194 | verify 195 | 196 | sign 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | --------------------------------------------------------------------------------