mirror of
https://github.com/spring-cloud/spring-cloud-netflix.git
synced 2026-09-18 08:09:07 +00:00
Compare commits
129
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8210f8c8f5 | ||
|
|
3dea444dd6 | ||
|
|
4ecf384881 | ||
|
|
e69b82c772 | ||
|
|
526a8c9e65 | ||
|
|
284a157c67 | ||
|
|
34793d6c75 | ||
|
|
7bd97eea49 | ||
|
|
11f557ac2e | ||
|
|
9713186651 | ||
|
|
8e70173fa5 | ||
|
|
44fab96fb1 | ||
|
|
c1451b0374 | ||
|
|
75b40713e7 | ||
|
|
1a2fd8a7cc | ||
|
|
663ca402ab | ||
|
|
bfbd6d15c7 | ||
|
|
04d15556ec | ||
|
|
f36a3de904 | ||
|
|
7e8bb2817f | ||
|
|
aa3b1ef5d7 | ||
|
|
c6fcfab533 | ||
|
|
a786a1416d | ||
|
|
4a58b44047 | ||
|
|
571157c264 | ||
|
|
b5863abc3d | ||
|
|
e2a6509bf6 | ||
|
|
0399522052 | ||
|
|
d7b86db464 | ||
|
|
5c6a64a043 | ||
|
|
0ddb014bc9 | ||
|
|
c9cff6faf0 | ||
|
|
96be7ab777 | ||
|
|
883ec871ab | ||
|
|
76e6104b4b | ||
|
|
00fa8e0f52 | ||
|
|
e4ab5faafd | ||
|
|
5af3121835 | ||
|
|
950553d9a1 | ||
|
|
6267dfc577 | ||
|
|
fe44b40dc4 | ||
|
|
d005cab913 | ||
|
|
9cf585c119 | ||
|
|
6f38cfe510 | ||
|
|
1dd38faa4a | ||
|
|
4236eb2af3 | ||
|
|
96c7ec7072 | ||
|
|
b9740eb452 | ||
|
|
a96375bd12 | ||
|
|
6f35b0e9f5 | ||
|
|
c25dc8fd77 | ||
|
|
3c093dcc04 | ||
|
|
011d181586 | ||
|
|
5d213f7928 | ||
|
|
4596c56e6e | ||
|
|
30635842c3 | ||
|
|
006fb6972c | ||
|
|
e02d8d3b31 | ||
|
|
3c13133920 | ||
|
|
b1a0375ce4 | ||
|
|
da9cb76fcc | ||
|
|
f4b445bdaf | ||
|
|
803abe6e6f | ||
|
|
7a7bb2f5c2 | ||
|
|
fb7abbdead | ||
|
|
572b10a5bd | ||
|
|
32eec04ef9 | ||
|
|
dd5793bed1 | ||
|
|
4516506416 | ||
|
|
361b16ce4f | ||
|
|
1de1e2a76e | ||
|
|
e9de82cec5 | ||
|
|
9a17332f88 | ||
|
|
7fc754b952 | ||
|
|
a0329a8b70 | ||
|
|
c8aa498382 | ||
|
|
b333f05733 | ||
|
|
71daf977a0 | ||
|
|
2dc3199a0b | ||
|
|
d82fd9f83d | ||
|
|
49569431bc | ||
|
|
9f757481b1 | ||
|
|
a3840dbd43 | ||
|
|
91ef8110c9 | ||
|
|
b23c587319 | ||
|
|
aa0670b1ee | ||
|
|
702c10d4f1 | ||
|
|
b43fa21fd8 | ||
|
|
f47e93c4f3 | ||
|
|
bf6dafed7d | ||
|
|
1e2f6eedef | ||
|
|
24716c69c9 | ||
|
|
5597c57577 | ||
|
|
aa45392a9a | ||
|
|
307b93bf5a | ||
|
|
f21d0046cd | ||
|
|
de6d506e9a | ||
|
|
2a8b7ed054 | ||
|
|
79a2eb8c4f | ||
|
|
dbb36fb0ed | ||
|
|
f8ed5c4163 | ||
|
|
47d3f7133c | ||
|
|
a74d8f966e | ||
|
|
5113f0abf3 | ||
|
|
99b8d2c6d4 | ||
|
|
3ef81ba9cd | ||
|
|
c7885631ed | ||
|
|
bb15b7f40e | ||
|
|
c97bd250af | ||
|
|
4b101efe19 | ||
|
|
61d5f5f9fb | ||
|
|
6b6173de3a | ||
|
|
4536954aca | ||
|
|
817ea2c88a | ||
|
|
1754585fc0 | ||
|
|
0bebfd1e3d | ||
|
|
a0c95db99e | ||
|
|
ad002b4da2 | ||
|
|
fb088832db | ||
|
|
3d30846108 | ||
|
|
3c84f2ec04 | ||
|
|
479f10e379 | ||
|
|
1bc989c5ce | ||
|
|
cf81e327ad | ||
|
|
35ef348fe9 | ||
|
|
45ddfdfb7c | ||
|
|
8ae4950200 | ||
|
|
d7275b888b | ||
|
|
ed9ca444c8 |
@@ -0,0 +1,2 @@
|
||||
require:
|
||||
members: false
|
||||
@@ -5,9 +5,9 @@ name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
branches: [ main, 4.1.x ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
branches: [ main, 4.1.x ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -28,6 +28,6 @@ jobs:
|
||||
cache: 'maven'
|
||||
- name: Build with Maven
|
||||
run: ./mvnw clean install -B -U -P sonar
|
||||
- uses: codecov/codecov-action@v3
|
||||
- uses: codecov/codecov-action@v5
|
||||
with:
|
||||
fail_ci_if_error: false
|
||||
|
||||
+1
-1
@@ -33,5 +33,5 @@ _configprops.adoc
|
||||
_spans.adoc
|
||||
_metrics.adoc
|
||||
_conventions.adoc
|
||||
package.json
|
||||
/package.json
|
||||
package-lock.json
|
||||
|
||||
+2
-2
@@ -49,7 +49,7 @@ build succeed, please raise a ticket to get the settings added to
|
||||
source control.
|
||||
|
||||
The projects that require middleware (i.e. Redis) for testing generally
|
||||
require that a local instance of [Docker](https://www.docker.com/get-started) is installed and running.
|
||||
require that a local instance of https://www.docker.com/get-started[Docker] is installed and running.
|
||||
|
||||
[[documentation]]
|
||||
== Documentation
|
||||
@@ -68,7 +68,7 @@ a modified file in the correct place. Just commit it and push the change.
|
||||
[[working-with-the-code]]
|
||||
== Working with the code
|
||||
If you don't have an IDE preference we would recommend that you use
|
||||
https://www.springsource.com/developer/sts[Spring Tools Suite] or
|
||||
https://spring.io/tools[Spring Tools Suite] or
|
||||
https://eclipse.org[Eclipse] when working with the code. We use the
|
||||
https://eclipse.org/m2e/[m2eclipse] eclipse plugin for maven support. Other IDEs and tools
|
||||
should also work without issue as long as they use Maven 3.3.3 or better.
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
antora:
|
||||
extensions:
|
||||
- '@springio/antora-extensions/partial-build-extension'
|
||||
- require: '@springio/antora-extensions/latest-version-extension'
|
||||
- require: '@springio/antora-extensions/inject-collector-cache-config-extension'
|
||||
- '@antora/collector-extension'
|
||||
- '@antora/atlas-extension'
|
||||
- require: '@springio/antora-extensions/root-component-extension'
|
||||
- require: '@springio/antora-extensions'
|
||||
root_component_name: 'cloud-netflix'
|
||||
- '@springio/antora-extensions/static-page-extension'
|
||||
site:
|
||||
title: Spring Cloud Netflix
|
||||
url: https://docs.spring.io/spring-cloud-netflix/reference/
|
||||
@@ -36,4 +30,4 @@ runtime:
|
||||
format: pretty
|
||||
ui:
|
||||
bundle:
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.2/ui-bundle.zip
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.15/ui-bundle.zip
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ nav:
|
||||
ext:
|
||||
collector:
|
||||
run:
|
||||
command: ./mvnw --no-transfer-progress -B process-resources -Pdocs -pl docs -Dantora-maven-plugin.phase=none -Dgenerate-docs.phase=none -Dgenerate-readme.phase=none -Dgenerate-cloud-resources.phase=none -Dmaven-dependency-plugin-for-docs.phase=none -Dmaven-dependency-plugin-for-docs-classes.phase=none -DskipTests
|
||||
command: ./mvnw --no-transfer-progress -B process-resources -Pdocs -pl docs -Dantora-maven-plugin.phase=none -Dgenerate-docs.phase=none -Dgenerate-readme.phase=none -Dgenerate-cloud-resources.phase=none -Dmaven-dependency-plugin-for-docs.phase=none -Dmaven-dependency-plugin-for-docs-classes.phase=none -DskipTests -DdisableConfigurationProperties
|
||||
local: true
|
||||
scan:
|
||||
dir: ./target/classes/antora-resources/
|
||||
|
||||
@@ -35,8 +35,9 @@ public class Application {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(Application.class).web(true).run(args);
|
||||
}
|
||||
SpringApplication.run(CustomerServiceTestApplication.class, args);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
----
|
||||
@@ -267,27 +268,35 @@ Do not use the `EurekaClient` in a `@PostConstruct` method or in a `@Scheduled`
|
||||
It is initialized in a `SmartLifecycle` (with `phase=0`), so the earliest you can rely on it being available is in another `SmartLifecycle` with a higher phase.
|
||||
====
|
||||
|
||||
==== EurekaClient with Jersey
|
||||
==== Underlying HTTP clients
|
||||
|
||||
`EurekaClient` uses either `RestTemplate`, `WebClient` or `JerseyClient` under the hood. In order to use the `EurekaClient`, you need to have one of the supported HTTP clients on your classpath.
|
||||
|
||||
To use `RestTemplate`, add `spring-boot-starter-web` to your dependencies. To use `WebClient`, add `spring-boot-starter-webflux` to your dependencies. If both `RestTemplate` and `WebClient` are on the classpath when `eureka.client.webclient.enabled` is set to `true`, `WebClient` is used. Otherwise, `RestTemplate` is used.
|
||||
|
||||
By default, EurekaClient uses Spring's `RestTemplate` for HTTP communication.
|
||||
If you wish to use Jersey instead, you need to add the Jersey dependencies to your classpath.
|
||||
The following example shows the dependencies you need to add:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey.contribs</groupId>
|
||||
<artifactId>jersey-apache-client4</artifactId>
|
||||
</dependency>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey.contribs</groupId>
|
||||
<artifactId>jersey-apache-client4</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
----
|
||||
|
||||
If you have `JerseyClient` on the classpath but do not wish to use it in your `EuerekaClient`, make sure to set `eureka.client.jersey.enabled` to `false`.
|
||||
|
||||
=== Alternatives to the Native Netflix EurekaClient
|
||||
|
||||
You need not use the raw Netflix `EurekaClient`.
|
||||
@@ -368,7 +377,9 @@ We take `eureka.client.availabilityZones`, which is a map from region name to a
|
||||
|
||||
Spring Cloud Netflix Eureka Client integration supports Spring AOT transformations and native images, however, only with refresh mode disabled.
|
||||
|
||||
WARNING: If you want to run Eureka Client in AOT or native image modes, make sure to set `spring.cloud.refresh.enabled` to `false`
|
||||
WARNING: If you want to run Eureka Client in AOT or native image modes, make sure to set `spring.cloud.refresh.enabled` to `false`.
|
||||
|
||||
NOTE: Given the AOT and native image closed-world assumption, using random port with Eureka clients is not supported for ahead of time compilation or native images.
|
||||
|
||||
[[spring-cloud-eureka-server]]
|
||||
== Service Discovery: Eureka Server
|
||||
@@ -403,8 +414,9 @@ The following example shows a minimal Eureka server:
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(Application.class).web(true).run(args);
|
||||
}
|
||||
SpringApplication.run(CustomerServiceTestApplication.class, args);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
----
|
||||
@@ -598,6 +610,17 @@ when running a Eureka server you must include these dependencies in your POM or
|
||||
|
||||
Spring Cloud Netflix Eureka Server does not support Spring AOT transformations or native images.
|
||||
|
||||
=== Metrics
|
||||
|
||||
`EurekaInstanceMonitor` listens to events related to Eureka instance registration and creates/updates `Gauge`s for Eureka instance information in Micrometer's `MeterRegistry`. By default, this behavior is disabled. If you want to enable it, you need to set `eureka.server.metrics.enabled` to `true`.
|
||||
|
||||
By default, the `Gauge`s are named `eureka.server.instances` and have the following tags:
|
||||
|
||||
- `application`: application name
|
||||
- `status`: instance status (`UP`, `DOWN`, `STARTING`, `OUT_OF_SERVICE`, `UNKNOWN`, see: `com.netflix.appinfo.InstanceInfo.InstanceStatus`)
|
||||
|
||||
You can add additional tags by injecting your own implementation of `EurekaInstanceTagsProvider`.
|
||||
|
||||
== Configuration properties
|
||||
|
||||
To see the list of all Spring Cloud Netflix related configuration properties please check link:appendix.html[the Appendix page].
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|eureka.client.eureka-server-total-connections | `+++200+++` | Gets the total number of connections that is allowed from eureka client to all eureka servers.
|
||||
|eureka.client.eureka-server-total-connections-per-host | `+++50+++` | Gets the total number of connections that is allowed from eureka client to a eureka server host.
|
||||
|eureka.client.eureka-server-u-r-l-context | | Gets the URL context to be used to construct the service url to contact eureka server when the list of eureka servers come from the DNS. This information is not required if the contract returns the service urls from eurekaServerServiceUrls. The DNS mechanism is used when useDnsForFetchingServiceUrls is set to true and the eureka client expects the DNS to configured a certain way so that it can fetch changing eureka servers dynamically. The changes are effective at runtime.
|
||||
|eureka.client.eureka-service-url-poll-interval-seconds | `+++0+++` | Indicates how often(in seconds) to poll for changes to eureka server information. Eureka servers could be added or removed and this setting controls how soon the eureka clients should know about it.
|
||||
|eureka.client.eureka-service-url-poll-interval-seconds | `+++300+++` | Indicates how often(in seconds) to poll for changes to eureka server information. Eureka servers could be added or removed and this setting controls how soon the eureka clients should know about it.
|
||||
|eureka.client.fetch-registry | `+++true+++` | Indicates whether this client should fetch eureka registry information from eureka server.
|
||||
|eureka.client.fetch-remote-regions-registry | | Comma separated list of regions for which the eureka registry information will be fetched. It is mandatory to define the availability zones for each of these regions as returned by availabilityZones. Failing to do so, will result in failure of discovery client startup.
|
||||
|eureka.client.filter-only-up-instances | `+++true+++` | Indicates whether to get the applications after filtering the applications for instances with only InstanceStatus UP states.
|
||||
@@ -31,6 +31,7 @@
|
||||
|eureka.client.heartbeat-executor-thread-pool-size | `+++2+++` | The thread pool size for the heartbeatExecutor to initialise with.
|
||||
|eureka.client.initial-instance-info-replication-interval-seconds | `+++40+++` | Indicates how long initially (in seconds) to replicate instance info to the eureka server.
|
||||
|eureka.client.instance-info-replication-interval-seconds | `+++30+++` | Indicates how often(in seconds) to replicate instance changes to be replicated to the eureka server.
|
||||
|eureka.client.jersey.enabled | `+++true+++` | Enables the use of JerseyClient for Eureka HTTP Client.
|
||||
|eureka.client.log-delta-diff | `+++false+++` | Indicates whether to log differences between the eureka server and the eureka client in terms of registry information. Eureka client tries to retrieve only delta changes from eureka server to minimize network traffic. After receiving the deltas, eureka client reconciles the information from the server to verify it has not missed out some information. Reconciliation failures could happen when the client has had network issues communicating to server.If the reconciliation fails, eureka client gets the full registry information. While getting the full registry information, the eureka client can log the differences between the client and the server and this setting controls that. The changes are effective at runtime at the next registry fetch cycle as specified by registryFetchIntervalSecondsr
|
||||
|eureka.client.on-demand-update-status-change | `+++true+++` | If set to true, local status updates via ApplicationInfoManager will trigger on-demand (but rate limited) register/updates to remote eureka servers.
|
||||
|eureka.client.order | `+++0+++` | Order of the discovery client used by `CompositeDiscoveryClient` for sorting available clients.
|
||||
@@ -45,9 +46,9 @@
|
||||
|eureka.client.register-with-eureka | `+++true+++` | Indicates whether or not this instance should register its information with eureka server for discovery by others. In some cases, you do not want your instances to be discovered whereas you just want do discover other instances.
|
||||
|eureka.client.registry-fetch-interval-seconds | `+++30+++` | Indicates how often(in seconds) to fetch the registry information from the eureka server.
|
||||
|eureka.client.registry-refresh-single-vip-address | | Indicates whether the client is only interested in the registry information for a single VIP.
|
||||
|eureka.client.rest-template-timeout.connect-request-timeout | `+++0+++` |
|
||||
|eureka.client.rest-template-timeout.connect-timeout | `+++0+++` | Default values are set to 180000, in keeping with {@link RequestConfig} and {@link SocketConfig} defaults.
|
||||
|eureka.client.rest-template-timeout.socket-timeout | `+++0+++` |
|
||||
|eureka.client.rest-template-timeout.connect-request-timeout | `+++180000+++` |
|
||||
|eureka.client.rest-template-timeout.connect-timeout | `+++180000+++` | Default values are set to 180000, in keeping with {@link RequestConfig} and {@link SocketConfig} defaults.
|
||||
|eureka.client.rest-template-timeout.socket-timeout | `+++180000+++` |
|
||||
|eureka.client.service-url | | Map of availability zone to list of fully qualified URLs to communicate with eureka server. Each value can be a single URL or a comma separated list of alternative locations. Typically the eureka server URLs carry protocol,host,port,context and version information if any. Example: https://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/ The changes are effective at runtime at the next service url refresh cycle as specified by eurekaServiceUrlPollIntervalSeconds.
|
||||
|eureka.client.should-enforce-registration-at-init | `+++false+++` | Indicates whether the client should enforce registration during initialization. Defaults to false.
|
||||
|eureka.client.should-unregister-on-shutdown | `+++true+++` | Indicates whether the client should explicitly unregister itself from the remote server on client shutdown.
|
||||
@@ -68,6 +69,7 @@
|
||||
|eureka.instance.a-s-g-name | | Gets the AWS autoscaling group name associated with this instance. This information is specifically used in an AWS environment to automatically put an instance out of service after the instance is launched and it has been disabled for traffic..
|
||||
|eureka.instance.app-group-name | | Get the name of the application group to be registered with eureka.
|
||||
|eureka.instance.appname | `+++unknown+++` | Get the name of the application to be registered with eureka.
|
||||
|eureka.instance.async-client-initialization | `+++false+++` | If true the EurekaClient will be initialized asynchronously when the InstanceRegistry bean is created.
|
||||
|eureka.instance.data-center-info | | Returns the data center this instance is deployed. This information is used to get some AWS specific instance information if the instance is deployed in AWS.
|
||||
|eureka.instance.default-address-resolution-order | `+++[]+++` |
|
||||
|eureka.instance.environment | |
|
||||
@@ -97,20 +99,20 @@
|
||||
|eureka.instance.status-page-url | | Gets the absolute status page URL path for this instance. The users can provide the statusPageUrlPath if the status page resides in the same instance talking to eureka, else in the cases where the instance is a proxy for some other server, users can provide the full URL. If the full URL is provided it takes precedence. It is normally used for informational purposes for other services to find about the status of this instance. Users can provide a simple HTML indicating what is the current status of the instance.
|
||||
|eureka.instance.status-page-url-path | | Gets the relative status page URL path for this instance. The status page URL is then constructed out of the hostName and the type of communication - secure or unsecure as specified in securePort and nonSecurePort. It is normally used for informational purposes for other services to find about the status of this instance. Users can provide a simple HTML indicating what is the current status of the instance.
|
||||
|eureka.instance.virtual-host-name | `+++unknown+++` | Gets the virtual host name defined for this instance. This is typically the way other instance would find this instance by using the virtual host name.Think of this as similar to the fully qualified domain name, that the users of your services will need to find this instance.
|
||||
|eureka.server.a-s-g-cache-expiry-timeout-ms | `+++0+++` |
|
||||
|eureka.server.a-s-g-cache-expiry-timeout-ms | `+++600000+++` |
|
||||
|eureka.server.a-s-g-query-timeout-ms | `+++300+++` |
|
||||
|eureka.server.a-s-g-update-interval-ms | `+++0+++` |
|
||||
|eureka.server.a-s-g-update-interval-ms | `+++300000+++` |
|
||||
|eureka.server.a-w-s-access-id | |
|
||||
|eureka.server.a-w-s-secret-key | |
|
||||
|eureka.server.batch-replication | `+++false+++` |
|
||||
|eureka.server.binding-strategy | |
|
||||
|eureka.server.delta-retention-timer-interval-in-ms | `+++0+++` |
|
||||
|eureka.server.delta-retention-timer-interval-in-ms | `+++30000+++` |
|
||||
|eureka.server.disable-delta | `+++false+++` |
|
||||
|eureka.server.disable-delta-for-remote-regions | `+++false+++` |
|
||||
|eureka.server.disable-transparent-fallback-to-other-region | `+++false+++` |
|
||||
|eureka.server.e-i-p-bind-rebind-retries | `+++3+++` |
|
||||
|eureka.server.e-i-p-binding-retry-interval-ms | `+++0+++` |
|
||||
|eureka.server.e-i-p-binding-retry-interval-ms-when-unbound | `+++0+++` |
|
||||
|eureka.server.e-i-p-binding-retry-interval-ms | `+++300000+++` |
|
||||
|eureka.server.e-i-p-binding-retry-interval-ms-when-unbound | `+++60000+++` |
|
||||
|eureka.server.enable-replicated-request-compression | `+++false+++` |
|
||||
|eureka.server.enable-self-preservation | `+++true+++` |
|
||||
|eureka.server.eviction-interval-timer-in-ms | `+++0+++` |
|
||||
@@ -127,12 +129,13 @@
|
||||
|eureka.server.max-threads-for-peer-replication | `+++20+++` |
|
||||
|eureka.server.max-threads-for-status-replication | `+++1+++` |
|
||||
|eureka.server.max-time-for-replication | `+++30000+++` |
|
||||
|eureka.server.metrics.enabled | `+++false+++` | Indicates whether the metrics should be enabled for eureka instances.
|
||||
|eureka.server.min-available-instances-for-peer-replication | `+++-1+++` |
|
||||
|eureka.server.min-threads-for-peer-replication | `+++5+++` |
|
||||
|eureka.server.min-threads-for-status-replication | `+++1+++` |
|
||||
|eureka.server.my-url | |
|
||||
|eureka.server.number-of-replication-retries | `+++5+++` |
|
||||
|eureka.server.peer-eureka-nodes-update-interval-ms | `+++0+++` |
|
||||
|eureka.server.peer-eureka-nodes-update-interval-ms | `+++600000+++` |
|
||||
|eureka.server.peer-eureka-status-refresh-time-interval-ms | `+++0+++` |
|
||||
|eureka.server.peer-node-connect-timeout-ms | `+++200+++` |
|
||||
|eureka.server.peer-node-connection-idle-timeout-seconds | `+++30+++` |
|
||||
@@ -162,18 +165,18 @@
|
||||
|eureka.server.remote-region-urls | |
|
||||
|eureka.server.remote-region-urls-with-name | |
|
||||
|eureka.server.renewal-percent-threshold | `+++0.85+++` |
|
||||
|eureka.server.renewal-threshold-update-interval-ms | `+++0+++` |
|
||||
|eureka.server.renewal-threshold-update-interval-ms | `+++900000+++` |
|
||||
|eureka.server.response-cache-auto-expiration-in-seconds | `+++180+++` |
|
||||
|eureka.server.response-cache-update-interval-ms | `+++0+++` |
|
||||
|eureka.server.retention-time-in-m-s-in-delta-queue | `+++0+++` |
|
||||
|eureka.server.response-cache-update-interval-ms | `+++30000+++` |
|
||||
|eureka.server.retention-time-in-m-s-in-delta-queue | `+++180000+++` |
|
||||
|eureka.server.route53-bind-rebind-retries | `+++3+++` |
|
||||
|eureka.server.route53-binding-retry-interval-ms | `+++0+++` |
|
||||
|eureka.server.route53-binding-retry-interval-ms | `+++300000+++` |
|
||||
|eureka.server.route53-domain-t-t-l | `+++30+++` |
|
||||
|eureka.server.sync-when-timestamp-differs | `+++true+++` |
|
||||
|eureka.server.use-read-only-response-cache | `+++true+++` |
|
||||
|eureka.server.wait-time-in-ms-when-sync-empty | `+++0+++` |
|
||||
|eureka.server.wait-time-in-ms-when-sync-empty | `+++300000+++` |
|
||||
|eureka.server.xml-codec-name | |
|
||||
|spring.cloud.compatibility-verifier.compatible-boot-versions | `+++3.2.x+++` | Default accepted versions for the Spring Boot dependency. You can set {@code x} for the patch version if you don't want to specify a concrete value. Example: {@code 3.4.x}
|
||||
|spring.cloud.compatibility-verifier.compatible-boot-versions | | Default accepted versions for the Spring Boot dependency. You can set {@code x} for the patch version if you don't want to specify a concrete value. Example: {@code 3.4.x}
|
||||
|spring.cloud.compatibility-verifier.enabled | `+++false+++` | Enables creation of Spring Cloud compatibility verification.
|
||||
|spring.cloud.config.allow-override | `+++true+++` | Flag to indicate that {@link #isOverrideSystemProperties() systemPropertiesOverride} can be used. Set to false to prevent users from changing the default accidentally. Default true.
|
||||
|spring.cloud.config.initialize-on-context-refresh | `+++false+++` | Flag to initialize bootstrap configuration on context refresh event. Default false.
|
||||
@@ -217,7 +220,6 @@
|
||||
|spring.cloud.loadbalancer.eureka.approximate-zone-from-hostname | `+++false+++` | Used to determine whether we should try to get the `zone` value from host name.
|
||||
|spring.cloud.loadbalancer.health-check.initial-delay | `+++0+++` | Initial delay value for the HealthCheck scheduler.
|
||||
|spring.cloud.loadbalancer.health-check.interval | `+++25s+++` | Interval for rerunning the HealthCheck scheduler.
|
||||
|spring.cloud.loadbalancer.health-check.interval | `+++25s+++` | Interval for rerunning the HealthCheck scheduler.
|
||||
|spring.cloud.loadbalancer.health-check.path | | Path at which the health-check request should be made. Can be set up per `serviceId`. A `default` value can be set up as well. If none is set up, `/actuator/health` will be used.
|
||||
|spring.cloud.loadbalancer.health-check.port | | Path at which the health-check request should be made. If none is set, the port under which the requested service is available at the service instance.
|
||||
|spring.cloud.loadbalancer.health-check.refetch-instances | `+++false+++` | Indicates whether the instances should be refetched by the `HealthCheckServiceInstanceListSupplier`. This can be used if the instances can be updated and the underlying delegate does not provide an ongoing flux.
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"antora": "3.2.0-alpha.8",
|
||||
"@antora/atlas-extension": "1.0.0-alpha.2",
|
||||
"@antora/collector-extension": "1.0.1",
|
||||
"@asciidoctor/tabs": "1.0.0-beta.6",
|
||||
"@springio/antora-extensions": "1.14.4",
|
||||
"@springio/asciidoctor-extensions": "1.0.0-alpha.17"
|
||||
}
|
||||
}
|
||||
+21
-12
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>4.1.1-SNAPSHOT</version>
|
||||
<version>4.1.7-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
@@ -21,20 +21,28 @@
|
||||
<!-- Don't upload docs jar to central / repo.spring.io -->
|
||||
<maven-deploy-plugin-default.phase>none</maven-deploy-plugin-default.phase>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<sourceDirectory>src/main/asciidoc</sourceDirectory>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>enable-configuration-properties</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>!disableConfigurationProperties</name>
|
||||
</property>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>docs</id>
|
||||
<build>
|
||||
@@ -62,7 +70,7 @@
|
||||
<artifactId>antora-component-version-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>io.spring.maven.antora</groupId>
|
||||
<groupId>org.antora</groupId>
|
||||
<artifactId>antora-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
@@ -70,6 +78,7 @@
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>4.1.1-SNAPSHOT</version>
|
||||
<version>4.1.7-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Spring Cloud Netflix</name>
|
||||
<description>Spring Cloud Netflix</description>
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-build</artifactId>
|
||||
<version>4.1.1-SNAPSHOT</version>
|
||||
<version>4.1.7-SNAPSHOT</version>
|
||||
<relativePath />
|
||||
</parent>
|
||||
<scm>
|
||||
@@ -21,9 +21,9 @@
|
||||
</scm>
|
||||
<properties>
|
||||
<bintray.package>netflix</bintray.package>
|
||||
<spring-cloud-commons.version>4.1.1-SNAPSHOT</spring-cloud-commons.version>
|
||||
<spring-cloud-config.version>4.1.1-SNAPSHOT</spring-cloud-config.version>
|
||||
<testcontainers.version>1.19.3</testcontainers.version>
|
||||
<spring-cloud-commons.version>4.1.7-SNAPSHOT</spring-cloud-commons.version>
|
||||
<spring-cloud-config.version>4.1.8-SNAPSHOT</spring-cloud-config.version>
|
||||
<testcontainers.version>1.20.6</testcontainers.version>
|
||||
<mockserverclient.version>5.15.0</mockserverclient.version>
|
||||
|
||||
<!-- Sonar -->
|
||||
@@ -32,8 +32,6 @@
|
||||
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
|
||||
<sonar.language>java</sonar.language>
|
||||
<maven-resources-plugin.version>3.1.0</maven-resources-plugin.version>
|
||||
<!-- FIXME: 4.0.0 -->
|
||||
<duplicate-finder-maven-plugin.skip>true</duplicate-finder-maven-plugin.skip>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -132,6 +130,12 @@
|
||||
<groupId>org.mock-server</groupId>
|
||||
<artifactId>mockserver-client-java</artifactId>
|
||||
<version>${mockserverclient.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
<parent>
|
||||
<artifactId>spring-cloud-dependencies-parent</artifactId>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<version>4.1.1-SNAPSHOT</version>
|
||||
<version>4.1.7-SNAPSHOT</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<artifactId>spring-cloud-netflix-dependencies</artifactId>
|
||||
<version>4.1.1-SNAPSHOT</version>
|
||||
<version>4.1.7-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>spring-cloud-netflix-dependencies</name>
|
||||
<description>Spring Cloud Netflix Dependencies</description>
|
||||
<properties>
|
||||
<eureka.version>2.0.1</eureka.version>
|
||||
<eureka.version>2.0.5</eureka.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
@@ -138,9 +138,12 @@
|
||||
<groupId>aopalliance</groupId>
|
||||
<artifactId>aopalliance</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- TODO: Move back to Eureka dependency when 1.10.17 released -->
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<profiles>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>4.1.1-SNAPSHOT</version>
|
||||
<version>4.1.7-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<artifactId>spring-cloud-netflix-eureka-client-tls-tests</artifactId>
|
||||
@@ -92,7 +92,17 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-suite-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-suite-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
|
||||
+2
-2
@@ -48,14 +48,14 @@ public class AppRunner implements AutoCloseable {
|
||||
SpringApplicationBuilder builder = new SpringApplicationBuilder(appClass);
|
||||
builder.properties("spring.application.name=" + appClass.getName());
|
||||
builder.properties("spring.jmx.enabled=false");
|
||||
builder.properties(String.format("server.port=%d", availabeTcpPort()));
|
||||
builder.properties(String.format("server.port=%d", availableTcpPort()));
|
||||
builder.properties(props());
|
||||
|
||||
app = builder.build().run();
|
||||
}
|
||||
}
|
||||
|
||||
private int availabeTcpPort() {
|
||||
private int availableTcpPort() {
|
||||
return TestSocketUtils.findAvailableTcpPort();
|
||||
}
|
||||
|
||||
|
||||
+6
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2022 the original author or authors.
|
||||
* Copyright 2018-2025 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.
|
||||
@@ -25,17 +25,17 @@ import java.util.function.Supplier;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
abstract class BaseCertTest {
|
||||
abstract class BaseCertTests {
|
||||
|
||||
private static final Log log = LogFactory.getLog(BaseCertTest.class);
|
||||
private static final Log log = LogFactory.getLog(BaseCertTests.class);
|
||||
|
||||
protected static final String KEY_STORE_PASSWORD = "test-key-store-password";
|
||||
|
||||
@@ -53,7 +53,7 @@ abstract class BaseCertTest {
|
||||
|
||||
protected static File wrongClientCert;
|
||||
|
||||
protected BaseCertTest() {
|
||||
protected BaseCertTests() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@@ -155,15 +155,7 @@ abstract class BaseCertTest {
|
||||
EurekaClientRunner client = createEurekaClient();
|
||||
enableTlsClient(client);
|
||||
client.setKeyStore(clientCert, WRONG_PASSWORD, WRONG_PASSWORD);
|
||||
Assertions.assertThrows(BeanCreationException.class, client::start);
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonExistKeyStoreCauseFailure() {
|
||||
EurekaClientRunner client = createEurekaClient();
|
||||
enableTlsClient(client);
|
||||
client.setKeyStore(new File("nonExistFile"));
|
||||
Assertions.assertThrows(BeanCreationException.class, client::start);
|
||||
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(client::start);
|
||||
}
|
||||
|
||||
@Test
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2022 the original author or authors.
|
||||
* Copyright 2018-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.
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.platform.suite.api.SelectClasses;
|
||||
import org.junit.platform.suite.api.Suite;
|
||||
|
||||
/**
|
||||
* We need to use a suite cause we need to first run all the Eureka Servers, then close
|
||||
@@ -26,8 +26,8 @@ import org.junit.runners.Suite;
|
||||
* That means that when the new context starts we will fail cause the executor service is
|
||||
* already shutdown.
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({ EurekaClientTest.class, RestTemplateEurekaClientTest.class })
|
||||
@SelectClasses({ EurekaClientTests.class, RestTemplateEurekaClientTests.class })
|
||||
@Suite
|
||||
public class EurekaClientSuite {
|
||||
|
||||
}
|
||||
|
||||
+23
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2022 the original author or authors.
|
||||
* Copyright 2018-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.
|
||||
@@ -22,14 +22,18 @@ import org.junit.jupiter.api.BeforeAll;
|
||||
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration;
|
||||
import org.springframework.cloud.netflix.eureka.http.DefaultEurekaClientHttpRequestFactorySupplier;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateTransportClientFactories;
|
||||
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class EurekaClientTest extends BaseCertTest {
|
||||
public class EurekaClientTests extends BaseCertTests {
|
||||
|
||||
private static final Log log = LogFactory.getLog(EurekaClientTest.class);
|
||||
private static final Log log = LogFactory.getLog(EurekaClientTests.class);
|
||||
|
||||
static EurekaServerRunner server;
|
||||
|
||||
@@ -37,11 +41,11 @@ public class EurekaClientTest extends BaseCertTest {
|
||||
|
||||
@BeforeAll
|
||||
public static void setupAll() {
|
||||
server = startEurekaServer(EurekaClientTest.TestEurekaServer.class);
|
||||
service = startService(server, EurekaClientTest.TestApp.class);
|
||||
server = startEurekaServer(EurekaClientTests.TestEurekaServer.class);
|
||||
service = startService(server, EurekaClientTests.TestApp.class);
|
||||
assertThat(service.discoveryClientOptionalArgs()).isInstanceOf(RestTemplateDiscoveryClientOptionalArgs.class);
|
||||
log.info("Successfully asserted that Jersey will be used");
|
||||
waitForRegistration(() -> new EurekaClientTest().createEurekaClient());
|
||||
waitForRegistration(() -> new EurekaClientTests().createEurekaClient());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,6 +57,19 @@ public class EurekaClientTest extends BaseCertTest {
|
||||
@EnableAutoConfiguration
|
||||
public static class TestApp {
|
||||
|
||||
@Bean
|
||||
public RestTemplateTransportClientFactories forceRestTemplateTransportClientFactories(
|
||||
DiscoveryClientOptionalArgsConfiguration configuration,
|
||||
RestTemplateDiscoveryClientOptionalArgs discoveryClientOptionalArgs) {
|
||||
return configuration.restTemplateTransportClientFactories(discoveryClientOptionalArgs);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RestTemplateDiscoveryClientOptionalArgs discoveryClientOptionalArgs() {
|
||||
return new RestTemplateDiscoveryClientOptionalArgs(
|
||||
new DefaultEurekaClientHttpRequestFactorySupplier(new RestTemplateTimeoutProperties()), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SpringBootConfiguration
|
||||
+46
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2022 the original author or authors.
|
||||
* Copyright 2018-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.
|
||||
@@ -24,20 +24,24 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.cloud.configuration.TlsProperties;
|
||||
import org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration;
|
||||
import org.springframework.cloud.netflix.eureka.http.EurekaClientHttpRequestFactorySupplier;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateTransportClientFactories;
|
||||
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class RestTemplateEurekaClientTest extends BaseCertTest {
|
||||
public class RestTemplateEurekaClientTests extends BaseCertTests {
|
||||
|
||||
private static final Log log = LogFactory.getLog(RestTemplateEurekaClientTest.class);
|
||||
private static final Log log = LogFactory.getLog(RestTemplateEurekaClientTests.class);
|
||||
|
||||
private static EurekaServerRunner server;
|
||||
|
||||
@@ -45,12 +49,12 @@ public class RestTemplateEurekaClientTest extends BaseCertTest {
|
||||
|
||||
@BeforeAll
|
||||
public static void setupAll() {
|
||||
server = startEurekaServer(RestTemplateEurekaClientTest.RestTemplateTestEurekaServer.class);
|
||||
service = startService(server, RestTemplateEurekaClientTest.RestTemplateTestApp.class);
|
||||
server = startEurekaServer(RestTemplateEurekaClientTests.RestTemplateTestEurekaServer.class);
|
||||
service = startService(server, RestTemplateEurekaClientTests.RestTemplateTestApp.class);
|
||||
// Will use RestTemplate
|
||||
assertThat(service.discoveryClientOptionalArgs()).isInstanceOf(RestTemplateDiscoveryClientOptionalArgs.class);
|
||||
log.info("Successfully asserted that RestTemplate will be used");
|
||||
waitForRegistration(() -> new RestTemplateEurekaClientTest().createEurekaClient());
|
||||
waitForRegistration(() -> new RestTemplateEurekaClientTests().createEurekaClient());
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
@@ -76,7 +80,16 @@ public class RestTemplateEurekaClientTest extends BaseCertTest {
|
||||
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier)
|
||||
throws GeneralSecurityException, IOException {
|
||||
return configuration.restTemplateDiscoveryClientOptionalArgs(tlsProperties,
|
||||
eurekaClientHttpRequestFactorySupplier);
|
||||
eurekaClientHttpRequestFactorySupplier, new RestTemplateBuilderObjectProvider());
|
||||
}
|
||||
|
||||
// Want to force reusing exactly the same bean as on production without excluding
|
||||
// jersey from the classpath
|
||||
@Bean
|
||||
public RestTemplateTransportClientFactories forceRestTemplateTransportClientFactories(
|
||||
DiscoveryClientOptionalArgsConfiguration configuration,
|
||||
RestTemplateDiscoveryClientOptionalArgs discoveryClientOptionalArgs) {
|
||||
return configuration.restTemplateTransportClientFactories(discoveryClientOptionalArgs);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -88,4 +101,30 @@ public class RestTemplateEurekaClientTest extends BaseCertTest {
|
||||
|
||||
}
|
||||
|
||||
private static class RestTemplateBuilderObjectProvider implements ObjectProvider<RestTemplateBuilder> {
|
||||
|
||||
private final RestTemplateBuilder builder = new RestTemplateBuilder();
|
||||
|
||||
@Override
|
||||
public RestTemplateBuilder getObject(Object... args) throws BeansException {
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTemplateBuilder getIfAvailable() throws BeansException {
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTemplateBuilder getIfUnique() throws BeansException {
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTemplateBuilder getObject() throws BeansException {
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>4.1.1-SNAPSHOT</version>
|
||||
<version>4.1.7-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<artifactId>spring-cloud-netflix-eureka-client</artifactId>
|
||||
|
||||
+37
-14
@@ -193,20 +193,43 @@ public class CloudEurekaTransportConfig implements EurekaTransportConfig {
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("CloudEurekaTransportConfig{").append("sessionedClientReconnectIntervalSeconds=")
|
||||
.append(sessionedClientReconnectIntervalSeconds).append(", ")
|
||||
.append("retryableClientQuarantineRefreshPercentage=")
|
||||
.append(retryableClientQuarantineRefreshPercentage).append(", ")
|
||||
.append("bootstrapResolverRefreshIntervalSeconds=").append(bootstrapResolverRefreshIntervalSeconds)
|
||||
.append(", ").append("applicationsResolverDataStalenessThresholdSeconds=")
|
||||
.append(applicationsResolverDataStalenessThresholdSeconds).append(", ")
|
||||
.append("asyncResolverRefreshIntervalMs=").append(asyncResolverRefreshIntervalMs).append(", ")
|
||||
.append("asyncResolverWarmUpTimeoutMs=").append(asyncResolverWarmUpTimeoutMs).append(", ")
|
||||
.append("asyncExecutorThreadPoolSize=").append(asyncExecutorThreadPoolSize).append(", ")
|
||||
.append("readClusterVip='").append(readClusterVip).append("', ").append("writeClusterVip='")
|
||||
.append(writeClusterVip).append("', ").append("bootstrapResolverForQuery=")
|
||||
.append(bootstrapResolverForQuery).append(", ").append("bootstrapResolverStrategy='")
|
||||
.append(bootstrapResolverStrategy).append("', ").append("applicationsResolverUseIp=")
|
||||
.append(applicationsResolverUseIp).append(", ").append("}").toString();
|
||||
.append(sessionedClientReconnectIntervalSeconds)
|
||||
.append(", ")
|
||||
.append("retryableClientQuarantineRefreshPercentage=")
|
||||
.append(retryableClientQuarantineRefreshPercentage)
|
||||
.append(", ")
|
||||
.append("bootstrapResolverRefreshIntervalSeconds=")
|
||||
.append(bootstrapResolverRefreshIntervalSeconds)
|
||||
.append(", ")
|
||||
.append("applicationsResolverDataStalenessThresholdSeconds=")
|
||||
.append(applicationsResolverDataStalenessThresholdSeconds)
|
||||
.append(", ")
|
||||
.append("asyncResolverRefreshIntervalMs=")
|
||||
.append(asyncResolverRefreshIntervalMs)
|
||||
.append(", ")
|
||||
.append("asyncResolverWarmUpTimeoutMs=")
|
||||
.append(asyncResolverWarmUpTimeoutMs)
|
||||
.append(", ")
|
||||
.append("asyncExecutorThreadPoolSize=")
|
||||
.append(asyncExecutorThreadPoolSize)
|
||||
.append(", ")
|
||||
.append("readClusterVip='")
|
||||
.append(readClusterVip)
|
||||
.append("', ")
|
||||
.append("writeClusterVip='")
|
||||
.append(writeClusterVip)
|
||||
.append("', ")
|
||||
.append("bootstrapResolverForQuery=")
|
||||
.append(bootstrapResolverForQuery)
|
||||
.append(", ")
|
||||
.append("bootstrapResolverStrategy='")
|
||||
.append(bootstrapResolverStrategy)
|
||||
.append("', ")
|
||||
.append("applicationsResolverUseIp=")
|
||||
.append(applicationsResolverUseIp)
|
||||
.append(", ")
|
||||
.append("}")
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+85
-76
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -103,6 +103,7 @@ import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceI
|
||||
* @author Daniel Lavoie
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Tim Ysewyn
|
||||
* @author Robert Bleyl
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
@@ -224,8 +225,8 @@ public class EurekaClientAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EurekaServiceRegistry eurekaServiceRegistry() {
|
||||
return new EurekaServiceRegistry();
|
||||
public EurekaServiceRegistry eurekaServiceRegistry(EurekaInstanceConfigBean eurekaInstanceConfigBean) {
|
||||
return new EurekaServiceRegistry(eurekaInstanceConfigBean);
|
||||
}
|
||||
|
||||
// @Bean
|
||||
@@ -280,8 +281,11 @@ public class EurekaClientAutoConfiguration {
|
||||
public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient,
|
||||
CloudEurekaInstanceConfig instanceConfig, ApplicationInfoManager applicationInfoManager,
|
||||
@Autowired(required = false) ObjectProvider<HealthCheckHandler> healthCheckHandler) {
|
||||
return EurekaRegistration.builder(instanceConfig).with(applicationInfoManager).with(eurekaClient)
|
||||
.with(healthCheckHandler).build();
|
||||
return EurekaRegistration.builder(instanceConfig)
|
||||
.with(applicationInfoManager)
|
||||
.with(eurekaClient)
|
||||
.with(healthCheckHandler)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -339,8 +343,11 @@ public class EurekaClientAutoConfiguration {
|
||||
public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient,
|
||||
CloudEurekaInstanceConfig instanceConfig, ApplicationInfoManager applicationInfoManager,
|
||||
@Autowired(required = false) ObjectProvider<HealthCheckHandler> healthCheckHandler) {
|
||||
return EurekaRegistration.builder(instanceConfig).with(applicationInfoManager).with(eurekaClient)
|
||||
.with(healthCheckHandler).build();
|
||||
return EurekaRegistration.builder(instanceConfig)
|
||||
.with(applicationInfoManager)
|
||||
.with(eurekaClient)
|
||||
.with(healthCheckHandler)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -410,75 +417,77 @@ class EurekaClientHints implements RuntimeHintsRegistrar {
|
||||
if (!ClassUtils.isPresent("com.netflix.discovery.DiscoveryClient", classLoader)) {
|
||||
return;
|
||||
}
|
||||
hints.reflection().registerType(TypeReference.of(DiscoveryClient.class),
|
||||
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INTROSPECT_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(EurekaEndpoint.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(DefaultEndpoint.class),
|
||||
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
|
||||
.registerType(TypeReference.of(EurekaHttpClientDecorator.class),
|
||||
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS,
|
||||
MemberCategory.INTROSPECT_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(EurekaHttpResponse.class),
|
||||
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
|
||||
.registerType(TypeReference.of(EurekaHttpClientDecorator.RequestExecutor.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(ApplicationInfoManager.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(InstanceInfo.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.DECLARED_FIELDS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
|
||||
.registerType(TypeReference.of(InstanceInfo.ActionType.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(InstanceInfo.PortWrapper.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(LeaseInfo.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(MyDataCenterInfo.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(DataCenterInfo.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(DataCenterInfo.Name.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(EurekaClient.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_PUBLIC_METHODS))
|
||||
.registerType(TypeReference.of(TimedSupervisorTask.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(DataCenterTypeInfoResolver.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS))
|
||||
.registerType(TypeReference.of(ApplicationsJacksonBuilder.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(InstanceInfoJsonMixIn.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(Application.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(Applications.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(AsyncResolver.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(RetryableEurekaHttpClient.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(SessionedEurekaHttpClient.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(EurekaServiceInstance.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS));
|
||||
hints.reflection()
|
||||
.registerType(TypeReference.of(DiscoveryClient.class),
|
||||
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS,
|
||||
MemberCategory.INTROSPECT_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(EurekaEndpoint.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(DefaultEndpoint.class),
|
||||
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
|
||||
.registerType(TypeReference.of(EurekaHttpClientDecorator.class),
|
||||
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS,
|
||||
MemberCategory.INTROSPECT_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(EurekaHttpResponse.class),
|
||||
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
|
||||
.registerType(TypeReference.of(EurekaHttpClientDecorator.RequestExecutor.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(ApplicationInfoManager.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(InstanceInfo.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.DECLARED_FIELDS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
|
||||
.registerType(TypeReference.of(InstanceInfo.ActionType.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(InstanceInfo.PortWrapper.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(LeaseInfo.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(MyDataCenterInfo.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(DataCenterInfo.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(DataCenterInfo.Name.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(EurekaClient.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_PUBLIC_METHODS))
|
||||
.registerType(TypeReference.of(TimedSupervisorTask.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(DataCenterTypeInfoResolver.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS))
|
||||
.registerType(TypeReference.of(ApplicationsJacksonBuilder.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(InstanceInfoJsonMixIn.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(Application.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(Applications.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(AsyncResolver.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(RetryableEurekaHttpClient.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(SessionedEurekaHttpClient.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(EurekaServiceInstance.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+144
-45
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -41,6 +41,7 @@ import static org.springframework.cloud.netflix.eureka.EurekaConstants.DEFAULT_P
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Gregor Zurowski
|
||||
* @author Mooyong Lee
|
||||
*/
|
||||
@ConfigurationProperties(EurekaClientConfigBean.PREFIX)
|
||||
public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
|
||||
@@ -60,8 +61,6 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
|
||||
*/
|
||||
public static final String DEFAULT_ZONE = "defaultZone";
|
||||
|
||||
private static final int MINUTES = 60;
|
||||
|
||||
@Autowired(required = false)
|
||||
PropertyResolver propertyResolver;
|
||||
|
||||
@@ -96,7 +95,7 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
|
||||
* Eureka servers could be added or removed and this setting controls how soon the
|
||||
* eureka clients should know about it.
|
||||
*/
|
||||
private int eurekaServiceUrlPollIntervalSeconds = 5 * MINUTES;
|
||||
private int eurekaServiceUrlPollIntervalSeconds = 300; // 5 * MINUTES
|
||||
|
||||
/**
|
||||
* Gets the proxy port to eureka server if any.
|
||||
@@ -998,47 +997,147 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("EurekaClientConfigBean{").append("propertyResolver=").append(propertyResolver)
|
||||
.append(", ").append("enabled=").append(enabled).append(", ").append("transport=").append(transport)
|
||||
.append(", ").append("registryFetchIntervalSeconds=").append(registryFetchIntervalSeconds).append(", ")
|
||||
.append("instanceInfoReplicationIntervalSeconds=").append(instanceInfoReplicationIntervalSeconds)
|
||||
.append(", ").append("initialInstanceInfoReplicationIntervalSeconds=")
|
||||
.append(initialInstanceInfoReplicationIntervalSeconds).append(", ")
|
||||
.append("eurekaServiceUrlPollIntervalSeconds=").append(eurekaServiceUrlPollIntervalSeconds).append(", ")
|
||||
.append("proxyPort='").append(proxyPort).append("', ").append("proxyHost='").append(proxyHost)
|
||||
.append("', ").append("proxyUserName='").append(proxyUserName).append("', ").append("proxyPassword='")
|
||||
.append(proxyPassword).append("', ").append("eurekaServerReadTimeoutSeconds=")
|
||||
.append(eurekaServerReadTimeoutSeconds).append(", ").append("eurekaServerConnectTimeoutSeconds=")
|
||||
.append(eurekaServerConnectTimeoutSeconds).append(", ").append("backupRegistryImpl='")
|
||||
.append(backupRegistryImpl).append("', ").append("eurekaServerTotalConnections=")
|
||||
.append(eurekaServerTotalConnections).append(", ").append("eurekaServerTotalConnectionsPerHost=")
|
||||
.append(eurekaServerTotalConnectionsPerHost).append(", ").append("eurekaServerURLContext='")
|
||||
.append(eurekaServerURLContext).append("', ").append("eurekaServerPort='").append(eurekaServerPort)
|
||||
.append("', ").append("eurekaServerDNSName='").append(eurekaServerDNSName).append("', ")
|
||||
.append("region='").append(region).append("', ").append("eurekaConnectionIdleTimeoutSeconds=")
|
||||
.append(eurekaConnectionIdleTimeoutSeconds).append(", ").append("registryRefreshSingleVipAddress='")
|
||||
.append(registryRefreshSingleVipAddress).append("', ").append("heartbeatExecutorThreadPoolSize=")
|
||||
.append(heartbeatExecutorThreadPoolSize).append(", ")
|
||||
.append("heartbeatExecutorExponentialBackOffBound=").append(heartbeatExecutorExponentialBackOffBound)
|
||||
.append(", ").append("cacheRefreshExecutorThreadPoolSize=").append(cacheRefreshExecutorThreadPoolSize)
|
||||
.append(", ").append("cacheRefreshExecutorExponentialBackOffBound=")
|
||||
.append(cacheRefreshExecutorExponentialBackOffBound).append(", ").append("serviceUrl=")
|
||||
.append(serviceUrl).append(", ").append("gZipContent=").append(gZipContent).append(", ")
|
||||
.append("useDnsForFetchingServiceUrls=").append(useDnsForFetchingServiceUrls).append(", ")
|
||||
.append("registerWithEureka=").append(registerWithEureka).append(", ").append("preferSameZoneEureka=")
|
||||
.append(preferSameZoneEureka).append(", ").append("logDeltaDiff=").append(logDeltaDiff).append(", ")
|
||||
.append("disableDelta=").append(disableDelta).append(", ").append("fetchRemoteRegionsRegistry='")
|
||||
.append(fetchRemoteRegionsRegistry).append("', ").append("availabilityZones=").append(availabilityZones)
|
||||
.append(", ").append("filterOnlyUpInstances=").append(filterOnlyUpInstances).append(", ")
|
||||
.append("fetchRegistry=").append(fetchRegistry).append(", ").append("dollarReplacement='")
|
||||
.append(dollarReplacement).append("', ").append("escapeCharReplacement='").append(escapeCharReplacement)
|
||||
.append("', ").append("allowRedirects=").append(allowRedirects).append(", ")
|
||||
.append("onDemandUpdateStatusChange=").append(onDemandUpdateStatusChange).append(", ")
|
||||
.append("encoderName='").append(encoderName).append("', ").append("decoderName='").append(decoderName)
|
||||
.append("', ").append("clientDataAccept='").append(clientDataAccept).append("', ")
|
||||
.append("shouldUnregisterOnShutdown='").append(shouldUnregisterOnShutdown)
|
||||
.append("shouldEnforceRegistrationAtInit='").append(shouldEnforceRegistrationAtInit).append("', ")
|
||||
.append("order='").append(order).append("'}").toString();
|
||||
return new StringBuilder("EurekaClientConfigBean{").append("propertyResolver=")
|
||||
.append(propertyResolver)
|
||||
.append(", ")
|
||||
.append("enabled=")
|
||||
.append(enabled)
|
||||
.append(", ")
|
||||
.append("transport=")
|
||||
.append(transport)
|
||||
.append(", ")
|
||||
.append("registryFetchIntervalSeconds=")
|
||||
.append(registryFetchIntervalSeconds)
|
||||
.append(", ")
|
||||
.append("instanceInfoReplicationIntervalSeconds=")
|
||||
.append(instanceInfoReplicationIntervalSeconds)
|
||||
.append(", ")
|
||||
.append("initialInstanceInfoReplicationIntervalSeconds=")
|
||||
.append(initialInstanceInfoReplicationIntervalSeconds)
|
||||
.append(", ")
|
||||
.append("eurekaServiceUrlPollIntervalSeconds=")
|
||||
.append(eurekaServiceUrlPollIntervalSeconds)
|
||||
.append(", ")
|
||||
.append("proxyPort='")
|
||||
.append(proxyPort)
|
||||
.append("', ")
|
||||
.append("proxyHost='")
|
||||
.append(proxyHost)
|
||||
.append("', ")
|
||||
.append("proxyUserName='")
|
||||
.append(proxyUserName)
|
||||
.append("', ")
|
||||
.append("proxyPassword='")
|
||||
.append(proxyPassword)
|
||||
.append("', ")
|
||||
.append("eurekaServerReadTimeoutSeconds=")
|
||||
.append(eurekaServerReadTimeoutSeconds)
|
||||
.append(", ")
|
||||
.append("eurekaServerConnectTimeoutSeconds=")
|
||||
.append(eurekaServerConnectTimeoutSeconds)
|
||||
.append(", ")
|
||||
.append("backupRegistryImpl='")
|
||||
.append(backupRegistryImpl)
|
||||
.append("', ")
|
||||
.append("eurekaServerTotalConnections=")
|
||||
.append(eurekaServerTotalConnections)
|
||||
.append(", ")
|
||||
.append("eurekaServerTotalConnectionsPerHost=")
|
||||
.append(eurekaServerTotalConnectionsPerHost)
|
||||
.append(", ")
|
||||
.append("eurekaServerURLContext='")
|
||||
.append(eurekaServerURLContext)
|
||||
.append("', ")
|
||||
.append("eurekaServerPort='")
|
||||
.append(eurekaServerPort)
|
||||
.append("', ")
|
||||
.append("eurekaServerDNSName='")
|
||||
.append(eurekaServerDNSName)
|
||||
.append("', ")
|
||||
.append("region='")
|
||||
.append(region)
|
||||
.append("', ")
|
||||
.append("eurekaConnectionIdleTimeoutSeconds=")
|
||||
.append(eurekaConnectionIdleTimeoutSeconds)
|
||||
.append(", ")
|
||||
.append("registryRefreshSingleVipAddress='")
|
||||
.append(registryRefreshSingleVipAddress)
|
||||
.append("', ")
|
||||
.append("heartbeatExecutorThreadPoolSize=")
|
||||
.append(heartbeatExecutorThreadPoolSize)
|
||||
.append(", ")
|
||||
.append("heartbeatExecutorExponentialBackOffBound=")
|
||||
.append(heartbeatExecutorExponentialBackOffBound)
|
||||
.append(", ")
|
||||
.append("cacheRefreshExecutorThreadPoolSize=")
|
||||
.append(cacheRefreshExecutorThreadPoolSize)
|
||||
.append(", ")
|
||||
.append("cacheRefreshExecutorExponentialBackOffBound=")
|
||||
.append(cacheRefreshExecutorExponentialBackOffBound)
|
||||
.append(", ")
|
||||
.append("serviceUrl=")
|
||||
.append(serviceUrl)
|
||||
.append(", ")
|
||||
.append("gZipContent=")
|
||||
.append(gZipContent)
|
||||
.append(", ")
|
||||
.append("useDnsForFetchingServiceUrls=")
|
||||
.append(useDnsForFetchingServiceUrls)
|
||||
.append(", ")
|
||||
.append("registerWithEureka=")
|
||||
.append(registerWithEureka)
|
||||
.append(", ")
|
||||
.append("preferSameZoneEureka=")
|
||||
.append(preferSameZoneEureka)
|
||||
.append(", ")
|
||||
.append("logDeltaDiff=")
|
||||
.append(logDeltaDiff)
|
||||
.append(", ")
|
||||
.append("disableDelta=")
|
||||
.append(disableDelta)
|
||||
.append(", ")
|
||||
.append("fetchRemoteRegionsRegistry='")
|
||||
.append(fetchRemoteRegionsRegistry)
|
||||
.append("', ")
|
||||
.append("availabilityZones=")
|
||||
.append(availabilityZones)
|
||||
.append(", ")
|
||||
.append("filterOnlyUpInstances=")
|
||||
.append(filterOnlyUpInstances)
|
||||
.append(", ")
|
||||
.append("fetchRegistry=")
|
||||
.append(fetchRegistry)
|
||||
.append(", ")
|
||||
.append("dollarReplacement='")
|
||||
.append(dollarReplacement)
|
||||
.append("', ")
|
||||
.append("escapeCharReplacement='")
|
||||
.append(escapeCharReplacement)
|
||||
.append("', ")
|
||||
.append("allowRedirects=")
|
||||
.append(allowRedirects)
|
||||
.append(", ")
|
||||
.append("onDemandUpdateStatusChange=")
|
||||
.append(onDemandUpdateStatusChange)
|
||||
.append(", ")
|
||||
.append("encoderName='")
|
||||
.append(encoderName)
|
||||
.append("', ")
|
||||
.append("decoderName='")
|
||||
.append(decoderName)
|
||||
.append("', ")
|
||||
.append("clientDataAccept='")
|
||||
.append(clientDataAccept)
|
||||
.append("', ")
|
||||
.append("shouldUnregisterOnShutdown='")
|
||||
.append(shouldUnregisterOnShutdown)
|
||||
.append("shouldEnforceRegistrationAtInit='")
|
||||
.append(shouldEnforceRegistrationAtInit)
|
||||
.append("', ")
|
||||
.append("order='")
|
||||
.append(order)
|
||||
.append("'}")
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.cloud.netflix.eureka;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
@@ -35,6 +36,7 @@ import org.springframework.core.Ordered;
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Tim Ysewyn
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public class EurekaDiscoveryClient implements DiscoveryClient {
|
||||
|
||||
@@ -79,7 +81,7 @@ public class EurekaDiscoveryClient implements DiscoveryClient {
|
||||
if (app.getInstances().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
names.add(app.getName().toLowerCase());
|
||||
names.add(app.getName().toLowerCase(Locale.ROOT));
|
||||
|
||||
}
|
||||
return names;
|
||||
|
||||
+116
-25
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -38,6 +38,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Spencer Gibb
|
||||
* @author Ryan Baxter
|
||||
* @author Gregor Zurowski
|
||||
* @author Robert Bleyl
|
||||
*/
|
||||
@ConfigurationProperties("eureka.instance")
|
||||
public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, EnvironmentAware {
|
||||
@@ -269,6 +270,12 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, Envi
|
||||
*/
|
||||
private boolean preferIpAddress = false;
|
||||
|
||||
/**
|
||||
* If true the EurekaClient will be initialized asynchronously when the
|
||||
* InstanceRegistry bean is created.
|
||||
*/
|
||||
private boolean asyncClientInitialization;
|
||||
|
||||
/**
|
||||
* Initial status to register with remote Eureka server.
|
||||
*/
|
||||
@@ -547,6 +554,14 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, Envi
|
||||
this.preferIpAddress = preferIpAddress;
|
||||
}
|
||||
|
||||
public boolean isAsyncClientInitialization() {
|
||||
return asyncClientInitialization;
|
||||
}
|
||||
|
||||
public void setAsyncClientInitialization(boolean asyncClientInitialization) {
|
||||
this.asyncClientInitialization = asyncClientInitialization;
|
||||
}
|
||||
|
||||
public InstanceStatus getInitialStatus() {
|
||||
return initialStatus;
|
||||
}
|
||||
@@ -597,6 +612,7 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, Envi
|
||||
&& Objects.equals(namespace, that.namespace) && Objects.equals(hostname, that.hostname)
|
||||
&& preferIpAddress == that.preferIpAddress && Objects.equals(initialStatus, that.initialStatus)
|
||||
&& Arrays.equals(defaultAddressResolutionOrder, that.defaultAddressResolutionOrder)
|
||||
&& asyncClientInitialization == that.asyncClientInitialization
|
||||
&& Objects.equals(environment, that.environment);
|
||||
}
|
||||
|
||||
@@ -607,34 +623,109 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, Envi
|
||||
leaseExpirationDurationInSeconds, virtualHostName, instanceId, secureVirtualHostName, aSGName,
|
||||
metadataMap, dataCenterInfo, ipAddress, statusPageUrlPath, statusPageUrl, homePageUrlPath, homePageUrl,
|
||||
healthCheckUrlPath, healthCheckUrl, secureHealthCheckUrl, namespace, hostname, preferIpAddress,
|
||||
initialStatus, Arrays.hashCode(defaultAddressResolutionOrder), environment);
|
||||
asyncClientInitialization, initialStatus, Arrays.hashCode(defaultAddressResolutionOrder), environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("EurekaInstanceConfigBean{").append("hostInfo=").append(hostInfo).append(", ")
|
||||
.append("inetUtils=").append(inetUtils).append(", ").append("appname='").append(appname).append("', ")
|
||||
.append("appGroupName='").append(appGroupName).append("', ").append("instanceEnabledOnit=")
|
||||
.append(instanceEnabledOnit).append(", ").append("nonSecurePort=").append(nonSecurePort).append(", ")
|
||||
.append("securePort=").append(securePort).append(", ").append("nonSecurePortEnabled=")
|
||||
.append(nonSecurePortEnabled).append(", ").append("securePortEnabled=").append(securePortEnabled)
|
||||
.append(", ").append("leaseRenewalIntervalInSeconds=").append(leaseRenewalIntervalInSeconds)
|
||||
.append(", ").append("leaseExpirationDurationInSeconds=").append(leaseExpirationDurationInSeconds)
|
||||
.append(", ").append("virtualHostName='").append(virtualHostName).append("', ").append("instanceId='")
|
||||
.append(instanceId).append("', ").append("secureVirtualHostName='").append(secureVirtualHostName)
|
||||
.append("', ").append("aSGName='").append(aSGName).append("', ").append("metadataMap=")
|
||||
.append(metadataMap).append(", ").append("dataCenterInfo=").append(dataCenterInfo).append(", ")
|
||||
.append("ipAddress='").append(ipAddress).append("', ").append("statusPageUrlPath='")
|
||||
.append(statusPageUrlPath).append("', ").append("statusPageUrl='").append(statusPageUrl).append("', ")
|
||||
.append("homePageUrlPath='").append(homePageUrlPath).append("', ").append("homePageUrl='")
|
||||
.append(homePageUrl).append("', ").append("healthCheckUrlPath='").append(healthCheckUrlPath)
|
||||
.append("', ").append("healthCheckUrl='").append(healthCheckUrl).append("', ")
|
||||
.append("secureHealthCheckUrl='").append(secureHealthCheckUrl).append("', ").append("namespace='")
|
||||
.append(namespace).append("', ").append("hostname='").append(hostname).append("', ")
|
||||
.append("preferIpAddress=").append(preferIpAddress).append(", ").append("initialStatus=")
|
||||
.append(initialStatus).append(", ").append("defaultAddressResolutionOrder=")
|
||||
.append(Arrays.toString(defaultAddressResolutionOrder)).append(", ").append("environment=")
|
||||
.append(environment).append(", ").append("}").toString();
|
||||
return new StringBuilder("EurekaInstanceConfigBean{").append("hostInfo=")
|
||||
.append(hostInfo)
|
||||
.append(", ")
|
||||
.append("inetUtils=")
|
||||
.append(inetUtils)
|
||||
.append(", ")
|
||||
.append("appname='")
|
||||
.append(appname)
|
||||
.append("', ")
|
||||
.append("appGroupName='")
|
||||
.append(appGroupName)
|
||||
.append("', ")
|
||||
.append("instanceEnabledOnit=")
|
||||
.append(instanceEnabledOnit)
|
||||
.append(", ")
|
||||
.append("nonSecurePort=")
|
||||
.append(nonSecurePort)
|
||||
.append(", ")
|
||||
.append("securePort=")
|
||||
.append(securePort)
|
||||
.append(", ")
|
||||
.append("nonSecurePortEnabled=")
|
||||
.append(nonSecurePortEnabled)
|
||||
.append(", ")
|
||||
.append("securePortEnabled=")
|
||||
.append(securePortEnabled)
|
||||
.append(", ")
|
||||
.append("leaseRenewalIntervalInSeconds=")
|
||||
.append(leaseRenewalIntervalInSeconds)
|
||||
.append(", ")
|
||||
.append("leaseExpirationDurationInSeconds=")
|
||||
.append(leaseExpirationDurationInSeconds)
|
||||
.append(", ")
|
||||
.append("virtualHostName='")
|
||||
.append(virtualHostName)
|
||||
.append("', ")
|
||||
.append("instanceId='")
|
||||
.append(instanceId)
|
||||
.append("', ")
|
||||
.append("secureVirtualHostName='")
|
||||
.append(secureVirtualHostName)
|
||||
.append("', ")
|
||||
.append("aSGName='")
|
||||
.append(aSGName)
|
||||
.append("', ")
|
||||
.append("metadataMap=")
|
||||
.append(metadataMap)
|
||||
.append(", ")
|
||||
.append("dataCenterInfo=")
|
||||
.append(dataCenterInfo)
|
||||
.append(", ")
|
||||
.append("ipAddress='")
|
||||
.append(ipAddress)
|
||||
.append("', ")
|
||||
.append("statusPageUrlPath='")
|
||||
.append(statusPageUrlPath)
|
||||
.append("', ")
|
||||
.append("statusPageUrl='")
|
||||
.append(statusPageUrl)
|
||||
.append("', ")
|
||||
.append("homePageUrlPath='")
|
||||
.append(homePageUrlPath)
|
||||
.append("', ")
|
||||
.append("homePageUrl='")
|
||||
.append(homePageUrl)
|
||||
.append("', ")
|
||||
.append("healthCheckUrlPath='")
|
||||
.append(healthCheckUrlPath)
|
||||
.append("', ")
|
||||
.append("healthCheckUrl='")
|
||||
.append(healthCheckUrl)
|
||||
.append("', ")
|
||||
.append("secureHealthCheckUrl='")
|
||||
.append(secureHealthCheckUrl)
|
||||
.append("', ")
|
||||
.append("namespace='")
|
||||
.append(namespace)
|
||||
.append("', ")
|
||||
.append("hostname='")
|
||||
.append(hostname)
|
||||
.append("', ")
|
||||
.append("asyncClientInitialization=")
|
||||
.append(asyncClientInitialization)
|
||||
.append(", ")
|
||||
.append("preferIpAddress=")
|
||||
.append(preferIpAddress)
|
||||
.append(", ")
|
||||
.append("initialStatus=")
|
||||
.append(initialStatus)
|
||||
.append(", ")
|
||||
.append("defaultAddressResolutionOrder=")
|
||||
.append(Arrays.toString(defaultAddressResolutionOrder))
|
||||
.append(", ")
|
||||
.append("environment=")
|
||||
.append(environment)
|
||||
.append(", ")
|
||||
.append("}")
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+20
-15
@@ -35,8 +35,8 @@ public class InstanceInfoFactory {
|
||||
|
||||
public InstanceInfo create(EurekaInstanceConfig config) {
|
||||
LeaseInfo.Builder leaseInfoBuilder = LeaseInfo.Builder.newBuilder()
|
||||
.setRenewalIntervalInSecs(config.getLeaseRenewalIntervalInSeconds())
|
||||
.setDurationInSecs(config.getLeaseExpirationDurationInSeconds());
|
||||
.setRenewalIntervalInSecs(config.getLeaseRenewalIntervalInSeconds())
|
||||
.setDurationInSecs(config.getLeaseExpirationDurationInSeconds());
|
||||
|
||||
// Builder the instance information to be registered with eureka
|
||||
// server
|
||||
@@ -46,19 +46,24 @@ public class InstanceInfoFactory {
|
||||
if (!namespace.endsWith(".")) {
|
||||
namespace = namespace + ".";
|
||||
}
|
||||
builder.setNamespace(namespace).setAppName(config.getAppname()).setInstanceId(config.getInstanceId())
|
||||
.setAppGroupName(config.getAppGroupName()).setDataCenterInfo(config.getDataCenterInfo())
|
||||
.setIPAddr(config.getIpAddress()).setHostName(config.getHostName(false))
|
||||
.setPort(config.getNonSecurePort())
|
||||
.enablePort(InstanceInfo.PortType.UNSECURE, config.isNonSecurePortEnabled())
|
||||
.setSecurePort(config.getSecurePort())
|
||||
.enablePort(InstanceInfo.PortType.SECURE, config.getSecurePortEnabled())
|
||||
.setVIPAddress(config.getVirtualHostName()).setSecureVIPAddress(config.getSecureVirtualHostName())
|
||||
.setHomePageUrl(config.getHomePageUrlPath(), config.getHomePageUrl())
|
||||
.setStatusPageUrl(config.getStatusPageUrlPath(), config.getStatusPageUrl())
|
||||
.setHealthCheckUrls(config.getHealthCheckUrlPath(), config.getHealthCheckUrl(),
|
||||
config.getSecureHealthCheckUrl())
|
||||
.setASGName(config.getASGName());
|
||||
builder.setNamespace(namespace)
|
||||
.setAppName(config.getAppname())
|
||||
.setInstanceId(config.getInstanceId())
|
||||
.setAppGroupName(config.getAppGroupName())
|
||||
.setDataCenterInfo(config.getDataCenterInfo())
|
||||
.setIPAddr(config.getIpAddress())
|
||||
.setHostName(config.getHostName(false))
|
||||
.setPort(config.getNonSecurePort())
|
||||
.enablePort(InstanceInfo.PortType.UNSECURE, config.isNonSecurePortEnabled())
|
||||
.setSecurePort(config.getSecurePort())
|
||||
.enablePort(InstanceInfo.PortType.SECURE, config.getSecurePortEnabled())
|
||||
.setVIPAddress(config.getVirtualHostName())
|
||||
.setSecureVIPAddress(config.getSecureVirtualHostName())
|
||||
.setHomePageUrl(config.getHomePageUrlPath(), config.getHomePageUrl())
|
||||
.setStatusPageUrl(config.getStatusPageUrlPath(), config.getStatusPageUrl())
|
||||
.setHealthCheckUrls(config.getHealthCheckUrlPath(), config.getHealthCheckUrl(),
|
||||
config.getSecureHealthCheckUrl())
|
||||
.setASGName(config.getASGName());
|
||||
|
||||
// Start off with the STARTING state to avoid traffic
|
||||
if (!config.isInstanceEnabledOnit()) {
|
||||
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -30,6 +30,7 @@ import org.springframework.web.client.RestTemplate;
|
||||
* {@link RestTemplateEurekaHttpClient}.
|
||||
*
|
||||
* @author Jiwon Jeon
|
||||
* @author Mooyong Lee
|
||||
* @since 3.1.6
|
||||
*/
|
||||
@ConfigurationProperties("eureka.client.rest-template-timeout")
|
||||
@@ -39,11 +40,11 @@ public class RestTemplateTimeoutProperties {
|
||||
* Default values are set to 180000, in keeping with {@link RequestConfig} and
|
||||
* {@link SocketConfig} defaults.
|
||||
*/
|
||||
private int connectTimeout = 3 * 60 * 1000;
|
||||
private int connectTimeout = 180000; // 3 * MINUTES
|
||||
|
||||
private int connectRequestTimeout = 3 * 60 * 1000;
|
||||
private int connectRequestTimeout = 180000; // 3 * MINUTES
|
||||
|
||||
private int socketTimeout = 3 * 60 * 1000;
|
||||
private int socketTimeout = 180000; // 3 * MINUTES
|
||||
|
||||
public int getConnectTimeout() {
|
||||
return connectTimeout;
|
||||
|
||||
+52
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -26,6 +26,8 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.AllNestedConditions;
|
||||
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
@@ -34,6 +36,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.cloud.configuration.SSLContextFactory;
|
||||
import org.springframework.cloud.configuration.TlsProperties;
|
||||
import org.springframework.cloud.netflix.eureka.RestTemplateTimeoutProperties;
|
||||
@@ -44,11 +47,14 @@ import org.springframework.cloud.netflix.eureka.http.RestTemplateTransportClient
|
||||
import org.springframework.cloud.netflix.eureka.http.WebClientDiscoveryClientOptionalArgs;
|
||||
import org.springframework.cloud.netflix.eureka.http.WebClientTransportClientFactories;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
* @author Armin Krezovic
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(RestTemplateTimeoutProperties.class)
|
||||
@@ -64,23 +70,23 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
|
||||
@ConditionalOnMissingClass("org.glassfish.jersey.client.JerseyClient")
|
||||
@Conditional(JerseyClientNotPresentOrNotEnabledCondition.class)
|
||||
@ConditionalOnMissingBean(value = { AbstractDiscoveryClientOptionalArgs.class }, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", matchIfMissing = true,
|
||||
havingValue = "false")
|
||||
public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs(TlsProperties tlsProperties,
|
||||
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier)
|
||||
throws GeneralSecurityException, IOException {
|
||||
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier,
|
||||
ObjectProvider<RestTemplateBuilder> restTemplateBuilders) throws GeneralSecurityException, IOException {
|
||||
logger.info("Eureka HTTP Client uses RestTemplate.");
|
||||
RestTemplateDiscoveryClientOptionalArgs result = new RestTemplateDiscoveryClientOptionalArgs(
|
||||
eurekaClientHttpRequestFactorySupplier);
|
||||
eurekaClientHttpRequestFactorySupplier, restTemplateBuilders::getIfAvailable);
|
||||
setupTLS(result, tlsProperties);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
|
||||
@ConditionalOnMissingClass("org.glassfish.jersey.client.JerseyClient")
|
||||
@Conditional(JerseyClientNotPresentOrNotEnabledCondition.class)
|
||||
@ConditionalOnMissingBean(value = { TransportClientFactories.class }, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", matchIfMissing = true,
|
||||
havingValue = "false")
|
||||
@@ -106,7 +112,7 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(name = "org.glassfish.jersey.client.JerseyClient")
|
||||
@Conditional(JerseyClientPresentAndEnabledCondition.class)
|
||||
@ConditionalOnBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
|
||||
static class DiscoveryClientOptionalArgsTlsConfiguration {
|
||||
|
||||
@@ -118,7 +124,7 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnMissingClass("org.glassfish.jersey.client.JerseyClient")
|
||||
@Conditional(JerseyClientNotPresentOrNotEnabledCondition.class)
|
||||
@ConditionalOnClass(name = "org.springframework.web.reactive.function.client.WebClient")
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", havingValue = "true")
|
||||
protected static class WebClientConfiguration {
|
||||
@@ -149,8 +155,8 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingClass({ "org.glassfish.jersey.client.JerseyClient",
|
||||
"org.springframework.web.reactive.function.client.WebClient" })
|
||||
@Conditional(JerseyClientNotPresentOrNotEnabledCondition.class)
|
||||
@ConditionalOnMissingClass("org.springframework.web.reactive.function.client.WebClient")
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", havingValue = "true")
|
||||
protected static class WebClientNotFoundConfiguration {
|
||||
|
||||
@@ -162,4 +168,40 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
|
||||
}
|
||||
|
||||
static class JerseyClientPresentAndEnabledCondition extends AllNestedConditions {
|
||||
|
||||
JerseyClientPresentAndEnabledCondition() {
|
||||
super(ConfigurationPhase.REGISTER_BEAN);
|
||||
}
|
||||
|
||||
@ConditionalOnClass(name = "org.glassfish.jersey.client.JerseyClient")
|
||||
static class OnJerseyClientPresent {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(value = "eureka.client.jersey.enabled", matchIfMissing = true)
|
||||
static class OnJerseyClientEnabled {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class JerseyClientNotPresentOrNotEnabledCondition extends AnyNestedCondition {
|
||||
|
||||
JerseyClientNotPresentOrNotEnabledCondition() {
|
||||
super(ConfigurationPhase.REGISTER_BEAN);
|
||||
}
|
||||
|
||||
@ConditionalOnMissingClass("org.glassfish.jersey.client.JerseyClient")
|
||||
static class OnJerseyClientMissing {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(value = "eureka.client.jersey.enabled", havingValue = "false")
|
||||
static class OnJerseyClientDisabled {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -29,10 +29,12 @@ import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.cloud.config.client.ConfigServerInstanceProvider;
|
||||
import org.springframework.cloud.config.client.ConfigServicePropertySourceLocator;
|
||||
import org.springframework.cloud.configuration.TlsProperties;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean;
|
||||
import org.springframework.cloud.netflix.eureka.RestTemplateTimeoutProperties;
|
||||
import org.springframework.cloud.netflix.eureka.http.DefaultEurekaClientHttpRequestFactorySupplier;
|
||||
import org.springframework.cloud.netflix.eureka.http.EurekaClientHttpRequestFactorySupplier;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateEurekaHttpClient;
|
||||
@@ -51,11 +53,12 @@ import org.springframework.web.reactive.function.client.WebClient;
|
||||
* discovery.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Armin Krezovic
|
||||
*/
|
||||
@ConditionalOnClass(ConfigServicePropertySourceLocator.class)
|
||||
@Conditional(EurekaConfigServerBootstrapConfiguration.EurekaConfigServerBootstrapCondition.class)
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
@EnableConfigurationProperties(RestTemplateTimeoutProperties.class)
|
||||
public class EurekaConfigServerBootstrapConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -70,16 +73,18 @@ public class EurekaConfigServerBootstrapConfiguration {
|
||||
havingValue = "false")
|
||||
public RestTemplateEurekaHttpClient configDiscoveryRestTemplateEurekaHttpClient(EurekaClientConfigBean config,
|
||||
Environment env, @Nullable TlsProperties properties,
|
||||
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) {
|
||||
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier,
|
||||
ObjectProvider<RestTemplateBuilder> restTemplateBuilders) {
|
||||
return (RestTemplateEurekaHttpClient) new RestTemplateTransportClientFactory(properties,
|
||||
eurekaClientHttpRequestFactorySupplier)
|
||||
.newClient(HostnameBasedUrlRandomizer.randomEndpoint(config, env));
|
||||
eurekaClientHttpRequestFactorySupplier, restTemplateBuilders::getIfAvailable)
|
||||
.newClient(HostnameBasedUrlRandomizer.randomEndpoint(config, env));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
EurekaClientHttpRequestFactorySupplier defaultEurekaClientHttpRequestFactorySupplier() {
|
||||
return new DefaultEurekaClientHttpRequestFactorySupplier();
|
||||
EurekaClientHttpRequestFactorySupplier defaultEurekaClientHttpRequestFactorySupplier(
|
||||
RestTemplateTimeoutProperties restTemplateTimeoutProperties) {
|
||||
return new DefaultEurekaClientHttpRequestFactorySupplier(restTemplateTimeoutProperties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -99,7 +104,7 @@ public class EurekaConfigServerBootstrapConfiguration {
|
||||
public WebClientEurekaHttpClient configDiscoveryWebClientEurekaHttpClient(EurekaClientConfigBean config,
|
||||
ObjectProvider<WebClient.Builder> builder, Environment env) {
|
||||
return (WebClientEurekaHttpClient) new WebClientTransportClientFactory(builder::getIfAvailable)
|
||||
.newClient(HostnameBasedUrlRandomizer.randomEndpoint(config, env));
|
||||
.newClient(HostnameBasedUrlRandomizer.randomEndpoint(config, env));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -60,8 +60,8 @@ public class EurekaConfigServerBootstrapper implements BootstrapRegistryInitiali
|
||||
EurekaHttpClient httpClient = new RestTemplateTransportClientFactory(
|
||||
context.getOrElse(TlsProperties.class, null),
|
||||
context.getOrElse(EurekaClientHttpRequestFactorySupplier.class,
|
||||
new DefaultEurekaClientHttpRequestFactorySupplier())).newClient(
|
||||
HostnameBasedUrlRandomizer.randomEndpoint(config, getPropertyResolver(context)));
|
||||
new DefaultEurekaClientHttpRequestFactorySupplier()))
|
||||
.newClient(HostnameBasedUrlRandomizer.randomEndpoint(config, getPropertyResolver(context)));
|
||||
return new EurekaConfigServerInstanceProvider(httpClient, config)::getInstances;
|
||||
});
|
||||
}
|
||||
|
||||
+9
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -31,6 +31,9 @@ import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaServiceInstance;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
/**
|
||||
* @author Tang Xiong
|
||||
*/
|
||||
public class EurekaConfigServerInstanceProvider {
|
||||
|
||||
private final Log log;
|
||||
@@ -53,7 +56,11 @@ public class EurekaConfigServerInstanceProvider {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("eurekaConfigServerInstanceProvider finding instances for " + serviceId);
|
||||
}
|
||||
EurekaHttpResponse<Applications> response = client.getApplications(config.getRegion());
|
||||
String remoteRegionsStr = config.fetchRegistryForRemoteRegions();
|
||||
String[] remoteRegions = remoteRegionsStr == null ? null : remoteRegionsStr.split(",");
|
||||
EurekaHttpResponse<Applications> response = config.getRegistryRefreshSingleVipAddress() == null
|
||||
? client.getApplications(remoteRegions)
|
||||
: client.getVip(config.getRegistryRefreshSingleVipAddress(), remoteRegions);
|
||||
List<ServiceInstance> instances = new ArrayList<>();
|
||||
if (!isSuccessful(response) || response.getEntity() == null) {
|
||||
return instances;
|
||||
|
||||
+8
-8
@@ -82,9 +82,9 @@ public class DefaultEurekaClientHttpRequestFactorySupplier implements EurekaClie
|
||||
private HttpClientConnectionManager buildConnectionManager(SSLContext sslContext, HostnameVerifier hostnameVerifier,
|
||||
RestTemplateTimeoutProperties restTemplateTimeoutProperties) {
|
||||
PoolingHttpClientConnectionManagerBuilder connectionManagerBuilder = PoolingHttpClientConnectionManagerBuilder
|
||||
.create();
|
||||
.create();
|
||||
SSLConnectionSocketFactoryBuilder sslConnectionSocketFactoryBuilder = SSLConnectionSocketFactoryBuilder
|
||||
.create();
|
||||
.create();
|
||||
if (sslContext != null) {
|
||||
sslConnectionSocketFactoryBuilder.setSslContext(sslContext);
|
||||
}
|
||||
@@ -94,18 +94,18 @@ public class DefaultEurekaClientHttpRequestFactorySupplier implements EurekaClie
|
||||
connectionManagerBuilder.setSSLSocketFactory(sslConnectionSocketFactoryBuilder.build());
|
||||
if (restTemplateTimeoutProperties != null) {
|
||||
connectionManagerBuilder.setDefaultSocketConfig(SocketConfig.custom()
|
||||
.setSoTimeout(Timeout.of(restTemplateTimeoutProperties.getSocketTimeout(), TimeUnit.MILLISECONDS))
|
||||
.build());
|
||||
.setSoTimeout(Timeout.of(restTemplateTimeoutProperties.getSocketTimeout(), TimeUnit.MILLISECONDS))
|
||||
.build());
|
||||
}
|
||||
return connectionManagerBuilder.build();
|
||||
}
|
||||
|
||||
private RequestConfig buildRequestConfig() {
|
||||
return RequestConfig.custom()
|
||||
.setConnectTimeout(Timeout.of(restTemplateTimeoutProperties.getConnectTimeout(), TimeUnit.MILLISECONDS))
|
||||
.setConnectionRequestTimeout(
|
||||
Timeout.of(restTemplateTimeoutProperties.getConnectRequestTimeout(), TimeUnit.MILLISECONDS))
|
||||
.build();
|
||||
.setConnectTimeout(Timeout.of(restTemplateTimeoutProperties.getConnectTimeout(), TimeUnit.MILLISECONDS))
|
||||
.setConnectionRequestTimeout(
|
||||
Timeout.of(restTemplateTimeoutProperties.getConnectRequestTimeout(), TimeUnit.MILLISECONDS))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -16,18 +16,32 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.http;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
|
||||
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
* @author Armin Krezovic
|
||||
*/
|
||||
public class RestTemplateDiscoveryClientOptionalArgs extends AbstractDiscoveryClientOptionalArgs<Void> {
|
||||
|
||||
protected final EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier;
|
||||
|
||||
protected final Supplier<RestTemplateBuilder> restTemplateBuilderSupplier;
|
||||
|
||||
public RestTemplateDiscoveryClientOptionalArgs(
|
||||
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) {
|
||||
this(eurekaClientHttpRequestFactorySupplier, RestTemplateBuilder::new);
|
||||
}
|
||||
|
||||
public RestTemplateDiscoveryClientOptionalArgs(
|
||||
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier,
|
||||
Supplier<RestTemplateBuilder> restTemplateBuilderSupplier) {
|
||||
this.eurekaClientHttpRequestFactorySupplier = eurekaClientHttpRequestFactorySupplier;
|
||||
this.restTemplateBuilderSupplier = restTemplateBuilderSupplier;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+58
-30
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.http;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -38,11 +39,13 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import static com.netflix.discovery.shared.transport.EurekaHttpResponse.anEurekaHttpResponse;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
* @author Václav Plic
|
||||
*/
|
||||
public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
@@ -68,13 +71,16 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Void> register(InstanceInfo info) {
|
||||
String urlPath = serviceUrl + "apps/" + info.getAppName();
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(serviceUrl)
|
||||
.path("apps/{appName}")
|
||||
.buildAndExpand(info.getAppName())
|
||||
.toUri();
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(HttpHeaders.ACCEPT_ENCODING, "gzip");
|
||||
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
|
||||
|
||||
ResponseEntity<Void> response = restTemplate.exchange(urlPath, HttpMethod.POST, new HttpEntity<>(info, headers),
|
||||
ResponseEntity<Void> response = restTemplate.exchange(uri, HttpMethod.POST, new HttpEntity<>(info, headers),
|
||||
Void.class);
|
||||
|
||||
return anEurekaHttpResponse(response.getStatusCode().value()).headers(headersOf(response)).build();
|
||||
@@ -82,9 +88,12 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Void> cancel(String appName, String id) {
|
||||
String urlPath = serviceUrl + "apps/" + appName + '/' + id;
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(serviceUrl)
|
||||
.path("apps/{appName}/{id}")
|
||||
.buildAndExpand(appName, id)
|
||||
.toUri();
|
||||
|
||||
ResponseEntity<Void> response = restTemplate.exchange(urlPath, HttpMethod.DELETE, null, Void.class);
|
||||
ResponseEntity<Void> response = restTemplate.exchange(uri, HttpMethod.DELETE, null, Void.class);
|
||||
|
||||
return anEurekaHttpResponse(response.getStatusCode().value()).headers(headersOf(response)).build();
|
||||
}
|
||||
@@ -92,15 +101,22 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
@Override
|
||||
public EurekaHttpResponse<InstanceInfo> sendHeartBeat(String appName, String id, InstanceInfo info,
|
||||
InstanceStatus overriddenStatus) {
|
||||
String urlPath = serviceUrl + "apps/" + appName + '/' + id + "?status=" + info.getStatus().toString()
|
||||
+ "&lastDirtyTimestamp=" + info.getLastDirtyTimestamp().toString()
|
||||
+ (overriddenStatus != null ? "&overriddenstatus=" + overriddenStatus.name() : "");
|
||||
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(serviceUrl)
|
||||
.path("apps/{appName}/{id}")
|
||||
.queryParam("status", info.getStatus().toString())
|
||||
.queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString());
|
||||
|
||||
ResponseEntity<InstanceInfo> response = restTemplate.exchange(urlPath, HttpMethod.PUT, null,
|
||||
InstanceInfo.class);
|
||||
if (overriddenStatus != null) {
|
||||
uriBuilder = uriBuilder.queryParam("overriddenstatus", overriddenStatus.name());
|
||||
}
|
||||
|
||||
URI uri = uriBuilder.buildAndExpand(appName, id).toUri();
|
||||
|
||||
ResponseEntity<InstanceInfo> response = restTemplate.exchange(uri, HttpMethod.PUT, null, InstanceInfo.class);
|
||||
|
||||
EurekaHttpResponseBuilder<InstanceInfo> eurekaResponseBuilder = anEurekaHttpResponse(
|
||||
response.getStatusCode().value(), InstanceInfo.class).headers(headersOf(response));
|
||||
response.getStatusCode().value(), InstanceInfo.class)
|
||||
.headers(headersOf(response));
|
||||
|
||||
if (response.hasBody()) {
|
||||
eurekaResponseBuilder.entity(response.getBody());
|
||||
@@ -112,20 +128,27 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
@Override
|
||||
public EurekaHttpResponse<Void> statusUpdate(String appName, String id, InstanceStatus newStatus,
|
||||
InstanceInfo info) {
|
||||
String urlPath = serviceUrl + "apps/" + appName + '/' + id + "/status?value=" + newStatus.name()
|
||||
+ "&lastDirtyTimestamp=" + info.getLastDirtyTimestamp().toString();
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(serviceUrl)
|
||||
.path("apps/{appName}/{id}/status")
|
||||
.queryParam("value", newStatus.name())
|
||||
.queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString())
|
||||
.buildAndExpand(appName, id)
|
||||
.toUri();
|
||||
|
||||
ResponseEntity<Void> response = restTemplate.exchange(urlPath, HttpMethod.PUT, null, Void.class);
|
||||
ResponseEntity<Void> response = restTemplate.exchange(uri, HttpMethod.PUT, null, Void.class);
|
||||
|
||||
return anEurekaHttpResponse(response.getStatusCode().value()).headers(headersOf(response)).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Void> deleteStatusOverride(String appName, String id, InstanceInfo info) {
|
||||
String urlPath = serviceUrl + "apps/" + appName + '/' + id + "/status?lastDirtyTimestamp="
|
||||
+ info.getLastDirtyTimestamp().toString();
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(serviceUrl)
|
||||
.path("apps/{appName}/{id}/status")
|
||||
.queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString())
|
||||
.buildAndExpand(appName, id)
|
||||
.toUri();
|
||||
|
||||
ResponseEntity<Void> response = restTemplate.exchange(urlPath, HttpMethod.DELETE, null, Void.class);
|
||||
ResponseEntity<Void> response = restTemplate.exchange(uri, HttpMethod.DELETE, null, Void.class);
|
||||
|
||||
return anEurekaHttpResponse(response.getStatusCode().value()).headers(headersOf(response)).build();
|
||||
}
|
||||
@@ -136,18 +159,22 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
}
|
||||
|
||||
private EurekaHttpResponse<Applications> getApplicationsInternal(String urlPath, String[] regions) {
|
||||
String url = serviceUrl + urlPath;
|
||||
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(serviceUrl).path(urlPath);
|
||||
|
||||
if (regions != null && regions.length > 0) {
|
||||
url = url + (urlPath.contains("?") ? "&" : "?") + "regions=" + StringUtil.join(regions);
|
||||
uriBuilder = uriBuilder.queryParam("regions", StringUtil.join(regions));
|
||||
}
|
||||
|
||||
ResponseEntity<EurekaApplications> response = restTemplate.exchange(url, HttpMethod.GET, null,
|
||||
URI uri = uriBuilder.build().toUri();
|
||||
|
||||
ResponseEntity<EurekaApplications> response = restTemplate.exchange(uri, HttpMethod.GET, null,
|
||||
EurekaApplications.class);
|
||||
|
||||
return anEurekaHttpResponse(response.getStatusCode().value(),
|
||||
response.getStatusCode().value() == HttpStatus.OK.value() && response.hasBody()
|
||||
? (Applications) response.getBody() : null).headers(headersOf(response)).build();
|
||||
? (Applications) response.getBody() : null)
|
||||
.headers(headersOf(response))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -167,9 +194,9 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Application> getApplication(String appName) {
|
||||
String urlPath = serviceUrl + "apps/" + appName;
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(serviceUrl).path("apps/{appName}").buildAndExpand(appName).toUri();
|
||||
|
||||
ResponseEntity<Application> response = restTemplate.exchange(urlPath, HttpMethod.GET, null, Application.class);
|
||||
ResponseEntity<Application> response = restTemplate.exchange(uri, HttpMethod.GET, null, Application.class);
|
||||
|
||||
Application application = response.getStatusCode().value() == HttpStatus.OK.value() && response.hasBody()
|
||||
? response.getBody() : null;
|
||||
@@ -179,23 +206,24 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<InstanceInfo> getInstance(String appName, String id) {
|
||||
return getInstanceInternal("apps/" + appName + '/' + id);
|
||||
return getInstanceInternal("apps", appName, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<InstanceInfo> getInstance(String id) {
|
||||
return getInstanceInternal("instances/" + id);
|
||||
return getInstanceInternal("instances", id);
|
||||
}
|
||||
|
||||
private EurekaHttpResponse<InstanceInfo> getInstanceInternal(String urlPath) {
|
||||
urlPath = serviceUrl + urlPath;
|
||||
private EurekaHttpResponse<InstanceInfo> getInstanceInternal(String... pathSegments) {
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(serviceUrl).pathSegment(pathSegments).build().toUri();
|
||||
|
||||
ResponseEntity<InstanceInfo> response = restTemplate.exchange(urlPath, HttpMethod.GET, null,
|
||||
InstanceInfo.class);
|
||||
ResponseEntity<InstanceInfo> response = restTemplate.exchange(uri, HttpMethod.GET, null, InstanceInfo.class);
|
||||
|
||||
return anEurekaHttpResponse(response.getStatusCode().value(),
|
||||
response.getStatusCode().value() == HttpStatus.OK.value() && response.hasBody() ? response.getBody()
|
||||
: null).headers(headersOf(response)).build();
|
||||
: null)
|
||||
.headers(headersOf(response))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -29,6 +29,7 @@ import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
* @author Armin Krezovic
|
||||
*/
|
||||
public class RestTemplateTransportClientFactories implements TransportClientFactories<Void> {
|
||||
|
||||
@@ -42,7 +43,7 @@ public class RestTemplateTransportClientFactories implements TransportClientFact
|
||||
public TransportClientFactory newTransportClientFactory(EurekaClientConfig clientConfig,
|
||||
Collection<Void> additionalFilters, InstanceInfo myInstanceInfo) {
|
||||
return new RestTemplateTransportClientFactory(this.args.getSSLContext(), this.args.getHostnameVerifier(),
|
||||
this.args.eurekaClientHttpRequestFactorySupplier);
|
||||
this.args.eurekaClientHttpRequestFactorySupplier, this.args.restTemplateBuilderSupplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,7 +51,7 @@ public class RestTemplateTransportClientFactories implements TransportClientFact
|
||||
final Collection<Void> additionalFilters, final InstanceInfo myInstanceInfo,
|
||||
final Optional<SSLContext> sslContext, final Optional<HostnameVerifier> hostnameVerifier) {
|
||||
return new RestTemplateTransportClientFactory(this.args.getSSLContext(), this.args.getHostnameVerifier(),
|
||||
this.args.eurekaClientHttpRequestFactorySupplier);
|
||||
this.args.eurekaClientHttpRequestFactorySupplier, this.args.restTemplateBuilderSupplier);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+39
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -21,6 +21,7 @@ import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLContext;
|
||||
@@ -44,6 +45,7 @@ import com.netflix.discovery.shared.resolver.EurekaEndpoint;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpClient;
|
||||
import com.netflix.discovery.shared.transport.TransportClientFactory;
|
||||
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.cloud.configuration.SSLContextFactory;
|
||||
import org.springframework.cloud.configuration.TlsProperties;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -63,6 +65,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
* deserialization.
|
||||
*
|
||||
* @author Daniel Lavoie
|
||||
* @author Armin Krezovic
|
||||
*/
|
||||
public class RestTemplateTransportClientFactory implements TransportClientFactory {
|
||||
|
||||
@@ -72,11 +75,20 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
|
||||
private final EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier;
|
||||
|
||||
private final Supplier<RestTemplateBuilder> restTemplateBuilderSupplier;
|
||||
|
||||
public RestTemplateTransportClientFactory(TlsProperties tlsProperties,
|
||||
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) {
|
||||
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier,
|
||||
Supplier<RestTemplateBuilder> restTemplateBuilderSupplier) {
|
||||
this.sslContext = context(tlsProperties);
|
||||
this.hostnameVerifier = Optional.empty();
|
||||
this.eurekaClientHttpRequestFactorySupplier = eurekaClientHttpRequestFactorySupplier;
|
||||
this.restTemplateBuilderSupplier = restTemplateBuilderSupplier;
|
||||
}
|
||||
|
||||
public RestTemplateTransportClientFactory(TlsProperties tlsProperties,
|
||||
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) {
|
||||
this(tlsProperties, eurekaClientHttpRequestFactorySupplier, RestTemplateBuilder::new);
|
||||
}
|
||||
|
||||
private Optional<SSLContext> context(TlsProperties properties) {
|
||||
@@ -93,16 +105,23 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
|
||||
public RestTemplateTransportClientFactory(Optional<SSLContext> sslContext,
|
||||
Optional<HostnameVerifier> hostnameVerifier,
|
||||
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) {
|
||||
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier,
|
||||
Supplier<RestTemplateBuilder> restTemplateBuilderSupplier) {
|
||||
this.sslContext = sslContext;
|
||||
this.hostnameVerifier = hostnameVerifier;
|
||||
this.eurekaClientHttpRequestFactorySupplier = eurekaClientHttpRequestFactorySupplier;
|
||||
this.restTemplateBuilderSupplier = restTemplateBuilderSupplier;
|
||||
}
|
||||
|
||||
public RestTemplateTransportClientFactory(Optional<SSLContext> sslContext,
|
||||
Optional<HostnameVerifier> hostnameVerifier,
|
||||
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) {
|
||||
|
||||
this(sslContext, hostnameVerifier, eurekaClientHttpRequestFactorySupplier, RestTemplateBuilder::new);
|
||||
}
|
||||
|
||||
public RestTemplateTransportClientFactory() {
|
||||
this.sslContext = Optional.empty();
|
||||
this.hostnameVerifier = Optional.empty();
|
||||
this.eurekaClientHttpRequestFactorySupplier = new DefaultEurekaClientHttpRequestFactorySupplier();
|
||||
this(Optional.empty(), Optional.empty(), new DefaultEurekaClientHttpRequestFactorySupplier());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,8 +138,16 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
|
||||
private RestTemplate restTemplate(String serviceUrl) {
|
||||
ClientHttpRequestFactory requestFactory = this.eurekaClientHttpRequestFactorySupplier
|
||||
.get(this.sslContext.orElse(null), this.hostnameVerifier.orElse(null));
|
||||
RestTemplate restTemplate = new RestTemplate(requestFactory);
|
||||
.get(this.sslContext.orElse(null), this.hostnameVerifier.orElse(null));
|
||||
|
||||
RestTemplate restTemplate;
|
||||
|
||||
if (restTemplateBuilderSupplier != null && restTemplateBuilderSupplier.get() != null) {
|
||||
restTemplate = restTemplateBuilderSupplier.get().requestFactory(() -> requestFactory).build();
|
||||
}
|
||||
else {
|
||||
restTemplate = new RestTemplate(requestFactory);
|
||||
}
|
||||
|
||||
try {
|
||||
URI serviceURI = new URI(serviceUrl);
|
||||
@@ -128,7 +155,7 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
String[] credentials = serviceURI.getUserInfo().split(":");
|
||||
if (credentials.length == 2) {
|
||||
restTemplate.getInterceptors()
|
||||
.add(new BasicAuthenticationInterceptor(credentials[0], credentials[1]));
|
||||
.add(new BasicAuthenticationInterceptor(credentials[0], credentials[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,11 +236,6 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
return response.getStatusCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRawStatusCode() throws IOException {
|
||||
return response.getRawStatusCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusText() throws IOException {
|
||||
return response.getStatusText();
|
||||
@@ -242,10 +264,10 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
@Override
|
||||
protected boolean hasError(HttpStatusCode statusCode) {
|
||||
/**
|
||||
* When the Eureka server restarts and a client tries to sent a heartbeat the
|
||||
* server will respond with a 404. By default RestTemplate will throw an
|
||||
* When the Eureka server restarts and a client tries to send a heartbeat the
|
||||
* server will respond with a 404. By default, RestTemplate will throw an
|
||||
* exception in this case. What we want is to return the 404 to the upstream
|
||||
* code so it will send another registration request to the server.
|
||||
* code, so it will send another registration request to the server.
|
||||
*/
|
||||
if (statusCode.is4xxClientError()) {
|
||||
return false;
|
||||
|
||||
+85
-49
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.netflix.eureka.http;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
|
||||
@@ -42,6 +43,7 @@ import static com.netflix.discovery.shared.transport.EurekaHttpResponse.anEureka
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
* @author Haytham Mohamed
|
||||
* @author Václav Plic
|
||||
*/
|
||||
public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
@@ -53,34 +55,48 @@ public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Void> register(InstanceInfo info) {
|
||||
return webClient.post().uri("apps/" + info.getAppName()).body(BodyInserters.fromValue(info))
|
||||
.header(HttpHeaders.ACCEPT_ENCODING, "gzip")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity().map(this::eurekaHttpResponse)
|
||||
.block();
|
||||
return webClient.post()
|
||||
.uri(uriBuilder -> uriBuilder.path("apps/{appName}").build(info.getAppName()))
|
||||
.body(BodyInserters.fromValue(info))
|
||||
.header(HttpHeaders.ACCEPT_ENCODING, "gzip")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError)
|
||||
.toBodilessEntity()
|
||||
.map(this::eurekaHttpResponse)
|
||||
.block();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Void> cancel(String appName, String id) {
|
||||
return webClient.delete().uri("apps/" + appName + '/' + id).retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity().map(this::eurekaHttpResponse)
|
||||
.block();
|
||||
return webClient.delete()
|
||||
.uri(uriBuilder -> uriBuilder.path("apps/{appName}/{id}").build(appName, id))
|
||||
.retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError)
|
||||
.toBodilessEntity()
|
||||
.map(this::eurekaHttpResponse)
|
||||
.block();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<InstanceInfo> sendHeartBeat(String appName, String id, InstanceInfo info,
|
||||
InstanceStatus overriddenStatus) {
|
||||
String urlPath = "apps/" + appName + '/' + id + "?status=" + info.getStatus().toString()
|
||||
+ "&lastDirtyTimestamp=" + info.getLastDirtyTimestamp().toString()
|
||||
+ (overriddenStatus != null ? "&overriddenstatus=" + overriddenStatus.name() : "");
|
||||
|
||||
ResponseEntity<InstanceInfo> response = webClient.put().uri(urlPath)
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError).toEntity(InstanceInfo.class).block();
|
||||
ResponseEntity<InstanceInfo> response = webClient.put()
|
||||
.uri(uriBuilder -> uriBuilder.path("apps/{appName}/{id}")
|
||||
.queryParam("status", info.getStatus().toString())
|
||||
.queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString())
|
||||
.build(appName, id))
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
||||
.retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError)
|
||||
.toEntity(InstanceInfo.class)
|
||||
.block();
|
||||
|
||||
EurekaHttpResponseBuilder<InstanceInfo> builder = anEurekaHttpResponse(statusCodeValueOf(response),
|
||||
InstanceInfo.class).headers(headersOf(response));
|
||||
InstanceInfo.class)
|
||||
.headers(headersOf(response));
|
||||
|
||||
InstanceInfo entity = response.getBody();
|
||||
|
||||
@@ -95,22 +111,31 @@ public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
@Override
|
||||
public EurekaHttpResponse<Void> statusUpdate(String appName, String id, InstanceStatus newStatus,
|
||||
InstanceInfo info) {
|
||||
String urlPath = "apps/" + appName + '/' + id + "/status?value=" + newStatus.name() + "&lastDirtyTimestamp="
|
||||
+ info.getLastDirtyTimestamp().toString();
|
||||
|
||||
return webClient.put().uri(urlPath).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.retrieve().onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity()
|
||||
.map(this::eurekaHttpResponse).block();
|
||||
return webClient.put()
|
||||
.uri(uriBuilder -> uriBuilder.path("apps/{appName}/{id}/status")
|
||||
.queryParam("value", newStatus.name())
|
||||
.queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString())
|
||||
.build(appName, id))
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError)
|
||||
.toBodilessEntity()
|
||||
.map(this::eurekaHttpResponse)
|
||||
.block();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Void> deleteStatusOverride(String appName, String id, InstanceInfo info) {
|
||||
String urlPath = "apps/" + appName + '/' + id + "/status?lastDirtyTimestamp="
|
||||
+ info.getLastDirtyTimestamp().toString();
|
||||
|
||||
return webClient.delete().uri(urlPath).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.retrieve().onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity()
|
||||
.map(this::eurekaHttpResponse).block();
|
||||
return webClient.delete()
|
||||
.uri(uriBuilder -> uriBuilder.path("apps/{appName}/{id}/status")
|
||||
.queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString())
|
||||
.build(appName, id))
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError)
|
||||
.toBodilessEntity()
|
||||
.map(this::eurekaHttpResponse)
|
||||
.block();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,23 +144,25 @@ public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
}
|
||||
|
||||
private EurekaHttpResponse<Applications> getApplicationsInternal(String urlPath, String[] regions) {
|
||||
String url = urlPath;
|
||||
Optional<String> regionsParam = (regions != null && regions.length > 0) ? Optional.of(StringUtil.join(regions))
|
||||
: Optional.empty();
|
||||
|
||||
if (regions != null && regions.length > 0) {
|
||||
url = url + (urlPath.contains("?") ? "&" : "?") + "regions=" + StringUtil.join(regions);
|
||||
}
|
||||
|
||||
ResponseEntity<Applications> response = webClient.get().uri(url)
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError).toEntity(Applications.class).block();
|
||||
ResponseEntity<Applications> response = webClient.get()
|
||||
.uri(uriBuilder -> uriBuilder.path(urlPath).queryParamIfPresent("regions", regionsParam).build())
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
||||
.retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError)
|
||||
.toEntity(Applications.class)
|
||||
.block();
|
||||
|
||||
int statusCode = statusCodeValueOf(response);
|
||||
|
||||
Applications body = response.getBody();
|
||||
|
||||
return anEurekaHttpResponse(statusCode, statusCode == HttpStatus.OK.value() && body != null ? body : null)
|
||||
.headers(headersOf(response)).build();
|
||||
.headers(headersOf(response))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -156,9 +183,13 @@ public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
@Override
|
||||
public EurekaHttpResponse<Application> getApplication(String appName) {
|
||||
|
||||
ResponseEntity<Application> response = webClient.get().uri("apps/" + appName)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError).toEntity(Application.class).block();
|
||||
ResponseEntity<Application> response = webClient.get()
|
||||
.uri(uriBuilder -> uriBuilder.path("apps/{appName}").build(appName))
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
||||
.retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError)
|
||||
.toEntity(Application.class)
|
||||
.block();
|
||||
|
||||
int statusCode = statusCodeValueOf(response);
|
||||
Application body = response.getBody();
|
||||
@@ -170,24 +201,29 @@ public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<InstanceInfo> getInstance(String appName, String id) {
|
||||
return getInstanceInternal("apps/" + appName + '/' + id);
|
||||
return getInstanceInternal("apps", appName, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<InstanceInfo> getInstance(String id) {
|
||||
return getInstanceInternal("instances/" + id);
|
||||
return getInstanceInternal("instances", id);
|
||||
}
|
||||
|
||||
private EurekaHttpResponse<InstanceInfo> getInstanceInternal(String urlPath) {
|
||||
ResponseEntity<InstanceInfo> response = webClient.get().uri(urlPath)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError).toEntity(InstanceInfo.class).block();
|
||||
private EurekaHttpResponse<InstanceInfo> getInstanceInternal(String... pathSegments) {
|
||||
ResponseEntity<InstanceInfo> response = webClient.get()
|
||||
.uri(uriBuilder -> uriBuilder.pathSegment(pathSegments).build())
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
||||
.retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError)
|
||||
.toEntity(InstanceInfo.class)
|
||||
.block();
|
||||
|
||||
int statusCode = statusCodeValueOf(response);
|
||||
InstanceInfo body = response.getBody();
|
||||
|
||||
return anEurekaHttpResponse(statusCode, statusCode == HttpStatus.OK.value() && body != null ? body : null)
|
||||
.headers(headersOf(response)).build();
|
||||
.headers(headersOf(response))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+10
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -50,6 +50,7 @@ import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFilterFunctions;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Provides the custom {@link WebClient.Builder} required by the
|
||||
@@ -58,6 +59,7 @@ import org.springframework.web.reactive.function.client.WebClient;
|
||||
*
|
||||
* @author Daniel Lavoie
|
||||
* @author Haytham Mohamed
|
||||
* @author Armin Krezovic
|
||||
*/
|
||||
public class WebClientTransportClientFactory implements TransportClientFactory {
|
||||
|
||||
@@ -78,14 +80,14 @@ public class WebClientTransportClientFactory implements TransportClientFactory {
|
||||
}
|
||||
|
||||
private WebClient.Builder setUrl(WebClient.Builder builder, String serviceUrl) {
|
||||
String url = serviceUrl;
|
||||
String url = UriComponentsBuilder.fromUriString(serviceUrl).userInfo(null).toUriString();
|
||||
|
||||
try {
|
||||
URI serviceURI = new URI(serviceUrl);
|
||||
if (serviceURI.getUserInfo() != null) {
|
||||
String[] credentials = serviceURI.getUserInfo().split(":");
|
||||
if (credentials.length == 2) {
|
||||
builder.filter(ExchangeFilterFunctions.basicAuthentication(credentials[0], credentials[1]));
|
||||
url = serviceUrl.replace(credentials[0] + ":" + credentials[1] + "@", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -153,9 +155,11 @@ public class WebClientTransportClientFactory implements TransportClientFactory {
|
||||
return Mono.just(newResponse);
|
||||
}
|
||||
if (clientResponse.statusCode().equals(HttpStatus.NOT_FOUND)) {
|
||||
ClientResponse newResponse = clientResponse.mutate().statusCode(clientResponse.statusCode())
|
||||
// ignore body on 404 for heartbeat, see gh-4145
|
||||
.body(Flux.empty()).build();
|
||||
ClientResponse newResponse = clientResponse.mutate()
|
||||
.statusCode(clientResponse.statusCode())
|
||||
// ignore body on 404 for heartbeat, see gh-4145
|
||||
.body(Flux.empty())
|
||||
.build();
|
||||
return Mono.just(newResponse);
|
||||
}
|
||||
return Mono.just(clientResponse);
|
||||
|
||||
+5
-4
@@ -52,15 +52,16 @@ public class EurekaReactiveDiscoveryClient implements ReactiveDiscoveryClient {
|
||||
@Override
|
||||
public Flux<ServiceInstance> getInstances(String serviceId) {
|
||||
return Flux.defer(() -> Flux.fromIterable(eurekaClient.getInstancesByVipAddress(serviceId, false)))
|
||||
.map(EurekaServiceInstance::new);
|
||||
.map(EurekaServiceInstance::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<String> getServices() {
|
||||
return Flux.defer(() -> Mono.justOrEmpty(eurekaClient.getApplications()))
|
||||
.flatMapIterable(Applications::getRegisteredApplications)
|
||||
.filter(application -> !application.getInstances().isEmpty()).map(Application::getName)
|
||||
.map(String::toLowerCase);
|
||||
.flatMapIterable(Applications::getRegisteredApplications)
|
||||
.filter(application -> !application.getInstances().isEmpty())
|
||||
.map(Application::getName)
|
||||
.map(String::toLowerCase);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+32
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -17,25 +17,54 @@
|
||||
package org.springframework.cloud.netflix.eureka.serviceregistry;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
|
||||
|
||||
import static com.netflix.appinfo.InstanceInfo.InstanceStatus.UNKNOWN;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Robert Bleyl
|
||||
*/
|
||||
public class EurekaServiceRegistry implements ServiceRegistry<EurekaRegistration> {
|
||||
|
||||
private static final Log log = LogFactory.getLog(EurekaServiceRegistry.class);
|
||||
|
||||
private EurekaInstanceConfigBean eurekaInstanceConfigBean;
|
||||
|
||||
public EurekaServiceRegistry() {
|
||||
|
||||
}
|
||||
|
||||
public EurekaServiceRegistry(EurekaInstanceConfigBean eurekaInstanceConfigBean) {
|
||||
this.eurekaInstanceConfigBean = eurekaInstanceConfigBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(EurekaRegistration reg) {
|
||||
maybeInitializeClient(reg);
|
||||
if (eurekaInstanceConfigBean != null && eurekaInstanceConfigBean.isAsyncClientInitialization()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Initializing client asynchronously...");
|
||||
}
|
||||
|
||||
ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
executorService.submit(() -> {
|
||||
maybeInitializeClient(reg);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Asynchronous client initialization done.");
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
maybeInitializeClient(reg);
|
||||
}
|
||||
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Registering application " + reg.getApplicationInfoManager().getInfo().getAppName()
|
||||
@@ -45,7 +74,7 @@ public class EurekaServiceRegistry implements ServiceRegistry<EurekaRegistration
|
||||
reg.getApplicationInfoManager().setInstanceStatus(reg.getInstanceConfig().getInitialStatus());
|
||||
|
||||
reg.getHealthCheckHandler()
|
||||
.ifAvailable(healthCheckHandler -> reg.getEurekaClient().registerHealthCheck(healthCheckHandler));
|
||||
.ifAvailable(healthCheckHandler -> reg.getEurekaClient().registerHealthCheck(healthCheckHandler));
|
||||
}
|
||||
|
||||
private void maybeInitializeClient(EurekaRegistration reg) {
|
||||
|
||||
+6
@@ -18,6 +18,12 @@
|
||||
"description": "Enables the use of WebClient for Eureka HTTP Client.",
|
||||
"type": "java.lang.Boolean"
|
||||
},
|
||||
{
|
||||
"defaultValue": true,
|
||||
"name": "eureka.client.jersey.enabled",
|
||||
"description": "Enables the use of JerseyClient for Eureka HTTP Client.",
|
||||
"type": "java.lang.Boolean"
|
||||
},
|
||||
{
|
||||
"defaultValue": 1,
|
||||
"name": "eureka.instance.metadata-map.weight",
|
||||
|
||||
+17
-13
@@ -37,20 +37,23 @@ class ConditionalOnRefreshScopeTests {
|
||||
@Test
|
||||
void refreshScopeIncluded() {
|
||||
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(RefreshAutoConfiguration.class))
|
||||
.withUserConfiguration(Beans.class).run(c -> {
|
||||
assertThat(c).hasSingleBean(org.springframework.cloud.context.scope.refresh.RefreshScope.class);
|
||||
assertThat(c.getBean("foo")).isEqualTo("foo");
|
||||
});
|
||||
.withUserConfiguration(Beans.class)
|
||||
.run(c -> {
|
||||
assertThat(c).hasSingleBean(org.springframework.cloud.context.scope.refresh.RefreshScope.class);
|
||||
assertThat(c.getBean("foo")).isEqualTo("foo");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void refreshScopeIncludedAndPropertyDisabled() {
|
||||
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(RefreshAutoConfiguration.class))
|
||||
.withPropertyValues("eureka.client.refresh.enable=false").withUserConfiguration(Beans.class).run(c -> {
|
||||
assertThat(c).hasSingleBean(org.springframework.cloud.context.scope.refresh.RefreshScope.class);
|
||||
assertThat(c).doesNotHaveBean("foo");
|
||||
assertThat(c.getBean("bar")).isEqualTo("bar");
|
||||
});
|
||||
.withPropertyValues("eureka.client.refresh.enable=false")
|
||||
.withUserConfiguration(Beans.class)
|
||||
.run(c -> {
|
||||
assertThat(c).hasSingleBean(org.springframework.cloud.context.scope.refresh.RefreshScope.class);
|
||||
assertThat(c).doesNotHaveBean("foo");
|
||||
assertThat(c.getBean("bar")).isEqualTo("bar");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -61,10 +64,11 @@ class ConditionalOnRefreshScopeTests {
|
||||
});
|
||||
|
||||
new ApplicationContextRunner().withUserConfiguration(Beans.class)
|
||||
.withPropertyValues("eureka.client.refresh.enable=false").run(c -> {
|
||||
assertThat(c).doesNotHaveBean("foo");
|
||||
assertThat(c.getBean("bar")).isEqualTo("bar");
|
||||
});
|
||||
.withPropertyValues("eureka.client.refresh.enable=false")
|
||||
.run(c -> {
|
||||
assertThat(c).doesNotHaveBean("foo");
|
||||
assertThat(c.getBean("bar")).isEqualTo("bar");
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
||||
+131
-87
@@ -118,7 +118,7 @@ class EurekaClientAutoConfigurationTests {
|
||||
@Test
|
||||
void shouldSetManagementAndJmxPortsInMetadataMap() {
|
||||
TestPropertyValues.of("management.server.port=9999", "com.sun.management.jmxremote.port=6789")
|
||||
.applyTo(this.context);
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
@@ -128,8 +128,10 @@ class EurekaClientAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
void shouldNotResetManagementAndJmxPortsInMetadataMap() {
|
||||
TestPropertyValues.of("management.server.port=9999", "eureka.instance.metadata-map.jmx.port=9898",
|
||||
"eureka.instance.metadata-map.management.port=7878").applyTo(this.context);
|
||||
TestPropertyValues
|
||||
.of("management.server.port=9999", "eureka.instance.metadata-map.jmx.port=9898",
|
||||
"eureka.instance.metadata-map.management.port=7878")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
@@ -178,112 +180,128 @@ class EurekaClientAutoConfigurationTests {
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getStatusPageUrl().contains("9999")).as("Wrong status page: " + instance.getStatusPageUrl())
|
||||
.isTrue();
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrlPathAndManagementPort() {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=9999",
|
||||
"eureka.instance.statusPageUrlPath=/myStatusPage").applyTo(this.context);
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "management.server.port=9999", "eureka.instance.statusPageUrlPath=/myStatusPage")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getStatusPageUrl().contains("/myStatusPage"))
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl()).isTrue();
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void healthCheckUrlPathAndManagementPort() {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=9999",
|
||||
"eureka.instance.healthCheckUrlPath=/myHealthCheck").applyTo(this.context);
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "management.server.port=9999", "eureka.instance.healthCheckUrlPath=/myHealthCheck")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getHealthCheckUrl().contains("/myHealthCheck"))
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl()).isTrue();
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrl_and_healthCheckUrl_do_not_contain_server_context_path() {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=9999", "server.contextPath=/service")
|
||||
.applyTo(this.context);
|
||||
.applyTo(this.context);
|
||||
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getStatusPageUrl().endsWith(":9999/actuator/info"))
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl()).isTrue();
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl())
|
||||
.isTrue();
|
||||
assertThat(instance.getHealthCheckUrl().endsWith(":9999/actuator/health"))
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl()).isTrue();
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrl_and_healthCheckUrl_contain_management_context_path() {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.servlet.context-path=/management")
|
||||
.applyTo(this.context);
|
||||
.applyTo(this.context);
|
||||
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getStatusPageUrl().endsWith(":8989/management/actuator/info"))
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl()).isTrue();
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl())
|
||||
.isTrue();
|
||||
assertThat(instance.getHealthCheckUrl().endsWith(":8989/management/actuator/health"))
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl()).isTrue();
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrl_and_healthCheckUrl_contain_management_context_path_random_port() {
|
||||
TestPropertyValues.of("server.port=0", "management.server.servlet.context-path=/management")
|
||||
.applyTo(this.context);
|
||||
.applyTo(this.context);
|
||||
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getStatusPageUrlPath().equals("/management/actuator/info"))
|
||||
.as("Wrong status page: " + instance.getStatusPageUrlPath()).isTrue();
|
||||
.as("Wrong status page: " + instance.getStatusPageUrlPath())
|
||||
.isTrue();
|
||||
assertThat(instance.getHealthCheckUrlPath().equals("/management/actuator/health"))
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrlPath()).isTrue();
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrlPath())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrlPathAndManagementPortAndContextPath() {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=9999",
|
||||
"management.server.servlet.context-path=/manage", "eureka.instance.status-page-url-path=/myStatusPage")
|
||||
.applyTo(this.context);
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "management.server.port=9999", "management.server.servlet.context-path=/manage",
|
||||
"eureka.instance.status-page-url-path=/myStatusPage")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getStatusPageUrl().endsWith(":9999/manage/myStatusPage"))
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl()).isTrue();
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void healthCheckUrlPathAndManagementPortAndContextPath() {
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "management.server.port=9999", "management.server.servlet.context-path=/manage",
|
||||
"eureka.instance.health-check-url-path=/myHealthCheck")
|
||||
.applyTo(this.context);
|
||||
.of("server.port=8989", "management.server.port=9999", "management.server.servlet.context-path=/manage",
|
||||
"eureka.instance.health-check-url-path=/myHealthCheck")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getHealthCheckUrl().endsWith(":9999/manage/myHealthCheck"))
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl()).isTrue();
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrlPathAndManagementPortAndContextPathKebobCase() {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=9999",
|
||||
"management.server.servlet.context-path=/manage", "eureka.instance.status-page-url-path=/myStatusPage")
|
||||
.applyTo(this.context);
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "management.server.port=9999", "management.server.servlet.context-path=/manage",
|
||||
"eureka.instance.status-page-url-path=/myStatusPage")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getStatusPageUrl().endsWith(":9999/manage/myStatusPage"))
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl()).isTrue();
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void healthCheckUrlPathAndManagementPortAndContextPathKebobCase() {
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "management.server.port=9999", "management.server.servlet.context-path=/manage",
|
||||
"eureka.instance.health-check-url-path=/myHealthCheck")
|
||||
.applyTo(this.context);
|
||||
.of("server.port=8989", "management.server.port=9999", "management.server.servlet.context-path=/manage",
|
||||
"eureka.instance.health-check-url-path=/myHealthCheck")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getHealthCheckUrl().endsWith(":9999/manage/myHealthCheck"))
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl()).isTrue();
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -293,9 +311,11 @@ class EurekaClientAutoConfigurationTests {
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getStatusPageUrl().endsWith(":8989/management/actuator/info"))
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl()).isTrue();
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl())
|
||||
.isTrue();
|
||||
assertThat(instance.getHealthCheckUrl().endsWith(":8989/management/actuator/health"))
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl()).isTrue();
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -305,111 +325,132 @@ class EurekaClientAutoConfigurationTests {
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getStatusPageUrlPath().equals("/management/actuator/info"))
|
||||
.as("Wrong status page: " + instance.getStatusPageUrlPath()).isTrue();
|
||||
.as("Wrong status page: " + instance.getStatusPageUrlPath())
|
||||
.isTrue();
|
||||
assertThat(instance.getHealthCheckUrlPath().equals("/management/actuator/health"))
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrlPath()).isTrue();
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrlPath())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrlPathAndManagementPortAndBasePath() {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=9999", "management.server.base-path=/manage",
|
||||
"eureka.instance.status-page-url-path=/myStatusPage").applyTo(this.context);
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "management.server.port=9999", "management.server.base-path=/manage",
|
||||
"eureka.instance.status-page-url-path=/myStatusPage")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getStatusPageUrl().endsWith(":9999/manage/myStatusPage"))
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl()).isTrue();
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void healthCheckUrlPathAndManagementPortAndBasePath() {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=9999", "management.server.base-path=/manage",
|
||||
"eureka.instance.health-check-url-path=/myHealthCheck").applyTo(this.context);
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "management.server.port=9999", "management.server.base-path=/manage",
|
||||
"eureka.instance.health-check-url-path=/myHealthCheck")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getHealthCheckUrl().endsWith(":9999/manage/myHealthCheck"))
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl()).isTrue();
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrlPathAndManagementPortAndBasePathKebobCase() {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=9999", "management.server.base-path=/manage",
|
||||
"eureka.instance.status-page-url-path=/myStatusPage").applyTo(this.context);
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "management.server.port=9999", "management.server.base-path=/manage",
|
||||
"eureka.instance.status-page-url-path=/myStatusPage")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getStatusPageUrl().endsWith(":9999/manage/myStatusPage"))
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl()).isTrue();
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void healthCheckUrlPathAndManagementPortAndBasePathKebobCase() {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=9999", "management.server.base-path=/manage",
|
||||
"eureka.instance.health-check-url-path=/myHealthCheck").applyTo(this.context);
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "management.server.port=9999", "management.server.base-path=/manage",
|
||||
"eureka.instance.health-check-url-path=/myHealthCheck")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getHealthCheckUrl().endsWith(":9999/manage/myHealthCheck"))
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl()).isTrue();
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void healthCheckUrlPathWithServerPortAndContextPathKebobCase() {
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "server.servlet.context-path=/servletContextPath",
|
||||
"eureka.instance.health-check-url-path=${server.servlet.context-path:}/myHealthCheck")
|
||||
.applyTo(this.context);
|
||||
.of("server.port=8989", "server.servlet.context-path=/servletContextPath",
|
||||
"eureka.instance.health-check-url-path=${server.servlet.context-path:}/myHealthCheck")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getHealthCheckUrl()).as("Wrong health check: " + instance.getHealthCheckUrl())
|
||||
.endsWith(":8989/servletContextPath/myHealthCheck");
|
||||
.endsWith(":8989/servletContextPath/myHealthCheck");
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrlPathAndManagementPortKabobCase() {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=9999",
|
||||
"eureka.instance.status-page-url-path=/myStatusPage").applyTo(this.context);
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "management.server.port=9999", "eureka.instance.status-page-url-path=/myStatusPage")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getStatusPageUrl().contains("/myStatusPage"))
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl()).isTrue();
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrlAndPreferIpAddress() {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=9999", "eureka.instance.hostname=foo",
|
||||
"eureka.instance.prefer-ip-address:true").applyTo(this.context);
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "management.server.port=9999", "eureka.instance.hostname=foo",
|
||||
"eureka.instance.prefer-ip-address:true")
|
||||
.applyTo(this.context);
|
||||
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
|
||||
assertThat(instance.getStatusPageUrl()).as("statusPageUrl is wrong")
|
||||
.isEqualTo("http://" + instance.getIpAddress() + ":9999/actuator/info");
|
||||
.isEqualTo("http://" + instance.getIpAddress() + ":9999/actuator/info");
|
||||
assertThat(instance.getHealthCheckUrl()).as("healthCheckUrl is wrong")
|
||||
.isEqualTo("http://" + instance.getIpAddress() + ":9999/actuator/health");
|
||||
.isEqualTo("http://" + instance.getIpAddress() + ":9999/actuator/health");
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageAndHealthCheckUrlsShouldSetUserDefinedIpAddress() {
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "management.server.port=9999", "eureka.instance.hostname=foo",
|
||||
"eureka.instance.ip-address:192.168.13.90", "eureka.instance.prefer-ip-address:true")
|
||||
.applyTo(this.context);
|
||||
.of("server.port=8989", "management.server.port=9999", "eureka.instance.hostname=foo",
|
||||
"eureka.instance.ip-address:192.168.13.90", "eureka.instance.prefer-ip-address:true")
|
||||
.applyTo(this.context);
|
||||
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
|
||||
assertThat(instance.getStatusPageUrl()).as("statusPageUrl is wrong")
|
||||
.isEqualTo("http://192.168.13.90:9999/actuator/info");
|
||||
.isEqualTo("http://192.168.13.90:9999/actuator/info");
|
||||
assertThat(instance.getHealthCheckUrl()).as("healthCheckUrl is wrong")
|
||||
.isEqualTo("http://192.168.13.90:9999/actuator/health");
|
||||
.isEqualTo("http://192.168.13.90:9999/actuator/health");
|
||||
}
|
||||
|
||||
@Test
|
||||
void healthCheckUrlPathAndManagementPortKabobCase() {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=9999",
|
||||
"eureka.instance.health-check-url-path=/myHealthCheck").applyTo(this.context);
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "management.server.port=9999",
|
||||
"eureka.instance.health-check-url-path=/myHealthCheck")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getHealthCheckUrl().contains("/myHealthCheck"))
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl()).isTrue();
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -419,7 +460,8 @@ class EurekaClientAutoConfigurationTests {
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getStatusPageUrl().contains("/myStatusPage"))
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl()).isTrue();
|
||||
.as("Wrong status page: " + instance.getStatusPageUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -429,35 +471,36 @@ class EurekaClientAutoConfigurationTests {
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getHealthCheckUrl().contains("/myHealthCheck"))
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl()).isTrue();
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void hostname() {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=9999", "eureka.instance.hostname=foo")
|
||||
.applyTo(this.context);
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getStatusPageUrl().contains("foo")).as("Wrong status page: " + instance.getStatusPageUrl())
|
||||
.isTrue();
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void refreshScopedBeans() {
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
assertThat(this.context.getBeanDefinition("eurekaClient").getBeanClassName())
|
||||
.startsWith(GenericScope.class.getName() + "$LockedScopedProxyFactoryBean");
|
||||
.startsWith(GenericScope.class.getName() + "$LockedScopedProxyFactoryBean");
|
||||
assertThat(this.context.getBeanDefinition("eurekaApplicationInfoManager").getBeanClassName())
|
||||
.startsWith(GenericScope.class.getName() + "$LockedScopedProxyFactoryBean");
|
||||
.startsWith(GenericScope.class.getName() + "$LockedScopedProxyFactoryBean");
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Test
|
||||
void shouldReregisterHealthCheckHandlerAfterRefresh() throws Exception {
|
||||
TestPropertyValues
|
||||
.of("eureka.client.healthcheck.enabled=true", "spring.cloud.config.import-check.enabled=false",
|
||||
"spring.cloud.refresh.additionalPropertySourcesToRetain=test")
|
||||
.applyTo(this.context);
|
||||
.of("eureka.client.healthcheck.enabled=true", "spring.cloud.config.import-check.enabled=false",
|
||||
"spring.cloud.refresh.additionalPropertySourcesToRetain=test")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class, AutoServiceRegistrationConfiguration.class);
|
||||
|
||||
EurekaClient oldEurekaClient = getLazyInitEurekaClient();
|
||||
@@ -597,13 +640,14 @@ class EurekaClientAutoConfigurationTests {
|
||||
@Test
|
||||
void shouldNotHaveDiscoveryClientWhenBlockingDiscoveryDisabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(UtilAutoConfiguration.class,
|
||||
DiscoveryClientOptionalArgsConfiguration.class, EurekaClientAutoConfiguration.class,
|
||||
EurekaDiscoveryClientConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.discovery.blocking.enabled=false").run(context -> {
|
||||
assertThat(context).doesNotHaveBean(DiscoveryClient.class);
|
||||
assertThat(context).doesNotHaveBean(DiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(UtilAutoConfiguration.class, DiscoveryClientOptionalArgsConfiguration.class,
|
||||
EurekaClientAutoConfiguration.class, EurekaDiscoveryClientConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.discovery.blocking.enabled=false")
|
||||
.run(context -> {
|
||||
assertThat(context).doesNotHaveBean(DiscoveryClient.class);
|
||||
assertThat(context).doesNotHaveBean(DiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@@ -641,7 +685,7 @@ class EurekaClientAutoConfigurationTests {
|
||||
|
||||
private EurekaClient getLazyInitEurekaClient() throws Exception {
|
||||
return (EurekaClient) ((Advised) this.context.getBean("eurekaClient", EurekaClient.class)).getTargetSource()
|
||||
.getTarget();
|
||||
.getTarget();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ class EurekaClientConfigBeanTests {
|
||||
this.context.register(PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBean(EurekaClientConfigBean.class).getServiceUrl().toString())
|
||||
.isEqualTo("{defaultZone=https://example.com}");
|
||||
.isEqualTo("{defaultZone=https://example.com}");
|
||||
assertThat(getEurekaServiceUrlsForDefaultZone()).isEqualTo("[https://example.com/]");
|
||||
}
|
||||
|
||||
|
||||
+9
-6
@@ -169,7 +169,8 @@ class EurekaInstanceConfigBeanTests {
|
||||
setupContext();
|
||||
EurekaInstanceConfigBean instance = getInstanceConfig();
|
||||
assertThat(getInstanceConfig().getHostname().equals(instance.getIpAddress()))
|
||||
.as("Wrong hostname: " + instance.getHostname()).isTrue();
|
||||
.as("Wrong hostname: " + instance.getHostname())
|
||||
.isTrue();
|
||||
|
||||
}
|
||||
|
||||
@@ -184,12 +185,14 @@ class EurekaInstanceConfigBeanTests {
|
||||
|
||||
@Test
|
||||
void testCustomVirtualHostName() {
|
||||
TestPropertyValues.of("spring.application.name:myapp", "eureka.instance.virtualHostName=myvirthost",
|
||||
"eureka.instance.secureVirtualHostName=mysecurevirthost").applyTo(this.context);
|
||||
TestPropertyValues
|
||||
.of("spring.application.name:myapp", "eureka.instance.virtualHostName=myvirthost",
|
||||
"eureka.instance.secureVirtualHostName=mysecurevirthost")
|
||||
.applyTo(this.context);
|
||||
setupContext();
|
||||
assertThat(getInstanceConfig().getVirtualHostName()).as("virtualHostName wrong").isEqualTo("myvirthost");
|
||||
assertThat(getInstanceConfig().getSecureVirtualHostName()).as("secureVirtualHostName wrong")
|
||||
.isEqualTo("mysecurevirthost");
|
||||
.isEqualTo("mysecurevirthost");
|
||||
|
||||
}
|
||||
|
||||
@@ -198,9 +201,9 @@ class EurekaInstanceConfigBeanTests {
|
||||
setupContext();
|
||||
assertThat(getInstanceConfig().getAppname()).as("default app name is wrong").isEqualTo("unknown");
|
||||
assertThat(getInstanceConfig().getVirtualHostName()).as("default virtual hostname is wrong")
|
||||
.isEqualTo("unknown");
|
||||
.isEqualTo("unknown");
|
||||
assertThat(getInstanceConfig().getSecureVirtualHostName()).as("default secure virtual hostname is wrong")
|
||||
.isEqualTo("unknown");
|
||||
.isEqualTo("unknown");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+5
-2
@@ -24,8 +24,11 @@ class EurekaServiceInstanceTests {
|
||||
|
||||
@Test
|
||||
void getSchemeReturnsNonNull() {
|
||||
InstanceInfo instanceInfo = InstanceInfo.Builder.newBuilder().setAppName("test").setHostName("myhost")
|
||||
.setPort(8080).build();
|
||||
InstanceInfo instanceInfo = InstanceInfo.Builder.newBuilder()
|
||||
.setAppName("test")
|
||||
.setHostName("myhost")
|
||||
.setPort(8080)
|
||||
.build();
|
||||
EurekaServiceInstance instance = new EurekaServiceInstance(instanceInfo);
|
||||
Assertions.assertThat(instance.getScheme()).isEqualTo("http");
|
||||
}
|
||||
|
||||
+6
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -31,6 +31,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
* @author Kaiyao Ke
|
||||
*/
|
||||
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = RefreshEurekaSampleApplication.class)
|
||||
class ConfigRefreshTests {
|
||||
@@ -42,6 +43,8 @@ class ConfigRefreshTests {
|
||||
// Mocked in RefreshEurekaSampleApplication
|
||||
private EurekaClient client;
|
||||
|
||||
private static boolean isFirstRun = true;
|
||||
|
||||
@Test
|
||||
// This test is used to verify that getApplications is called the correct number of
|
||||
// times when a refresh event is fired. The getApplications call in
|
||||
@@ -49,8 +52,9 @@ class ConfigRefreshTests {
|
||||
// ensures that the EurekaClient bean is recreated after a refresh event and that we
|
||||
// reregister the client with the server
|
||||
void verifyGetApplications() {
|
||||
if (publisher != null) {
|
||||
if (publisher != null && isFirstRun) {
|
||||
publisher.publishEvent(new RefreshScopeRefreshedEvent());
|
||||
isFirstRun = false;
|
||||
}
|
||||
verify(client, times(3)).getApplications();
|
||||
}
|
||||
|
||||
+19
-17
@@ -36,33 +36,35 @@ class EurekaClientConfigServerAutoConfigurationTests {
|
||||
@Test
|
||||
void offByDefault() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaClientConfigServerAutoConfiguration.class))
|
||||
.run(c -> assertThat(c.getBeanNamesForType(EurekaInstanceConfigBean.class).length).isEqualTo(0));
|
||||
.withConfiguration(AutoConfigurations.of(EurekaClientConfigServerAutoConfiguration.class))
|
||||
.run(c -> assertThat(c.getBeanNamesForType(EurekaInstanceConfigBean.class).length).isEqualTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void onWhenRequested() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaClientConfigServerAutoConfiguration.class,
|
||||
UtilAutoConfiguration.class, ConfigServerProperties.class, EurekaInstanceConfigBean.class))
|
||||
.withPropertyValues("spring.cloud.config.server.prefix=/config").run(c -> {
|
||||
assertThat(c.getBeanNamesForType(EurekaInstanceConfig.class).length).isEqualTo(1);
|
||||
EurekaInstanceConfig instance = c.getBean(EurekaInstanceConfig.class);
|
||||
assertThat(instance.getMetadataMap().get("configPath")).isEqualTo("/config");
|
||||
});
|
||||
.withConfiguration(AutoConfigurations.of(EurekaClientConfigServerAutoConfiguration.class,
|
||||
UtilAutoConfiguration.class, ConfigServerProperties.class, EurekaInstanceConfigBean.class))
|
||||
.withPropertyValues("spring.cloud.config.server.prefix=/config")
|
||||
.run(c -> {
|
||||
assertThat(c.getBeanNamesForType(EurekaInstanceConfig.class).length).isEqualTo(1);
|
||||
EurekaInstanceConfig instance = c.getBean(EurekaInstanceConfig.class);
|
||||
assertThat(instance.getMetadataMap().get("configPath")).isEqualTo("/config");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void notOverridingMetamapSettings() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaClientConfigServerAutoConfiguration.class,
|
||||
UtilAutoConfiguration.class, ConfigServerProperties.class, EurekaInstanceConfigBean.class))
|
||||
.withPropertyValues("spring.cloud.config.server.prefix=/config")
|
||||
.withPropertyValues("eureka.instance.metadataMap.configPath=/differentpath").run(c -> {
|
||||
assertThat(c.getBeanNamesForType(EurekaInstanceConfig.class).length).isEqualTo(1);
|
||||
EurekaInstanceConfig instance = c.getBean(EurekaInstanceConfig.class);
|
||||
assertThat(instance.getMetadataMap().get("configPath")).isEqualTo("/differentpath");
|
||||
});
|
||||
.withConfiguration(AutoConfigurations.of(EurekaClientConfigServerAutoConfiguration.class,
|
||||
UtilAutoConfiguration.class, ConfigServerProperties.class, EurekaInstanceConfigBean.class))
|
||||
.withPropertyValues("spring.cloud.config.server.prefix=/config")
|
||||
.withPropertyValues("eureka.instance.metadataMap.configPath=/differentpath")
|
||||
.run(c -> {
|
||||
assertThat(c.getBeanNamesForType(EurekaInstanceConfig.class).length).isEqualTo(1);
|
||||
EurekaInstanceConfig instance = c.getBean(EurekaInstanceConfig.class);
|
||||
assertThat(instance.getMetadataMap().get("configPath")).isEqualTo("/differentpath");
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+80
-43
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -51,6 +51,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Tang Xiong
|
||||
*/
|
||||
@RunWith(ModifiedClassPathRunner.class)
|
||||
@ClassPathExclusions("spring-webflux-*")
|
||||
@@ -62,96 +63,100 @@ public class EurekaConfigServerBootstrapConfigurationTests {
|
||||
@Test
|
||||
public void offByDefault() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void properBeansCreatedWhenDiscoveryEnabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true").run(this::assertEurekaBeansPresent);
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true")
|
||||
.run(this::assertEurekaBeansPresent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beansNotCreatedWhenDiscoveryNotEnabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=false")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=false")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beansNotCreatedWhenDiscoveryDisabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.disabled").run(this::assertEurekaBeansNotPresent);
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.disabled")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beansNotCreatedWhenEurekaClientEnabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("eureka.client.enabled=true").run(this::assertEurekaBeansNotPresent);
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("eureka.client.enabled=true")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beansNotCreatedWhenEurekaClientNotEnabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("eureka.client.enabled=false").run(this::assertEurekaBeansNotPresent);
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("eureka.client.enabled=false")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beansNotCreatedWhenEurekaClientDisabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("eureka.client.disabled").run(this::assertEurekaBeansNotPresent);
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("eureka.client.disabled")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void properBeansCreatedWhenDiscoveryEnabled_EurekaEnabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=true")
|
||||
.run(this::assertEurekaBeansPresent);
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=true")
|
||||
.run(this::assertEurekaBeansPresent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beansNotCreatedWhenDiscoveryEnabled_EurekaNotEnabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=false")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=false")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beansNotCreatedWhenDiscoveryNotEnabled_EurekaEnabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=false", "eureka.client.enabled=true")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=false", "eureka.client.enabled=true")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beansNotCreatedWhenDiscoveryNotEnabled_EurekaNotEnabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=false", "eureka.client.enabled=false")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=false", "eureka.client.enabled=false")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eurekaDnsConfigurationWorks() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=true",
|
||||
"eureka.instance.hostname=eurekaclient1",
|
||||
"eureka.client.use-dns-for-fetching-service-urls=true",
|
||||
"eureka.client.eureka-server-d-n-s-name=myeurekahost",
|
||||
"eureka.client.eureka-server-u-r-l-context=eureka", "eureka.client.eureka-server-port=30000")
|
||||
.run(context -> assertThat(output)
|
||||
.contains("Cannot get cnames bound to the region:txt.us-east-1.myeurekahost"));
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=true",
|
||||
"eureka.instance.hostname=eurekaclient1", "eureka.client.use-dns-for-fetching-service-urls=true",
|
||||
"eureka.client.eureka-server-d-n-s-name=myeurekahost",
|
||||
"eureka.client.eureka-server-u-r-l-context=eureka", "eureka.client.eureka-server-port=30000")
|
||||
.run(context -> assertThat(output)
|
||||
.contains("Cannot get cnames bound to the region:txt.us-east-1.myeurekahost"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -159,13 +164,43 @@ public class EurekaConfigServerBootstrapConfigurationTests {
|
||||
// FIXME: why do I need to do this? (fails in maven build without it.
|
||||
TomcatURLStreamHandlerFactory.disable();
|
||||
new SpringApplicationBuilder(TestConfigDiscoveryConfiguration.class)
|
||||
.properties("spring.config.use-legacy-processing=true", "spring.cloud.config.discovery.enabled=true",
|
||||
"eureka.client.enabled=true",
|
||||
"spring.main.sources=" + TestConfigDiscoveryBootstrapConfiguration.class.getName(),
|
||||
"logging.level.org.springframework.cloud.netflix.eureka.config=DEBUG")
|
||||
.run();
|
||||
.properties("spring.config.use-legacy-processing=true", "spring.cloud.config.discovery.enabled=true",
|
||||
"eureka.client.enabled=true",
|
||||
"spring.main.sources=" + TestConfigDiscoveryBootstrapConfiguration.class.getName(),
|
||||
"logging.level.org.springframework.cloud.netflix.eureka.config=DEBUG")
|
||||
.run()
|
||||
.close();
|
||||
assertThat(output).contains("eurekaConfigServerInstanceProvider finding instances for configserver")
|
||||
.contains("eurekaConfigServerInstanceProvider found 1 instance(s) for configserver");
|
||||
.contains("eurekaConfigServerInstanceProvider found 1 instance(s) for configserver");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eurekaConfigServerInstanceProviderCalledWithRemoteRegions() {
|
||||
TomcatURLStreamHandlerFactory.disable();
|
||||
new SpringApplicationBuilder(TestConfigDiscoveryConfiguration.class)
|
||||
.properties("spring.config.use-legacy-processing=true", "spring.cloud.config.discovery.enabled=true",
|
||||
"eureka.client.enabled=true", "eureka.client.fetchRemoteRegionsRegistry=us-east-1,us-east-2",
|
||||
"spring.main.sources=" + TestConfigDiscoveryBootstrapConfiguration.class.getName(),
|
||||
"logging.level.org.springframework.cloud.netflix.eureka.config=DEBUG")
|
||||
.run()
|
||||
.close();
|
||||
assertThat(output).contains("eurekaConfigServerInstanceProvider finding instances for configserver")
|
||||
.contains("eurekaConfigServerInstanceProvider found 1 instance(s) for configserver");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eurekaConfigServerInstanceProviderCalledWithVipAddress() {
|
||||
TomcatURLStreamHandlerFactory.disable();
|
||||
new SpringApplicationBuilder(TestConfigDiscoveryConfiguration.class)
|
||||
.properties("spring.config.use-legacy-processing=true", "spring.cloud.config.discovery.enabled=true",
|
||||
"eureka.client.enabled=true", "eureka.client.registryRefreshSingleVipAddress=vip1",
|
||||
"eureka.client.fetchRemoteRegionsRegistry=us-east-1,us-east-2",
|
||||
"spring.main.sources=" + TestConfigDiscoveryBootstrapConfiguration.class.getName(),
|
||||
"logging.level.org.springframework.cloud.netflix.eureka.config=DEBUG")
|
||||
.run()
|
||||
.close();
|
||||
assertThat(output).contains("eurekaConfigServerInstanceProvider finding instances for configserver")
|
||||
.contains("eurekaConfigServerInstanceProvider found 1 instance(s) for configserver");
|
||||
}
|
||||
|
||||
private void assertEurekaBeansPresent(AssertableApplicationContext context) {
|
||||
@@ -208,7 +243,9 @@ public class EurekaConfigServerBootstrapConfigurationTests {
|
||||
when(response.getEntity()).thenReturn(applications);
|
||||
|
||||
EurekaHttpClient client = mock(EurekaHttpClient.class);
|
||||
when(client.getApplications("us-east-1")).thenReturn(response);
|
||||
when(client.getApplications("us-east-1", "us-east-2")).thenReturn(response);
|
||||
when(client.getApplications((String) null)).thenReturn(response);
|
||||
when(client.getVip("vip1", "us-east-1", "us-east-2")).thenReturn(response);
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
+14
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -26,11 +26,12 @@ import org.springframework.boot.test.web.server.LocalServerPort;
|
||||
import org.springframework.cloud.netflix.eureka.http.WebClientEurekaHttpClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -53,10 +54,15 @@ class EurekaConfigServerBootstrapConfigurationWebClientIntegrationTests {
|
||||
@Test
|
||||
void webClientRespectsCodecProperties() {
|
||||
WebClient webClient = eurekaHttpClient.getWebClient();
|
||||
ClientResponse response = webClient.get().uri("http://localhost:" + port).exchange().block();
|
||||
ResponseEntity<String> response = webClient.get()
|
||||
.uri("http://localhost:" + port)
|
||||
.retrieve()
|
||||
.toEntity(String.class)
|
||||
.block();
|
||||
|
||||
assertThat(response).isNotNull();
|
||||
assertThat(response.statusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(response.bodyToMono(String.class).block()).startsWith("....").hasSize(300000);
|
||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(response.getBody()).startsWith("....").hasSize(300000);
|
||||
}
|
||||
|
||||
@SpringBootConfiguration
|
||||
@@ -71,8 +77,9 @@ class EurekaConfigServerBootstrapConfigurationWebClientIntegrationTests {
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests().anyRequest().permitAll().and().csrf().disable();
|
||||
return http.build();
|
||||
return http.authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
-16
@@ -35,27 +35,27 @@ class EurekaConfigServerBootstrapConfigurationWebClientTests {
|
||||
@Test
|
||||
void properBeansCreatedWhenEnabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=true",
|
||||
"eureka.client.webclient.enabled=true")
|
||||
.run(context -> {
|
||||
assertThat(context).hasSingleBean(EurekaClientConfigBean.class);
|
||||
assertThat(context).hasSingleBean(WebClientEurekaHttpClient.class);
|
||||
assertThat(context).hasSingleBean(ConfigServerInstanceProvider.Function.class);
|
||||
});
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=true",
|
||||
"eureka.client.webclient.enabled=true")
|
||||
.run(context -> {
|
||||
assertThat(context).hasSingleBean(EurekaClientConfigBean.class);
|
||||
assertThat(context).hasSingleBean(WebClientEurekaHttpClient.class);
|
||||
assertThat(context).hasSingleBean(ConfigServerInstanceProvider.Function.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void properBeansCreatedWhenEnabledWebClientDisabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=true")
|
||||
.run(context -> {
|
||||
assertThat(context).hasSingleBean(EurekaClientConfigBean.class);
|
||||
assertThat(context).doesNotHaveBean(WebClientEurekaHttpClient.class);
|
||||
assertThat(context).hasSingleBean(RestTemplateEurekaHttpClient.class);
|
||||
assertThat(context).hasSingleBean(ConfigServerInstanceProvider.Function.class);
|
||||
});
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=true")
|
||||
.run(context -> {
|
||||
assertThat(context).hasSingleBean(EurekaClientConfigBean.class);
|
||||
assertThat(context).doesNotHaveBean(WebClientEurekaHttpClient.class);
|
||||
assertThat(context).hasSingleBean(RestTemplateEurekaHttpClient.class);
|
||||
assertThat(context).hasSingleBean(ConfigServerInstanceProvider.Function.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+17
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -59,10 +59,10 @@ import static org.mockserver.model.HttpResponse.response;
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@Testcontainers
|
||||
public class EurekaConfigServerBootstrapperIT {
|
||||
public class EurekaConfigServerBootstrapperIntegrationTests {
|
||||
|
||||
public static final DockerImageName MOCKSERVER_IMAGE = DockerImageName.parse("mockserver/mockserver")
|
||||
.withTag("mockserver-" + MockServerClient.class.getPackage().getImplementationVersion());
|
||||
.withTag("mockserver-" + MockServerClient.class.getPackage().getImplementationVersion());
|
||||
|
||||
@Container
|
||||
static MockServerContainer mockServer = new MockServerContainer(MOCKSERVER_IMAGE);
|
||||
@@ -93,21 +93,25 @@ public class EurekaConfigServerBootstrapperIT {
|
||||
try (MockServerClient mockServerClient = new MockServerClient(mockServer.getHost(),
|
||||
mockServer.getMappedPort(MockServerContainer.PORT))) {
|
||||
mockServerClient.when(request().withPath("/application/default"))
|
||||
.respond(response().withBody(objectMapper.writeValueAsString(environment))
|
||||
.withHeader("content-type", "application/json"));
|
||||
.respond(response().withBody(objectMapper.writeValueAsString(environment))
|
||||
.withHeader("content-type", "application/json"));
|
||||
InstanceInfo configServerInstanceInfo = InstanceInfo.Builder.newBuilder()
|
||||
.setVIPAddress("eureka-configserver").setInstanceId("eureka-configserver")
|
||||
.setAppName("eureka-configserver").setStatus(InstanceInfo.InstanceStatus.UP)
|
||||
.enablePort(InstanceInfo.PortType.UNSECURE, true).setHostName("localhost")
|
||||
.setPort(mockServer.getMappedPort(MockServerContainer.PORT)).build();
|
||||
.setVIPAddress("eureka-configserver")
|
||||
.setInstanceId("eureka-configserver")
|
||||
.setAppName("eureka-configserver")
|
||||
.setStatus(InstanceInfo.InstanceStatus.UP)
|
||||
.enablePort(InstanceInfo.PortType.UNSECURE, true)
|
||||
.setHostName("localhost")
|
||||
.setPort(mockServer.getMappedPort(MockServerContainer.PORT))
|
||||
.build();
|
||||
Application configServer = new Application("eureka-configserver",
|
||||
Collections.singletonList(configServerInstanceInfo));
|
||||
EurekaApplications eurekaApplications = new EurekaApplications("hashcode", 0L,
|
||||
Collections.singletonList(configServer));
|
||||
mockServerClient.when(request().withPath("/apps/"))
|
||||
.respond(response()
|
||||
.withBody("{\"applications\":" + objectMapper.writeValueAsString(eurekaApplications) + "}")
|
||||
.withHeader("content-type", "application/json"));
|
||||
.respond(response()
|
||||
.withBody("{\"applications\":" + objectMapper.writeValueAsString(eurekaApplications) + "}")
|
||||
.withHeader("content-type", "application/json"));
|
||||
this.context = setup().run();
|
||||
assertThat(this.context.getEnvironment().getProperty("hello")).isEqualTo("world");
|
||||
}
|
||||
@@ -129,7 +133,7 @@ public class EurekaConfigServerBootstrapperIT {
|
||||
|
||||
SpringApplicationBuilder setup(String... env) {
|
||||
SpringApplicationBuilder builder = new SpringApplicationBuilder(TestConfig.class)
|
||||
.properties(addDefaultEnv(env));
|
||||
.properties(addDefaultEnv(env));
|
||||
return builder;
|
||||
}
|
||||
|
||||
+46
-38
@@ -37,59 +37,67 @@ class EurekaConfigServerBootstrapperTests {
|
||||
@Test
|
||||
void notEnabledReturnsEmptyList() {
|
||||
new SpringApplicationBuilder(TestConfig.class)
|
||||
.properties("spring.cloud.service-registry.auto-registration.enabled=false")
|
||||
.addBootstrapRegistryInitializer(registry -> registry.addCloseListener(event -> {
|
||||
ConfigServerInstanceProvider.Function providerFn = event.getBootstrapContext()
|
||||
.get(ConfigServerInstanceProvider.Function.class);
|
||||
assertThat(providerFn.apply("id")).as("Should return empty list").isEmpty();
|
||||
})).run().close();
|
||||
.properties("spring.cloud.service-registry.auto-registration.enabled=false")
|
||||
.addBootstrapRegistryInitializer(registry -> registry.addCloseListener(event -> {
|
||||
ConfigServerInstanceProvider.Function providerFn = event.getBootstrapContext()
|
||||
.get(ConfigServerInstanceProvider.Function.class);
|
||||
assertThat(providerFn.apply("id")).as("Should return empty list").isEmpty();
|
||||
}))
|
||||
.run()
|
||||
.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoveryClientNotEnabledProvidesEmptyList() {
|
||||
new SpringApplicationBuilder(TestConfig.class)
|
||||
.properties("spring.cloud.config.discovery.enabled=true", "spring.cloud.discovery.enabled=false",
|
||||
"spring.cloud.service-registry.auto-registration.enabled=false")
|
||||
.addBootstrapRegistryInitializer(registry -> registry.addCloseListener(event -> {
|
||||
ConfigServerInstanceProvider.Function providerFn = event.getBootstrapContext()
|
||||
.get(ConfigServerInstanceProvider.Function.class);
|
||||
Binder binder = event.getBootstrapContext().get(Binder.class);
|
||||
BindHandler bindHandler = event.getBootstrapContext().get(BindHandler.class);
|
||||
assertThat(providerFn.apply("id", binder, bindHandler, mock(Log.class)))
|
||||
.as("Should return empty list").isEmpty();
|
||||
})).run().close();
|
||||
.properties("spring.cloud.config.discovery.enabled=true", "spring.cloud.discovery.enabled=false",
|
||||
"spring.cloud.service-registry.auto-registration.enabled=false")
|
||||
.addBootstrapRegistryInitializer(registry -> registry.addCloseListener(event -> {
|
||||
ConfigServerInstanceProvider.Function providerFn = event.getBootstrapContext()
|
||||
.get(ConfigServerInstanceProvider.Function.class);
|
||||
Binder binder = event.getBootstrapContext().get(Binder.class);
|
||||
BindHandler bindHandler = event.getBootstrapContext().get(BindHandler.class);
|
||||
assertThat(providerFn.apply("id", binder, bindHandler, mock(Log.class))).as("Should return empty list")
|
||||
.isEmpty();
|
||||
}))
|
||||
.run()
|
||||
.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eurekaClientNotEnabledProvidesEmptyList() {
|
||||
new SpringApplicationBuilder(TestConfig.class)
|
||||
.properties("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=false",
|
||||
"spring.cloud.service-registry.auto-registration.enabled=false")
|
||||
.addBootstrapRegistryInitializer(registry -> registry.addCloseListener(event -> {
|
||||
ConfigServerInstanceProvider.Function providerFn = event.getBootstrapContext()
|
||||
.get(ConfigServerInstanceProvider.Function.class);
|
||||
Binder binder = event.getBootstrapContext().get(Binder.class);
|
||||
BindHandler bindHandler = event.getBootstrapContext().get(BindHandler.class);
|
||||
assertThat(providerFn.apply("id", binder, bindHandler, mock(Log.class)))
|
||||
.as("Should return empty list").isEmpty();
|
||||
})).run().close();
|
||||
.properties("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=false",
|
||||
"spring.cloud.service-registry.auto-registration.enabled=false")
|
||||
.addBootstrapRegistryInitializer(registry -> registry.addCloseListener(event -> {
|
||||
ConfigServerInstanceProvider.Function providerFn = event.getBootstrapContext()
|
||||
.get(ConfigServerInstanceProvider.Function.class);
|
||||
Binder binder = event.getBootstrapContext().get(Binder.class);
|
||||
BindHandler bindHandler = event.getBootstrapContext().get(BindHandler.class);
|
||||
assertThat(providerFn.apply("id", binder, bindHandler, mock(Log.class))).as("Should return empty list")
|
||||
.isEmpty();
|
||||
}))
|
||||
.run()
|
||||
.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void enabledAddsInstanceProviderFn() {
|
||||
new SpringApplicationBuilder(TestConfig.class)
|
||||
.properties("spring.config.import: classpath:bootstrapper.yaml",
|
||||
ConfigClientProperties.PREFIX + ".enabled=true")
|
||||
.addBootstrapRegistryInitializer(registry -> registry.addCloseListener(event -> {
|
||||
ConfigServerInstanceProvider.Function providerFn = event.getBootstrapContext()
|
||||
.get(ConfigServerInstanceProvider.Function.class);
|
||||
Binder binder = event.getBootstrapContext().get(Binder.class);
|
||||
BindHandler bindHandler = event.getBootstrapContext().get(BindHandler.class);
|
||||
assertThatThrownBy(() -> providerFn.apply("id", binder, bindHandler, mock(Log.class)))
|
||||
.isInstanceOf(ResourceAccessException.class)
|
||||
.hasMessageContaining("I/O error on GET request for \"http://localhost:8761/eureka/apps/\"")
|
||||
.as("Should have tried to connect to Eureka to fetch instances.");
|
||||
})).run().close();
|
||||
.properties("spring.config.import: classpath:bootstrapper.yaml",
|
||||
ConfigClientProperties.PREFIX + ".enabled=true")
|
||||
.addBootstrapRegistryInitializer(registry -> registry.addCloseListener(event -> {
|
||||
ConfigServerInstanceProvider.Function providerFn = event.getBootstrapContext()
|
||||
.get(ConfigServerInstanceProvider.Function.class);
|
||||
Binder binder = event.getBootstrapContext().get(Binder.class);
|
||||
BindHandler bindHandler = event.getBootstrapContext().get(BindHandler.class);
|
||||
assertThatThrownBy(() -> providerFn.apply("id", binder, bindHandler, mock(Log.class)))
|
||||
.isInstanceOf(ResourceAccessException.class)
|
||||
.hasMessageContaining("I/O error on GET request for \"http://localhost:8761/eureka/apps/\"")
|
||||
.as("Should have tried to connect to Eureka to fetch instances.");
|
||||
}))
|
||||
.run()
|
||||
.close();
|
||||
}
|
||||
|
||||
@SpringBootConfiguration
|
||||
|
||||
+4
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -37,7 +37,7 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
|
||||
@RunWith(ModifiedClassPathRunner.class)
|
||||
@ClassPathExclusions({ "jersey-client-*", "jersey-core-*", "jersey-apache-client4-*", "spring-webflux-*" })
|
||||
@SpringBootTest(classes = EurekaSampleApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class EurekaHttpClientsOptionalArgsConfigurationNoWebfluxTest {
|
||||
public class EurekaHttpClientsOptionalArgsConfigurationNoWebFluxTests {
|
||||
|
||||
@Test
|
||||
public void contextFailsWithoutWebClient() {
|
||||
@@ -46,7 +46,8 @@ public class EurekaHttpClientsOptionalArgsConfigurationNoWebfluxTest {
|
||||
try {
|
||||
TomcatURLStreamHandlerFactory.disable();
|
||||
ctx = new SpringApplicationBuilder(EurekaSampleApplication.class)
|
||||
.properties("eureka.client.webclient.enabled=true").run();
|
||||
.properties("eureka.client.webclient.enabled=true")
|
||||
.run();
|
||||
fail("exception not thrown");
|
||||
}
|
||||
catch (Exception e) {
|
||||
+12
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -36,24 +36,26 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
|
||||
@RunWith(ModifiedClassPathRunner.class)
|
||||
@ClassPathExclusions({ "jersey-client-*", "jersey-core-*", "jersey-apache-client4-*" })
|
||||
@SpringBootTest(classes = EurekaSampleApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class EurekaHttpClientsOptionalArgsConfigurationTest {
|
||||
public class EurekaHttpClientsOptionalArgsConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void contextLoadsWithRestTemplate() {
|
||||
new WebApplicationContextRunner().withUserConfiguration(EurekaSampleApplication.class)
|
||||
.withPropertyValues("eureka.client.webclient.enabled=false").run(context -> {
|
||||
assertThat(context).hasSingleBean(RestTemplateDiscoveryClientOptionalArgs.class);
|
||||
assertThat(context).doesNotHaveBean(WebClientDiscoveryClientOptionalArgs.class);
|
||||
});
|
||||
.withPropertyValues("eureka.client.webclient.enabled=false")
|
||||
.run(context -> {
|
||||
assertThat(context).hasSingleBean(RestTemplateDiscoveryClientOptionalArgs.class);
|
||||
assertThat(context).doesNotHaveBean(WebClientDiscoveryClientOptionalArgs.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextLoadsWithWebClient() {
|
||||
new WebApplicationContextRunner().withUserConfiguration(EurekaSampleApplication.class)
|
||||
.withPropertyValues("eureka.client.webclient.enabled=true").run(context -> {
|
||||
assertThat(context).doesNotHaveBean(RestTemplateDiscoveryClientOptionalArgs.class);
|
||||
assertThat(context).hasSingleBean(WebClientDiscoveryClientOptionalArgs.class);
|
||||
});
|
||||
.withPropertyValues("eureka.client.webclient.enabled=true")
|
||||
.run(context -> {
|
||||
assertThat(context).doesNotHaveBean(RestTemplateDiscoveryClientOptionalArgs.class);
|
||||
assertThat(context).hasSingleBean(WebClientDiscoveryClientOptionalArgs.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2017-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.cloud.netflix.eureka.config;
|
||||
|
||||
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for Jersey client setup in DiscoveryClientOptionalArgsConfiguration.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public class JerseyClientOptionalArgsConfigurationTests {
|
||||
|
||||
@SuppressWarnings("OptionalGetWithoutIsPresent")
|
||||
@Test
|
||||
void shouldCreateRestTemplateDiscoveryClientOptionalArgsWhenJerseyClientDisabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(DiscoveryClientOptionalArgsConfiguration.class))
|
||||
.withPropertyValues("eureka.client.jersey.enabled=false")
|
||||
.run(context -> {
|
||||
assertThat(context).hasSingleBean(AbstractDiscoveryClientOptionalArgs.class);
|
||||
assertThat(context.getBeansOfType(AbstractDiscoveryClientOptionalArgs.class)
|
||||
.values()
|
||||
.stream()
|
||||
.findFirst()
|
||||
.get()).isInstanceOf(RestTemplateDiscoveryClientOptionalArgs.class);
|
||||
assertThat(context).hasSingleBean(RestTemplateDiscoveryClientOptionalArgs.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -32,7 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
@DirtiesContext
|
||||
@SpringBootTest(classes = EurekaSampleApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
class JerseyOptionalArgsConfigurationTest {
|
||||
class JerseyOptionalArgsConfigurationApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private AbstractDiscoveryClientOptionalArgs optionalArgs;
|
||||
+2
-2
@@ -51,7 +51,7 @@ class EurekaHealthCheckTests {
|
||||
System.setProperty("status", "UP");
|
||||
|
||||
InstanceInfo.InstanceStatus status = this.discoveryClient.getHealthCheckHandler()
|
||||
.getStatus(InstanceInfo.InstanceStatus.UNKNOWN);
|
||||
.getStatus(InstanceInfo.InstanceStatus.UNKNOWN);
|
||||
|
||||
assertThat(status).isNotNull();
|
||||
assertThat(status).isEqualTo(InstanceInfo.InstanceStatus.UP);
|
||||
@@ -62,7 +62,7 @@ class EurekaHealthCheckTests {
|
||||
System.setProperty("status", "OUT_OF_SERVICE");
|
||||
|
||||
InstanceInfo.InstanceStatus status = this.discoveryClient.getHealthCheckHandler()
|
||||
.getStatus(InstanceInfo.InstanceStatus.UNKNOWN);
|
||||
.getStatus(InstanceInfo.InstanceStatus.UNKNOWN);
|
||||
|
||||
assertThat(status).isNotNull();
|
||||
assertThat(status).isEqualTo(InstanceInfo.InstanceStatus.DOWN);
|
||||
|
||||
+22
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -21,6 +21,8 @@ import com.netflix.discovery.shared.Applications;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpClient;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
@@ -28,6 +30,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Haytham Mohamed
|
||||
* @author Václav Plic
|
||||
**/
|
||||
abstract class AbstractEurekaHttpClientTests {
|
||||
|
||||
@@ -47,9 +50,10 @@ abstract class AbstractEurekaHttpClientTests {
|
||||
assertThat(eurekaHttpClient.cancel("test", "test").getStatusCode()).isEqualTo(HttpStatus.OK.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendHeartBeat() {
|
||||
EurekaHttpResponse<InstanceInfo> response = eurekaHttpClient.sendHeartBeat("test", "test", info, null);
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "test", "test#1.[3.?]!" })
|
||||
void testSendHeartBeat(String instanceId) {
|
||||
EurekaHttpResponse<InstanceInfo> response = eurekaHttpClient.sendHeartBeat("test", instanceId, info, null);
|
||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK.value());
|
||||
assertThat(response.getEntity()).isNotNull();
|
||||
}
|
||||
@@ -57,25 +61,27 @@ abstract class AbstractEurekaHttpClientTests {
|
||||
@Test
|
||||
void testSendHeartBeatFourOFour() {
|
||||
assertThat(eurekaHttpClient.sendHeartBeat("fourOFour", "test", info, null).getStatusCode())
|
||||
.isEqualTo(HttpStatus.NOT_FOUND.value());
|
||||
.isEqualTo(HttpStatus.NOT_FOUND.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendHeartBeatFourOFourWithBody() {
|
||||
assertThat(eurekaHttpClient.sendHeartBeat("fourOFourWithBody", "test", info, null).getStatusCode())
|
||||
.isEqualTo(HttpStatus.NOT_FOUND.value());
|
||||
.isEqualTo(HttpStatus.NOT_FOUND.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStatusUpdate() {
|
||||
assertThat(eurekaHttpClient.statusUpdate("test", "test", InstanceInfo.InstanceStatus.UP, info).getStatusCode())
|
||||
.isEqualTo(HttpStatus.OK.value());
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "test", "test#1.[3.?]!" })
|
||||
void testStatusUpdate(String instanceId) {
|
||||
assertThat(
|
||||
eurekaHttpClient.statusUpdate("test", instanceId, InstanceInfo.InstanceStatus.UP, info).getStatusCode())
|
||||
.isEqualTo(HttpStatus.OK.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteStatusOverride() {
|
||||
assertThat(eurekaHttpClient.deleteStatusOverride("test", "test", info).getStatusCode())
|
||||
.isEqualTo(HttpStatus.OK.value());
|
||||
.isEqualTo(HttpStatus.OK.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -108,10 +114,11 @@ abstract class AbstractEurekaHttpClientTests {
|
||||
eurekaHttpClient.getApplication("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetInstance() {
|
||||
eurekaHttpClient.getInstance("test");
|
||||
eurekaHttpClient.getInstance("test", "test");
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "test", "test#1.[3.?]!" })
|
||||
void testGetInstance(String instanceId) {
|
||||
eurekaHttpClient.getInstance(instanceId);
|
||||
eurekaHttpClient.getInstance("test", instanceId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+45
-22
@@ -65,26 +65,46 @@ import static org.springframework.util.Assert.isTrue;
|
||||
@SpringBootApplication
|
||||
public class EurekaServerMockApplication {
|
||||
|
||||
private static final InstanceInfo INFO = InstanceInfo.Builder.newBuilder().setInstanceId("app1instance1")
|
||||
.setAppName("app1").setAppNameForDeser("app1fordeser").setAppGroupName("app1group")
|
||||
.setAppGroupNameForDeser("app1group1fordeser").setHostName("app1host1")
|
||||
.setStatus(InstanceInfo.InstanceStatus.UP).setOverriddenStatus(InstanceInfo.InstanceStatus.DOWN)
|
||||
.setIPAddr("127.0.0.1").setSID("app1sid").setPort(8080).setSecurePort(4443)
|
||||
.enablePort(InstanceInfo.PortType.UNSECURE, true).setHomePageUrl("/", "http://localhost/")
|
||||
.setHomePageUrlForDeser("http://localhost/").setStatusPageUrl("/status", "http://localhost/info")
|
||||
.setStatusPageUrlForDeser("http://localhost/status")
|
||||
.setHealthCheckUrls("/ping", "http://localhost/ping", null)
|
||||
.setHealthCheckUrlsForDeser("http://localhost/ping", null).setVIPAddress("localhost:8080")
|
||||
.setVIPAddressDeser("localhost:8080").setSecureVIPAddress("localhost:4443")
|
||||
.setSecureVIPAddressDeser("localhost:4443")
|
||||
.setDataCenterInfo(new MyDataCenterInfo(DataCenterInfo.Name.MyOwn))
|
||||
.setLeaseInfo(LeaseInfo.Builder.newBuilder().setDurationInSecs(30).setRenewalIntervalInSecs(30)
|
||||
.setEvictionTimestamp(System.currentTimeMillis() + 30000)
|
||||
.setRenewalTimestamp(System.currentTimeMillis() - 1000)
|
||||
.setRegistrationTimestamp(System.currentTimeMillis() - 2000).build())
|
||||
.add("metadatakey1", "metadatavalue1").setASGName("asg1").setIsCoordinatingDiscoveryServer(false)
|
||||
.setLastUpdatedTimestamp(System.currentTimeMillis()).setLastDirtyTimestamp(System.currentTimeMillis())
|
||||
.setActionType(InstanceInfo.ActionType.ADDED).setNamespace("namespace1").build();
|
||||
private static final InstanceInfo INFO = InstanceInfo.Builder.newBuilder()
|
||||
.setInstanceId("app1instance1")
|
||||
.setAppName("app1")
|
||||
.setAppNameForDeser("app1fordeser")
|
||||
.setAppGroupName("app1group")
|
||||
.setAppGroupNameForDeser("app1group1fordeser")
|
||||
.setHostName("app1host1")
|
||||
.setStatus(InstanceInfo.InstanceStatus.UP)
|
||||
.setOverriddenStatus(InstanceInfo.InstanceStatus.DOWN)
|
||||
.setIPAddr("127.0.0.1")
|
||||
.setSID("app1sid")
|
||||
.setPort(8080)
|
||||
.setSecurePort(4443)
|
||||
.enablePort(InstanceInfo.PortType.UNSECURE, true)
|
||||
.setHomePageUrl("/", "http://localhost/")
|
||||
.setHomePageUrlForDeser("http://localhost/")
|
||||
.setStatusPageUrl("/status", "http://localhost/info")
|
||||
.setStatusPageUrlForDeser("http://localhost/status")
|
||||
.setHealthCheckUrls("/ping", "http://localhost/ping", null)
|
||||
.setHealthCheckUrlsForDeser("http://localhost/ping", null)
|
||||
.setVIPAddress("localhost:8080")
|
||||
.setVIPAddressDeser("localhost:8080")
|
||||
.setSecureVIPAddress("localhost:4443")
|
||||
.setSecureVIPAddressDeser("localhost:4443")
|
||||
.setDataCenterInfo(new MyDataCenterInfo(DataCenterInfo.Name.MyOwn))
|
||||
.setLeaseInfo(LeaseInfo.Builder.newBuilder()
|
||||
.setDurationInSecs(30)
|
||||
.setRenewalIntervalInSecs(30)
|
||||
.setEvictionTimestamp(System.currentTimeMillis() + 30000)
|
||||
.setRenewalTimestamp(System.currentTimeMillis() - 1000)
|
||||
.setRegistrationTimestamp(System.currentTimeMillis() - 2000)
|
||||
.build())
|
||||
.add("metadatakey1", "metadatavalue1")
|
||||
.setASGName("asg1")
|
||||
.setIsCoordinatingDiscoveryServer(false)
|
||||
.setLastUpdatedTimestamp(System.currentTimeMillis())
|
||||
.setLastDirtyTimestamp(System.currentTimeMillis())
|
||||
.setActionType(InstanceInfo.ActionType.ADDED)
|
||||
.setNamespace("namespace1")
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Simulates Eureka Server own's serialization.
|
||||
@@ -166,8 +186,11 @@ public class EurekaServerMockApplication {
|
||||
|
||||
@Bean
|
||||
public InMemoryUserDetailsManager userDetailsService() {
|
||||
UserDetails user = User.withDefaultPasswordEncoder().username("test").password("test").roles("USER")
|
||||
.build();
|
||||
UserDetails user = User.withDefaultPasswordEncoder()
|
||||
.username("test")
|
||||
.password("test")
|
||||
.roles("USER")
|
||||
.build();
|
||||
return new InMemoryUserDetailsManager(user);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ class RestTemplateEurekaHttpClientTests extends AbstractEurekaHttpClientTests {
|
||||
RestTemplate restTemplate = restTemplateEurekaHttpClient.getRestTemplate();
|
||||
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
|
||||
boolean hasBasicAuth = interceptors.stream()
|
||||
.anyMatch(interceptor -> interceptor instanceof BasicAuthenticationInterceptor);
|
||||
.anyMatch(interceptor -> interceptor instanceof BasicAuthenticationInterceptor);
|
||||
assertThat(hasBasicAuth).as("Basic Auth not configured").isTrue();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -24,7 +24,7 @@ import org.junit.jupiter.api.Test;
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
*/
|
||||
class RestTemplateTransportClientFactoryTest {
|
||||
class RestTemplateTransportClientFactoryTests {
|
||||
|
||||
private RestTemplateTransportClientFactory transportClientFatory;
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ class WebClientEurekaHttpClientTests extends AbstractEurekaHttpClientTests {
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
eurekaHttpClient = new WebClientTransportClientFactory(WebClient::builder)
|
||||
.newClient(new DefaultEndpoint(serviceUrl));
|
||||
.newClient(new DefaultEndpoint(serviceUrl));
|
||||
|
||||
EurekaInstanceConfigBean config = new EurekaInstanceConfigBean(inetUtils);
|
||||
|
||||
|
||||
+60
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -16,23 +16,57 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.http;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import com.netflix.discovery.shared.resolver.DefaultEndpoint;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.reactive.function.client.ClientRequest;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFunction;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
* @author Armin Krezovic
|
||||
*/
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
class WebClientTransportClientFactoryTest {
|
||||
|
||||
@Mock
|
||||
private ExchangeFunction exchangeFunction;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<ClientRequest> captor;
|
||||
|
||||
private WebClientTransportClientFactory transportClientFatory;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
transportClientFatory = new WebClientTransportClientFactory(WebClient::builder);
|
||||
ClientResponse mockResponse = mock();
|
||||
when(mockResponse.statusCode()).thenReturn(HttpStatus.OK);
|
||||
when(mockResponse.bodyToMono(Void.class)).thenReturn(Mono.empty());
|
||||
given(exchangeFunction.exchange(captor.capture())).willReturn(Mono.just(mockResponse));
|
||||
|
||||
transportClientFatory = new WebClientTransportClientFactory(
|
||||
() -> WebClient.builder().exchangeFunction(exchangeFunction));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -45,6 +79,23 @@ class WebClientTransportClientFactoryTest {
|
||||
transportClientFatory.newClient(new DefaultEndpoint("http://test@localhost:8761"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUserInfoWithEncodedCharacters() {
|
||||
String encodedBasicAuth = HttpHeaders.encodeBasicAuth("test", "MyPassword@", null);
|
||||
String expectedAuthHeader = "Basic " + encodedBasicAuth;
|
||||
String expectedUrl = "http://localhost:8761";
|
||||
|
||||
WebClientEurekaHttpClient client = (WebClientEurekaHttpClient) transportClientFatory
|
||||
.newClient(new DefaultEndpoint("http://test:MyPassword%40@localhost:8761"));
|
||||
|
||||
client.getWebClient().get().retrieve().bodyToMono(Void.class).block(Duration.ofSeconds(10));
|
||||
|
||||
ClientRequest request = verifyAndGetRequest();
|
||||
|
||||
assertThat(request.headers().getFirst(HttpHeaders.AUTHORIZATION)).isEqualTo(expectedAuthHeader);
|
||||
assertThat(request.url().toString()).isEqualTo(expectedUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUserInfo() {
|
||||
transportClientFatory.newClient(new DefaultEndpoint("http://test:test@localhost:8761"));
|
||||
@@ -55,4 +106,11 @@ class WebClientTransportClientFactoryTest {
|
||||
transportClientFatory.shutdown();
|
||||
}
|
||||
|
||||
private ClientRequest verifyAndGetRequest() {
|
||||
ClientRequest request = captor.getValue();
|
||||
verify(exchangeFunction).exchange(request);
|
||||
verifyNoMoreInteractions(exchangeFunction);
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-5
@@ -76,11 +76,12 @@ class EurekaLoadBalancerClientConfigurationTests {
|
||||
@Test
|
||||
void disabledViaProperty() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(LoadBalancerEurekaAutoConfiguration.class))
|
||||
.withPropertyValues("eureka.client.enabled=false").run(context -> {
|
||||
assertThat(context).doesNotHaveBean(EurekaLoadBalancerProperties.class);
|
||||
assertThat(context).doesNotHaveBean(LoadBalancerZoneConfig.class);
|
||||
});
|
||||
.withConfiguration(AutoConfigurations.of(LoadBalancerEurekaAutoConfiguration.class))
|
||||
.withPropertyValues("eureka.client.enabled=false")
|
||||
.run(context -> {
|
||||
assertThat(context).doesNotHaveBean(EurekaLoadBalancerProperties.class);
|
||||
assertThat(context).doesNotHaveBean(LoadBalancerZoneConfig.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -36,9 +36,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class EurekaReactiveDiscoveryClientConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(UtilAutoConfiguration.class,
|
||||
ReactiveCommonsClientAutoConfiguration.class, EurekaClientAutoConfiguration.class,
|
||||
DiscoveryClientOptionalArgsConfiguration.class, EurekaReactiveDiscoveryClientConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(UtilAutoConfiguration.class,
|
||||
ReactiveCommonsClientAutoConfiguration.class, EurekaClientAutoConfiguration.class,
|
||||
DiscoveryClientOptionalArgsConfiguration.class, EurekaReactiveDiscoveryClientConfiguration.class));
|
||||
|
||||
@Test
|
||||
void shouldWorkWithDefaults() {
|
||||
|
||||
+100
-18
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -16,14 +16,20 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.serviceregistry;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.netflix.appinfo.ApplicationInfoManager;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import org.springframework.cloud.commons.util.InetUtils;
|
||||
import org.springframework.cloud.commons.util.InetUtilsProperties;
|
||||
import org.springframework.cloud.loadbalancer.support.SimpleObjectProvider;
|
||||
import org.springframework.cloud.netflix.eureka.CloudEurekaClient;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
|
||||
@@ -33,16 +39,24 @@ import static com.netflix.appinfo.InstanceInfo.InstanceStatus.DOWN;
|
||||
import static com.netflix.appinfo.InstanceInfo.InstanceStatus.OUT_OF_SERVICE;
|
||||
import static com.netflix.appinfo.InstanceInfo.InstanceStatus.UNKNOWN;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Tim Ysewyn
|
||||
* @author Robert Bleyl
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class EurekaServiceRegistryTests {
|
||||
|
||||
@Mock
|
||||
private EurekaInstanceConfigBean eurekaInstanceConfigBean;
|
||||
|
||||
@Test
|
||||
void eurekaClientNotShutdownInDeregister() {
|
||||
EurekaServiceRegistry registry = new EurekaServiceRegistry();
|
||||
@@ -53,9 +67,11 @@ class EurekaServiceRegistryTests {
|
||||
when(applicationInfoManager.getInfo()).thenReturn(mock(InstanceInfo.class));
|
||||
|
||||
EurekaRegistration registration = EurekaRegistration
|
||||
.builder(new EurekaInstanceConfigBean(new InetUtils(new InetUtilsProperties()))).with(eurekaClient)
|
||||
.with(applicationInfoManager).with(new EurekaClientConfigBean(), mock(ApplicationEventPublisher.class))
|
||||
.build();
|
||||
.builder(new EurekaInstanceConfigBean(new InetUtils(new InetUtilsProperties())))
|
||||
.with(eurekaClient)
|
||||
.with(applicationInfoManager)
|
||||
.with(new EurekaClientConfigBean(), mock(ApplicationEventPublisher.class))
|
||||
.build();
|
||||
|
||||
registry.deregister(registration);
|
||||
|
||||
@@ -71,11 +87,18 @@ class EurekaServiceRegistryTests {
|
||||
config.setAppname("myapp");
|
||||
config.setInstanceId("1234");
|
||||
|
||||
InstanceInfo local = InstanceInfo.Builder.newBuilder().setAppName("myapp").setInstanceId("1234").setStatus(DOWN)
|
||||
.build();
|
||||
InstanceInfo local = InstanceInfo.Builder.newBuilder()
|
||||
.setAppName("myapp")
|
||||
.setInstanceId("1234")
|
||||
.setStatus(DOWN)
|
||||
.build();
|
||||
|
||||
InstanceInfo remote = InstanceInfo.Builder.newBuilder().setAppName("myapp").setInstanceId("1234")
|
||||
.setStatus(DOWN).setOverriddenStatus(OUT_OF_SERVICE).build();
|
||||
InstanceInfo remote = InstanceInfo.Builder.newBuilder()
|
||||
.setAppName("myapp")
|
||||
.setInstanceId("1234")
|
||||
.setStatus(DOWN)
|
||||
.setOverriddenStatus(OUT_OF_SERVICE)
|
||||
.build();
|
||||
|
||||
CloudEurekaClient eurekaClient = mock(CloudEurekaClient.class);
|
||||
when(eurekaClient.getInstanceInfo(local.getAppName(), local.getId())).thenReturn(remote);
|
||||
@@ -83,9 +106,11 @@ class EurekaServiceRegistryTests {
|
||||
ApplicationInfoManager applicationInfoManager = mock(ApplicationInfoManager.class);
|
||||
when(applicationInfoManager.getInfo()).thenReturn(local);
|
||||
|
||||
EurekaRegistration registration = EurekaRegistration.builder(config).with(eurekaClient)
|
||||
.with(applicationInfoManager).with(new EurekaClientConfigBean(), mock(ApplicationEventPublisher.class))
|
||||
.build();
|
||||
EurekaRegistration registration = EurekaRegistration.builder(config)
|
||||
.with(eurekaClient)
|
||||
.with(applicationInfoManager)
|
||||
.with(new EurekaClientConfigBean(), mock(ApplicationEventPublisher.class))
|
||||
.build();
|
||||
|
||||
Object status = registry.getStatus(registration);
|
||||
|
||||
@@ -95,8 +120,9 @@ class EurekaServiceRegistryTests {
|
||||
|
||||
Map<Object, Object> map = (Map<Object, Object>) status;
|
||||
|
||||
assertThat(map).hasSize(2).containsEntry("status", DOWN.toString()).containsEntry("overriddenStatus",
|
||||
OUT_OF_SERVICE.toString());
|
||||
assertThat(map).hasSize(2)
|
||||
.containsEntry("status", DOWN.toString())
|
||||
.containsEntry("overriddenStatus", OUT_OF_SERVICE.toString());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -110,14 +136,14 @@ class EurekaServiceRegistryTests {
|
||||
|
||||
CloudEurekaClient eurekaClient = mock(CloudEurekaClient.class);
|
||||
|
||||
when(eurekaClient.getInstanceInfo("myapp", "1234")).thenReturn(null);
|
||||
|
||||
ApplicationInfoManager applicationInfoManager = mock(ApplicationInfoManager.class);
|
||||
when(applicationInfoManager.getInfo()).thenReturn(mock(InstanceInfo.class));
|
||||
|
||||
EurekaRegistration registration = EurekaRegistration.builder(config).with(eurekaClient)
|
||||
.with(applicationInfoManager).with(new EurekaClientConfigBean(), mock(ApplicationEventPublisher.class))
|
||||
.build();
|
||||
EurekaRegistration registration = EurekaRegistration.builder(config)
|
||||
.with(eurekaClient)
|
||||
.with(applicationInfoManager)
|
||||
.with(new EurekaClientConfigBean(), mock(ApplicationEventPublisher.class))
|
||||
.build();
|
||||
|
||||
Object status = registry.getStatus(registration);
|
||||
|
||||
@@ -130,4 +156,60 @@ class EurekaServiceRegistryTests {
|
||||
assertThat(map).hasSize(1).containsEntry("status", UNKNOWN.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void eurekaClientInitializesClientAsynchronously() {
|
||||
when(eurekaInstanceConfigBean.isAsyncClientInitialization()).thenReturn(true);
|
||||
EurekaServiceRegistry registry = new EurekaServiceRegistry(eurekaInstanceConfigBean);
|
||||
|
||||
final AtomicBoolean applicationsFetched = new AtomicBoolean();
|
||||
|
||||
CloudEurekaClient eurekaClient = mock(CloudEurekaClient.class);
|
||||
when(eurekaClient.getApplications()).thenAnswer((answer) -> {
|
||||
applicationsFetched.set(true);
|
||||
return answer;
|
||||
});
|
||||
|
||||
ApplicationInfoManager applicationInfoManager = mock(ApplicationInfoManager.class);
|
||||
|
||||
when(applicationInfoManager.getInfo()).thenReturn(mock(InstanceInfo.class));
|
||||
|
||||
EurekaRegistration registration = EurekaRegistration
|
||||
.builder(new EurekaInstanceConfigBean(new InetUtils(new InetUtilsProperties())))
|
||||
.with(eurekaClient)
|
||||
.with(applicationInfoManager)
|
||||
.with(new EurekaClientConfigBean(), mock(ApplicationEventPublisher.class))
|
||||
.with(new SimpleObjectProvider<>(null))
|
||||
.build();
|
||||
|
||||
registry.register(registration);
|
||||
|
||||
await().atMost(Duration.ofSeconds(5)).pollInterval(Duration.ofMillis(500)).until(applicationsFetched::get);
|
||||
|
||||
verify(eurekaClient).getApplications();
|
||||
assertThat(applicationsFetched).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void eurekaClientInitializesClientSynchronously() {
|
||||
EurekaServiceRegistry registry = new EurekaServiceRegistry(eurekaInstanceConfigBean);
|
||||
|
||||
CloudEurekaClient eurekaClient = mock(CloudEurekaClient.class);
|
||||
ApplicationInfoManager applicationInfoManager = mock(ApplicationInfoManager.class);
|
||||
|
||||
when(applicationInfoManager.getInfo()).thenReturn(mock(InstanceInfo.class));
|
||||
|
||||
EurekaRegistration registration = EurekaRegistration
|
||||
.builder(new EurekaInstanceConfigBean(new InetUtils(new InetUtilsProperties())))
|
||||
.with(eurekaClient)
|
||||
.with(applicationInfoManager)
|
||||
.with(new EurekaClientConfigBean(), mock(ApplicationEventPublisher.class))
|
||||
.with(new SimpleObjectProvider<>(null))
|
||||
.build();
|
||||
|
||||
registry.register(registration);
|
||||
|
||||
verify(eurekaClient).getApplications();
|
||||
verify(eurekaClient, never()).getEurekaClientConfig();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>4.1.1-SNAPSHOT</version>
|
||||
<version>4.1.7-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<artifactId>spring-cloud-netflix-eureka-server</artifactId>
|
||||
@@ -14,8 +14,6 @@
|
||||
<properties>
|
||||
<wro4j.version>1.10.1</wro4j.version>
|
||||
<wiremock.version>2.27.2</wiremock.version>
|
||||
<!-- FIXME: 4.0.0 -->
|
||||
<duplicate-finder-maven-plugin.skip>true</duplicate-finder-maven-plugin.skip>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -71,18 +69,18 @@
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.inject</groupId>
|
||||
<artifactId>jersey-hk2</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.glassfish.hk2.external</groupId>
|
||||
<artifactId>aopalliance-repackaged</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.hk2</groupId>
|
||||
<artifactId>spring-bridge</artifactId>
|
||||
<!-- FIXME: 4.0 -->
|
||||
<version>3.0.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.inject</groupId>
|
||||
<artifactId>jakarta.inject-api</artifactId>
|
||||
<!-- FIXME: 4.0 -->
|
||||
<version>2.0.1</version>
|
||||
<version>3.1.1</version>
|
||||
</dependency>
|
||||
<!-- Eureka deps that are now optional in eureka -->
|
||||
<dependency>
|
||||
@@ -104,6 +102,12 @@
|
||||
<artifactId>spring-security-rsa</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<resources>
|
||||
|
||||
+1
-1
@@ -201,7 +201,7 @@ public class EurekaController {
|
||||
ArrayList<Map<String, Object>> instanceInfos = new ArrayList<>();
|
||||
appData.put("instanceInfos", instanceInfos);
|
||||
for (Map.Entry<InstanceInfo.InstanceStatus, List<Pair<String, String>>> entry : instancesByStatus
|
||||
.entrySet()) {
|
||||
.entrySet()) {
|
||||
List<Pair<String, String>> value = entry.getValue();
|
||||
InstanceInfo.InstanceStatus status = entry.getKey();
|
||||
LinkedHashMap<String, Object> instanceData = new LinkedHashMap<>();
|
||||
|
||||
+38
-38
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -25,21 +25,19 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.netflix.appinfo.ApplicationInfoManager;
|
||||
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.Jersey3DiscoveryClientOptionalArgs;
|
||||
import com.netflix.discovery.converters.EurekaJacksonCodec;
|
||||
import com.netflix.discovery.converters.wrappers.CodecWrapper;
|
||||
import com.netflix.discovery.converters.wrappers.CodecWrappers;
|
||||
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
|
||||
import com.netflix.discovery.shared.transport.jersey3.EurekaIdentityHeaderFilter;
|
||||
import com.netflix.discovery.shared.transport.jersey3.EurekaJersey3Client;
|
||||
import com.netflix.discovery.shared.transport.jersey3.EurekaJersey3ClientImpl;
|
||||
import com.netflix.discovery.shared.transport.jersey3.Jersey3TransportClientFactories;
|
||||
import com.netflix.eureka.DefaultEurekaServerContext;
|
||||
import com.netflix.eureka.EurekaServerConfig;
|
||||
import com.netflix.eureka.EurekaServerContext;
|
||||
@@ -51,7 +49,6 @@ import com.netflix.eureka.resources.DefaultServerCodecs;
|
||||
import com.netflix.eureka.resources.ServerCodecs;
|
||||
import com.netflix.eureka.transport.EurekaServerHttpClientFactory;
|
||||
import com.netflix.eureka.transport.Jersey3DynamicGZIPContentEncodingFilter;
|
||||
import com.netflix.eureka.transport.Jersey3EurekaServerHttpClientFactory;
|
||||
import com.netflix.eureka.transport.Jersey3ReplicationClient;
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
@@ -88,6 +85,7 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.cloud.client.actuator.HasFeatures;
|
||||
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaConstants;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
@@ -108,6 +106,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
* @author Biju Kunjummen
|
||||
* @author Fahim Farook
|
||||
* @author Weix Sun
|
||||
* @author Robert Bleyl
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Import(EurekaServerInitializerConfiguration.class)
|
||||
@@ -186,29 +186,27 @@ public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
|
||||
return new ReplicationClientAdditionalFilters(Collections.emptySet());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(TransportClientFactories.class)
|
||||
public Jersey3TransportClientFactories jersey3TransportClientFactories() {
|
||||
return Jersey3TransportClientFactories.getInstance();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(EurekaServerHttpClientFactory.class)
|
||||
public Jersey3EurekaServerHttpClientFactory jersey3EurekaServerHttpClientFactory() {
|
||||
return new Jersey3EurekaServerHttpClientFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AbstractDiscoveryClientOptionalArgs.class)
|
||||
public Jersey3DiscoveryClientOptionalArgs jersey3DiscoveryClientOptionalArgs() {
|
||||
return new Jersey3DiscoveryClientOptionalArgs();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PeerAwareInstanceRegistry peerAwareInstanceRegistry(ServerCodecs serverCodecs,
|
||||
EurekaServerHttpClientFactory eurekaServerHttpClientFactory) {
|
||||
this.eurekaClient.getApplications(); // force initialization
|
||||
EurekaServerHttpClientFactory eurekaServerHttpClientFactory,
|
||||
EurekaInstanceConfigBean eurekaInstanceConfigBean) {
|
||||
if (eurekaInstanceConfigBean.isAsyncClientInitialization()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Initializing client asynchronously...");
|
||||
}
|
||||
|
||||
ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
executorService.submit(() -> {
|
||||
this.eurekaClient.getApplications();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Asynchronous client initialization done.");
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.eurekaClient.getApplications(); // force initialization
|
||||
}
|
||||
|
||||
return new InstanceRegistry(this.eurekaServerConfig, this.eurekaClientConfig, serverCodecs, this.eurekaClient,
|
||||
eurekaServerHttpClientFactory,
|
||||
this.instanceRegistryProperties.getExpectedNumberOfClientsSendingRenews(),
|
||||
@@ -352,8 +350,9 @@ public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
|
||||
rc.register(new ContainerLifecycleListener() {
|
||||
@Override
|
||||
public void onStartup(Container container) {
|
||||
ServiceLocator serviceLocator = container.getApplicationHandler().getInjectionManager()
|
||||
.getInstance(ServiceLocator.class);
|
||||
ServiceLocator serviceLocator = container.getApplicationHandler()
|
||||
.getInjectionManager()
|
||||
.getInstance(ServiceLocator.class);
|
||||
SpringBridge.getSpringBridge().initializeSpringBridge(serviceLocator);
|
||||
serviceLocator.getService(SpringIntoHK2Bridge.class).bridgeSpringBeanFactory(beanFactory);
|
||||
}
|
||||
@@ -452,17 +451,18 @@ public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
|
||||
|
||||
String jerseyClientName = "Discovery-PeerNodeClient-" + hostname;
|
||||
EurekaJersey3ClientImpl.EurekaJersey3ClientBuilder clientBuilder = new EurekaJersey3ClientImpl.EurekaJersey3ClientBuilder()
|
||||
.withClientName(jerseyClientName).withUserAgent("Java-EurekaClient-Replication")
|
||||
.withEncoderWrapper(serverCodecs.getFullJsonCodec())
|
||||
.withDecoderWrapper(serverCodecs.getFullJsonCodec())
|
||||
.withConnectionTimeout(config.getPeerNodeConnectTimeoutMs())
|
||||
.withReadTimeout(config.getPeerNodeReadTimeoutMs())
|
||||
.withMaxConnectionsPerHost(config.getPeerNodeTotalConnectionsPerHost())
|
||||
.withMaxTotalConnections(config.getPeerNodeTotalConnections())
|
||||
.withConnectionIdleTimeout(config.getPeerNodeConnectionIdleTimeoutSeconds());
|
||||
.withClientName(jerseyClientName)
|
||||
.withUserAgent("Java-EurekaClient-Replication")
|
||||
.withEncoderWrapper(serverCodecs.getFullJsonCodec())
|
||||
.withDecoderWrapper(serverCodecs.getFullJsonCodec())
|
||||
.withConnectionTimeout(config.getPeerNodeConnectTimeoutMs())
|
||||
.withReadTimeout(config.getPeerNodeReadTimeoutMs())
|
||||
.withMaxConnectionsPerHost(config.getPeerNodeTotalConnectionsPerHost())
|
||||
.withMaxTotalConnections(config.getPeerNodeTotalConnections())
|
||||
.withConnectionIdleTimeout(config.getPeerNodeConnectionIdleTimeoutSeconds());
|
||||
|
||||
if (serviceUrl.startsWith("https://") && "true"
|
||||
.equals(System.getProperty("com.netflix.eureka.shouldSSLConnectionsUseSystemSocketFactory"))) {
|
||||
.equals(System.getProperty("com.netflix.eureka.shouldSSLConnectionsUseSystemSocketFactory"))) {
|
||||
clientBuilder.withSystemSSLConfiguration();
|
||||
}
|
||||
jerseyClient = clientBuilder.build();
|
||||
|
||||
+94
-89
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.cloud.netflix.eureka.server;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
@@ -34,6 +35,7 @@ import org.springframework.core.style.ToStringCreator;
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Gregor Zurowski
|
||||
* @author Mooyong Lee
|
||||
*/
|
||||
@ConfigurationProperties(EurekaServerConfigBean.PREFIX)
|
||||
public class EurekaServerConfigBean implements EurekaServerConfig {
|
||||
@@ -43,8 +45,6 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
|
||||
*/
|
||||
public static final String PREFIX = "eureka.server";
|
||||
|
||||
private static final int MINUTES = 60 * 1000;
|
||||
|
||||
@Autowired(required = false)
|
||||
PropertyResolver propertyResolver;
|
||||
|
||||
@@ -54,23 +54,23 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
|
||||
|
||||
private int eIPBindRebindRetries = 3;
|
||||
|
||||
private int eIPBindingRetryIntervalMs = 5 * MINUTES;
|
||||
private int eIPBindingRetryIntervalMs = 300000; // 5 * MINUTES
|
||||
|
||||
private int eIPBindingRetryIntervalMsWhenUnbound = 1 * MINUTES;
|
||||
private int eIPBindingRetryIntervalMsWhenUnbound = 60000; // 1 * MINUTES
|
||||
|
||||
private boolean enableSelfPreservation = true;
|
||||
|
||||
private double renewalPercentThreshold = 0.85;
|
||||
|
||||
private int renewalThresholdUpdateIntervalMs = 15 * MINUTES;
|
||||
private int renewalThresholdUpdateIntervalMs = 900000; // 15 * MINUTES
|
||||
|
||||
private int peerEurekaNodesUpdateIntervalMs = 10 * MINUTES;
|
||||
private int peerEurekaNodesUpdateIntervalMs = 600000; // 10 * MINUTES
|
||||
|
||||
private int numberOfReplicationRetries = 5;
|
||||
|
||||
private int peerEurekaStatusRefreshTimeIntervalMs = 30 * 1000;
|
||||
|
||||
private int waitTimeInMsWhenSyncEmpty = 5 * MINUTES;
|
||||
private int waitTimeInMsWhenSyncEmpty = 300000; // 5 * MINUTES
|
||||
|
||||
private int peerNodeConnectTimeoutMs = 200;
|
||||
|
||||
@@ -82,23 +82,24 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
|
||||
|
||||
private int peerNodeConnectionIdleTimeoutSeconds = 30;
|
||||
|
||||
private long retentionTimeInMSInDeltaQueue = 3 * MINUTES;
|
||||
private long retentionTimeInMSInDeltaQueue = 180000; // 3 * MINUTES
|
||||
|
||||
private long deltaRetentionTimerIntervalInMs = 30 * 1000;
|
||||
private long deltaRetentionTimerIntervalInMs = 30000; // 30 * SECONDS
|
||||
|
||||
private long evictionIntervalTimerInMs = 60 * 1000;
|
||||
|
||||
private int aSGQueryTimeoutMs = 300;
|
||||
|
||||
private long aSGUpdateIntervalMs = 5 * MINUTES;
|
||||
private long aSGUpdateIntervalMs = 300000; // 5 * MINUTES
|
||||
|
||||
private long aSGCacheExpiryTimeoutMs = 10 * MINUTES; // defaults to longer than the
|
||||
private long aSGCacheExpiryTimeoutMs = 600000; // 10 * MINUTES // defaults to longer
|
||||
// than the
|
||||
|
||||
// asg update interval
|
||||
|
||||
private long responseCacheAutoExpirationInSeconds = 180;
|
||||
|
||||
private long responseCacheUpdateIntervalMs = 30 * 1000;
|
||||
private long responseCacheUpdateIntervalMs = 30000; // 30 * SECONDS
|
||||
|
||||
private boolean useReadOnlyResponseCache = true;
|
||||
|
||||
@@ -186,7 +187,7 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
|
||||
|
||||
private int route53BindRebindRetries = 3;
|
||||
|
||||
private int route53BindingRetryIntervalMs = 5 * MINUTES;
|
||||
private int route53BindingRetryIntervalMs = 300000; // 5 * MINUTES
|
||||
|
||||
private long route53DomainTTL = 30;
|
||||
|
||||
@@ -234,7 +235,8 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
|
||||
|
||||
@Override
|
||||
public Set<String> getRemoteRegionAppWhitelist(String regionName) {
|
||||
return this.remoteRegionAppWhitelist.get(regionName == null ? "global" : regionName.trim().toLowerCase());
|
||||
return this.remoteRegionAppWhitelist
|
||||
.get(regionName == null ? "global" : regionName.trim().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1060,80 +1062,83 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("aSGCacheExpiryTimeoutMs", this.aSGCacheExpiryTimeoutMs)
|
||||
.append("aSGQueryTimeoutMs", this.aSGQueryTimeoutMs)
|
||||
.append("aSGUpdateIntervalMs", this.aSGUpdateIntervalMs).append("aWSAccessId", this.aWSAccessId)
|
||||
.append("aWSSecretKey", this.aWSSecretKey).append("batchReplication", this.batchReplication)
|
||||
.append("bindingStrategy", this.bindingStrategy)
|
||||
.append("deltaRetentionTimerIntervalInMs", this.deltaRetentionTimerIntervalInMs)
|
||||
.append("disableDelta", this.disableDelta)
|
||||
.append("disableDeltaForRemoteRegions", this.disableDeltaForRemoteRegions)
|
||||
.append("disableTransparentFallbackToOtherRegion", this.disableTransparentFallbackToOtherRegion)
|
||||
.append("eIPBindRebindRetries", this.eIPBindRebindRetries)
|
||||
.append("eIPBindingRetryIntervalMs", this.eIPBindingRetryIntervalMs)
|
||||
.append("eIPBindingRetryIntervalMsWhenUnbound", this.eIPBindingRetryIntervalMsWhenUnbound)
|
||||
.append("enableReplicatedRequestCompression", this.enableReplicatedRequestCompression)
|
||||
.append("enableSelfPreservation", this.enableSelfPreservation)
|
||||
.append("evictionIntervalTimerInMs", this.evictionIntervalTimerInMs)
|
||||
.append("gZipContentFromRemoteRegion", this.gZipContentFromRemoteRegion)
|
||||
.append("jsonCodecName", this.jsonCodecName)
|
||||
.append("listAutoScalingGroupsRoleName", this.listAutoScalingGroupsRoleName)
|
||||
.append("logIdentityHeaders", this.logIdentityHeaders)
|
||||
.append("maxElementsInPeerReplicationPool", this.maxElementsInPeerReplicationPool)
|
||||
.append("maxElementsInStatusReplicationPool", this.maxElementsInStatusReplicationPool)
|
||||
.append("maxIdleThreadAgeInMinutesForPeerReplication", this.maxIdleThreadAgeInMinutesForPeerReplication)
|
||||
.append("maxIdleThreadInMinutesAgeForStatusReplication",
|
||||
this.maxIdleThreadInMinutesAgeForStatusReplication)
|
||||
.append("maxThreadsForPeerReplication", this.maxThreadsForPeerReplication)
|
||||
.append("maxThreadsForStatusReplication", this.maxThreadsForStatusReplication)
|
||||
.append("maxTimeForReplication", this.maxTimeForReplication)
|
||||
.append("minAvailableInstancesForPeerReplication", this.minAvailableInstancesForPeerReplication)
|
||||
.append("minThreadsForPeerReplication", this.minThreadsForPeerReplication)
|
||||
.append("minThreadsForStatusReplication", this.minThreadsForStatusReplication)
|
||||
.append("numberOfReplicationRetries", this.numberOfReplicationRetries)
|
||||
.append("peerEurekaNodesUpdateIntervalMs", this.peerEurekaNodesUpdateIntervalMs)
|
||||
.append("peerEurekaStatusRefreshTimeIntervalMs", this.peerEurekaStatusRefreshTimeIntervalMs)
|
||||
.append("peerNodeConnectTimeoutMs", this.peerNodeConnectTimeoutMs)
|
||||
.append("peerNodeConnectionIdleTimeoutSeconds", this.peerNodeConnectionIdleTimeoutSeconds)
|
||||
.append("peerNodeReadTimeoutMs", this.peerNodeReadTimeoutMs)
|
||||
.append("peerNodeTotalConnections", this.peerNodeTotalConnections)
|
||||
.append("peerNodeTotalConnectionsPerHost", this.peerNodeTotalConnectionsPerHost)
|
||||
.append("primeAwsReplicaConnections", this.primeAwsReplicaConnections)
|
||||
.append("propertyResolver", this.propertyResolver)
|
||||
.append("rateLimiterBurstSize", this.rateLimiterBurstSize)
|
||||
.append("rateLimiterEnabled", this.rateLimiterEnabled)
|
||||
.append("rateLimiterFullFetchAverageRate", this.rateLimiterFullFetchAverageRate)
|
||||
.append("rateLimiterPrivilegedClients", this.rateLimiterPrivilegedClients)
|
||||
.append("rateLimiterRegistryFetchAverageRate", this.rateLimiterRegistryFetchAverageRate)
|
||||
.append("rateLimiterThrottleStandardClients", this.rateLimiterThrottleStandardClients)
|
||||
.append("registrySyncRetries", this.registrySyncRetries)
|
||||
.append("registrySyncRetryWaitMs", this.registrySyncRetryWaitMs)
|
||||
.append("remoteRegionAppWhitelist", this.remoteRegionAppWhitelist)
|
||||
.append("remoteRegionConnectTimeoutMs", this.remoteRegionConnectTimeoutMs)
|
||||
.append("remoteRegionConnectionIdleTimeoutSeconds", this.remoteRegionConnectionIdleTimeoutSeconds)
|
||||
.append("remoteRegionFetchThreadPoolSize", this.remoteRegionFetchThreadPoolSize)
|
||||
.append("remoteRegionReadTimeoutMs", this.remoteRegionReadTimeoutMs)
|
||||
.append("remoteRegionRegistryFetchInterval", this.remoteRegionRegistryFetchInterval)
|
||||
.append("remoteRegionTotalConnections", this.remoteRegionTotalConnections)
|
||||
.append("remoteRegionTotalConnectionsPerHost", this.remoteRegionTotalConnectionsPerHost)
|
||||
.append("remoteRegionTrustStore", this.remoteRegionTrustStore)
|
||||
.append("remoteRegionTrustStorePassword", this.remoteRegionTrustStorePassword)
|
||||
.append("remoteRegionUrls", this.remoteRegionUrls)
|
||||
.append("remoteRegionUrlsWithName", this.remoteRegionUrlsWithName)
|
||||
.append("renewalPercentThreshold", this.renewalPercentThreshold)
|
||||
.append("renewalThresholdUpdateIntervalMs", this.renewalThresholdUpdateIntervalMs)
|
||||
.append("responseCacheAutoExpirationInSeconds", this.responseCacheAutoExpirationInSeconds)
|
||||
.append("responseCacheUpdateIntervalMs", this.responseCacheUpdateIntervalMs)
|
||||
.append("retentionTimeInMSInDeltaQueue", this.retentionTimeInMSInDeltaQueue)
|
||||
.append("route53BindRebindRetries", this.route53BindRebindRetries)
|
||||
.append("route53BindingRetryIntervalMs", this.route53BindingRetryIntervalMs)
|
||||
.append("route53DomainTTL", this.route53DomainTTL)
|
||||
.append("syncWhenTimestampDiffers", this.syncWhenTimestampDiffers)
|
||||
.append("useReadOnlyResponseCache", this.useReadOnlyResponseCache)
|
||||
.append("waitTimeInMsWhenSyncEmpty", this.waitTimeInMsWhenSyncEmpty)
|
||||
.append("xmlCodecName", this.xmlCodecName)
|
||||
.append("initialCapacityOfResponseCache", this.initialCapacityOfResponseCache)
|
||||
.append("expectedClientRenewalIntervalSeconds", this.expectedClientRenewalIntervalSeconds)
|
||||
.append("useAwsAsgApi", this.useAwsAsgApi).append("myUrl", this.myUrl).toString();
|
||||
.append("aSGQueryTimeoutMs", this.aSGQueryTimeoutMs)
|
||||
.append("aSGUpdateIntervalMs", this.aSGUpdateIntervalMs)
|
||||
.append("aWSAccessId", this.aWSAccessId)
|
||||
.append("aWSSecretKey", this.aWSSecretKey)
|
||||
.append("batchReplication", this.batchReplication)
|
||||
.append("bindingStrategy", this.bindingStrategy)
|
||||
.append("deltaRetentionTimerIntervalInMs", this.deltaRetentionTimerIntervalInMs)
|
||||
.append("disableDelta", this.disableDelta)
|
||||
.append("disableDeltaForRemoteRegions", this.disableDeltaForRemoteRegions)
|
||||
.append("disableTransparentFallbackToOtherRegion", this.disableTransparentFallbackToOtherRegion)
|
||||
.append("eIPBindRebindRetries", this.eIPBindRebindRetries)
|
||||
.append("eIPBindingRetryIntervalMs", this.eIPBindingRetryIntervalMs)
|
||||
.append("eIPBindingRetryIntervalMsWhenUnbound", this.eIPBindingRetryIntervalMsWhenUnbound)
|
||||
.append("enableReplicatedRequestCompression", this.enableReplicatedRequestCompression)
|
||||
.append("enableSelfPreservation", this.enableSelfPreservation)
|
||||
.append("evictionIntervalTimerInMs", this.evictionIntervalTimerInMs)
|
||||
.append("gZipContentFromRemoteRegion", this.gZipContentFromRemoteRegion)
|
||||
.append("jsonCodecName", this.jsonCodecName)
|
||||
.append("listAutoScalingGroupsRoleName", this.listAutoScalingGroupsRoleName)
|
||||
.append("logIdentityHeaders", this.logIdentityHeaders)
|
||||
.append("maxElementsInPeerReplicationPool", this.maxElementsInPeerReplicationPool)
|
||||
.append("maxElementsInStatusReplicationPool", this.maxElementsInStatusReplicationPool)
|
||||
.append("maxIdleThreadAgeInMinutesForPeerReplication", this.maxIdleThreadAgeInMinutesForPeerReplication)
|
||||
.append("maxIdleThreadInMinutesAgeForStatusReplication", this.maxIdleThreadInMinutesAgeForStatusReplication)
|
||||
.append("maxThreadsForPeerReplication", this.maxThreadsForPeerReplication)
|
||||
.append("maxThreadsForStatusReplication", this.maxThreadsForStatusReplication)
|
||||
.append("maxTimeForReplication", this.maxTimeForReplication)
|
||||
.append("minAvailableInstancesForPeerReplication", this.minAvailableInstancesForPeerReplication)
|
||||
.append("minThreadsForPeerReplication", this.minThreadsForPeerReplication)
|
||||
.append("minThreadsForStatusReplication", this.minThreadsForStatusReplication)
|
||||
.append("numberOfReplicationRetries", this.numberOfReplicationRetries)
|
||||
.append("peerEurekaNodesUpdateIntervalMs", this.peerEurekaNodesUpdateIntervalMs)
|
||||
.append("peerEurekaStatusRefreshTimeIntervalMs", this.peerEurekaStatusRefreshTimeIntervalMs)
|
||||
.append("peerNodeConnectTimeoutMs", this.peerNodeConnectTimeoutMs)
|
||||
.append("peerNodeConnectionIdleTimeoutSeconds", this.peerNodeConnectionIdleTimeoutSeconds)
|
||||
.append("peerNodeReadTimeoutMs", this.peerNodeReadTimeoutMs)
|
||||
.append("peerNodeTotalConnections", this.peerNodeTotalConnections)
|
||||
.append("peerNodeTotalConnectionsPerHost", this.peerNodeTotalConnectionsPerHost)
|
||||
.append("primeAwsReplicaConnections", this.primeAwsReplicaConnections)
|
||||
.append("propertyResolver", this.propertyResolver)
|
||||
.append("rateLimiterBurstSize", this.rateLimiterBurstSize)
|
||||
.append("rateLimiterEnabled", this.rateLimiterEnabled)
|
||||
.append("rateLimiterFullFetchAverageRate", this.rateLimiterFullFetchAverageRate)
|
||||
.append("rateLimiterPrivilegedClients", this.rateLimiterPrivilegedClients)
|
||||
.append("rateLimiterRegistryFetchAverageRate", this.rateLimiterRegistryFetchAverageRate)
|
||||
.append("rateLimiterThrottleStandardClients", this.rateLimiterThrottleStandardClients)
|
||||
.append("registrySyncRetries", this.registrySyncRetries)
|
||||
.append("registrySyncRetryWaitMs", this.registrySyncRetryWaitMs)
|
||||
.append("remoteRegionAppWhitelist", this.remoteRegionAppWhitelist)
|
||||
.append("remoteRegionConnectTimeoutMs", this.remoteRegionConnectTimeoutMs)
|
||||
.append("remoteRegionConnectionIdleTimeoutSeconds", this.remoteRegionConnectionIdleTimeoutSeconds)
|
||||
.append("remoteRegionFetchThreadPoolSize", this.remoteRegionFetchThreadPoolSize)
|
||||
.append("remoteRegionReadTimeoutMs", this.remoteRegionReadTimeoutMs)
|
||||
.append("remoteRegionRegistryFetchInterval", this.remoteRegionRegistryFetchInterval)
|
||||
.append("remoteRegionTotalConnections", this.remoteRegionTotalConnections)
|
||||
.append("remoteRegionTotalConnectionsPerHost", this.remoteRegionTotalConnectionsPerHost)
|
||||
.append("remoteRegionTrustStore", this.remoteRegionTrustStore)
|
||||
.append("remoteRegionTrustStorePassword", this.remoteRegionTrustStorePassword)
|
||||
.append("remoteRegionUrls", this.remoteRegionUrls)
|
||||
.append("remoteRegionUrlsWithName", this.remoteRegionUrlsWithName)
|
||||
.append("renewalPercentThreshold", this.renewalPercentThreshold)
|
||||
.append("renewalThresholdUpdateIntervalMs", this.renewalThresholdUpdateIntervalMs)
|
||||
.append("responseCacheAutoExpirationInSeconds", this.responseCacheAutoExpirationInSeconds)
|
||||
.append("responseCacheUpdateIntervalMs", this.responseCacheUpdateIntervalMs)
|
||||
.append("retentionTimeInMSInDeltaQueue", this.retentionTimeInMSInDeltaQueue)
|
||||
.append("route53BindRebindRetries", this.route53BindRebindRetries)
|
||||
.append("route53BindingRetryIntervalMs", this.route53BindingRetryIntervalMs)
|
||||
.append("route53DomainTTL", this.route53DomainTTL)
|
||||
.append("syncWhenTimestampDiffers", this.syncWhenTimestampDiffers)
|
||||
.append("useReadOnlyResponseCache", this.useReadOnlyResponseCache)
|
||||
.append("waitTimeInMsWhenSyncEmpty", this.waitTimeInMsWhenSyncEmpty)
|
||||
.append("xmlCodecName", this.xmlCodecName)
|
||||
.append("initialCapacityOfResponseCache", this.initialCapacityOfResponseCache)
|
||||
.append("expectedClientRenewalIntervalSeconds", this.expectedClientRenewalIntervalSeconds)
|
||||
.append("useAwsAsgApi", this.useAwsAsgApi)
|
||||
.append("myUrl", this.myUrl)
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2013-2025 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.cloud.netflix.eureka.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
|
||||
import com.netflix.discovery.Jersey3DiscoveryClientOptionalArgs;
|
||||
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
|
||||
import com.netflix.discovery.shared.transport.jersey3.Jersey3TransportClientFactories;
|
||||
import com.netflix.eureka.transport.EurekaServerHttpClientFactory;
|
||||
import com.netflix.eureka.transport.Jersey3EurekaServerHttpClientFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cloud.configuration.SSLContextFactory;
|
||||
import org.springframework.cloud.configuration.TlsProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
/**
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
|
||||
public class EurekaServerJerseyClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AbstractDiscoveryClientOptionalArgs.class)
|
||||
public Jersey3DiscoveryClientOptionalArgs jersey3DiscoveryClientOptionalArgs(
|
||||
@Autowired(required = false) TlsProperties tlsProperties) throws GeneralSecurityException, IOException {
|
||||
Jersey3DiscoveryClientOptionalArgs optionalArgs = new Jersey3DiscoveryClientOptionalArgs();
|
||||
if (tlsProperties != null && tlsProperties.isEnabled()) {
|
||||
SSLContextFactory factory = new SSLContextFactory(tlsProperties);
|
||||
optionalArgs.setSSLContext(factory.createSSLContext());
|
||||
}
|
||||
return optionalArgs;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(TransportClientFactories.class)
|
||||
public Jersey3TransportClientFactories jersey3TransportClientFactories() {
|
||||
return Jersey3TransportClientFactories.getInstance();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(EurekaServerHttpClientFactory.class)
|
||||
public Jersey3EurekaServerHttpClientFactory jersey3EurekaServerHttpClientFactory() {
|
||||
return new Jersey3EurekaServerHttpClientFactory();
|
||||
}
|
||||
|
||||
}
|
||||
+31
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -39,6 +39,7 @@ import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Wonchul Heo
|
||||
*/
|
||||
public class InstanceRegistry extends PeerAwareInstanceRegistryImpl implements ApplicationContextAware {
|
||||
|
||||
@@ -78,52 +79,65 @@ public class InstanceRegistry extends PeerAwareInstanceRegistryImpl implements A
|
||||
|
||||
@Override
|
||||
public void register(InstanceInfo info, int leaseDuration, boolean isReplication) {
|
||||
handleRegistration(info, leaseDuration, isReplication);
|
||||
super.register(info, leaseDuration, isReplication);
|
||||
handleRegistration(info, leaseDuration, isReplication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(final InstanceInfo info, final boolean isReplication) {
|
||||
handleRegistration(info, resolveInstanceLeaseDuration(info), isReplication);
|
||||
super.register(info, isReplication);
|
||||
handleRegistration(info, resolveInstanceLeaseDuration(info), isReplication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(String appName, String serverId, boolean isReplication) {
|
||||
handleCancelation(appName, serverId, isReplication);
|
||||
return super.cancel(appName, serverId, isReplication);
|
||||
final boolean cancelled = super.cancel(appName, serverId, isReplication);
|
||||
if (cancelled) {
|
||||
handleCancelation(appName, serverId, isReplication);
|
||||
}
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean renew(final String appName, final String serverId, boolean isReplication) {
|
||||
log("renew " + appName + " serverId " + serverId + ", isReplication {}" + isReplication);
|
||||
Application application = getApplication(appName);
|
||||
if (application != null) {
|
||||
InstanceInfo instanceInfo = application.getByInstanceId(serverId);
|
||||
if (instanceInfo != null) {
|
||||
publishEvent(new EurekaInstanceRenewedEvent(this, appName, serverId, instanceInfo, isReplication));
|
||||
}
|
||||
final boolean renewed = super.renew(appName, serverId, isReplication);
|
||||
if (renewed) {
|
||||
handleRenewal(appName, serverId, isReplication);
|
||||
}
|
||||
return super.renew(appName, serverId, isReplication);
|
||||
return renewed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean internalCancel(String appName, String id, boolean isReplication) {
|
||||
handleCancelation(appName, id, isReplication);
|
||||
return super.internalCancel(appName, id, isReplication);
|
||||
final boolean cancelled = super.internalCancel(appName, id, isReplication);
|
||||
if (cancelled) {
|
||||
handleCancelation(appName, id, isReplication);
|
||||
}
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
private void handleCancelation(String appName, String id, boolean isReplication) {
|
||||
log("cancel " + appName + ", serverId " + id + ", isReplication " + isReplication);
|
||||
log("cancelled " + appName + ", serverId " + id + ", isReplication " + isReplication);
|
||||
publishEvent(new EurekaInstanceCanceledEvent(this, appName, id, isReplication));
|
||||
}
|
||||
|
||||
private void handleRegistration(InstanceInfo info, int leaseDuration, boolean isReplication) {
|
||||
log("register " + info.getAppName() + ", vip " + info.getVIPAddress() + ", leaseDuration " + leaseDuration
|
||||
log("registered " + info.getAppName() + ", vip " + info.getVIPAddress() + ", leaseDuration " + leaseDuration
|
||||
+ ", isReplication " + isReplication);
|
||||
publishEvent(new EurekaInstanceRegisteredEvent(this, info, leaseDuration, isReplication));
|
||||
}
|
||||
|
||||
private void handleRenewal(final String appName, final String serverId, boolean isReplication) {
|
||||
log("renewed " + appName + ", serverId " + serverId + ", isReplication " + isReplication);
|
||||
final Application application = getApplication(appName);
|
||||
if (application != null) {
|
||||
final InstanceInfo instanceInfo = application.getByInstanceId(serverId);
|
||||
if (instanceInfo != null) {
|
||||
publishEvent(new EurekaInstanceRenewedEvent(this, appName, serverId, instanceInfo, isReplication));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void log(String message) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(message);
|
||||
|
||||
+10
-3
@@ -84,9 +84,16 @@ public class EurekaInstanceCanceledEvent extends ApplicationEvent {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("EurekaInstanceCanceledEvent{").append("appName='").append(appName).append("', ")
|
||||
.append("serverId='").append(serverId).append("', ").append("replication=").append(replication)
|
||||
.append("}").toString();
|
||||
return new StringBuilder("EurekaInstanceCanceledEvent{").append("appName='")
|
||||
.append(appName)
|
||||
.append("', ")
|
||||
.append("serverId='")
|
||||
.append(serverId)
|
||||
.append("', ")
|
||||
.append("replication=")
|
||||
.append(replication)
|
||||
.append("}")
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-3
@@ -87,9 +87,16 @@ public class EurekaInstanceRegisteredEvent extends ApplicationEvent {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("EurekaInstanceRegisteredEvent{").append("instanceInfo=").append(instanceInfo)
|
||||
.append(", ").append("leaseDuration=").append(leaseDuration).append(", ").append("replication=")
|
||||
.append(replication).append("}").toString();
|
||||
return new StringBuilder("EurekaInstanceRegisteredEvent{").append("instanceInfo=")
|
||||
.append(instanceInfo)
|
||||
.append(", ")
|
||||
.append("leaseDuration=")
|
||||
.append(leaseDuration)
|
||||
.append(", ")
|
||||
.append("replication=")
|
||||
.append(replication)
|
||||
.append("}")
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-3
@@ -98,9 +98,19 @@ public class EurekaInstanceRenewedEvent extends ApplicationEvent {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("EurekaInstanceRenewedEvent{").append("appName='").append(appName).append("', ")
|
||||
.append("serverId='").append(serverId).append("', ").append("instanceInfo=").append(instanceInfo)
|
||||
.append(", ").append("replication=").append(replication).append("}").toString();
|
||||
return new StringBuilder("EurekaInstanceRenewedEvent{").append("appName='")
|
||||
.append(appName)
|
||||
.append("', ")
|
||||
.append("serverId='")
|
||||
.append(serverId)
|
||||
.append("', ")
|
||||
.append("instanceInfo=")
|
||||
.append(instanceInfo)
|
||||
.append(", ")
|
||||
.append("replication=")
|
||||
.append(replication)
|
||||
.append("}")
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2013-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.cloud.netflix.eureka.server.metrics;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import io.micrometer.core.instrument.Tag;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
|
||||
/**
|
||||
* Default implementation for {@link EurekaInstanceTagsProvider}.
|
||||
*
|
||||
* @author Wonchul Heo
|
||||
* @since 4.1.2
|
||||
*/
|
||||
class DefaultEurekaInstanceTagsProvider implements EurekaInstanceTagsProvider {
|
||||
|
||||
@Override
|
||||
public Tags eurekaInstanceTags(InstanceInfo instanceInfo) {
|
||||
return Tags.of(Tag.of("application", instanceInfo.getAppName()),
|
||||
Tag.of("status", instanceInfo.getStatus().name()));
|
||||
}
|
||||
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2013-2025 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.cloud.netflix.eureka.server.metrics;
|
||||
|
||||
import com.netflix.eureka.registry.PeerAwareInstanceRegistry;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import static org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME;
|
||||
|
||||
/**
|
||||
* Auto-configuration for Eureka Instance metrics.
|
||||
*
|
||||
* @author Wonchul Heo
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 4.1.2
|
||||
*/
|
||||
@ConditionalOnClass({ MeterRegistry.class, ThreadPoolTaskExecutor.class })
|
||||
@ConditionalOnBean(MeterRegistry.class)
|
||||
@AutoConfiguration(after = { MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class,
|
||||
EurekaServerAutoConfiguration.class, TaskExecutionAutoConfiguration.class })
|
||||
@ConditionalOnProperty(name = "eureka.server.metrics.enabled", havingValue = "true")
|
||||
class EurekaInstanceMetricsAutoConfiguration {
|
||||
|
||||
@ConditionalOnMissingBean
|
||||
@Bean
|
||||
public EurekaInstanceTagsProvider eurekaInstanceTagProvider() {
|
||||
return new DefaultEurekaInstanceTagsProvider();
|
||||
}
|
||||
|
||||
@ConditionalOnMissingBean
|
||||
@Bean
|
||||
public EurekaInstanceMonitor eurekaInstanceMeterBinder(MeterRegistry meterRegistry,
|
||||
PeerAwareInstanceRegistry instanceRegistry, EurekaInstanceTagsProvider tagProvider,
|
||||
@Qualifier(APPLICATION_TASK_EXECUTOR_BEAN_NAME) TaskExecutor executor) {
|
||||
return new EurekaInstanceMonitor(meterRegistry, instanceRegistry, tagProvider, executor);
|
||||
}
|
||||
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2013-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.cloud.netflix.eureka.server.metrics;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.netflix.eureka.registry.PeerAwareInstanceRegistry;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.MultiGauge;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
|
||||
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceCanceledEvent;
|
||||
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent;
|
||||
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRenewedEvent;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.event.SmartApplicationListener;
|
||||
|
||||
/**
|
||||
* {@link SmartApplicationListener} for collecting event metrics from
|
||||
* {@link PeerAwareInstanceRegistry}.
|
||||
*
|
||||
* @author Wonchul Heo
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 4.1.2
|
||||
*/
|
||||
public class EurekaInstanceMonitor implements SmartApplicationListener {
|
||||
|
||||
private final MultiGauge eurekaInstances;
|
||||
|
||||
private final PeerAwareInstanceRegistry instanceRegistry;
|
||||
|
||||
private final EurekaInstanceTagsProvider tagProvider;
|
||||
|
||||
private final Executor executor;
|
||||
|
||||
EurekaInstanceMonitor(MeterRegistry meterRegistry, PeerAwareInstanceRegistry instanceRegistry,
|
||||
EurekaInstanceTagsProvider tagProvider, Executor executor) {
|
||||
Objects.requireNonNull(meterRegistry);
|
||||
this.instanceRegistry = Objects.requireNonNull(instanceRegistry);
|
||||
this.tagProvider = Objects.requireNonNull(tagProvider);
|
||||
this.eurekaInstances = MultiGauge.builder("eureka.server.instances")
|
||||
.description("Number of application instances registered with the Eureka server.")
|
||||
.register(meterRegistry);
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
|
||||
// If events that change state are added, an event class must be added.
|
||||
return EurekaInstanceCanceledEvent.class.isAssignableFrom(eventType)
|
||||
|| EurekaInstanceRegisteredEvent.class.isAssignableFrom(eventType)
|
||||
|| EurekaInstanceRenewedEvent.class.isAssignableFrom(eventType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
executor.execute(() -> {
|
||||
Map<Tags, Long> aggregatedCounts = collectAggregatedCounts();
|
||||
registerMetrics(aggregatedCounts);
|
||||
});
|
||||
}
|
||||
|
||||
private Map<Tags, Long> collectAggregatedCounts() {
|
||||
return instanceRegistry.getApplications()
|
||||
.getRegisteredApplications()
|
||||
.stream()
|
||||
.flatMap(application -> application.getInstances().stream())
|
||||
.collect(Collectors.groupingBy(tagProvider::eurekaInstanceTags, Collectors.counting()));
|
||||
}
|
||||
|
||||
private void registerMetrics(Map<Tags, Long> aggregatedCounts) {
|
||||
eurekaInstances.register(aggregatedCounts.entrySet()
|
||||
.stream()
|
||||
.map(entry -> MultiGauge.Row.of(entry.getKey(), entry.getValue()))
|
||||
.collect(Collectors.toList()), true);
|
||||
}
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2013-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.cloud.netflix.eureka.server.metrics;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
|
||||
/**
|
||||
* Provides {@link Tags} for Eureka instance metrics.
|
||||
*
|
||||
* @author Wonchul Heo
|
||||
* @since 4.1.2
|
||||
*/
|
||||
public interface EurekaInstanceTagsProvider {
|
||||
|
||||
Tags eurekaInstanceTags(InstanceInfo instanceInfo);
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"properties": [
|
||||
{
|
||||
"name": "eureka.server.metrics.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"defaultValue": "false",
|
||||
"description": "Indicates whether the metrics should be enabled for eureka instances."
|
||||
}
|
||||
]
|
||||
}
|
||||
+3
-1
@@ -1 +1,3 @@
|
||||
org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration
|
||||
org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration
|
||||
org.springframework.cloud.netflix.eureka.server.EurekaServerJerseyClientAutoConfiguration
|
||||
org.springframework.cloud.netflix.eureka.server.metrics.EurekaInstanceMetricsAutoConfiguration
|
||||
|
||||
+4
-4
@@ -53,7 +53,7 @@ class ApplicationContextTests {
|
||||
void catalogLoads() {
|
||||
@SuppressWarnings("rawtypes")
|
||||
ResponseEntity<Map> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/context/eureka/apps", Map.class);
|
||||
.getForEntity("http://localhost:" + this.port + "/context/eureka/apps", Map.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
String computedPath = entity.getHeaders().getFirst("X-Version-Filter-Computed-Path");
|
||||
assertThat(computedPath).isEqualTo("/context/eureka/v2/apps");
|
||||
@@ -62,7 +62,7 @@ class ApplicationContextTests {
|
||||
@Test
|
||||
void dashboardLoads() {
|
||||
ResponseEntity<String> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/context/", String.class);
|
||||
.getForEntity("http://localhost:" + this.port + "/context/", String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
String body = entity.getBody();
|
||||
// System.err.println(body);
|
||||
@@ -75,14 +75,14 @@ class ApplicationContextTests {
|
||||
@Test
|
||||
void cssAvailable() {
|
||||
ResponseEntity<String> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/context/eureka/css/wro.css", String.class);
|
||||
.getForEntity("http://localhost:" + this.port + "/context/eureka/css/wro.css", String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
void jsAvailable() {
|
||||
ResponseEntity<String> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/context/eureka/js/wro.js", String.class);
|
||||
.getForEntity("http://localhost:" + this.port + "/context/eureka/js/wro.js", String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ class ApplicationDashboardDisabledTests {
|
||||
void catalogLoads() {
|
||||
@SuppressWarnings("rawtypes")
|
||||
ResponseEntity<Map> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/eureka/apps", Map.class);
|
||||
.getForEntity("http://localhost:" + this.port + "/eureka/apps", Map.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -41,14 +41,14 @@ class ApplicationDashboardPathTests {
|
||||
void catalogLoads() {
|
||||
@SuppressWarnings("rawtypes")
|
||||
ResponseEntity<Map> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/eureka/apps", Map.class);
|
||||
.getForEntity("http://localhost:" + this.port + "/eureka/apps", Map.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
void dashboardLoads() {
|
||||
ResponseEntity<String> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/dashboard", String.class);
|
||||
.getForEntity("http://localhost:" + this.port + "/dashboard", String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
String body = entity.getBody();
|
||||
// System.err.println(body);
|
||||
@@ -65,14 +65,14 @@ class ApplicationDashboardPathTests {
|
||||
@Test
|
||||
void cssAvailable() {
|
||||
ResponseEntity<String> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/eureka/css/wro.css", String.class);
|
||||
.getForEntity("http://localhost:" + this.port + "/eureka/css/wro.css", String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
void jsAvailable() {
|
||||
ResponseEntity<String> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/eureka/js/wro.js", String.class);
|
||||
.getForEntity("http://localhost:" + this.port + "/eureka/js/wro.js", String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -52,14 +52,14 @@ class ApplicationServletPathTests {
|
||||
void catalogLoads() {
|
||||
@SuppressWarnings("rawtypes")
|
||||
ResponseEntity<Map> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/servlet/eureka/apps", Map.class);
|
||||
.getForEntity("http://localhost:" + this.port + "/servlet/eureka/apps", Map.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
void dashboardLoads() {
|
||||
ResponseEntity<String> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/servlet/", String.class);
|
||||
.getForEntity("http://localhost:" + this.port + "/servlet/", String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
String body = entity.getBody();
|
||||
// System.err.println(body);
|
||||
@@ -72,14 +72,14 @@ class ApplicationServletPathTests {
|
||||
@Test
|
||||
void cssAvailable() {
|
||||
ResponseEntity<String> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/servlet/eureka/css/wro.css", String.class);
|
||||
.getForEntity("http://localhost:" + this.port + "/servlet/eureka/css/wro.css", String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
void jsAvailable() {
|
||||
ResponseEntity<String> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/servlet/eureka/js/wro.js", String.class);
|
||||
.getForEntity("http://localhost:" + this.port + "/servlet/eureka/js/wro.js", String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -59,7 +59,7 @@ class ApplicationTests {
|
||||
void catalogLoads() {
|
||||
@SuppressWarnings("rawtypes")
|
||||
ResponseEntity<Map> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/eureka/apps", Map.class);
|
||||
.getForEntity("http://localhost:" + this.port + "/eureka/apps", Map.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@@ -99,12 +99,14 @@ class ApplicationTests {
|
||||
@Test
|
||||
void customCodecWorks() throws Exception {
|
||||
assertThat(this.serverCodecs).as("serverCodecs is wrong type")
|
||||
.isInstanceOf(EurekaServerAutoConfiguration.CloudServerCodecs.class);
|
||||
.isInstanceOf(EurekaServerAutoConfiguration.CloudServerCodecs.class);
|
||||
CodecWrapper codec = this.serverCodecs.getFullJsonCodec();
|
||||
assertThat(codec).as("codec is wrong type").isInstanceOf(CloudJacksonJson.class);
|
||||
|
||||
InstanceInfo instanceInfo = InstanceInfo.Builder.newBuilder().setAppName("fooapp").add("instanceId", "foo")
|
||||
.build();
|
||||
InstanceInfo instanceInfo = InstanceInfo.Builder.newBuilder()
|
||||
.setAppName("fooapp")
|
||||
.add("instanceId", "foo")
|
||||
.build();
|
||||
String encoded = codec.encode(instanceInfo);
|
||||
InstanceInfo decoded = codec.decode(encoded, InstanceInfo.class);
|
||||
assertThat(decoded.getInstanceId()).as("instanceId was wrong").isEqualTo("foo");
|
||||
|
||||
+18
-9
@@ -74,9 +74,12 @@ class EurekaControllerReplicasTests {
|
||||
@Test
|
||||
void testFilterReplicasNoAuth() {
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
StatusInfo statusInfo = StatusInfo.Builder.newBuilder().add("registered-replicas", empty)
|
||||
.add("available-replicas", noAuthList1).add("unavailable-replicas", noAuthList2)
|
||||
.withInstanceInfo(this.instanceInfo).build();
|
||||
StatusInfo statusInfo = StatusInfo.Builder.newBuilder()
|
||||
.add("registered-replicas", empty)
|
||||
.add("available-replicas", noAuthList1)
|
||||
.add("unavailable-replicas", noAuthList2)
|
||||
.withInstanceInfo(this.instanceInfo)
|
||||
.build();
|
||||
EurekaController controller = new EurekaController(null, new EurekaProperties());
|
||||
|
||||
controller.filterReplicas(model, statusInfo);
|
||||
@@ -92,9 +95,12 @@ class EurekaControllerReplicasTests {
|
||||
@Test
|
||||
void testFilterReplicasAuth() {
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
StatusInfo statusInfo = StatusInfo.Builder.newBuilder().add("registered-replicas", authList2)
|
||||
.add("available-replicas", authList1).add("unavailable-replicas", empty).withInstanceInfo(instanceInfo)
|
||||
.build();
|
||||
StatusInfo statusInfo = StatusInfo.Builder.newBuilder()
|
||||
.add("registered-replicas", authList2)
|
||||
.add("available-replicas", authList1)
|
||||
.add("unavailable-replicas", empty)
|
||||
.withInstanceInfo(instanceInfo)
|
||||
.build();
|
||||
EurekaController controller = new EurekaController(null, new EurekaProperties());
|
||||
|
||||
controller.filterReplicas(model, statusInfo);
|
||||
@@ -110,9 +116,12 @@ class EurekaControllerReplicasTests {
|
||||
@Test
|
||||
void testFilterReplicasAuthWithCombinationList() {
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
StatusInfo statusInfo = StatusInfo.Builder.newBuilder().add("registered-replicas", totalAutoList)
|
||||
.add("available-replicas", combinationAuthList1).add("unavailable-replicas", combinationAuthList2)
|
||||
.withInstanceInfo(instanceInfo).build();
|
||||
StatusInfo statusInfo = StatusInfo.Builder.newBuilder()
|
||||
.add("registered-replicas", totalAutoList)
|
||||
.add("available-replicas", combinationAuthList1)
|
||||
.add("unavailable-replicas", combinationAuthList2)
|
||||
.withInstanceInfo(instanceInfo)
|
||||
.build();
|
||||
EurekaController controller = new EurekaController(null, new EurekaProperties());
|
||||
|
||||
controller.filterReplicas(model, statusInfo);
|
||||
|
||||
+9
-4
@@ -55,8 +55,10 @@ class EurekaControllerTests {
|
||||
PeerEurekaNodes peerEurekaNodes = mock(PeerEurekaNodes.class);
|
||||
when(peerEurekaNodes.getPeerNodesView()).thenReturn(Collections.<PeerEurekaNode>emptyList());
|
||||
|
||||
InstanceInfo instanceInfo = InstanceInfo.Builder.newBuilder().setAppName("test")
|
||||
.setDataCenterInfo(new MyDataCenterInfo(DataCenterInfo.Name.MyOwn)).build();
|
||||
InstanceInfo instanceInfo = InstanceInfo.Builder.newBuilder()
|
||||
.setAppName("test")
|
||||
.setDataCenterInfo(new MyDataCenterInfo(DataCenterInfo.Name.MyOwn))
|
||||
.build();
|
||||
|
||||
this.infoManager = mock(ApplicationInfoManager.class);
|
||||
this.original = ApplicationInfoManager.getInstance();
|
||||
@@ -64,8 +66,11 @@ class EurekaControllerTests {
|
||||
when(this.infoManager.getInfo()).thenReturn(instanceInfo);
|
||||
|
||||
Application myapp = new Application("myapp");
|
||||
myapp.addInstance(InstanceInfo.Builder.newBuilder().setAppName("myapp")
|
||||
.setDataCenterInfo(new MyDataCenterInfo(DataCenterInfo.Name.MyOwn)).setInstanceId("myapp:1").build());
|
||||
myapp.addInstance(InstanceInfo.Builder.newBuilder()
|
||||
.setAppName("myapp")
|
||||
.setDataCenterInfo(new MyDataCenterInfo(DataCenterInfo.Name.MyOwn))
|
||||
.setInstanceId("myapp:1")
|
||||
.build());
|
||||
|
||||
ArrayList<Application> applications = new ArrayList<>();
|
||||
applications.add(myapp);
|
||||
|
||||
+2
-1
@@ -45,7 +45,8 @@ class EurekaCustomPeerNodesTests {
|
||||
@Test
|
||||
void testCustomPeerNodesShouldTakePrecedenceOverDefault() {
|
||||
assertThat(peerEurekaNodes instanceof CustomEurekaPeerNodes)
|
||||
.as("PeerEurekaNodes should be the user created one").isTrue();
|
||||
.as("PeerEurekaNodes should be the user created one")
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2013-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.cloud.netflix.eureka.server;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.appinfo.LeaseInfo;
|
||||
|
||||
public final class EurekaInstanceFixture {
|
||||
|
||||
private EurekaInstanceFixture() {
|
||||
}
|
||||
|
||||
public static LeaseInfo getLeaseInfo() {
|
||||
LeaseInfo.Builder leaseBuilder = LeaseInfo.Builder.newBuilder();
|
||||
leaseBuilder.setRenewalIntervalInSecs(10);
|
||||
leaseBuilder.setDurationInSecs(15);
|
||||
return leaseBuilder.build();
|
||||
}
|
||||
|
||||
public static InstanceInfo getInstanceInfo(String appName, String hostName, String instanceId, int port,
|
||||
LeaseInfo leaseInfo) {
|
||||
InstanceInfo.Builder builder = InstanceInfo.Builder.newBuilder();
|
||||
builder.setAppName(appName);
|
||||
builder.setHostName(hostName);
|
||||
builder.setInstanceId(instanceId);
|
||||
builder.setPort(port);
|
||||
builder.setLeaseInfo(leaseInfo);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright 2013-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.cloud.netflix.eureka.server;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Tag;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.netflix.eureka.server.metrics.EurekaInstanceMonitor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci;
|
||||
import static org.springframework.cloud.netflix.eureka.server.EurekaInstanceFixture.getInstanceInfo;
|
||||
import static org.springframework.cloud.netflix.eureka.server.EurekaInstanceFixture.getLeaseInfo;
|
||||
|
||||
//FIXME: fix flaky test
|
||||
/**
|
||||
* Tests for {@link EurekaInstanceMonitor}.
|
||||
*
|
||||
* @author Wonchul Heo
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@Disabled
|
||||
@SpringBootTest(classes = EurekaInstanceMonitorTests.Application.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
value = { "spring.application.name=eureka", "eureka.server.metrics.enabled=true" })
|
||||
class EurekaInstanceMonitorTests {
|
||||
|
||||
private static final String FOO_APP_NAME = "FOO-APP-NAME";
|
||||
|
||||
private static final String BAR_APP_NAME = "BAR-APP-NAME";
|
||||
|
||||
@Autowired
|
||||
private InstanceRegistry instanceRegistry;
|
||||
|
||||
@Autowired
|
||||
private MeterRegistry meterRegistry;
|
||||
|
||||
private InstanceInfo fooInstanceInfo;
|
||||
|
||||
private InstanceInfo fooInstanceInfo2;
|
||||
|
||||
private InstanceInfo barInstanceInfo;
|
||||
|
||||
private InstanceInfo barInstanceInfo2;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
instanceRegistry.clearRegistry();
|
||||
meterRegistry.clear();
|
||||
fooInstanceInfo = getInstanceInfo(FOO_APP_NAME, "my-host-name", "my-host-name:8008", 8008, getLeaseInfo());
|
||||
fooInstanceInfo2 = getInstanceInfo(FOO_APP_NAME, "my-host-name", "my-host-name:8009", 8009, getLeaseInfo());
|
||||
barInstanceInfo = getInstanceInfo(BAR_APP_NAME, "my-host-name", "my-host-name:8010", 8010, getLeaseInfo());
|
||||
barInstanceInfo2 = getInstanceInfo(BAR_APP_NAME, "my-host-name", "my-host-name:8011", 8011, getLeaseInfo());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoRegistration() {
|
||||
assertThat(meterRegistry.find("eureka.server.instances").gauge()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultipleRegistrations() {
|
||||
instanceRegistry.register(fooInstanceInfo, false);
|
||||
instanceRegistry.register(fooInstanceInfo2, false);
|
||||
instanceRegistry.register(barInstanceInfo, false);
|
||||
|
||||
final Map<Tags, Long> counts = Map.of(tags(fooInstanceInfo), 2L, tags(barInstanceInfo), 1L);
|
||||
assertEurekaInstance(counts);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPartialDeregistrationAfterMultipleRegistrations() {
|
||||
instanceRegistry.register(fooInstanceInfo, false);
|
||||
instanceRegistry.register(fooInstanceInfo2, false);
|
||||
instanceRegistry.register(barInstanceInfo, false);
|
||||
instanceRegistry.register(barInstanceInfo2, false);
|
||||
|
||||
instanceRegistry.internalCancel(fooInstanceInfo.getAppName(), fooInstanceInfo.getInstanceId(), false);
|
||||
|
||||
final Map<Tags, Long> counts = Map.of(tags(fooInstanceInfo), 1L, tags(barInstanceInfo), 2L);
|
||||
assertEurekaInstance(counts);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPartialDeregistrationAndThenRegistrationAfterMultipleRegistrations() {
|
||||
instanceRegistry.register(fooInstanceInfo, false);
|
||||
instanceRegistry.register(fooInstanceInfo2, false);
|
||||
instanceRegistry.register(barInstanceInfo, false);
|
||||
instanceRegistry.register(barInstanceInfo2, false);
|
||||
|
||||
instanceRegistry.internalCancel(fooInstanceInfo.getAppName(), fooInstanceInfo.getInstanceId(), false);
|
||||
instanceRegistry.register(fooInstanceInfo, false);
|
||||
|
||||
final Map<Tags, Long> counts = Map.of(tags(fooInstanceInfo), 2L, tags(barInstanceInfo), 2L);
|
||||
assertEurekaInstance(counts);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPartialNonRenewalAfterMultipleRegistrations() {
|
||||
instanceRegistry.register(fooInstanceInfo, false);
|
||||
instanceRegistry.register(fooInstanceInfo2, false);
|
||||
instanceRegistry.register(barInstanceInfo, false);
|
||||
instanceRegistry.register(barInstanceInfo2, false);
|
||||
|
||||
instanceRegistry.statusUpdate(fooInstanceInfo.getAppName(), fooInstanceInfo.getInstanceId(),
|
||||
InstanceInfo.InstanceStatus.DOWN, null, false);
|
||||
|
||||
final Map<Tags, Long> meterRegistryCounts = Map.of(tags(fooInstanceInfo2), 2L);
|
||||
assertEurekaInstance(meterRegistryCounts);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPartialRenewalAfterMultipleRegistrations() {
|
||||
instanceRegistry.register(fooInstanceInfo, false);
|
||||
instanceRegistry.register(fooInstanceInfo2, false);
|
||||
instanceRegistry.register(barInstanceInfo, false);
|
||||
instanceRegistry.register(barInstanceInfo2, false);
|
||||
|
||||
instanceRegistry.statusUpdate(fooInstanceInfo.getAppName(), fooInstanceInfo.getInstanceId(),
|
||||
InstanceInfo.InstanceStatus.DOWN, null, false);
|
||||
instanceRegistry.statusUpdate(barInstanceInfo2.getAppName(), barInstanceInfo2.getInstanceId(),
|
||||
InstanceInfo.InstanceStatus.STARTING, null, false);
|
||||
instanceRegistry.renew(fooInstanceInfo.getAppName(), fooInstanceInfo.getInstanceId(), false);
|
||||
instanceRegistry.renew(barInstanceInfo2.getAppName(), barInstanceInfo2.getInstanceId(), false);
|
||||
|
||||
final Map<Tags, Long> counts = Map.of(tags(fooInstanceInfo), 1L, tags(fooInstanceInfo2), 1L,
|
||||
tags(barInstanceInfo), 1L, tags(barInstanceInfo2), 1L);
|
||||
assertEurekaInstance(counts);
|
||||
}
|
||||
|
||||
private static Tags tags(InstanceInfo instanceInfo) {
|
||||
return Tags.of(Tag.of("application", instanceInfo.getAppName()),
|
||||
Tag.of("status", instanceInfo.getStatus().name()));
|
||||
}
|
||||
|
||||
private void assertEurekaInstance(Map<Tags, Long> meterRegistryCounts) {
|
||||
await().pollDelay(5, MILLISECONDS)
|
||||
.atMost(10, SECONDS)
|
||||
.pollInterval(fibonacci())
|
||||
.untilAsserted(() -> meterRegistryCounts.forEach((tags,
|
||||
count) -> assertThat((long) meterRegistry.get("eureka.server.instances").tags(tags).gauge().value())
|
||||
.isEqualTo(count)));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableAutoConfiguration
|
||||
@EnableEurekaServer
|
||||
@RestController
|
||||
protected static class Application {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2013-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.cloud.netflix.eureka.server;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
import org.assertj.core.api.SoftAssertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.netflix.eureka.server.metrics.EurekaInstanceMonitor;
|
||||
import org.springframework.cloud.netflix.eureka.server.metrics.EurekaInstanceTagsProvider;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci;
|
||||
import static org.springframework.cloud.netflix.eureka.server.EurekaInstanceFixture.getInstanceInfo;
|
||||
import static org.springframework.cloud.netflix.eureka.server.EurekaInstanceFixture.getLeaseInfo;
|
||||
|
||||
//FIXME: fix flaky test
|
||||
/**
|
||||
* Tests for {@link EurekaInstanceMonitor} with custom tags provider.
|
||||
*
|
||||
* @author Wonchul Heo
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@Disabled
|
||||
@SpringBootTest(classes = EurekaInstanceMonitorWithCustomTagsProviderTests.Application.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
value = { "spring.application.name=eureka", "eureka.server.metrics.enabled=true",
|
||||
"eureka.client.register-with-eureka=false", "eureka.client.fetch-registry=false" })
|
||||
class EurekaInstanceMonitorWithCustomTagsProviderTests {
|
||||
|
||||
private static final String APP_NAME = "FOO-APP-NAME";
|
||||
|
||||
@Autowired
|
||||
private InstanceRegistry instanceRegistry;
|
||||
|
||||
@Autowired
|
||||
private MeterRegistry meterRegistry;
|
||||
|
||||
private InstanceInfo firstInstanceInfo;
|
||||
|
||||
private InstanceInfo secondInstanceInfo;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
instanceRegistry.clearRegistry();
|
||||
meterRegistry.clear();
|
||||
firstInstanceInfo = getInstanceInfo(APP_NAME, "my-host-name", "my-host-name:8008", 8008, getLeaseInfo());
|
||||
secondInstanceInfo = getInstanceInfo(APP_NAME, "my-host-name", "my-host-name:8009", 8009, getLeaseInfo());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoRegistration() {
|
||||
assertThat(meterRegistry.find("eureka.server.instances").gauge()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultipleRegistrations() {
|
||||
instanceRegistry.register(firstInstanceInfo, false);
|
||||
instanceRegistry.register(secondInstanceInfo, false);
|
||||
|
||||
final Map<Tags, Long> counts = Map.of(tags(firstInstanceInfo), 1L, tags(secondInstanceInfo), 1L);
|
||||
assertEurekaInstance(counts);
|
||||
}
|
||||
|
||||
private static Tags tags(InstanceInfo instanceInfo) {
|
||||
return Tags.of("port", String.valueOf(instanceInfo.getPort()));
|
||||
}
|
||||
|
||||
private void assertEurekaInstance(Map<Tags, Long> meterRegistryCounts) {
|
||||
await().pollDelay(5, MILLISECONDS)
|
||||
.atMost(5, SECONDS)
|
||||
.pollInterval(fibonacci())
|
||||
.untilAsserted(() -> meterRegistryCounts.forEach((tags, count) -> {
|
||||
SoftAssertions softAssertions = new SoftAssertions();
|
||||
softAssertions
|
||||
.assertThat((long) meterRegistry.get("eureka.server.instances").tags(tags).gauge().value())
|
||||
.isNotNull();
|
||||
softAssertions
|
||||
.assertThat((long) meterRegistry.get("eureka.server.instances").tags(tags).gauge().value())
|
||||
.isEqualTo(count);
|
||||
softAssertions.assertAll();
|
||||
}));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableAutoConfiguration
|
||||
@EnableEurekaServer
|
||||
protected static class Application {
|
||||
|
||||
@Bean
|
||||
EurekaInstanceTagsProvider customEurekaInstanceTagsProvider() {
|
||||
return instanceInfo -> Tags.of("port", String.valueOf(instanceInfo.getPort()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2013-2025 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.cloud.netflix.eureka.server;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
|
||||
/**
|
||||
* Verifies the behaviour of Eureka server with peer registration enabled and refresh
|
||||
* disabled.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@SpringBootTest(classes = EurekaServerRefreshDisabledTests.Application.class, webEnvironment = RANDOM_PORT,
|
||||
properties = { "management.endpoints.web.exposure.include=*", "spring.cloud.refresh.enabled=false" })
|
||||
public class EurekaServerRefreshDisabledTests {
|
||||
|
||||
@LocalServerPort
|
||||
private int port = 0;
|
||||
|
||||
// verifies GH-4407
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Test
|
||||
void appCatalogLoads() {
|
||||
ResponseEntity<Map> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/eureka/apps", Map.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableAutoConfiguration
|
||||
@EnableEurekaServer
|
||||
protected static class Application {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+24
-42
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 the original author or authors.
|
||||
* 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.
|
||||
@@ -16,21 +16,17 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.server;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.appinfo.LeaseInfo;
|
||||
import com.netflix.discovery.shared.Application;
|
||||
import com.netflix.eureka.registry.PeerAwareInstanceRegistry;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
||||
import org.springframework.cloud.netflix.eureka.server.InstanceRegistryTests.TestApplication;
|
||||
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceCanceledEvent;
|
||||
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent;
|
||||
@@ -41,7 +37,8 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.SmartApplicationListener;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.springframework.cloud.netflix.eureka.server.EurekaInstanceFixture.getInstanceInfo;
|
||||
import static org.springframework.cloud.netflix.eureka.server.EurekaInstanceFixture.getLeaseInfo;
|
||||
|
||||
/**
|
||||
* @author Bartlomiej Slota
|
||||
@@ -59,12 +56,13 @@ class InstanceRegistryTests {
|
||||
|
||||
private static final int PORT = 8008;
|
||||
|
||||
@SpyBean(PeerAwareInstanceRegistry.class)
|
||||
@Autowired
|
||||
private InstanceRegistry instanceRegistry;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
this.testEvents.applicationEvents.clear();
|
||||
this.instanceRegistry.clearRegistry();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@@ -82,7 +80,7 @@ class InstanceRegistryTests {
|
||||
assertThat(this.testEvents.applicationEvents.get(0) instanceof EurekaInstanceRegisteredEvent).isTrue();
|
||||
// event details are correct
|
||||
final EurekaInstanceRegisteredEvent registeredEvent = (EurekaInstanceRegisteredEvent) (this.testEvents.applicationEvents
|
||||
.get(0));
|
||||
.get(0));
|
||||
assertThat(registeredEvent.getInstanceInfo()).isEqualTo(instanceInfo);
|
||||
assertThat(registeredEvent.getLeaseDuration()).isEqualTo(leaseInfo.getDurationInSecs());
|
||||
assertThat(registeredEvent.getSource()).isEqualTo(instanceRegistry);
|
||||
@@ -97,45 +95,47 @@ class InstanceRegistryTests {
|
||||
instanceRegistry.register(instanceInfo, false);
|
||||
// instance info duration is set to default
|
||||
final EurekaInstanceRegisteredEvent registeredEvent = (EurekaInstanceRegisteredEvent) (this.testEvents.applicationEvents
|
||||
.get(0));
|
||||
.get(0));
|
||||
assertThat(registeredEvent.getLeaseDuration()).isEqualTo(LeaseInfo.DEFAULT_LEASE_DURATION);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInternalCancel() {
|
||||
// registering instance info
|
||||
final InstanceInfo instanceInfo = getInstanceInfo(APP_NAME, HOST_NAME, INSTANCE_ID, PORT, null);
|
||||
instanceRegistry.register(instanceInfo, false);
|
||||
// calling tested method
|
||||
instanceRegistry.internalCancel(APP_NAME, HOST_NAME, false);
|
||||
instanceRegistry.internalCancel(APP_NAME, INSTANCE_ID, false);
|
||||
// event of proper type is registered
|
||||
assertThat(this.testEvents.applicationEvents.size()).isEqualTo(1);
|
||||
assertThat(this.testEvents.applicationEvents.get(0) instanceof EurekaInstanceCanceledEvent).isTrue();
|
||||
assertThat(this.testEvents.applicationEvents.size()).isEqualTo(2);
|
||||
assertThat(this.testEvents.applicationEvents.get(0) instanceof EurekaInstanceRegisteredEvent).isTrue();
|
||||
assertThat(this.testEvents.applicationEvents.get(1) instanceof EurekaInstanceCanceledEvent).isTrue();
|
||||
// event details are correct
|
||||
final EurekaInstanceCanceledEvent registeredEvent = (EurekaInstanceCanceledEvent) (this.testEvents.applicationEvents
|
||||
.get(0));
|
||||
.get(1));
|
||||
assertThat(registeredEvent.getAppName()).isEqualTo(APP_NAME);
|
||||
assertThat(registeredEvent.getServerId()).isEqualTo(HOST_NAME);
|
||||
assertThat(registeredEvent.getServerId()).isEqualTo(INSTANCE_ID);
|
||||
assertThat(registeredEvent.getSource()).isEqualTo(instanceRegistry);
|
||||
assertThat(registeredEvent.isReplication()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRenew() {
|
||||
// Creating two instances of the app
|
||||
// registering two instances of the app
|
||||
final InstanceInfo instanceInfo1 = getInstanceInfo(APP_NAME, HOST_NAME, INSTANCE_ID, PORT, null);
|
||||
final InstanceInfo instanceInfo2 = getInstanceInfo(APP_NAME, HOST_NAME, "my-host-name:8009", 8009, null);
|
||||
// creating application list with an app having two instances
|
||||
final Application application = new Application(APP_NAME, Arrays.asList(instanceInfo1, instanceInfo2));
|
||||
// stubbing application
|
||||
doReturn(application).when(instanceRegistry).getApplication(APP_NAME);
|
||||
instanceRegistry.register(instanceInfo1, false);
|
||||
instanceRegistry.register(instanceInfo2, false);
|
||||
// calling tested method
|
||||
instanceRegistry.renew(APP_NAME, INSTANCE_ID, false);
|
||||
instanceRegistry.renew(APP_NAME, "my-host-name:8009", false);
|
||||
// event of proper type is registered
|
||||
assertThat(this.testEvents.applicationEvents.size()).isEqualTo(2);
|
||||
assertThat(this.testEvents.applicationEvents.get(0) instanceof EurekaInstanceRenewedEvent).isTrue();
|
||||
assertThat(this.testEvents.applicationEvents.get(1) instanceof EurekaInstanceRenewedEvent).isTrue();
|
||||
assertThat(this.testEvents.applicationEvents.size()).isEqualTo(4);
|
||||
assertThat(this.testEvents.applicationEvents.get(2) instanceof EurekaInstanceRenewedEvent).isTrue();
|
||||
assertThat(this.testEvents.applicationEvents.get(3) instanceof EurekaInstanceRenewedEvent).isTrue();
|
||||
// event details are correct
|
||||
final EurekaInstanceRenewedEvent event1 = (EurekaInstanceRenewedEvent) (this.testEvents.applicationEvents
|
||||
.get(0));
|
||||
.get(2));
|
||||
assertThat(event1.getAppName()).isEqualTo(APP_NAME);
|
||||
assertThat(event1.getServerId()).isEqualTo(INSTANCE_ID);
|
||||
assertThat(event1.getSource()).isEqualTo(instanceRegistry);
|
||||
@@ -143,28 +143,10 @@ class InstanceRegistryTests {
|
||||
assertThat(event1.isReplication()).isFalse();
|
||||
|
||||
final EurekaInstanceRenewedEvent event2 = (EurekaInstanceRenewedEvent) (this.testEvents.applicationEvents
|
||||
.get(1));
|
||||
.get(3));
|
||||
assertThat(event2.getInstanceInfo()).isEqualTo(instanceInfo2);
|
||||
}
|
||||
|
||||
private LeaseInfo getLeaseInfo() {
|
||||
LeaseInfo.Builder leaseBuilder = LeaseInfo.Builder.newBuilder();
|
||||
leaseBuilder.setRenewalIntervalInSecs(10);
|
||||
leaseBuilder.setDurationInSecs(15);
|
||||
return leaseBuilder.build();
|
||||
}
|
||||
|
||||
private InstanceInfo getInstanceInfo(String appName, String hostName, String instanceId, int port,
|
||||
LeaseInfo leaseInfo) {
|
||||
InstanceInfo.Builder builder = InstanceInfo.Builder.newBuilder();
|
||||
builder.setAppName(appName);
|
||||
builder.setHostName(hostName);
|
||||
builder.setInstanceId(instanceId);
|
||||
builder.setPort(port);
|
||||
builder.setLeaseInfo(leaseInfo);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableAutoConfiguration
|
||||
@EnableEurekaServer
|
||||
|
||||
+27
-18
@@ -83,8 +83,8 @@ class RefreshablePeerEurekaNodesTests {
|
||||
this.context.publishEvent(new EnvironmentChangeEvent(new HashSet<>(Arrays.asList(USE_DNS, DEFAULT_ZONE))));
|
||||
|
||||
assertThat(serviceUrlMatches("https://default-host1:8678/eureka/"))
|
||||
.as("PeerEurekaNodes' are updated when eureka.client.use-dns-for-fetching-service-urls is true")
|
||||
.isFalse();
|
||||
.as("PeerEurekaNodes' are updated when eureka.client.use-dns-for-fetching-service-urls is true")
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -95,8 +95,8 @@ class RefreshablePeerEurekaNodesTests {
|
||||
this.context.publishEvent(new EnvironmentChangeEvent(new HashSet<>(Arrays.asList(USE_DNS, DEFAULT_ZONE))));
|
||||
|
||||
assertThat(serviceUrlMatches("https://default-host2:8678/eureka/"))
|
||||
.as("PeerEurekaNodes' are not updated when eureka.client.use-dns-for-fetching-service-urls is false")
|
||||
.isTrue();
|
||||
.as("PeerEurekaNodes' are not updated when eureka.client.use-dns-for-fetching-service-urls is false")
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -108,12 +108,14 @@ class RefreshablePeerEurekaNodesTests {
|
||||
"eureka.client.service-url.region2-zone=https://region2-zone-host:8678/eureka/");
|
||||
this.context.publishEvent(new EnvironmentChangeEvent(Collections.singleton(REGION)));
|
||||
assertThat(serviceUrlMatches("https://region1-zone-host:8678/eureka/"))
|
||||
.as("PeerEurekaNodes' are not updated when eureka.client.region is changed").isTrue();
|
||||
.as("PeerEurekaNodes' are not updated when eureka.client.region is changed")
|
||||
.isTrue();
|
||||
|
||||
changeProperty("eureka.client.region=region2");
|
||||
this.context.publishEvent(new EnvironmentChangeEvent(Collections.singleton(REGION)));
|
||||
assertThat(serviceUrlMatches("https://region2-zone-host:8678/eureka/"))
|
||||
.as("PeerEurekaNodes' are not updated when eureka.client.region is changed").isTrue();
|
||||
.as("PeerEurekaNodes' are not updated when eureka.client.region is changed")
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -124,14 +126,17 @@ class RefreshablePeerEurekaNodesTests {
|
||||
"eureka.client.service-url.defaultZone=https://default-host3:8678/eureka/");
|
||||
this.context.publishEvent(
|
||||
new EnvironmentChangeEvent(Collections.singleton("eureka.client.availability-zones.region3")));
|
||||
assertThat(this.peerEurekaNodes.getPeerEurekaNodes().get(0).getServiceUrl()
|
||||
.equals("https://default-host3:8678/eureka/")).isTrue();
|
||||
assertThat(this.peerEurekaNodes.getPeerEurekaNodes()
|
||||
.get(0)
|
||||
.getServiceUrl()
|
||||
.equals("https://default-host3:8678/eureka/")).isTrue();
|
||||
|
||||
changeProperty("eureka.client.availability-zones.region4=region4-zone");
|
||||
this.context.publishEvent(
|
||||
new EnvironmentChangeEvent(Collections.singleton("eureka.client.availability-zones.region4")));
|
||||
assertThat(serviceUrlMatches("https://region4-zone-host:8678/eureka/"))
|
||||
.as("PeerEurekaNodes' are not updated when eureka.client.availability-zones are changed").isTrue();
|
||||
.as("PeerEurekaNodes' are not updated when eureka.client.availability-zones are changed")
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -168,7 +173,8 @@ class RefreshablePeerEurekaNodesTests {
|
||||
void peerEurekaNodesIsRefreshablePeerEurekaNodes() {
|
||||
assertThat(this.peerEurekaNodes).isNotNull();
|
||||
assertThat(this.peerEurekaNodes instanceof RefreshablePeerEurekaNodes)
|
||||
.as("PeerEurekaNodes should be an instance of RefreshablePeerEurekaNodes").isTrue();
|
||||
.as("PeerEurekaNodes should be an instance of RefreshablePeerEurekaNodes")
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -177,7 +183,7 @@ class RefreshablePeerEurekaNodesTests {
|
||||
"eureka.client.service-url.defaultZone=https://defaul-host3:8678/eureka/,http://defaul-host4:8678/eureka/");
|
||||
forceUpdate();
|
||||
assertThat(this.peerEurekaNodes.getPeerEurekaNodes().size()).as("PeerEurekaNodes' peer count is incorrect.")
|
||||
.isEqualTo(2);
|
||||
.isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -185,7 +191,8 @@ class RefreshablePeerEurekaNodesTests {
|
||||
changeProperty("eureka.client.service-url.defaultZone=https://defaul-host4:8678/eureka/");
|
||||
forceUpdate();
|
||||
assertThat(serviceUrlMatches("https://defaul-host4:8678/eureka/"))
|
||||
.as("PeerEurekaNodes' new peer[0] is incorrect").isTrue();
|
||||
.as("PeerEurekaNodes' new peer[0] is incorrect")
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -198,7 +205,8 @@ class RefreshablePeerEurekaNodesTests {
|
||||
final String body = entity.getBody();
|
||||
assertThat(body).isNotNull();
|
||||
assertThat(body.contains("https://defaul-host5:8678/eureka/"))
|
||||
.as("DS Replicas not updated in the Eureka Server dashboard").isTrue();
|
||||
.as("DS Replicas not updated in the Eureka Server dashboard")
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -206,10 +214,11 @@ class RefreshablePeerEurekaNodesTests {
|
||||
changeProperty("eureka.client.use-dns-for-fetching-service-urls=false",
|
||||
"eureka.client.region=unavailable-region", // to force defaultZone
|
||||
"eureka.client.service-url.defaultZone=https://defaul-host6:8678/eureka/");
|
||||
this.context.publishEvent(
|
||||
new EnvironmentChangeEvent(Collections.singleton("eureka.client.serviceUrl.defaultZone")));
|
||||
this.context
|
||||
.publishEvent(new EnvironmentChangeEvent(Collections.singleton("eureka.client.serviceUrl.defaultZone")));
|
||||
assertThat(serviceUrlMatches("https://defaul-host6:8678/eureka/"))
|
||||
.as("PeerEurekaNodes' are updated for keys with relaxed binding").isFalse();
|
||||
.as("PeerEurekaNodes' are updated for keys with relaxed binding")
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -225,8 +234,8 @@ class RefreshablePeerEurekaNodesTests {
|
||||
private void forceUpdate() {
|
||||
changeProperty("eureka.client.use-dns-for-fetching-service-urls=false",
|
||||
"eureka.client.region=unavailable-region"); // to force defaultZone
|
||||
this.context.publishEvent(
|
||||
new EnvironmentChangeEvent(Collections.singleton("eureka.client.service-url.defaultZone")));
|
||||
this.context
|
||||
.publishEvent(new EnvironmentChangeEvent(Collections.singleton("eureka.client.service-url.defaultZone")));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+6
-3
@@ -49,14 +49,17 @@ class RefreshablePeerEurekaNodesWithCustomFiltersTests {
|
||||
@Test
|
||||
void testCustomPeerNodesShouldTakePrecedenceOverDefault() {
|
||||
assertThat(peerEurekaNodes instanceof RefreshablePeerEurekaNodes)
|
||||
.as("PeerEurekaNodes should be an instance of RefreshablePeerEurekaNodes").isTrue();
|
||||
.as("PeerEurekaNodes should be an instance of RefreshablePeerEurekaNodes")
|
||||
.isTrue();
|
||||
RefreshablePeerEurekaNodes refreshablePeerEurekaNodes = (RefreshablePeerEurekaNodes) peerEurekaNodes;
|
||||
|
||||
ReplicationClientAdditionalFilters filters = refreshablePeerEurekaNodes.replicationClientAdditionalFilters;
|
||||
assertThat(filters.getFilters())
|
||||
.as("PeerEurekaNodes'should have only one filter set on replicationClientAdditionalFilters").hasSize(1);
|
||||
.as("PeerEurekaNodes'should have only one filter set on replicationClientAdditionalFilters")
|
||||
.hasSize(1);
|
||||
assertThat(filters.getFilters().iterator().next() instanceof Application.CustomClientFilter)
|
||||
.as("The type of the filter should be CustomClientFilter as user declared so").isTrue();
|
||||
.as("The type of the filter should be CustomClientFilter as user declared so")
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
private static <T, R> R getField(Class<T> clazz, T target, String fieldName) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>4.1.1-SNAPSHOT</version>
|
||||
<version>4.1.7-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
||||
<name>Spring Cloud Starter Netflix Eureka Client</name>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>4.1.1-SNAPSHOT</version>
|
||||
<version>4.1.7-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
|
||||
<name>Spring Cloud Starter Netflix Eureka Server</name>
|
||||
|
||||
@@ -14,4 +14,8 @@
|
||||
<suppress files=".*TestAutoConfiguration\.java" checks="JavadocStyle"/>
|
||||
<suppress files=".*Tests\.java" checks="JavadocVariable"/>
|
||||
<suppress files=".*EurekaConfigServerBootstrapperIT\.java" checks="JavadocVariable"/>
|
||||
<suppress files="[\\/]src[\\/](test|testFixtures)[\\/](java|java21)[\\/]"
|
||||
checks="RegexpSinglelineJava" id="toLowerCaseWithoutLocale"/>
|
||||
<suppress files="[\\/]src[\\/](test|testFixtures)[\\/](java|java21)[\\/]"
|
||||
checks="RegexpSinglelineJava" id="toUpperCaseWithoutLocale"/>
|
||||
</suppressions>
|
||||
Reference in New Issue
Block a user