首页 \ 问答 \ 具有Spring Boot的Docker和Eureka无法注册客户端(Docker and Eureka with Spring Boot failing to register clients)

具有Spring Boot的Docker和Eureka无法注册客户端(Docker and Eureka with Spring Boot failing to register clients)

我有一个使用Spring Boot + Docker Compose + Eureka的非常简单的演示。

我的服务器在端口8671上运行,具有以下应用程序属性:

server:
  port: 8761
eureka:
  instance:
    prefer-ip-address: true
  client:
    registerWithEureka: false
    fetchRegistry: false
  server:
    waitTimeInMsWhenSyncEmpty: 0

我的Eureka客户端在端口9000上运行,具有以下应用程序属性:

server:
  port: 9000
spring:
  application:
    name: user-registration
eureka:
  client:
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

当我在父maven项目中启动docker.compose文件时,这是我的docker-compose文件的内容:

eureka-server:
  image: rosenthal/eureka-server
ports:
   - "8761:8761"
user-registration:
  image: rosenthal/user-registration
  ports:
   - "9000:9000"
  links:
   - eureka-server

当我通过首先启动eureka服务器来运行我的应用程序时,由客户端通过

mvn spring-boot:run 

服务器成功注册我的客户端(我称之为用户注册)。

当我通过docker-compose运行我的应用程序时,客户端无法注册以下输出:

 DiscoveryClient_USER-REGISTRATION/0fd640cbc3ba:user-registration:9000: 
 registering service...
 user-registration_1  | 2017-06-21 04:36:05.120 ERROR 1 --- [nfoReplicator-0]        
 c.n.d.s.t.d.RedirectingEurekaHttpClient  : Request execution error
 user-registration_1  | 
 user-registration_1  | com.sun.jersey.api.client.ClientHandlerException: 
 java.net.ConnectException: Connection refused (Connection refused)

我的第一个假设是,在等待服务器启动时运行docker-compose遇到竞争条件,但是我的eureka客户端似乎有一个心跳试图回家到它配置的服务器。 这意味着它无法找到我已注册的Eureka服务器(并且正在运行,我可以在localhost:8671上导航到它)。

我在这里想念的是什么? 一切都运行良好,本地运行spring-boot启动它自己的嵌入式tomcat容器。 一旦我开始用docker-compose做它,它就不想工作了。

编辑

我相信,我意识到了自己的问题。 所以docker不在localhost上运行,它在我启动docker时分配的公共IP上运行。 导航到此ip +端口显示我的服务正在运行Eureka Server。 客户仍然没有注册。

所以,我对我的eureka客户端的application.yml文件进行了更改:

serviceUrl:
  defaultZone: http://192.168.59.103:8761/eureka/

IP是我的docker守护程序运行的IP。 现在,当我做docker-compose时,它错过了第一次注册,但是第二次心跳接收了我的客户端。

如何确保客户端在服务器完全启动之前等待? 我在我的docket compose文件中使用了正确的docker“links”字段,但它并没有像我希望的那样工作。 另外,如何将defaultZone文件视为我的DOCKER_HOST IP?

最后结果

生成一切对我有用的生成的docker-compose文件是:

eureka-server:
  image: thorrism/eureka-server
  ports:
   - "8761:8761"
user-registration:
  image: thorrism/user-registration
  ports:
   - "9000:9000"
  links:
   - eureka-server
  environment:
    EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://eureka-server:8761/eureka

I have a very simple demo of using Spring Boot + Docker Compose + Eureka.

My server runs on port 8671 with the following application properties:

server:
  port: 8761
eureka:
  instance:
    prefer-ip-address: true
  client:
    registerWithEureka: false
    fetchRegistry: false
  server:
    waitTimeInMsWhenSyncEmpty: 0

My Eureka client runs on port 9000 with the following application properties:

server:
  port: 9000
spring:
  application:
    name: user-registration
eureka:
  client:
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

