我们有一个sidecar应用程序,它使我们能够向Eureka注册我们的node.js应用程序,以启用服务发现。
我们的sidecar应用程序配置如下:
server:
port: 9000
spring:
application:
name: session-service
sidecar:
port: 3000
health-url: http://sessionServiceNode:${sidecar.port}/health.json
eureka:
client:
serviceUrl:
defaultZone: http://discoveryService:8761/eureka/
instance:
lease-renewal-interval-in-seconds: 5
prefer-ip-address: true根据配置,我们的节点应用程序运行在由sidecar.port属性定义的端口sidecar.port上,我们的sidecar应用程序应该按照server.port在端口9000上运行。
我们在节点应用程序中添加了一个端点,以允许sidecar检查应用程序(sidecar.health-url)的运行状况。主机名sessionServiceNode是我们为运行节点应用程序的容器提供的别名的名称。
我们的Eureka服务运行在一个单独的容器中,该容器还通过别名discoveryService链接到sidecar应用程序容器。
我们有一个单独的测试弹簧引导应用程序,它运行在一个独立的容器中,它是会话服务的使用者。此容器仅链接到发现服务容器。
sidecar应用程序按预期向Eureka注册。

测试服务使用会话服务的两种查找形式。一种是使用假客户端:
@FeignClient(value = "session-service") // name of our registered service in eureka
interface SessionServiceClient {
@RequestMapping(value = "/document/get/24324", method = GET)
String documentGetTest();
}另一种方法使用更多的编程查找:
@Autowired
private DiscoveryClient discoveryClient;
...
discoveryClient.getInstances("session-service");当我们向测试服务发出请求时,测试服务会查找会话服务,但是eureka提供给我们的实例信息有不正确的URI:http://172.17.0.5:3000。172.17.0.5是sidecar应用程序容器的IP地址,但是端口3000是节点应用程序运行的地方吗?
应该期望看到eureka返回会话服务端口(http://172.17.0.5:9000)的会话服务容器的位置,然后sidecar通过zuul代理对节点应用程序(http://172.17.0.6:3000)进行“转发”?或者尤里卡应该直接告诉我们节点应用程序的位置?
我在下面包含了来自尤里卡的会话服务实例信息:
<?xml version="1.0" encoding="UTF-8"?>
<application>
<name>SESSION-SERVICE</name>
<instance>
<hostName>172.17.0.5</hostName>
<app>SESSION-SERVICE</app>
<ipAddr>172.17.0.5</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">3000</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>5</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1461223810081</registrationTimestamp>
<lastRenewalTimestamp>1461224812429</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1461223810081</serviceUpTimestamp>
</leaseInfo>
<metadata class="java.util.Collections$EmptyMap" />
<homePageUrl>http://c892e0c03cf4:3000/</homePageUrl>
<statusPageUrl>http://c892e0c03cf4:9000/info</statusPageUrl>
<healthCheckUrl>http://c892e0c03cf4:9000/health</healthCheckUrl>
<vipAddress>session-service</vipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1461223810081</lastUpdatedTimestamp>
<lastDirtyTimestamp>1461223033045</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>编辑:
在查看代码之后,Eureka分别使用从InetAddress.getLocalHost().getHostAddress()和InetAddress.getLocalHost().getHostName()返回的主机信息来确定实例的地址。这就是为什么我们要获得侧加容器的IP地址。我们有什么办法可以推翻这种行为吗?
发布于 2016-04-22 10:17:01
因此,从外观上看,Sidecar假设spring引导sidecar应用程序和非jvm应用程序运行在同一个主机上。在我们的场景中,我们在单独的容器中运行所有的东西。一个容器用于侧jvm应用程序,一个容器用于node.js应用程序。理论上,我们可以让这两个应用程序运行在同一个容器中,但这违反了Docker的最佳实践,即每个容器只有一个unix进程。
为了使它正常工作,我们重写了EurekaInstanceConfigBean,它允许我们控制为实例选择的主机名和IP地址。在本例中,我们将委托给inetUtils类,并从主机名(这是通过docker链接的非jvm应用程序的别名)查找IP地址。我们使用spring @ConfigurationProperties从application.yml配置文件中控制主机名/端口。
SessionServiceSidecar.java
@Component
@ConfigurationProperties
public class SessionServiceSidecarProperties {
@Value("${sidecar.hostname}")
private String hostname;
@Value("${sidecar.port}")
private Integer port;
public String getHostname() {
return hostname;
}
public Integer getPort() {
return port;
}
}SessionServiceApp.java
@SpringBootApplication
@EnableSidecar
@EnableDiscoveryClient
@Configuration
@ComponentScan
@EnableConfigurationProperties
public class SessionServiceApp {
private @Autowired SessionServiceSidecarProperties properties;
public static void main(String[] args) {
SpringApplication.run(SessionServiceApp.class, args);
}
@Bean
public EurekaInstanceConfigBean eurekaInstanceConfigBean(InetUtils inetUtils) {
final String sidecarHostname = properties.getHostname();
final Integer sidecarPort = properties.getPort();
try {
final EurekaInstanceConfigBean instance = new EurekaInstanceConfigBean(inetUtils);
instance.setHostname(sidecarHostname);
instance.setIpAddress(inetUtils.convertAddress(InetAddress.getByName(sidecarHostname)).getIpAddress());
instance.setNonSecurePort(sidecarPort);
return instance;
} catch(UnknownHostException e) {
throw new IllegalStateException("Could not resolve IP address of sidecar application using hostname: " + sidecarHostname);
}
}
}application.yml
spring:
application:
name: session-service
server:
port: 9000
sidecar:
hostname: sessionServiceNode
port: 3000
health-url: http://sessionServiceNode:${sidecar.port}/health.json
eureka:
client:
serviceUrl:
defaultZone: http://discoveryService:8761/eureka/
instance:
lease-renewal-interval-in-seconds: 5
prefer-ip-address: true希望Spring将允许我们在将来通过sidecar.hostname属性控制sidecar应用程序的主机名和端口。
希望这能有所帮助!
发布于 2016-04-21 08:24:30
Spring正在挑选第一个没有回环的ip地址。你可以做几件事之一。
第一:忽略您不想从中选择的网络接口。这里.
spring:
cloud:
inetutils:
ignoredInterfaces:
- docker0
- veth.*或者二:显式设置eureka注册的ipaddress或主机名(如果在任何地方都使用相同的docker别名)。对于主机名,设置eureka.instance.hostname=sessionServiceNode并删除prefer-ip-address=true选项。对于ip地址,eureka.instance.ipAddress=<ipaddr>。
https://stackoverflow.com/questions/36763171
复制相似问题