具有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
最满意答案
当执行流出声明为返回值的函数的末尾时,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 ofrand_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.
相关问答
更多-
引导初始化(Bootstrapping initialization)[2022-05-13]
正是由于这个原因,不应该在构造函数中调用抽象成员。 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 { ... -
构造值初始化(Structuring value initialization)[2023-03-18]
以下是一个很好的约定。 它可以使用null但我会建议返回一个'a option类型。 选项 let x = match TryCalculateX() with | Some x -> x | None -> TryAnotherCalculation() someProcessing x 空值 let x = match TryCalculateX() with | null -> TryAnotherCalculation() | x -> x ... -
什么是初始化块?(What is an initialization block?)[2022-10-12]
首先,有两种类型的初始化块 : 实例初始化块 ,和 静态初始化块 。 该代码应该说明它们的使用,并按照它们执行的顺序: 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 ...
-
.net值类型初始化(.net value type initialization)[2022-12-24]
类型使用全零的内存进行初始化。 我不知道这是否符合所有值类型的规范,因此除非您检查,否则您不能指望这一点。 对于不同的值类型,内存中的零可能意味着不同的东西,具体取决于类型所代表的内容。 值类型是自动初始化的,可以在它们是类的字段而不是局部变量时使用。 据我所知,CLR本身没有初始化检查。 初始化检查由编译器执行,并在使用未初始化变量时报告编译时错误。 Types are initialized with memory that is all zeros. I don't know if this is a ... -
初始化与分配(Initialization vs assignment)[2022-03-17]
TLDR: { // declaration (hoisted) // Temporal deadzone let foo; // declaration and initialization to undefined foo = 1; // assignment } 有点长: 宣言 声明变量意味着我们在当前范围内保留标识符。 在javascript声明中被提升,这意味着它在变量所在的范围变得可见时被声明(它所处的块被执行)。 但是,您现在无法访问该变量 时间死区 这是代码的特定部分,它位于范 ... -
返回值初始化(Return value initialization)[2023-10-02]
当执行流出声明为返回值的函数的末尾时,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 ...
-
延迟初始化(Lazy initialization)[2024-03-02]
来自Reflector: public Lazy(FuncvalueFactory, bool isThreadSafe) : this(valueFactory, isThreadSafe ?LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None) { } 因此,如果您传递true ,它将转换为LazyThreadSafetyMode.ExecutionAndPublication 。 false将转换为L ... -
看来你的主要目标是找到复制elision的规格。 这是在12.8 [class.copy]第31段,第一个(用于返回)和第三个(用于传递参数)子弹 当符合某些条件时,即使为复制/移动操作选择的构造函数和/或对象的析构函数具有副作用,也允许实现省略类对象的复制/移动构造。 在这种情况下,实现将被忽略的复制/移动操作的来源和目标视为简单地引用同一对象的两种不同方式,并且对象的销毁发生在两个对象将在没有优化就被破坏了。 复制/移动操作的缩写(称为复制删除)在下列情况下可以被使用(可以合并以消除多个副本): 在具有 ...