When I start up my docker.compose file in the parent maven project, this is the contents of my docker-compose file:

eureka-server:
  image: rosenthal/eureka-server
ports:
   - "8761:8761"
user-registration:
  image: rosenthal/user-registration
  ports:
   - "9000:9000"
  links:
   - eureka-server

When I run my application by first starting the eureka server, following by the client via

mvn spring-boot:run 

The server successfully registers my client (I call it user-registration).

When I run my application through docker-compose, the client fails to register with the following output:

 DiscoveryClient_USER-REGISTRATION/0fd640cbc3ba:user-registration:9000: 
 registering service...
 user-registration_1  | 2017-06-21 04:36:05.120 ERROR 1 --- [nfoReplicator-0]        
 c.n.d.s.t.d.RedirectingEurekaHttpClient  : Request execution error
 user-registration_1  | 
 user-registration_1  | com.sun.jersey.api.client.ClientHandlerException: 
 java.net.ConnectException: Connection refused (Connection refused)

My first assumption was that running docker-compose ran into a race condition on waiting for the server to start, but my eureka client seems to have a heartbeat trying to call home to the server it's configured with. This means it's just not able to find the Eureka server I have registered (and is running, I can navigate to it on localhost:8671).

What am I missing here? Everything runs fine running locally with spring-boot starting up with it's own embedded tomcat containers. As soon as I start to do it with docker-compose, it doesn't want to work.

EDIT

I realized my problem, I believe. So docker doesn't run on localhost, it runs on the public IP it is assigned when I start up docker. Navigating to this ip + port shows my service running for Eureka Server. The client still doesn't register.

SO, I made changes to the application.yml file for my eureka client to:

serviceUrl:
  defaultZone: http://192.168.59.103:8761/eureka/

That IP is the one my docker daemon is running under. Now, it misses the first registration when I do docker-compose, but the second heartbeat picks up my client.

How can I ensure the client waits until the server is FULLY up? I used the proper docker "links" field in my docket compose file, but it didn't work as I hoped. Additionally, how can I see the defaultZone file to be my DOCKER_HOST IP?

Final result

The resulting docker-compose file that got everything working for me was:

eureka-server:
  image: thorrism/eureka-server
  ports:
   - "8761:8761"
user-registration:
  image: thorrism/user-registration
  ports:
   - "9000:9000"
  links:
   - eureka-server
  environment:
    EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://eureka-server:8761/eureka

原文:https://stackoverflow.com/questions/44667063
更新时间:2023-06-05 12:06

最满意答案

当执行流出声明为返回值的函数的末尾时,C ++标准没有定义行为(除了main ,这是特殊的)。 因此,行为是特定计算平台上的事物的结果。

首先,应该注意的是,C ++标准未定义的任何行为都会在编译器优化期间发生变化。 编译器可能会以激进的方式更改您的程序,即使编译器开关,源代码或其他因素稍有变化,更改也可能会有很大差异。

也就是说,处理器通常具有用于整数数据和浮点数据的单独寄存器。 在进程进入main例程之前,它会执行一些启动代码来准备堆栈和各种环境状态。 当代码完成时,它会将其数据保留在寄存器中(因为它没有理由将其擦除),包括分配用于保存函数调用的返回值的寄存器。 当您打印rand_int()的结果时,您可能会在该寄存器中看到剩余的一些数据。

启动代码可能没有理由使用浮点寄存器,因此它可能不会在其中放入任何数据。 当您打印rand_float()的结果时,您可能会看到零,因为操作系统在创建您的进程时将浮点寄存器初始化为零。


The C++ standard does not define the behavior when execution flows off the end of a function that is declared to return a value (other than main, which is special). So the behavior is a consequence of things on your particular computing platform.

First, it should be noted that any behavior not defined by the C++ standard is subject to changes during optimization by the compiler. The compiler may alter your program in radical ways, and the changes may differ drastically even with slight changes in compiler switches, source code, or other factors.

That said, processors commonly have separate registers for integer data and for floating-point data. Before your process enters the main routine, it executes some startup code that prepares the stack and various environmental states. As that code completes, it will leave its data in registers (since it has no reason to erase it), including the register that is assigned to hold the return value of a function call. When you print the result of rand_int(), you may be seeing some data leftover in that register.

The startup code may have no reason to use the floating-point registers, so it might not put any data in them. When you print the result of rand_float(), you may be seeing zero because the operating system initialized the floating-point registers to zero when it created your process.

相关问答

更多
  • 正是由于这个原因,不应该在构造函数中调用抽象成员。 http://msdn.microsoft.com/en-us/library/ms182331(v=vs.100).aspx 如果您可以控制抽象类,我建议通过基类构造函数传递值。 public abstract class A { public A(IExample x) { // Do Stuff var _privateY = x.Foo(); } } public class B : A { ...
  • 以下是一个很好的约定。 它可以使用null但我会建议返回一个'a option类型。 选项 let x = match TryCalculateX() with | Some x -> x | None -> TryAnotherCalculation() someProcessing x 空值 let x = match TryCalculateX() with | null -> TryAnotherCalculation() | x -> x ...
  • 首先,有两种类型的初始化块 : 实例初始化块 ,和 静态初始化块 。 该代码应该说明它们的使用,并按照它们执行的顺序: public class Test { static int staticVariable; int nonStaticVariable; // Static initialization block: // Runs once (when the class is initialized) static { Sy ...
  • 其原因在于,为了确定函数产生的值需要执行代码,并且在初始化静态变量和全局变量时C中没有执行代码执行。 编译器和链接器一起工作以准备全局内存段的字节图像:编译器提供值,并且链接器执行它们的最终布局。 在运行时,段的图像按原样加载到内存中,无需进一步修改。 这发生在任何代码执行之前,因此不能进行函数调用。 请注意,这并不意味着某些技术原因是不可能的,只有C设计师决定不这样做。 例如,C ++编译器生成一个调用全局对象的构造函数的代码段,在控制传递给main()之前执行该代码段。 The reason behin ...
  • 类型使用全零的内存进行初始化。 我不知道这是否符合所有值类型的规范,因此除非您检查,否则您不能指望这一点。 对于不同的值类型,内存中的零可能意味着不同的东西,具体取决于类型所代表的内容。 值类型是自动初始化的,可以在它们是类的字段而不是局部变量时使用。 据我所知,CLR本身没有初始化检查。 初始化检查由编译器执行,并在使用未初始化变量时报告编译时错误。 Types are initialized with memory that is all zeros. I don't know if this is a ...
  • TLDR: { // declaration (hoisted) // Temporal deadzone let foo; // declaration and initialization to undefined foo = 1; // assignment } 有点长: 宣言 声明变量意味着我们在当前范围内保留标识符。 在javascript声明中被提升,这意味着它在变量所在的范围变得可见时被声明(它所处的块被执行)。 但是,您现在无法访问该变量 时间死区 这是代码的特定部分,它位于范 ...
  • 当执行流出声明为返回值的函数的末尾时,C ++标准没有定义行为(除了main ,这是特殊的)。 因此,行为是特定计算平台上的事物的结果。 首先,应该注意的是,C ++标准未定义的任何行为都会在编译器优化期间发生变化。 编译器可能会以激进的方式更改您的程序,即使编译器开关,源代码或其他因素稍有变化,更改也可能会有很大差异。 也就是说,处理器通常具有用于整数数据和浮点数据的单独寄存器。 在进程进入main例程之前,它会执行一些启动代码来准备堆栈和各种环境状态。 当代码完成时,它会将其数据保留在寄存器中(因为它没 ...
  • 作为Core Issue 1301的结果,这是针对C ++ 11的缺陷,列表初始化的优先级从以下变为: 列表初始化对象或类型T的引用定义如下: 如果初始化列表没有元素且T是具有默认构造函数的类类型,则该对象是值初始化的。 否则,如果T是聚合,则执行聚合初始化(8.5.1) 至: 列表初始化对象或类型T的引用定义如下: 如果T是聚合,则执行聚合初始化(8.5.1) 否则,如果初始化列表没有元素且T是具有默认构造函数的类类型,则对象将进行值初始化。 因此,场景A中的foo{}仍然是聚合初始化。 As a res ...
  • 来自Reflector: public Lazy(Func valueFactory, bool isThreadSafe) : this(valueFactory, isThreadSafe ?LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None) { } 因此,如果您传递true ,它将转换为LazyThreadSafetyMode.ExecutionAndPublication 。 false将转换为L ...
  • 看来你的主要目标是找到复制elision的规格。 这是在12.8 [class.copy]第31段,第一个(用于返回)和第三个(用于传递参数)子弹 当符合某些条件时,即使为复制/移动操作选择的构造函数和/或对象的析构函数具有副作用,也允许实现省略类对象的复制/移动构造。 在这种情况下,实现将被忽略的复制/移动操作的来源和目标视为简单地引用同一对象的两种不同方式,并且对象的销毁发生在两个对象将在没有优化就被破坏了。 复制/移动操作的缩写(称为复制删除)在下列情况下可以被使用(可以合并以消除多个副本): 在具有 ...

相关文章

更多

最新问答

更多
  • h2元素推动其他h2和div。(h2 element pushing other h2 and div down. two divs, two headers, and they're wrapped within a parent div)
  • 创建一个功能(Create a function)
  • 我投了份简历,是电脑编程方面的学徒,面试时说要培训三个月,前面
  • PDO语句不显示获取的结果(PDOstatement not displaying fetched results)
  • Qt冻结循环的原因?(Qt freezing cause of the loop?)
  • TableView重复youtube-api结果(TableView Repeating youtube-api result)
  • 如何使用自由职业者帐户登录我的php网站?(How can I login into my php website using freelancer account? [closed])
  • SQL Server 2014版本支持的最大数据库数(Maximum number of databases supported by SQL Server 2014 editions)
  • 我如何获得DynamicJasper 3.1.2(或更高版本)的Maven仓库?(How do I get the maven repository for DynamicJasper 3.1.2 (or higher)?)
  • 以编程方式创建UITableView(Creating a UITableView Programmatically)
  • 如何打破按钮上的生命周期循环(How to break do-while loop on button)
  • C#使用EF访问MVC上的部分类的自定义属性(C# access custom attributes of a partial class on MVC with EF)
  • 如何获得facebook app的publish_stream权限?(How to get publish_stream permissions for facebook app?)
  • 如何防止调用冗余函数的postgres视图(how to prevent postgres views calling redundant functions)
  • Sql Server在欧洲获取当前日期时间(Sql Server get current date time in Europe)
  • 设置kotlin扩展名(Setting a kotlin extension)
  • 如何并排放置两个元件?(How to position two elements side by side?)
  • 如何在vim中启用python3?(How to enable python3 in vim?)
  • 在MySQL和/或多列中使用多个表用于Rails应用程序(Using multiple tables in MySQL and/or multiple columns for a Rails application)
  • 如何隐藏谷歌地图上的登录按钮?(How to hide the Sign in button from Google maps?)
  • Mysql左连接旋转90°表(Mysql Left join rotate 90° table)
  • dedecms如何安装?
  • 在哪儿学计算机最好?
  • 学php哪个的书 最好,本人菜鸟
  • 触摸时不要突出显示表格视图行(Do not highlight table view row when touched)
  • 如何覆盖错误堆栈getter(How to override Error stack getter)
  • 带有ImageMagick和许多图像的GIF动画(GIF animation with ImageMagick and many images)
  • USSD INTERFACE - > java web应用程序通信(USSD INTERFACE -> java web app communication)
  • 电脑高中毕业学习去哪里培训
  • 正则表达式验证SMTP响应(Regex to validate SMTP Responses)