mirror of
https://github.com/spring-cloud/spring-cloud-netflix.git
synced 2026-09-20 00:59:01 +00:00
Compare commits
163
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a579eb4594 | ||
|
|
624bbc8b50 | ||
|
|
4de8761123 | ||
|
|
8d5a3f8ec1 | ||
|
|
f6120d525f | ||
|
|
4bf57b9cd2 | ||
|
|
3bd44d69ca | ||
|
|
6506e03bcf | ||
|
|
443628827e | ||
|
|
85261361d7 | ||
|
|
34a07a15e2 | ||
|
|
21b8599be5 | ||
|
|
a8539b33db | ||
|
|
5d983b082e | ||
|
|
e556ccc7ed | ||
|
|
529b7ae12a | ||
|
|
a18479da64 | ||
|
|
8d19948f4b | ||
|
|
182951a0d5 | ||
|
|
0783016676 | ||
|
|
c36743de83 | ||
|
|
297f8950b1 | ||
|
|
849642ff84 | ||
|
|
dff3b91bef | ||
|
|
7db58f7d16 | ||
|
|
e820a484d6 | ||
|
|
2afba0977f | ||
|
|
61d2f956e3 | ||
|
|
17b9002fef | ||
|
|
d6f375490a | ||
|
|
bee39ec1bf | ||
|
|
0dc755518c | ||
|
|
ad3f2cb53a | ||
|
|
74f9fd4f9d | ||
|
|
c69a3eed70 | ||
|
|
0c12ec9132 | ||
|
|
2f6f0a0f05 | ||
|
|
c0174be906 | ||
|
|
7e96ed15f2 | ||
|
|
1b07143fde | ||
|
|
ea31d78891 | ||
|
|
492731632c | ||
|
|
551fecde83 | ||
|
|
aed8d19aea | ||
|
|
ff6b50d0a8 | ||
|
|
3cb98b70ce | ||
|
|
d1ffc8d72e | ||
|
|
49f88c4e7c | ||
|
|
53bffa7f04 | ||
|
|
8e1ada2b3d | ||
|
|
4122aadb73 | ||
|
|
92c0c7d503 | ||
|
|
34b1a07124 | ||
|
|
2cd7e41c05 | ||
|
|
b904eaa886 | ||
|
|
3455489f47 | ||
|
|
af919cac66 | ||
|
|
ead46658c0 | ||
|
|
732f7d40ea | ||
|
|
67444a07c2 | ||
|
|
55dabe8e6b | ||
|
|
7e82a47dd3 | ||
|
|
c56e4a35d5 | ||
|
|
02f3bb8bba | ||
|
|
a4fc71a5b1 | ||
|
|
a33387faa6 | ||
|
|
ec087d0747 | ||
|
|
23659f8aea | ||
|
|
b51a15c3f2 | ||
|
|
dc30eb2073 | ||
|
|
c6b8873f0c | ||
|
|
78cce48aa1 | ||
|
|
73c40cf561 | ||
|
|
a10d7b69d4 | ||
|
|
4164297a89 | ||
|
|
56534dba1c | ||
|
|
f50e3d60a9 | ||
|
|
e31d478c11 | ||
|
|
0fa901f6bc | ||
|
|
67fd109d68 | ||
|
|
3ecf5a7420 | ||
|
|
69f4c901a9 | ||
|
|
3130493a3c | ||
|
|
87529e0994 | ||
|
|
e8816398a8 | ||
|
|
bb1269d635 | ||
|
|
38cec4e35d | ||
|
|
2b5d246725 | ||
|
|
9b2405f3eb | ||
|
|
4ca1901417 | ||
|
|
2208011dd3 | ||
|
|
9a2b254d0c | ||
|
|
d74b319b44 | ||
|
|
3d3d528e02 | ||
|
|
28326b506b | ||
|
|
392565f395 | ||
|
|
532a95e783 | ||
|
|
ac60c28baa | ||
|
|
40ec6066c1 | ||
|
|
e8ff2ebaf8 | ||
|
|
24f5e0b043 | ||
|
|
8eb843c951 | ||
|
|
543ab09012 | ||
|
|
7389f25f1c | ||
|
|
669ce753b2 | ||
|
|
7dbac954d1 | ||
|
|
828bc82363 | ||
|
|
e8b50d80ed | ||
|
|
181d210aa5 | ||
|
|
d4db93a86a | ||
|
|
438d3f9b0e | ||
|
|
d5de0fc55c | ||
|
|
388faaa8e5 | ||
|
|
b386a78dae | ||
|
|
0ea0472b4f | ||
|
|
6d74bebf66 | ||
|
|
a99b5d66ca | ||
|
|
b0e694601e | ||
|
|
e160395978 | ||
|
|
46c25b38d7 | ||
|
|
455c60c15c | ||
|
|
00b419be94 | ||
|
|
df33d0bd07 | ||
|
|
9d40b5dc4e | ||
|
|
b8fb056981 | ||
|
|
b0ace4774e | ||
|
|
34c96c99cf | ||
|
|
c24e7e05bf | ||
|
|
fd710d8a7d | ||
|
|
62deb59314 | ||
|
|
925f460d64 | ||
|
|
6c2359a0ca | ||
|
|
571d1b7bb7 | ||
|
|
c01d9e6b59 | ||
|
|
609b4f5838 | ||
|
|
23e1c36462 | ||
|
|
4d765b37bb | ||
|
|
e606cc527e | ||
|
|
4403e1c8ff | ||
|
|
0b0f5d2334 | ||
|
|
25cd7a5810 | ||
|
|
7aab07365d | ||
|
|
6acaa9be8b | ||
|
|
11a9819e3b | ||
|
|
4997b69433 | ||
|
|
e2f1f368b5 | ||
|
|
7ea5c3a32f | ||
|
|
03b1e326ce | ||
|
|
7449915919 | ||
|
|
0e66862cbb | ||
|
|
ee9c704a4c | ||
|
|
105f8d85b3 | ||
|
|
cc6ec1572b | ||
|
|
37d39617bf | ||
|
|
3c92af4a06 | ||
|
|
eff47e0464 | ||
|
|
c1771dce56 | ||
|
|
88b71f05fa | ||
|
|
52e4f5ea59 | ||
|
|
77b8965e29 | ||
|
|
0791a02223 | ||
|
|
8fdc6f0898 | ||
|
|
3d5484e410 |
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: waiting-for-triage
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
Please provide details of the problem, including the version of Spring Cloud that you
|
||||
are using.
|
||||
|
||||
**Sample**
|
||||
If possible, please provide a test case or sample application that reproduces
|
||||
the problem. This makes it much easier for us to diagnose the problem and to verify that
|
||||
we have fixed it.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -18,3 +18,6 @@ _site/
|
||||
.shelf
|
||||
*.swp
|
||||
*.swo
|
||||
.vscode/
|
||||
.flattened-pom.xml
|
||||
.sdkmanrc
|
||||
|
||||
+194
-4
@@ -1,10 +1,46 @@
|
||||
// Do not edit this file (e.g. go instead to src/main/asciidoc)
|
||||
////
|
||||
DO NOT EDIT THIS FILE. IT WAS GENERATED.
|
||||
Manual changes to this file will be lost when it is generated again.
|
||||
Edit the files in the src/main/asciidoc/ directory instead.
|
||||
////
|
||||
|
||||
:doctype: book
|
||||
:idprefix:
|
||||
:idseparator: -
|
||||
:toc: left
|
||||
:toclevels: 4
|
||||
:tabsize: 4
|
||||
:numbered:
|
||||
:sectanchors:
|
||||
:sectnums:
|
||||
:icons: font
|
||||
:hide-uri-scheme:
|
||||
:docinfo: shared,private
|
||||
|
||||
:sc-ext: java
|
||||
:project-full-name: Spring Cloud Netflix
|
||||
|
||||
image::https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/master.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/master"]
|
||||
image::https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/master/graph/badge.svg["Codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/master"]
|
||||
image::https://api.codacy.com/project/badge/Grade/a6885a06921e4f72a0df0b7aabd6d118["Codacy code quality", link="https://www.codacy.com/app/Spring-Cloud/spring-cloud-netflix?utm_source=github.com&utm_medium=referral&utm_content=spring-cloud/spring-cloud-netflix&utm_campaign=Badge_Grade"]
|
||||
|
||||
|
||||
:doctype: book
|
||||
:idprefix:
|
||||
:idseparator: -
|
||||
:toc: left
|
||||
:toclevels: 4
|
||||
:tabsize: 4
|
||||
:numbered:
|
||||
:sectanchors:
|
||||
:sectnums:
|
||||
:icons: font
|
||||
:hide-uri-scheme:
|
||||
:docinfo: shared,private
|
||||
|
||||
:sc-ext: java
|
||||
:project-full-name: Spring Cloud Netflix
|
||||
|
||||
This project provides Netflix OSS integrations for Spring Boot apps through autoconfiguration
|
||||
and binding to the Spring Environment and other Spring programming model idioms. With a few
|
||||
simple annotations you can quickly enable and configure the common patterns inside your
|
||||
@@ -23,6 +59,21 @@ Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon).
|
||||
* External Configuration: a bridge from the Spring Environment to Archaius (enables native configuration of Netflix components using Spring Boot conventions)
|
||||
* Router and Filter: automatic registration of Zuul filters, and a simple convention over configuration approach to reverse proxy creation
|
||||
|
||||
:doctype: book
|
||||
:idprefix:
|
||||
:idseparator: -
|
||||
:toc: left
|
||||
:toclevels: 4
|
||||
:tabsize: 4
|
||||
:numbered:
|
||||
:sectanchors:
|
||||
:sectnums:
|
||||
:icons: font
|
||||
:hide-uri-scheme:
|
||||
:docinfo: shared,private
|
||||
|
||||
:sc-ext: java
|
||||
:project-full-name: Spring Cloud Netflix
|
||||
|
||||
== Modules In Maintenance Mode
|
||||
|
||||
@@ -35,6 +86,7 @@ of the Greenwich release train.
|
||||
The following Spring Cloud Netflix modules and corresponding starters will be placed into maintenance mode:
|
||||
|
||||
* spring-cloud-netflix-archaius
|
||||
* spring-cloud-netflix-concurrency-limits
|
||||
* spring-cloud-netflix-hystrix-contract
|
||||
* spring-cloud-netflix-hystrix-dashboard
|
||||
* spring-cloud-netflix-hystrix-stream
|
||||
@@ -44,7 +96,7 @@ The following Spring Cloud Netflix modules and corresponding starters will be pl
|
||||
* spring-cloud-netflix-turbine
|
||||
* spring-cloud-netflix-zuul
|
||||
|
||||
NOTE: This does not include the Eureka or concurrency-limits modules.
|
||||
NOTE: This does not include the Eureka modules.
|
||||
|
||||
|
||||
== Building
|
||||
@@ -84,7 +136,7 @@ credentials and you already have those.
|
||||
|
||||
The projects that require middleware generally include a
|
||||
`docker-compose.yml`, so consider using
|
||||
https://compose.docker.io/[Docker Compose] to run the middeware servers
|
||||
https://docs.docker.com/compose/[Docker Compose] to run the middeware servers
|
||||
in Docker containers. See the README in the
|
||||
https://github.com/spring-cloud-samples/scripts[scripts demo
|
||||
repository] for specific instructions about the common cases of mongo,
|
||||
@@ -139,8 +191,13 @@ from the `file` menu.
|
||||
|
||||
|
||||
|
||||
NOTE: To build the module `spring-cloud-netflix-hystrix-contract` along with the entire Netflix project run the
|
||||
`build.sh` script in the `scripts` directory.
|
||||
|
||||
== Contributing
|
||||
|
||||
:spring-cloud-build-branch: master
|
||||
|
||||
Spring Cloud is released under the non-restrictive Apache 2.0 license,
|
||||
and follows a very standard Github development process, using Github
|
||||
tracker for issues and merging pull requests into master. If you want
|
||||
@@ -184,4 +241,137 @@ added after the original pull request but before a merge.
|
||||
other target branch in the main project).
|
||||
* When writing a commit message please follow https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions],
|
||||
if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit
|
||||
message (where XXXX is the issue number).
|
||||
message (where XXXX is the issue number).
|
||||
|
||||
=== Checkstyle
|
||||
|
||||
Spring Cloud Build comes with a set of checkstyle rules. You can find them in the `spring-cloud-build-tools` module. The most notable files under the module are:
|
||||
|
||||
.spring-cloud-build-tools/
|
||||
----
|
||||
└── src
|
||||
├── checkstyle
|
||||
│ └── checkstyle-suppressions.xml <3>
|
||||
└── main
|
||||
└── resources
|
||||
├── checkstyle-header.txt <2>
|
||||
└── checkstyle.xml <1>
|
||||
----
|
||||
<1> Default Checkstyle rules
|
||||
<2> File header setup
|
||||
<3> Default suppression rules
|
||||
|
||||
==== Checkstyle configuration
|
||||
|
||||
Checkstyle rules are *disabled by default*. To add checkstyle to your project just define the following properties and plugins.
|
||||
|
||||
.pom.xml
|
||||
----
|
||||
<properties>
|
||||
<maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError> <1>
|
||||
<maven-checkstyle-plugin.failsOnViolation>true
|
||||
</maven-checkstyle-plugin.failsOnViolation> <2>
|
||||
<maven-checkstyle-plugin.includeTestSourceDirectory>true
|
||||
</maven-checkstyle-plugin.includeTestSourceDirectory> <3>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin> <4>
|
||||
<groupId>io.spring.javaformat</groupId>
|
||||
<artifactId>spring-javaformat-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin> <5>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin> <5>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
</build>
|
||||
----
|
||||
<1> Fails the build upon Checkstyle errors
|
||||
<2> Fails the build upon Checkstyle violations
|
||||
<3> Checkstyle analyzes also the test sources
|
||||
<4> Add the Spring Java Format plugin that will reformat your code to pass most of the Checkstyle formatting rules
|
||||
<5> Add checkstyle plugin to your build and reporting phases
|
||||
|
||||
If you need to suppress some rules (e.g. line length needs to be longer), then it's enough for you to define a file under `${project.root}/src/checkstyle/checkstyle-suppressions.xml` with your suppressions. Example:
|
||||
|
||||
.projectRoot/src/checkstyle/checkstyle-suppresions.xml
|
||||
----
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE suppressions PUBLIC
|
||||
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
|
||||
"https://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
|
||||
<suppressions>
|
||||
<suppress files=".*ConfigServerApplication\.java" checks="HideUtilityClassConstructor"/>
|
||||
<suppress files=".*ConfigClientWatch\.java" checks="LineLengthCheck"/>
|
||||
</suppressions>
|
||||
----
|
||||
|
||||
It's advisable to copy the `${spring-cloud-build.rootFolder}/.editorconfig` and `${spring-cloud-build.rootFolder}/.springformat` to your project. That way, some default formatting rules will be applied. You can do so by running this script:
|
||||
|
||||
```bash
|
||||
$ curl https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/.editorconfig -o .editorconfig
|
||||
$ touch .springformat
|
||||
```
|
||||
|
||||
=== IDE setup
|
||||
|
||||
==== Intellij IDEA
|
||||
|
||||
In order to setup Intellij you should import our coding conventions, inspection profiles and set up the checkstyle plugin.
|
||||
The following files can be found in the https://github.com/spring-cloud/spring-cloud-build/tree/master/spring-cloud-build-tools[Spring Cloud Build] project.
|
||||
|
||||
.spring-cloud-build-tools/
|
||||
----
|
||||
└── src
|
||||
├── checkstyle
|
||||
│ └── checkstyle-suppressions.xml <3>
|
||||
└── main
|
||||
└── resources
|
||||
├── checkstyle-header.txt <2>
|
||||
├── checkstyle.xml <1>
|
||||
└── intellij
|
||||
├── Intellij_Project_Defaults.xml <4>
|
||||
└── Intellij_Spring_Boot_Java_Conventions.xml <5>
|
||||
----
|
||||
<1> Default Checkstyle rules
|
||||
<2> File header setup
|
||||
<3> Default suppression rules
|
||||
<4> Project defaults for Intellij that apply most of Checkstyle rules
|
||||
<5> Project style conventions for Intellij that apply most of Checkstyle rules
|
||||
|
||||
.Code style
|
||||
|
||||
image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-code-style.png[Code style]
|
||||
|
||||
Go to `File` -> `Settings` -> `Editor` -> `Code style`. There click on the icon next to the `Scheme` section. There, click on the `Import Scheme` value and pick the `Intellij IDEA code style XML` option. Import the `spring-cloud-build-tools/src/main/resources/intellij/Intellij_Spring_Boot_Java_Conventions.xml` file.
|
||||
|
||||
.Inspection profiles
|
||||
|
||||
image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-inspections.png[Code style]
|
||||
|
||||
Go to `File` -> `Settings` -> `Editor` -> `Inspections`. There click on the icon next to the `Profile` section. There, click on the `Import Profile` and import the `spring-cloud-build-tools/src/main/resources/intellij/Intellij_Project_Defaults.xml` file.
|
||||
|
||||
.Checkstyle
|
||||
|
||||
To have Intellij work with Checkstyle, you have to install the `Checkstyle` plugin. It's advisable to also install the `Assertions2Assertj` to automatically convert the JUnit assertions
|
||||
|
||||
image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-checkstyle.png[Checkstyle]
|
||||
|
||||
Go to `File` -> `Settings` -> `Other settings` -> `Checkstyle`. There click on the `+` icon in the `Configuration file` section. There, you'll have to define where the checkstyle rules should be picked from. In the image above, we've picked the rules from the cloned Spring Cloud Build repository. However, you can point to the Spring Cloud Build's GitHub repository (e.g. for the `checkstyle.xml` : `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle.xml`). We need to provide the following variables:
|
||||
|
||||
- `checkstyle.header.file` - please point it to the Spring Cloud Build's, `spring-cloud-build-tools/src/main/resources/checkstyle-header.txt` file either in your cloned repo or via the `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle-header.txt` URL.
|
||||
- `checkstyle.suppressions.file` - default suppressions. Please point it to the Spring Cloud Build's, `spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml` file either in your cloned repo or via the `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml` URL.
|
||||
- `checkstyle.additional.suppressions.file` - this variable corresponds to suppressions in your local project. E.g. you're working on `spring-cloud-contract`. Then point to the `project-root/src/checkstyle/checkstyle-suppressions.xml` folder. Example for `spring-cloud-contract` would be: `/home/username/spring-cloud-contract/src/checkstyle/checkstyle-suppressions.xml`.
|
||||
|
||||
IMPORTANT: Remember to set the `Scan Scope` to `All sources` since we apply checkstyle rules for production and test sources.
|
||||
@@ -0,0 +1,5 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
To report security vulnerabilities, please go to https://pivotal.io/security.
|
||||
+57
-3
@@ -4,11 +4,44 @@ Manual changes to this file will be lost when it is generated again.
|
||||
Edit the files in the src/main/asciidoc/ directory instead.
|
||||
////
|
||||
|
||||
|
||||
:doctype: book
|
||||
:idprefix:
|
||||
:idseparator: -
|
||||
:toc: left
|
||||
:toclevels: 4
|
||||
:tabsize: 4
|
||||
:numbered:
|
||||
:sectanchors:
|
||||
:sectnums:
|
||||
:icons: font
|
||||
:hide-uri-scheme:
|
||||
:docinfo: shared,private
|
||||
|
||||
:sc-ext: java
|
||||
:project-full-name: Spring Cloud Netflix
|
||||
|
||||
image::https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/master.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/master"]
|
||||
image::https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/master/graph/badge.svg["Codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/master"]
|
||||
image::https://api.codacy.com/project/badge/Grade/a6885a06921e4f72a0df0b7aabd6d118["Codacy code quality", link="https://www.codacy.com/app/Spring-Cloud/spring-cloud-netflix?utm_source=github.com&utm_medium=referral&utm_content=spring-cloud/spring-cloud-netflix&utm_campaign=Badge_Grade"]
|
||||
|
||||
|
||||
:doctype: book
|
||||
:idprefix:
|
||||
:idseparator: -
|
||||
:toc: left
|
||||
:toclevels: 4
|
||||
:tabsize: 4
|
||||
:numbered:
|
||||
:sectanchors:
|
||||
:sectnums:
|
||||
:icons: font
|
||||
:hide-uri-scheme:
|
||||
:docinfo: shared,private
|
||||
|
||||
:sc-ext: java
|
||||
:project-full-name: Spring Cloud Netflix
|
||||
|
||||
This project provides Netflix OSS integrations for Spring Boot apps through autoconfiguration
|
||||
and binding to the Spring Environment and other Spring programming model idioms. With a few
|
||||
simple annotations you can quickly enable and configure the common patterns inside your
|
||||
@@ -27,6 +60,21 @@ Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon).
|
||||
* External Configuration: a bridge from the Spring Environment to Archaius (enables native configuration of Netflix components using Spring Boot conventions)
|
||||
* Router and Filter: automatic registration of Zuul filters, and a simple convention over configuration approach to reverse proxy creation
|
||||
|
||||
:doctype: book
|
||||
:idprefix:
|
||||
:idseparator: -
|
||||
:toc: left
|
||||
:toclevels: 4
|
||||
:tabsize: 4
|
||||
:numbered:
|
||||
:sectanchors:
|
||||
:sectnums:
|
||||
:icons: font
|
||||
:hide-uri-scheme:
|
||||
:docinfo: shared,private
|
||||
|
||||
:sc-ext: java
|
||||
:project-full-name: Spring Cloud Netflix
|
||||
|
||||
== Modules In Maintenance Mode
|
||||
|
||||
@@ -39,6 +87,7 @@ of the Greenwich release train.
|
||||
The following Spring Cloud Netflix modules and corresponding starters will be placed into maintenance mode:
|
||||
|
||||
* spring-cloud-netflix-archaius
|
||||
* spring-cloud-netflix-concurrency-limits
|
||||
* spring-cloud-netflix-hystrix-contract
|
||||
* spring-cloud-netflix-hystrix-dashboard
|
||||
* spring-cloud-netflix-hystrix-stream
|
||||
@@ -48,7 +97,7 @@ The following Spring Cloud Netflix modules and corresponding starters will be pl
|
||||
* spring-cloud-netflix-turbine
|
||||
* spring-cloud-netflix-zuul
|
||||
|
||||
NOTE: This does not include the Eureka or concurrency-limits modules.
|
||||
NOTE: This does not include the Eureka modules.
|
||||
|
||||
|
||||
== Building
|
||||
@@ -115,6 +164,11 @@ 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.
|
||||
|
||||
==== Activate the Spring Maven profile
|
||||
Spring Cloud projects require the 'spring' Maven profile to be activated to resolve
|
||||
the spring milestone and snapshot repositories. Use your preferred IDE to set this
|
||||
profile to be active, or you may experience build errors.
|
||||
|
||||
==== Importing into eclipse with m2eclipse
|
||||
We recommend the https://eclipse.org/m2e/[m2eclipse] eclipse plugin when working with
|
||||
eclipse. If you don't already have m2eclipse installed it is available from the "eclipse
|
||||
@@ -322,8 +376,8 @@ image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring
|
||||
|
||||
Go to `File` -> `Settings` -> `Other settings` -> `Checkstyle`. There click on the `+` icon in the `Configuration file` section. There, you'll have to define where the checkstyle rules should be picked from. In the image above, we've picked the rules from the cloned Spring Cloud Build repository. However, you can point to the Spring Cloud Build's GitHub repository (e.g. for the `checkstyle.xml` : `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle.xml`). We need to provide the following variables:
|
||||
|
||||
- `checkstyle.header.file` - please point it to the Spring Cloud Build's, `spring-cloud-build-tools/src/main/resources/checkstyle/checkstyle-header.txt` file either in your cloned repo or via the `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle-header.txt` URL.
|
||||
- `checkstyle.header.file` - please point it to the Spring Cloud Build's, `spring-cloud-build-tools/src/main/resources/checkstyle-header.txt` file either in your cloned repo or via the `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle-header.txt` URL.
|
||||
- `checkstyle.suppressions.file` - default suppressions. Please point it to the Spring Cloud Build's, `spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml` file either in your cloned repo or via the `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml` URL.
|
||||
- `checkstyle.additional.suppressions.file` - this variable corresponds to suppressions in your local project. E.g. you're working on `spring-cloud-contract`. Then point to the `project-root/src/checkstyle/checkstyle-suppressions.xml` folder. Example for `spring-cloud-contract` would be: `/home/username/spring-cloud-contract/src/checkstyle/checkstyle-suppressions.xml`.
|
||||
|
||||
IMPORTANT: Remember to set the `Scan Scope` to `All sources` since we apply checkstyle rules for production and test sources.
|
||||
IMPORTANT: Remember to set the `Scan Scope` to `All sources` since we apply checkstyle rules for production and test sources.
|
||||
|
||||
+55
-23
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>2.1.7.SNAPSHOT</version>
|
||||
<version>2.2.4.RELEASE</version>
|
||||
</parent>
|
||||
<artifactId>spring-cloud-netflix-docs</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
@@ -13,45 +13,77 @@
|
||||
<description>Spring Cloud Docs</description>
|
||||
<properties>
|
||||
<docs.main>spring-cloud-netflix</docs.main>
|
||||
<docs.whitelisted.branches>1.2.x,1.3.x,1.4.x</docs.whitelisted.branches>
|
||||
<configprops.inclusionPattern>
|
||||
.*.eureka.*|.*.hystrix.*|.*.ribbon.*|.*.sidecar.*|.*.turbine.*|.*.zuul.*|.*.archaius.*
|
||||
</configprops.inclusionPattern>
|
||||
<upload-docs-zip.phase>deploy</upload-docs-zip.phase>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-archaius</artifactId>
|
||||
</dependency>
|
||||
<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>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-turbine-stream</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>docs</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<groupId>pl.project13.maven</groupId>
|
||||
<artifactId>git-commit-id-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.asciidoctor</groupId>
|
||||
<artifactId>asciidoctor-maven-plugin</artifactId>
|
||||
<inherited>false</inherited>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.agilejava.docbkx</groupId>
|
||||
<artifactId>docbkx-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<inherited>false</inherited>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<inherited>false</inherited>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
include::_attributes.adoc[]
|
||||
|
||||
image::https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/master.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/master"]
|
||||
image::https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/master/graph/badge.svg["Codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/master"]
|
||||
image::https://api.codacy.com/project/badge/Grade/a6885a06921e4f72a0df0b7aabd6d118["Codacy code quality", link="https://www.codacy.com/app/Spring-Cloud/spring-cloud-netflix?utm_source=github.com&utm_medium=referral&utm_content=spring-cloud/spring-cloud-netflix&utm_campaign=Badge_Grade"]
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
:doctype: book
|
||||
:idprefix:
|
||||
:idseparator: -
|
||||
:toc: left
|
||||
:toclevels: 4
|
||||
:tabsize: 4
|
||||
:numbered:
|
||||
:sectanchors:
|
||||
:sectnums:
|
||||
:icons: font
|
||||
:hide-uri-scheme:
|
||||
:docinfo: shared,private
|
||||
|
||||
:sc-ext: java
|
||||
:project-full-name: Spring Cloud Netflix
|
||||
@@ -0,0 +1,27 @@
|
||||
|===
|
||||
|Name | Default | Description
|
||||
|
||||
|eureka.client.eureka-connection-idle-timeout-seconds | 30 | Indicates how much time (in seconds) that the HTTP connections to eureka server can stay idle before it can be closed. In the AWS environment, it is recommended that the values is 30 seconds or less, since the firewall cleans up the connection information after a few mins leaving the connection hanging in limbo.
|
||||
|eureka.client.eureka-server-connect-timeout-seconds | 5 | Indicates how long to wait (in seconds) before a connection to eureka server needs to timeout. Note that the connections in the client are pooled by org.apache.http.client.HttpClient and this setting affects the actual connection creation and also the wait time to get the connection from the pool.
|
||||
|eureka.client.eureka-server-d-n-s-name | | Gets the DNS name to be queried to get the list of eureka servers.This information is not required if the contract returns the service urls by implementing serviceUrls. 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-server-port | | Gets the port 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 eurekaServerServiceUrls(String). 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-server-read-timeout-seconds | 8 | Indicates how long to wait (in seconds) before a read from eureka server needs to timeout.
|
||||
|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.prefer-same-zone-eureka | true | Indicates whether or not this instance should try to use the eureka server in the same zone for latency and/or other reason. Ideally eureka clients are configured to talk to servers in the same zone The changes are effective at runtime at the next registry fetch cycle as specified by registryFetchIntervalSeconds
|
||||
|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.server.peer-eureka-nodes-update-interval-ms | 0 |
|
||||
|eureka.server.peer-eureka-status-refresh-time-interval-ms | 0 |
|
||||
|management.endpoint.hystrix.config | | Hystrix settings. These are traditionally set using servlet parameters. Refer to the documentation of Hystrix for more details.
|
||||
|management.endpoint.hystrix.stream.enabled | true | Whether to enable the hystrix.stream endpoint.
|
||||
|management.metrics.binders.hystrix.enabled | true | Enables creation of OK Http Client factory beans.
|
||||
|ribbon.eureka.enabled | true | Enables the use of Eureka with Ribbon.
|
||||
|spring.cloud.circuitbreaker.hystrix.enabled | true | Enables auto-configuration of the Hystrix Spring Cloud CircuitBreaker API implementation.
|
||||
|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.ribbon.enabled | true | Causes `RibbonLoadBalancerClient` to be used by default.
|
||||
|zuul.ribbon-isolation-strategy | |
|
||||
|zuul.ribbon.eager-load.enabled | false | Enables eager loading of Ribbon clients on startup.
|
||||
|
||||
|===
|
||||
@@ -0,0 +1,14 @@
|
||||
:numbered!:
|
||||
[appendix]
|
||||
[[common-application-properties]]
|
||||
== Common application properties
|
||||
|
||||
include::_attributes.adoc[]
|
||||
|
||||
Various properties can be specified inside your `application.properties` file, inside your `application.yml` file, or as command line switches.
|
||||
This appendix provides a list of common {project-full-name} properties and references to the underlying classes that consume them.
|
||||
|
||||
NOTE: Property contributions can come from additional jar files on your classpath, so you should not consider this an exhaustive list.
|
||||
Also, you can define your own properties.
|
||||
|
||||
include::_configprops.adoc[]
|
||||
@@ -1,3 +1,5 @@
|
||||
include::_attributes.adoc[]
|
||||
|
||||
This project provides Netflix OSS integrations for Spring Boot apps through autoconfiguration
|
||||
and binding to the Spring Environment and other Spring programming model idioms. With a few
|
||||
simple annotations you can quickly enable and configure the common patterns inside your
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
include::_attributes.adoc[]
|
||||
|
||||
== Modules In Maintenance Mode
|
||||
|
||||
@@ -10,6 +11,7 @@ of the Greenwich release train.
|
||||
The following Spring Cloud Netflix modules and corresponding starters will be placed into maintenance mode:
|
||||
|
||||
* spring-cloud-netflix-archaius
|
||||
* spring-cloud-netflix-concurrency-limits
|
||||
* spring-cloud-netflix-hystrix-contract
|
||||
* spring-cloud-netflix-hystrix-dashboard
|
||||
* spring-cloud-netflix-hystrix-stream
|
||||
@@ -19,5 +21,5 @@ The following Spring Cloud Netflix modules and corresponding starters will be pl
|
||||
* spring-cloud-netflix-turbine
|
||||
* spring-cloud-netflix-zuul
|
||||
|
||||
NOTE: This does not include the Eureka or concurrency-limits modules.
|
||||
NOTE: This does not include the Eureka modules.
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
include::_attributes.adoc[]
|
||||
@@ -0,0 +1,41 @@
|
||||
Spring Cloud Netflix provides Netflix OSS integrations for Spring Boot apps through autoconfiguration and binding to the Spring Environment and other Spring programming model idioms. With a few simple annotations you can quickly enable and configure the common patterns inside your application and build large distributed systems with battle-tested Netflix components. The patterns provided include Service Discovery (Eureka), Circuit Breaker (Hystrix), Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon)..
|
||||
|
||||
## Features
|
||||
|
||||
Spring Cloud Netflix features:
|
||||
|
||||
* Service Discovery: Eureka instances can be registered and clients can discover the instances using Spring-managed beans
|
||||
* Service Discovery: an embedded Eureka server can be created with declarative Java configuration
|
||||
* Circuit Breaker: Hystrix clients can be built with a simple annotation-driven method decorator
|
||||
* Circuit Breaker: embedded Hystrix dashboard with declarative Java configuration
|
||||
* Declarative REST Client: Feign creates a dynamic implementation of an interface decorated with JAX-RS or Spring MVC annotations
|
||||
* Client Side Load Balancer: Ribbon
|
||||
* External Configuration: a bridge from the Spring Environment to Archaius (enables native configuration of Netflix components using Spring Boot conventions)
|
||||
* Router and Filter: automatic registration of Zuul filters, and a simple convention over configuration approach to reverse proxy creation
|
||||
|
||||
## Getting Started
|
||||
|
||||
As long as Spring Cloud Netflix and Eureka Core are on the
|
||||
classpath any Spring Boot application with `@EnableEurekaClient` will try to contact a Eureka
|
||||
server on `http://localhost:8761` (the default value of
|
||||
`eureka.client.serviceUrl.defaultZone`):
|
||||
|
||||
```java
|
||||
@SpringBootApplication
|
||||
@EnableEurekaClient
|
||||
@RestController
|
||||
public class Application {
|
||||
|
||||
@RequestMapping("/")
|
||||
public String home() {
|
||||
return "Hello World";
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
To run your own server use the `spring-cloud-starter-netflix-eureka-server` dependency and `@EnableEurekaServer`.
|
||||
@@ -0,0 +1,70 @@
|
||||
include::_attributes.adoc[]
|
||||
=== Disabling Spring Cloud Circuit Breaker Hystrix
|
||||
|
||||
You can disable the auto-configuration by setting `spring.cloud.circuitbreaker.hystrix.enabled`
|
||||
to `false`.
|
||||
|
||||
=== Configuring Hystrix Circuit Breakers
|
||||
|
||||
==== Default Configuration
|
||||
|
||||
To provide a default configuration for all of your circuit breakers create a `Customize` bean that is passed a
|
||||
`HystrixCircuitBreakerFactory` or `ReactiveHystrixCircuitBreakerFactory`.
|
||||
The `configureDefault` method can be used to provide a default configuration.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public Customizer<HystrixCircuitBreakerFactory> defaultConfig() {
|
||||
return factory -> factory.configureDefault(id -> HystrixCommand.Setter
|
||||
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(id))
|
||||
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
|
||||
.withExecutionTimeoutInMilliseconds(4000)));
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
===== Reactive Example
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public Customizer<ReactiveHystrixCircuitBreakerFactory> defaultConfig() {
|
||||
return factory -> factory.configureDefault(id -> HystrixObservableCommand.Setter
|
||||
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(id))
|
||||
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
|
||||
.withExecutionTimeoutInMilliseconds(4000)));
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
==== Specific Circuit Breaker Configuration
|
||||
|
||||
Similarly to providing a default configuration, you can create a `Customize` bean this is passed a
|
||||
`HystrixCircuitBreakerFactory`
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public Customizer<HystrixCircuitBreakerFactory> customizer() {
|
||||
return factory -> factory.configure(builder -> builder.commandProperties(
|
||||
HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(2000)), "foo", "bar");
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
===== Reactive Example
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public Customizer<ReactiveHystrixCircuitBreakerFactory> customizer() {
|
||||
return factory -> factory.configure(builder -> builder.commandProperties(
|
||||
HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(2000)), "foo", "bar");
|
||||
}
|
||||
----
|
||||
====
|
||||
@@ -1,3 +1,6 @@
|
||||
include::_attributes.adoc[]
|
||||
|
||||
|
||||
:github-tag: master
|
||||
:github-repo: spring-cloud/spring-cloud-netflix
|
||||
:github-raw: https://raw.github.com/{github-repo}/{github-tag}
|
||||
@@ -5,6 +8,7 @@
|
||||
:all: {asterisk}{asterisk}
|
||||
:nofooter:
|
||||
:branch: master
|
||||
|
||||
= Spring Cloud Netflix
|
||||
|
||||
*{spring-cloud-version}*
|
||||
@@ -78,7 +82,7 @@ To disable the Eureka Discovery Client, you can set `eureka.client.enabled` to `
|
||||
|
||||
=== Authenticating with the Eureka Server
|
||||
|
||||
HTTP basic authentication is automatically added to your eureka client if one of the `eureka.client.serviceUrl.defaultZone` URLs has credentials embedded in it (curl style, as follows: `http://user:password@localhost:8761/eureka`).
|
||||
HTTP basic authentication is automatically added to your eureka client if one of the `eureka.client.serviceUrl.defaultZone` URLs has credentials embedded in it (curl style, as follows: `https://user:password@localhost:8761/eureka`).
|
||||
For more complex needs, you can create a `@Bean` of type `DiscoveryClientOptionalArgs` and inject `ClientFilter` instances into it, all of which is applied to the calls from the client to the server.
|
||||
|
||||
NOTE: Because of a limitation in Eureka, it is not possible to support per-server basic auth credentials, so only the first set that are found is used.
|
||||
@@ -333,6 +337,18 @@ When a refresh occurs clients will be unregistered from the Eureka server and th
|
||||
where all instance of a given service are not available. One way to eliminate this from happening is to disable
|
||||
the ability to refresh Eureka clients. To do this set `eureka.client.refresh.enable=false`.
|
||||
|
||||
=== Using Eureka with Spring Cloud LoadBalancer
|
||||
|
||||
We offer support for the Spring Cloud LoadBalancer `ZonePreferenceServiceInstanceListSupplier`.
|
||||
The `zone` value from the Eureka instance metadata (`eureka.instance.metadataMap.zone`) is used for setting the
|
||||
value of `spring-clod-loadbalancer-zone` property that is used to filter service instances by zone.
|
||||
|
||||
If that is missing and if the `spring.cloud.loadbalancer.eureka.approximateZoneFromHostname` flag is set to `true`,
|
||||
it can use the domain name from the server hostname as a proxy for the zone.
|
||||
|
||||
If there is no other source of zone data, then a guess is made, based on the client configuration (as opposed to the instance configuration).
|
||||
We take `eureka.client.availabilityZones`, which is a map from region name to a list of zones, and pull out the first zone for the instance's own region (that is, the `eureka.client.region`, which defaults to "us-east-1", for compatibility with native Netflix).
|
||||
|
||||
[[spring-cloud-eureka-server]]
|
||||
== Service Discovery: Eureka Server
|
||||
|
||||
@@ -452,7 +468,7 @@ eureka:
|
||||
hostname: peer1
|
||||
client:
|
||||
serviceUrl:
|
||||
defaultZone: http://peer2/eureka/
|
||||
defaultZone: https://peer2/eureka/
|
||||
|
||||
---
|
||||
spring:
|
||||
@@ -462,7 +478,7 @@ eureka:
|
||||
hostname: peer2
|
||||
client:
|
||||
serviceUrl:
|
||||
defaultZone: http://peer1/eureka/
|
||||
defaultZone: https://peer1/eureka/
|
||||
----
|
||||
|
||||
In the preceding example, we have a YAML file that can be used to run the same server on two hosts (`peer1` and `peer2`) by running it in different Spring profiles.
|
||||
@@ -481,7 +497,7 @@ the registrations amongst themselves.
|
||||
eureka:
|
||||
client:
|
||||
serviceUrl:
|
||||
defaultZone: http://peer1/eureka/,http://peer2/eureka/,http://peer3/eureka/
|
||||
defaultZone: https://peer1/eureka/,http://peer2/eureka/,http://peer3/eureka/
|
||||
|
||||
---
|
||||
spring:
|
||||
@@ -543,6 +559,34 @@ For more information on CSRF see the https://docs.spring.io/spring-security/site
|
||||
|
||||
A demo Eureka Server can be found in the Spring Cloud Samples https://github.com/spring-cloud-samples/eureka/tree/Eureka-With-Security[repo].
|
||||
|
||||
=== Disabling Ribbon with Eureka Server and Client starters
|
||||
|
||||
`spring-cloud-starter-netflix-eureka-server` and `spring-cloud-starter-netflix-eureka-client` come along with
|
||||
a `spring-cloud-starter-netflix-ribbon`. Since Ribbon load-balancer is now in maintenance mode,
|
||||
we suggest switching to using the Spring Cloud LoadBalancer, also included in Eureka starters, instead.
|
||||
|
||||
In order to that, you can set the value of `spring.cloud.loadbalancer.ribbon.enabled` property to `false`.
|
||||
|
||||
You can then also exclude ribbon-related dependencies from Eureka starters in your build files, like so:
|
||||
|
||||
[source,xml,indent=0]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-ribbon</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.netflix.ribbon</groupId>
|
||||
<artifactId>ribbon-eureka</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
=== JDK 11 Support
|
||||
|
||||
The JAXB modules which the Eureka server depends upon were removed in JDK 11. If you intend to use JDK 11
|
||||
@@ -556,6 +600,10 @@ when running a Eureka server you must include these dependencies in your POM or
|
||||
</dependency>
|
||||
----
|
||||
|
||||
== Circuit Breaker: Spring Cloud Circuit Breaker With Hystrix
|
||||
|
||||
include::spring-cloud-circuitbreaker-hystrix.adoc[]
|
||||
|
||||
== Circuit Breaker: Hystrix Clients
|
||||
|
||||
Netflix has created a library called https://github.com/Netflix/Hystrix[Hystrix] that implements the https://martinfowler.com/bliki/CircuitBreaker.html[circuit breaker pattern].
|
||||
@@ -812,7 +860,7 @@ The Turbine Stream server requires the use of Spring Webflux, therefore `spring-
|
||||
By default `spring-boot-starter-webflux` is included when adding `spring-cloud-starter-netflix-turbine-stream` to your application.
|
||||
|
||||
You can then point the Hystrix Dashboard to the Turbine Stream Server instead of individual Hystrix streams.
|
||||
If Turbine Stream is running on port 8989 on myhost, then put `http://myhost:8989` in the stream input field in the Hystrix Dashboard.
|
||||
If Turbine Stream is running on port 8989 on myhost, then put `https://myhost:8989` in the stream input field in the Hystrix Dashboard.
|
||||
Circuits are prefixed by their respective `serviceId`, followed by a dot (`.`), and then the circuit name.
|
||||
|
||||
Spring Cloud provides a `spring-cloud-starter-netflix-turbine-stream` that has all the dependencies you need to get a Turbine Stream server running.
|
||||
@@ -872,7 +920,7 @@ public class TestConfiguration {
|
||||
In this case, the client is composed from the components already in `RibbonClientConfiguration`, together with any in `CustomConfiguration` (where the latter generally overrides the former).
|
||||
// TODO "generally"? We should link to the rules that dictate this behavior.
|
||||
|
||||
WARNING: The `CustomConfiguration` clas must be a `@Configuration` class, but take care that it is not in a `@ComponentScan` for the main application context.
|
||||
WARNING: The `CustomConfiguration` class must be a `@Configuration` class, but take care that it is not in a `@ComponentScan` for the main application context.
|
||||
Otherwise, it is shared by all the `@RibbonClients`. If you use `@ComponentScan` (or `@SpringBootApplication`), you need to take steps to avoid it being included (for instance, you can put it in a separate, non-overlapping package or specify the packages to scan explicitly in the `@ComponentScan`).
|
||||
|
||||
The following table shows the beans that Spring Cloud Netflix provides by default for Ribbon:
|
||||
@@ -894,7 +942,7 @@ Creating a bean of one of those type and placing it in a `@RibbonClient` configu
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../../../spring-cloud-netflix-ribbon/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonClientsPreprocessorIntegrationTests.java[tags=sample_override_ribbon_config,indent=0]
|
||||
include::{project-root}/spring-cloud-netflix-ribbon/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonClientsPreprocessorIntegrationTests.java[tags=sample_override_ribbon_config,indent=0]
|
||||
----
|
||||
|
||||
The include statement in the preceding example replaces `NoOpPing` with `PingUrl` and provides a custom `serverListFilter`.
|
||||
@@ -905,7 +953,7 @@ A default configuration can be provided for all Ribbon Clients by using the `@Ri
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../../../spring-cloud-netflix-ribbon/src/test/java/org/springframework/cloud/netflix/ribbon/test/RibbonClientDefaultConfigurationTestsConfig.java[tags=sample_default_ribbon_config,indent=0]
|
||||
include::{project-root}/spring-cloud-netflix-ribbon/src/test/java/org/springframework/cloud/netflix/ribbon/test/RibbonClientDefaultConfigurationTestsConfig.java[tags=sample_default_ribbon_config,indent=0]
|
||||
|
||||
----
|
||||
|
||||
@@ -993,7 +1041,7 @@ public class MyClass {
|
||||
|
||||
public void doStuff() {
|
||||
ServiceInstance instance = loadBalancer.choose("stores");
|
||||
URI storesUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));
|
||||
URI storesUri = URI.create(String.format("https://%s:%s", instance.getHost(), instance.getPort()));
|
||||
// ... do something with the URI
|
||||
}
|
||||
}
|
||||
@@ -1332,7 +1380,7 @@ path, rendering the `users` path unreachable.
|
||||
|
||||
The default HTTP client used by Zuul is now backed by the Apache HTTP Client instead of the deprecated Ribbon `RestClient`.
|
||||
To use `RestClient` or `okhttp3.OkHttpClient`, set `ribbon.restclient.enabled=true` or `ribbon.okhttp.enabled=true`, respectively.
|
||||
If you would like to customize the Apache HTTP client or the OK HTTP client, provide a bean of type `ClosableHttpClient` or `OkHttpClient`.
|
||||
If you would like to customize the Apache HTTP client or the OK HTTP client, provide a bean of type `CloseableHttpClient` or `OkHttpClient`.
|
||||
|
||||
=== Cookies and Sensitive Headers
|
||||
|
||||
@@ -1774,7 +1822,7 @@ The following filters are installed (as normal Spring Beans):
|
||||
** `ServletDetectionFilter`: Detects whether the request is through the Spring Dispatcher. Sets a boolean with a key of `FilterConstants.IS_DISPATCHER_SERVLET_REQUEST_KEY`.
|
||||
** `FormBodyWrapperFilter`: Parses form data and re-encodes it for downstream requests.
|
||||
** `DebugFilter`: If the `debug` request parameter is set, sets `RequestContext.setDebugRouting()` and `RequestContext.setDebugRequest()` to `true`.
|
||||
*Route filters:
|
||||
* Route filters:
|
||||
** `SendForwardFilter`: Forwards requests by using the Servlet `RequestDispatcher`. The forwarding location is stored in the `RequestContext` attribute, `FilterConstants.FORWARD_TO_KEY`. This is useful for forwarding to endpoints in the current application.
|
||||
* Post filters:
|
||||
** `SendResponseFilter`: Writes responses from proxied requests to the current response.
|
||||
@@ -2056,14 +2104,14 @@ The following example response for `/hosts/customers` returns two instances on d
|
||||
{
|
||||
"host": "myhost",
|
||||
"port": 9000,
|
||||
"uri": "http://myhost:9000",
|
||||
"uri": "https://myhost:9000",
|
||||
"serviceId": "CUSTOMERS",
|
||||
"secure": false
|
||||
},
|
||||
{
|
||||
"host": "myhost2",
|
||||
"port": 9000,
|
||||
"uri": "http://myhost2:9000",
|
||||
"uri": "https://myhost2:9000",
|
||||
"serviceId": "CUSTOMERS",
|
||||
"secure": false
|
||||
}
|
||||
@@ -2135,6 +2183,8 @@ See the https://github.com/Netflix/ribbon/wiki/Getting-Started#the-properties-fi
|
||||
WARNING: Enabling `client.ribbon.OkToRetryOnAllOperations` includes retrying POST requests, which can have an impact
|
||||
on the server's resources, due to the buffering of the request body.
|
||||
|
||||
CAUTION: The property names are case-sensitive, and since some of these properties are defined in the Netflix Ribbon project, they are in Pascal Case and the ones from Spring Cloud are in Camel Case.
|
||||
|
||||
In addition, you may want to retry requests when certain status codes are returned in the response.
|
||||
You can list the response codes you would like the Ribbon client to retry by setting the `clientName.ribbon.retryableStatusCodes` property, as shown in the following example:
|
||||
|
||||
@@ -2158,8 +2208,8 @@ You can also disable retry functionality on a route-by-route basis by setting `z
|
||||
|
||||
Spring Cloud Netflix automatically creates the HTTP client used by Ribbon, Feign, and Zuul for you.
|
||||
However, you can also provide your own HTTP clients customized as you need them to be.
|
||||
To do so, you can create a bean of type `ClosableHttpClient` if you
|
||||
are using the Apache Http Cient or `OkHttpClient` if you are using OK HTTP.
|
||||
To do so, you can create a bean of type `CloseableHttpClient` if you
|
||||
are using the Apache HTTP Client or `OkHttpClient` if you are using OK HTTP.
|
||||
|
||||
NOTE: When you create your own HTTP client, you are also responsible for implementing the correct connection management strategies for these clients.
|
||||
Doing so improperly can result in resource management issues.
|
||||
@@ -2167,3 +2217,9 @@ Doing so improperly can result in resource management issues.
|
||||
|
||||
include::maintenance-mode.adoc[]
|
||||
|
||||
== Configuration properties
|
||||
|
||||
To see the list of all Spring Cloud Netflix related configuration properties please check link:appendix.html[the Appendix page].
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM https://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
|
||||
@@ -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>2.1.7.SNAPSHOT</version>
|
||||
<version>2.2.4.RELEASE</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>2.1.12.SNAPSHOT</version>
|
||||
<version>2.3.1.RELEASE</version>
|
||||
<relativePath />
|
||||
</parent>
|
||||
<scm>
|
||||
@@ -21,27 +21,26 @@
|
||||
</scm>
|
||||
<properties>
|
||||
<bintray.package>netflix</bintray.package>
|
||||
<spring-cloud-commons.version>2.1.7.SNAPSHOT</spring-cloud-commons.version>
|
||||
<spring-cloud-config.version>2.1.9.SNAPSHOT</spring-cloud-config.version>
|
||||
<spring-cloud-stream.version>Fishtown.SR4</spring-cloud-stream.version>
|
||||
<spring-cloud-commons.version>2.2.4.RELEASE</spring-cloud-commons.version>
|
||||
<spring-cloud-config.version>2.2.4.RELEASE</spring-cloud-config.version>
|
||||
<spring-cloud-stream.version>Horsham.SR7</spring-cloud-stream.version>
|
||||
<!-- Has to be a stable version (not one that depends on this version of netflix): -->
|
||||
<donotreplacespring-cloud-contract.version>2.1.3.RELEASE</donotreplacespring-cloud-contract.version>
|
||||
<donotreplacespring-cloud-contract.version>2.2.1.RELEASE</donotreplacespring-cloud-contract.version>
|
||||
|
||||
<!-- Sonar -->
|
||||
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
|
||||
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
|
||||
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
|
||||
<sonar.language>java</sonar.language>
|
||||
<maven-checkstyle-plugin.includeTestSourceDirectory>true
|
||||
</maven-checkstyle-plugin.includeTestSourceDirectory>
|
||||
<maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError>
|
||||
<maven-checkstyle-plugin.failOnViolation>true
|
||||
</maven-checkstyle-plugin.failOnViolation>
|
||||
<eureka-jersey.version>1.19.1</eureka-jersey.version>
|
||||
<xstream.version>1.4.11.1</xstream.version>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>flatten-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-eclipse-plugin</artifactId>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<version>2.1.7.SNAPSHOT</version>
|
||||
<version>2.2.4.RELEASE</version>
|
||||
<relativePath>..</relativePath> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
|
||||
+11
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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,7 +41,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
|
||||
import org.springframework.boot.actuate.health.Health;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
@@ -51,6 +51,7 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
@@ -65,8 +66,10 @@ import static com.netflix.config.ConfigurationManager.URL_CONFIG_NAME;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Liang Yong
|
||||
*/
|
||||
@Configuration
|
||||
@Lazy(false)
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ ConcurrentCompositeConfiguration.class,
|
||||
ConfigurationBuilder.class })
|
||||
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
|
||||
@@ -194,20 +197,21 @@ public class ArchaiusAutoConfiguration {
|
||||
ReflectionUtils.setField(field, null, value);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(Health.class)
|
||||
protected static class ArchaiusEndpointConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnEnabledEndpoint
|
||||
@ConditionalOnAvailableEndpoint
|
||||
protected ArchaiusEndpoint archaiusEndpoint() {
|
||||
return new ArchaiusEndpoint();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "archaius.propagate.environmentChangedEvent", matchIfMissing = true)
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(value = "archaius.propagate.environmentChangedEvent",
|
||||
matchIfMissing = true)
|
||||
@ConditionalOnClass(EnvironmentChangeEvent.class)
|
||||
protected static class PropagateEventsConfiguration
|
||||
implements ApplicationListener<EnvironmentChangeEvent> {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2013-2020 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.archaius;
|
||||
|
||||
import com.netflix.config.DynamicProperty;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Liang Yong
|
||||
*/
|
||||
|
||||
@SpringBootTest(classes = LazyLoadConfigurationTests.TestConfig.class,
|
||||
properties = { "client.ribbon.listOfServers=foo.com,bar.com",
|
||||
"spring.main.lazy-initialization=true" })
|
||||
public class LazyLoadConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void enableLazyInitialization() {
|
||||
DynamicProperty instance = DynamicProperty
|
||||
.getInstance("client.ribbon.listOfServers");
|
||||
assertThat(instance.getString()).isEqualTo("foo.com,bar.com");
|
||||
}
|
||||
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration
|
||||
static class TestConfig {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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,7 +26,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
/**
|
||||
* @author Alexandru-George Burghelea
|
||||
*/
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class TestArchaiusExternalConfiguration {
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>2.1.7.SNAPSHOT</version>
|
||||
<version>2.2.4.RELEASE</version>
|
||||
<relativePath>..</relativePath> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<artifactId>spring-cloud-netflix-concurrency-limits</artifactId>
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
@@ -27,7 +27,9 @@ import io.micrometer.core.instrument.Tags;
|
||||
* A Micrometer-specific {@link MetricRegistry} implementation.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @deprecated to be removed in 3.0.0
|
||||
*/
|
||||
@Deprecated
|
||||
public class MicrometerMetricRegistry implements MetricRegistry {
|
||||
|
||||
private final MeterRegistry meterRegistry;
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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,7 +29,9 @@ import org.springframework.web.server.WebFilterChain;
|
||||
* {@link Limiter} to handle requests.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @deprecated to be removed in 3.0.0
|
||||
*/
|
||||
@Deprecated
|
||||
public class ConcurrencyLimitsWebFilter implements WebFilter {
|
||||
|
||||
private final Limiter<ServerWebExchange> limiter;
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
@@ -35,8 +35,10 @@ import org.springframework.web.server.WebFilter;
|
||||
* Reactive autoconfiguration class for registering Netflix {@link Limiter} bean.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @deprecated to be removed in 3.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@Deprecated
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnWebApplication(type = Type.REACTIVE)
|
||||
@ConditionalOnClass({ WebFilter.class, Mono.class })
|
||||
public class ReactiveConcurrencyLimitsAutoConfiguration {
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
@@ -27,7 +27,9 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
* Builder for ServerWebExchange Limiter.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @deprecated to be removed in 3.0.0
|
||||
*/
|
||||
@Deprecated
|
||||
public class ServerWebExchangeLimiterBuilder extends
|
||||
AbstractPartitionedLimiter.Builder<ServerWebExchangeLimiterBuilder, ServerWebExchange> {
|
||||
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
@@ -34,7 +34,9 @@ import org.springframework.web.servlet.ModelAndView;
|
||||
* {@link Limiter} to handle requests.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @deprecated to be removed in 3.0.0
|
||||
*/
|
||||
@Deprecated
|
||||
public class ConcurrencyLimitsHandlerInterceptor implements HandlerInterceptor {
|
||||
|
||||
private final Limiter<HttpServletRequest> limiter;
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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,10 +39,12 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
* MVC autoconfiguration class for registering Netflix {@link Limiter} bean.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @deprecated to be removed in 3.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnWebApplication(type = Type.SERVLET)
|
||||
@ConditionalOnClass({ HttpServletRequest.class, HandlerInterceptor.class })
|
||||
@Deprecated
|
||||
public class MvcConcurrencyLimitsAutoConfiguration implements WebMvcConfigurer {
|
||||
|
||||
private final ObjectProvider<Consumer<ServletLimiterBuilder>> configurerProvider;
|
||||
@@ -62,7 +64,7 @@ public class MvcConcurrencyLimitsAutoConfiguration implements WebMvcConfigurer {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
protected static class HandlerInterceptorConfiguration implements WebMvcConfigurer {
|
||||
|
||||
@Autowired
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
@@ -66,7 +66,7 @@ public class AbstractConcurrencyLimitsTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@RestController
|
||||
protected static class HelloControllerConfiguration {
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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,8 @@ import org.springframework.web.reactive.function.client.WebClient;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(properties = "logging.level.reactor.netty=DEBUG", webEnvironment = RANDOM_PORT)
|
||||
@SpringBootTest(properties = "logging.level.reactor.netty=DEBUG",
|
||||
webEnvironment = RANDOM_PORT)
|
||||
public class ConcurrencyLimitsHandlerInterceptorTests
|
||||
extends AbstractConcurrencyLimitsTests {
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>2.1.7.SNAPSHOT</version>
|
||||
<version>2.2.4.RELEASE</version>
|
||||
<relativePath>..</relativePath> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<artifactId>spring-cloud-netflix-core</artifactId>
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2019 the original author or authors.
|
||||
* Copyright 2018-2020 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.
|
||||
@@ -27,7 +27,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
* @deprecated Module spring-cloud-netflix-core is deprecated as of 2.1.0, use
|
||||
* spring-cloud-netflix-hystrix instead.
|
||||
*/
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Deprecated
|
||||
public class CoreAutoConfiguration {
|
||||
|
||||
|
||||
@@ -5,20 +5,20 @@
|
||||
<parent>
|
||||
<artifactId>spring-cloud-dependencies-parent</artifactId>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<version>2.1.12.SNAPSHOT</version>
|
||||
<version>2.3.1.RELEASE</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<artifactId>spring-cloud-netflix-dependencies</artifactId>
|
||||
<version>2.1.7.SNAPSHOT</version>
|
||||
<version>2.2.4.RELEASE</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>spring-cloud-netflix-dependencies</name>
|
||||
<description>Spring Cloud Netflix Dependencies</description>
|
||||
<properties>
|
||||
<archaius.version>0.7.6</archaius.version>
|
||||
<concurrency-limits.version>0.1.12</concurrency-limits.version>
|
||||
<eureka.version>1.9.13</eureka.version>
|
||||
<eureka.version>1.9.25</eureka.version>
|
||||
<eventbus.version>0.3.0</eventbus.version>
|
||||
<hystrix.version>1.5.18</hystrix.version>
|
||||
<okhttp3.version>3.8.1</okhttp3.version>
|
||||
<ribbon.version>2.3.0</ribbon.version>
|
||||
<servo.version>0.12.21</servo.version>
|
||||
<zuul.version>1.3.1</zuul.version>
|
||||
@@ -56,11 +56,6 @@
|
||||
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix-hystrix-contract</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
|
||||
@@ -370,14 +365,9 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${okhttp3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>logging-interceptor</artifactId>
|
||||
<version>${okhttp3.version}</version>
|
||||
<groupId>com.netflix.netflix-commons</groupId>
|
||||
<artifactId>netflix-eventbus</artifactId>
|
||||
<version>${eventbus.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>2.1.7.SNAPSHOT</version>
|
||||
<version>2.2.4.RELEASE</version>
|
||||
<relativePath>..</relativePath> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<artifactId>spring-cloud-netflix-eureka-client</artifactId>
|
||||
@@ -27,6 +27,11 @@
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix-hystrix</artifactId>
|
||||
@@ -46,6 +51,11 @@
|
||||
<artifactId>spring-cloud-config-server</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-loadbalancer</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.eureka</groupId>
|
||||
<artifactId>eureka-client</artifactId>
|
||||
@@ -82,6 +92,11 @@
|
||||
<artifactId>ribbon</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.netflix-commons</groupId>
|
||||
<artifactId>netflix-eventbus</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.ribbon</groupId>
|
||||
<artifactId>ribbon-core</artifactId>
|
||||
@@ -127,5 +142,10 @@
|
||||
<artifactId>spring-retry</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* Copyright 2013-2020 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
-38
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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,13 +50,11 @@ import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
|
||||
import org.springframework.cloud.client.CommonsClientAutoConfiguration;
|
||||
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
|
||||
import org.springframework.cloud.client.actuator.HasFeatures;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.noop.NoopDiscoveryClientAutoConfiguration;
|
||||
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
|
||||
import org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration;
|
||||
import org.springframework.cloud.commons.util.InetUtils;
|
||||
import org.springframework.cloud.context.scope.refresh.RefreshScope;
|
||||
import org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration;
|
||||
import org.springframework.cloud.netflix.eureka.metadata.DefaultManagementMetadataProvider;
|
||||
import org.springframework.cloud.netflix.eureka.metadata.ManagementMetadata;
|
||||
import org.springframework.cloud.netflix.eureka.metadata.ManagementMetadataProvider;
|
||||
@@ -68,7 +66,6 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -83,17 +80,17 @@ import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceI
|
||||
* @author Ryan Baxter
|
||||
* @author Daniel Lavoie
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Tim Ysewyn
|
||||
*/
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
@ConditionalOnClass(EurekaClientConfig.class)
|
||||
@Import(DiscoveryClientOptionalArgsConfiguration.class)
|
||||
@ConditionalOnBean(EurekaDiscoveryClientConfiguration.Marker.class)
|
||||
@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
|
||||
@ConditionalOnDiscoveryEnabled
|
||||
@AutoConfigureBefore({ NoopDiscoveryClientAutoConfiguration.class,
|
||||
CommonsClientAutoConfiguration.class, ServiceRegistryAutoConfiguration.class })
|
||||
@AutoConfigureAfter(name = {
|
||||
"org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration",
|
||||
"org.springframework.cloud.autoconfigure.RefreshAutoConfiguration",
|
||||
"org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration",
|
||||
"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration" })
|
||||
@@ -111,15 +108,10 @@ public class EurekaClientAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = EurekaClientConfig.class, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnMissingBean(value = EurekaClientConfig.class,
|
||||
search = SearchStrategy.CURRENT)
|
||||
public EurekaClientConfigBean eurekaClientConfigBean(ConfigurableEnvironment env) {
|
||||
EurekaClientConfigBean client = new EurekaClientConfigBean();
|
||||
if ("bootstrap".equals(this.env.getProperty("spring.config.name"))) {
|
||||
// We don't register during bootstrap by default, but there will be another
|
||||
// chance later.
|
||||
client.setRegisterWithEureka(false);
|
||||
}
|
||||
return client;
|
||||
return new EurekaClientConfigBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -133,7 +125,8 @@ public class EurekaClientAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = EurekaInstanceConfig.class, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnMissingBean(value = EurekaInstanceConfig.class,
|
||||
search = SearchStrategy.CURRENT)
|
||||
public EurekaInstanceConfigBean eurekaInstanceConfigBean(InetUtils inetUtils,
|
||||
ManagementMetadataProvider managementMetadataProvider) {
|
||||
String hostname = getProperty("eureka.instance.hostname");
|
||||
@@ -215,12 +208,6 @@ public class EurekaClientAutoConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DiscoveryClient discoveryClient(EurekaClient client,
|
||||
EurekaClientConfig clientConfig) {
|
||||
return new EurekaDiscoveryClient(client, clientConfig);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EurekaServiceRegistry eurekaServiceRegistry() {
|
||||
return new EurekaServiceRegistry();
|
||||
@@ -242,14 +229,16 @@ public class EurekaClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
|
||||
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
|
||||
@ConditionalOnProperty(
|
||||
value = "spring.cloud.service-registry.auto-registration.enabled",
|
||||
matchIfMissing = true)
|
||||
public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(
|
||||
ApplicationContext context, EurekaServiceRegistry registry,
|
||||
EurekaRegistration registration) {
|
||||
return new EurekaAutoServiceRegistration(context, registry, registration);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnMissingRefreshScope
|
||||
protected static class EurekaClientConfiguration {
|
||||
|
||||
@@ -260,7 +249,8 @@ public class EurekaClientAutoConfiguration {
|
||||
private AbstractDiscoveryClientOptionalArgs<?> optionalArgs;
|
||||
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnMissingBean(value = EurekaClient.class,
|
||||
search = SearchStrategy.CURRENT)
|
||||
public EurekaClient eurekaClient(ApplicationInfoManager manager,
|
||||
EurekaClientConfig config) {
|
||||
return new CloudEurekaClient(manager, config, this.optionalArgs,
|
||||
@@ -268,7 +258,8 @@ public class EurekaClientAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = ApplicationInfoManager.class, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnMissingBean(value = ApplicationInfoManager.class,
|
||||
search = SearchStrategy.CURRENT)
|
||||
public ApplicationInfoManager eurekaApplicationInfoManager(
|
||||
EurekaInstanceConfig config) {
|
||||
InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);
|
||||
@@ -277,18 +268,20 @@ public class EurekaClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
|
||||
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
|
||||
@ConditionalOnProperty(
|
||||
value = "spring.cloud.service-registry.auto-registration.enabled",
|
||||
matchIfMissing = true)
|
||||
public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient,
|
||||
CloudEurekaInstanceConfig instanceConfig,
|
||||
ApplicationInfoManager applicationInfoManager,
|
||||
@Autowired(required = false) ObjectProvider<HealthCheckHandler> healthCheckHandler) {
|
||||
ApplicationInfoManager applicationInfoManager, @Autowired(
|
||||
required = false) ObjectProvider<HealthCheckHandler> healthCheckHandler) {
|
||||
return EurekaRegistration.builder(instanceConfig).with(applicationInfoManager)
|
||||
.with(eurekaClient).with(healthCheckHandler).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnRefreshScope
|
||||
protected static class RefreshableEurekaClientConfiguration {
|
||||
|
||||
@@ -299,7 +292,8 @@ public class EurekaClientAutoConfiguration {
|
||||
private AbstractDiscoveryClientOptionalArgs<?> optionalArgs;
|
||||
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnMissingBean(value = EurekaClient.class,
|
||||
search = SearchStrategy.CURRENT)
|
||||
@org.springframework.cloud.context.config.annotation.RefreshScope
|
||||
@Lazy
|
||||
public EurekaClient eurekaClient(ApplicationInfoManager manager,
|
||||
@@ -326,7 +320,8 @@ public class EurekaClientAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = ApplicationInfoManager.class, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnMissingBean(value = ApplicationInfoManager.class,
|
||||
search = SearchStrategy.CURRENT)
|
||||
@org.springframework.cloud.context.config.annotation.RefreshScope
|
||||
@Lazy
|
||||
public ApplicationInfoManager eurekaApplicationInfoManager(
|
||||
@@ -338,11 +333,13 @@ public class EurekaClientAutoConfiguration {
|
||||
@Bean
|
||||
@org.springframework.cloud.context.config.annotation.RefreshScope
|
||||
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
|
||||
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
|
||||
@ConditionalOnProperty(
|
||||
value = "spring.cloud.service-registry.auto-registration.enabled",
|
||||
matchIfMissing = true)
|
||||
public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient,
|
||||
CloudEurekaInstanceConfig instanceConfig,
|
||||
ApplicationInfoManager applicationInfoManager,
|
||||
@Autowired(required = false) ObjectProvider<HealthCheckHandler> healthCheckHandler) {
|
||||
ApplicationInfoManager applicationInfoManager, @Autowired(
|
||||
required = false) ObjectProvider<HealthCheckHandler> healthCheckHandler) {
|
||||
return EurekaRegistration.builder(instanceConfig).with(applicationInfoManager)
|
||||
.with(eurekaClient).with(healthCheckHandler).build();
|
||||
}
|
||||
@@ -362,7 +359,8 @@ public class EurekaClientAutoConfiguration {
|
||||
@Documented
|
||||
@ConditionalOnClass(RefreshScope.class)
|
||||
@ConditionalOnBean(RefreshAutoConfiguration.class)
|
||||
@ConditionalOnProperty(value = "eureka.client.refresh.enable", havingValue = "true", matchIfMissing = true)
|
||||
@ConditionalOnProperty(value = "eureka.client.refresh.enable", havingValue = "true",
|
||||
matchIfMissing = true)
|
||||
@interface ConditionalOnRefreshScope {
|
||||
|
||||
}
|
||||
@@ -383,14 +381,15 @@ public class EurekaClientAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(value = "eureka.client.refresh.enable", havingValue = "false")
|
||||
@ConditionalOnProperty(value = "eureka.client.refresh.enable",
|
||||
havingValue = "false")
|
||||
static class OnPropertyDisabled {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(Health.class)
|
||||
protected static class EurekaHealthIndicatorConfiguration {
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
@@ -1086,7 +1086,7 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
|
||||
.append(decoderName).append("', ").append("clientDataAccept='")
|
||||
.append(clientDataAccept).append("', ")
|
||||
.append("shouldUnregisterOnShutdown='").append(shouldUnregisterOnShutdown)
|
||||
.append("', ").append("shouldEnforceRegistrationAtInit='")
|
||||
.append("shouldEnforceRegistrationAtInit='")
|
||||
.append(shouldEnforceRegistrationAtInit).append("', ").append("order='")
|
||||
.append(order).append("'}").toString();
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+11
-60
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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,11 +16,9 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.netflix.appinfo.EurekaInstanceConfig;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
@@ -29,13 +27,9 @@ import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.shared.Application;
|
||||
import com.netflix.discovery.shared.Applications;
|
||||
|
||||
import org.springframework.cloud.client.DefaultServiceInstance;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import static com.netflix.appinfo.InstanceInfo.PortType.SECURE;
|
||||
|
||||
/**
|
||||
* A {@link DiscoveryClient} implementation for Eureka.
|
||||
@@ -106,64 +100,21 @@ public class EurekaDiscoveryClient implements DiscoveryClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* An Eureka-specific {@link ServiceInstance} implementation.
|
||||
* An Eureka-specific {@link ServiceInstance} implementation. Extends
|
||||
* {@link org.springframework.cloud.netflix.eureka.EurekaServiceInstance} for
|
||||
* backwards compatibility.
|
||||
*
|
||||
* @deprecated In favor of
|
||||
* {@link org.springframework.cloud.netflix.eureka.EurekaServiceInstance}.
|
||||
*/
|
||||
public static class EurekaServiceInstance implements ServiceInstance {
|
||||
|
||||
private InstanceInfo instance;
|
||||
@Deprecated
|
||||
public static class EurekaServiceInstance
|
||||
extends org.springframework.cloud.netflix.eureka.EurekaServiceInstance {
|
||||
|
||||
public EurekaServiceInstance(InstanceInfo instance) {
|
||||
Assert.notNull(instance, "Service instance required");
|
||||
this.instance = instance;
|
||||
super(instance);
|
||||
}
|
||||
|
||||
public InstanceInfo getInstanceInfo() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInstanceId() {
|
||||
return this.instance.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceId() {
|
||||
return this.instance.getAppName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHost() {
|
||||
return this.instance.getHostName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPort() {
|
||||
if (isSecure()) {
|
||||
return this.instance.getSecurePort();
|
||||
}
|
||||
return this.instance.getPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
// assume if secure is enabled, that is the default
|
||||
return this.instance.isPortEnabled(SECURE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getUri() {
|
||||
return DefaultServiceInstance.getUri(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getMetadata() {
|
||||
return this.instance.getMetadata();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScheme() {
|
||||
return getUri().getScheme();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+32
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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,12 +21,13 @@ import com.netflix.discovery.EurekaClient;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.health.HealthAggregator;
|
||||
import org.springframework.boot.actuate.health.OrderedHealthAggregator;
|
||||
import org.springframework.boot.actuate.health.SimpleStatusAggregator;
|
||||
import org.springframework.boot.actuate.health.StatusAggregator;
|
||||
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.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled;
|
||||
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
|
||||
import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent;
|
||||
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration;
|
||||
@@ -40,39 +41,61 @@ import org.springframework.context.annotation.Configuration;
|
||||
* @author Jon Schneider
|
||||
* @author Jakub Narloch
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Tim Ysewyn
|
||||
*/
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
@ConditionalOnClass(EurekaClientConfig.class)
|
||||
@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
|
||||
@ConditionalOnDiscoveryEnabled
|
||||
@ConditionalOnBlockingDiscoveryEnabled
|
||||
public class EurekaDiscoveryClientConfiguration {
|
||||
|
||||
/**
|
||||
* Deprecated in favor of auto configuration order.
|
||||
* @return Marker bean
|
||||
* @deprecated in favor of auto configuration order.
|
||||
*/
|
||||
@Deprecated
|
||||
@Bean
|
||||
public Marker eurekaDiscoverClientMarker() {
|
||||
return new Marker();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "eureka.client.healthcheck.enabled", matchIfMissing = false)
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EurekaDiscoveryClient discoveryClient(EurekaClient client,
|
||||
EurekaClientConfig clientConfig) {
|
||||
return new EurekaDiscoveryClient(client, clientConfig);
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(value = "eureka.client.healthcheck.enabled",
|
||||
matchIfMissing = false)
|
||||
protected static class EurekaHealthCheckHandlerConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private HealthAggregator healthAggregator = new OrderedHealthAggregator();
|
||||
private StatusAggregator statusAggregator = new SimpleStatusAggregator();
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(HealthCheckHandler.class)
|
||||
public EurekaHealthCheckHandler eurekaHealthCheckHandler() {
|
||||
return new EurekaHealthCheckHandler(this.healthAggregator);
|
||||
return new EurekaHealthCheckHandler(this.statusAggregator);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated in favor of auto configuration order.
|
||||
*
|
||||
* @deprecated in favor of auto configuration order.
|
||||
*/
|
||||
@Deprecated
|
||||
class Marker {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(RefreshScopeRefreshedEvent.class)
|
||||
protected static class EurekaClientConfigurationRefresher
|
||||
implements ApplicationListener<RefreshScopeRefreshedEvent> {
|
||||
|
||||
+94
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
@@ -18,6 +18,8 @@ package org.springframework.cloud.netflix.eureka;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.netflix.appinfo.HealthCheckHandler;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
@@ -25,9 +27,14 @@ import com.netflix.appinfo.InstanceInfo;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.actuate.health.CompositeHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.DefaultHealthIndicatorRegistry;
|
||||
import org.springframework.boot.actuate.health.Health;
|
||||
import org.springframework.boot.actuate.health.HealthAggregator;
|
||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
import org.springframework.boot.actuate.health.HealthIndicatorRegistryFactory;
|
||||
import org.springframework.boot.actuate.health.Status;
|
||||
import org.springframework.boot.actuate.health.StatusAggregator;
|
||||
import org.springframework.cloud.client.discovery.health.DiscoveryCompositeHealthContributor;
|
||||
import org.springframework.cloud.client.discovery.health.DiscoveryCompositeHealthIndicator;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
@@ -44,7 +51,9 @@ import static com.netflix.appinfo.InstanceInfo.InstanceStatus;
|
||||
* all registered {@link HealthIndicator} through registered {@link HealthAggregator}.
|
||||
*
|
||||
* @author Jakub Narloch
|
||||
* @author Spencer Gibb
|
||||
* @see HealthCheckHandler
|
||||
* @see StatusAggregator
|
||||
* @see HealthAggregator
|
||||
*/
|
||||
public class EurekaHealthCheckHandler
|
||||
@@ -59,13 +68,34 @@ public class EurekaHealthCheckHandler
|
||||
}
|
||||
};
|
||||
|
||||
private final CompositeHealthIndicator healthIndicator;
|
||||
private StatusAggregator statusAggregator;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private Map<String, HealthIndicator> healthIndicators;
|
||||
|
||||
@Deprecated
|
||||
private CompositeHealthIndicator healthIndicator;
|
||||
|
||||
@Deprecated
|
||||
private HealthIndicatorRegistryFactory healthIndicatorRegistryFactory;
|
||||
|
||||
@Deprecated
|
||||
private HealthAggregator healthAggregator;
|
||||
|
||||
@Deprecated
|
||||
public EurekaHealthCheckHandler(HealthAggregator healthAggregator) {
|
||||
Assert.notNull(healthAggregator, "HealthAggregator must not be null");
|
||||
this.healthIndicator = new CompositeHealthIndicator(healthAggregator);
|
||||
this.healthAggregator = healthAggregator;
|
||||
this.healthIndicatorRegistryFactory = new HealthIndicatorRegistryFactory();
|
||||
this.healthIndicator = new CompositeHealthIndicator(this.healthAggregator,
|
||||
new DefaultHealthIndicatorRegistry());
|
||||
}
|
||||
|
||||
public EurekaHealthCheckHandler(StatusAggregator statusAggregator) {
|
||||
this.statusAggregator = statusAggregator;
|
||||
Assert.notNull(statusAggregator, "StatusAggregator must not be null");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -78,7 +108,18 @@ public class EurekaHealthCheckHandler
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
final Map<String, HealthIndicator> healthIndicators = applicationContext
|
||||
.getBeansOfType(HealthIndicator.class);
|
||||
this.healthIndicators = new HashMap<>();
|
||||
|
||||
if (statusAggregator != null) {
|
||||
populateHealthIndicators(healthIndicators);
|
||||
}
|
||||
else {
|
||||
createHealthIndicator(healthIndicators);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
void createHealthIndicator(Map<String, HealthIndicator> healthIndicators) {
|
||||
for (Map.Entry<String, HealthIndicator> entry : healthIndicators.entrySet()) {
|
||||
|
||||
// ignore EurekaHealthIndicator and flatten the rest of the composite
|
||||
@@ -89,14 +130,37 @@ public class EurekaHealthCheckHandler
|
||||
for (DiscoveryCompositeHealthIndicator.Holder holder : indicator
|
||||
.getHealthIndicators()) {
|
||||
if (!(holder.getDelegate() instanceof EurekaHealthIndicator)) {
|
||||
healthIndicator.addHealthIndicator(holder.getDelegate().getName(),
|
||||
holder);
|
||||
this.healthIndicators.put(holder.getDelegate().getName(), holder);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
healthIndicator.addHealthIndicator(entry.getKey(), entry.getValue());
|
||||
this.healthIndicators.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
this.healthIndicator = new CompositeHealthIndicator(healthAggregator,
|
||||
healthIndicatorRegistryFactory
|
||||
.createHealthIndicatorRegistry(this.healthIndicators));
|
||||
}
|
||||
|
||||
void populateHealthIndicators(Map<String, HealthIndicator> healthIndicators) {
|
||||
for (Map.Entry<String, HealthIndicator> entry : healthIndicators.entrySet()) {
|
||||
// ignore EurekaHealthIndicator and flatten the rest of the composite
|
||||
// otherwise there is a never ending cycle of down. See gh-643
|
||||
if (entry.getValue() instanceof DiscoveryCompositeHealthContributor) {
|
||||
DiscoveryCompositeHealthContributor indicator = (DiscoveryCompositeHealthContributor) entry
|
||||
.getValue();
|
||||
indicator.forEach(contributor -> {
|
||||
if (!(contributor
|
||||
.getContributor() instanceof EurekaHealthIndicator)) {
|
||||
this.healthIndicators.put(contributor.getName(),
|
||||
(HealthIndicator) contributor.getContributor());
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.healthIndicators.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,10 +171,32 @@ public class EurekaHealthCheckHandler
|
||||
}
|
||||
|
||||
protected InstanceStatus getHealthStatus() {
|
||||
final Status status = getHealthIndicator().health().getStatus();
|
||||
final Status status;
|
||||
if (statusAggregator != null) {
|
||||
status = getStatus(statusAggregator);
|
||||
}
|
||||
else {
|
||||
status = getStatus(getHealthIndicator());
|
||||
}
|
||||
return mapToInstanceStatus(status);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private Status getStatus(CompositeHealthIndicator healthIndicator) {
|
||||
Status status;
|
||||
status = healthIndicator.health().getStatus();
|
||||
return status;
|
||||
}
|
||||
|
||||
protected Status getStatus(StatusAggregator statusAggregator) {
|
||||
Status status;
|
||||
Set<Status> statusSet = healthIndicators.values().stream()
|
||||
.map(HealthIndicator::health).map(Health::getStatus)
|
||||
.collect(Collectors.toSet());
|
||||
status = statusAggregator.getAggregateStatus(statusSet);
|
||||
return status;
|
||||
}
|
||||
|
||||
protected InstanceStatus mapToInstanceStatus(Status status) {
|
||||
if (!STATUS_MAPPING.containsKey(status)) {
|
||||
return InstanceStatus.UNKNOWN;
|
||||
@@ -118,6 +204,7 @@ public class EurekaHealthCheckHandler
|
||||
return STATUS_MAPPING.get(status);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected CompositeHealthIndicator getHealthIndicator() {
|
||||
return healthIndicator;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2013-2020 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;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
|
||||
import org.springframework.cloud.client.DefaultServiceInstance;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import static com.netflix.appinfo.InstanceInfo.PortType.SECURE;
|
||||
|
||||
/**
|
||||
* An Eureka-specific {@link ServiceInstance} implementation.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Dave Syer
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Tim Ysewyn
|
||||
*/
|
||||
public class EurekaServiceInstance implements ServiceInstance {
|
||||
|
||||
private InstanceInfo instance;
|
||||
|
||||
public EurekaServiceInstance(InstanceInfo instance) {
|
||||
Assert.notNull(instance, "Service instance required");
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
public InstanceInfo getInstanceInfo() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInstanceId() {
|
||||
return this.instance.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceId() {
|
||||
return this.instance.getAppName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHost() {
|
||||
return this.instance.getHostName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPort() {
|
||||
if (isSecure()) {
|
||||
return this.instance.getSecurePort();
|
||||
}
|
||||
return this.instance.getPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
// assume if secure is enabled, that is the default
|
||||
return this.instance.isPortEnabled(SECURE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getUri() {
|
||||
return DefaultServiceInstance.getUri(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getMetadata() {
|
||||
return this.instance.getMetadata();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScheme() {
|
||||
return getUri().getScheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
EurekaServiceInstance that = (EurekaServiceInstance) o;
|
||||
return Objects.equals(this.instance, that.instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("instance", instance).toString();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+53
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2020 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,34 +17,83 @@
|
||||
package org.springframework.cloud.netflix.eureka.config;
|
||||
|
||||
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.cloud.netflix.eureka.MutableDiscoveryClientOptionalArgs;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs;
|
||||
import org.springframework.cloud.netflix.eureka.http.WebClientDiscoveryClientOptionalArgs;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
*/
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class DiscoveryClientOptionalArgsConfiguration {
|
||||
|
||||
protected static final Log logger = LogFactory
|
||||
.getLog(DiscoveryClientOptionalArgsConfiguration.class);
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingClass("com.sun.jersey.api.client.filter.ClientFilter")
|
||||
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnMissingBean(value = { AbstractDiscoveryClientOptionalArgs.class },
|
||||
search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
|
||||
matchIfMissing = true, havingValue = "false")
|
||||
public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs() {
|
||||
logger.info("Eureka HTTP Client uses RestTemplate.");
|
||||
return new RestTemplateDiscoveryClientOptionalArgs();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = "com.sun.jersey.api.client.filter.ClientFilter")
|
||||
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class,
|
||||
search = SearchStrategy.CURRENT)
|
||||
public MutableDiscoveryClientOptionalArgs discoveryClientOptionalArgs() {
|
||||
return new MutableDiscoveryClientOptionalArgs();
|
||||
}
|
||||
|
||||
@ConditionalOnMissingClass("com.sun.jersey.api.client.filter.ClientFilter")
|
||||
@ConditionalOnClass(
|
||||
name = "org.springframework.web.reactive.function.client.WebClient")
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
|
||||
havingValue = "true")
|
||||
protected static class WebClientConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(
|
||||
value = { AbstractDiscoveryClientOptionalArgs.class,
|
||||
RestTemplateDiscoveryClientOptionalArgs.class },
|
||||
search = SearchStrategy.CURRENT)
|
||||
public WebClientDiscoveryClientOptionalArgs webClientDiscoveryClientOptionalArgs(
|
||||
ObjectProvider<WebClient.Builder> builder) {
|
||||
logger.info("Eureka HTTP Client uses WebClient.");
|
||||
return new WebClientDiscoveryClientOptionalArgs(builder::getIfAvailable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingClass({ "com.sun.jersey.api.client.filter.ClientFilter",
|
||||
"org.springframework.web.reactive.function.client.WebClient" })
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
|
||||
havingValue = "true")
|
||||
protected static class WebClientNotFoundConfiguration {
|
||||
|
||||
public WebClientNotFoundConfiguration() {
|
||||
throw new IllegalStateException("eureka.client.webclient.enabled is true, "
|
||||
+ "but WebClient is not on the classpath. Please add "
|
||||
+ "spring-boot-starter-webflux as a dependency.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
@@ -34,7 +34,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
@ConditionalOnClass({ EurekaInstanceConfigBean.class, EurekaClient.class,
|
||||
ConfigServerProperties.class })
|
||||
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright 2013-2020 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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.endpoint.EndpointUtils;
|
||||
import com.netflix.discovery.shared.Applications;
|
||||
import com.netflix.discovery.shared.resolver.DefaultEndpoint;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpClient;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpResponse;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
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.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.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.config.client.ConfigServerInstanceProvider;
|
||||
import org.springframework.cloud.config.client.ConfigServicePropertySourceLocator;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaServiceInstance;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateEurekaHttpClient;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateTransportClientFactory;
|
||||
import org.springframework.cloud.netflix.eureka.http.WebClientEurekaHttpClient;
|
||||
import org.springframework.cloud.netflix.eureka.http.WebClientTransportClientFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* Bootstrap configuration for config client that wants to lookup the config server via
|
||||
* discovery.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConditionalOnClass(ConfigServicePropertySourceLocator.class)
|
||||
@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled",
|
||||
matchIfMissing = false)
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
public class EurekaConfigServerBootstrapConfiguration {
|
||||
|
||||
private static final Log log = LogFactory
|
||||
.getLog(EurekaConfigServerBootstrapConfiguration.class);
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = EurekaClientConfig.class,
|
||||
search = SearchStrategy.CURRENT)
|
||||
public EurekaClientConfigBean eurekaClientConfigBean() {
|
||||
return new EurekaClientConfigBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(EurekaHttpClient.class)
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
|
||||
matchIfMissing = true, havingValue = "false")
|
||||
public RestTemplateEurekaHttpClient configDiscoveryRestTemplateEurekaHttpClient(
|
||||
EurekaClientConfigBean config, Environment env) {
|
||||
return (RestTemplateEurekaHttpClient) new RestTemplateTransportClientFactory()
|
||||
.newClient(new DefaultEndpoint(getEurekaUrl(config, env)));
|
||||
}
|
||||
|
||||
private static String getEurekaUrl(EurekaClientConfigBean config, Environment env) {
|
||||
List<String> urls = EndpointUtils.getDiscoveryServiceUrls(config,
|
||||
EurekaClientConfigBean.DEFAULT_ZONE, new HostnameBasedUrlRandomizer(
|
||||
env.getProperty("eureka.instance.hostname")));
|
||||
return urls.get(0);
|
||||
}
|
||||
|
||||
private boolean isSuccessful(EurekaHttpResponse<Applications> response) {
|
||||
HttpStatus httpStatus = HttpStatus.resolve(response.getStatusCode());
|
||||
return httpStatus != null && httpStatus.is2xxSuccessful();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigServerInstanceProvider.Function eurekaConfigServerInstanceProvider(
|
||||
EurekaHttpClient client, EurekaClientConfig config) {
|
||||
|
||||
return serviceId -> {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("eurekaConfigServerInstanceProvider finding instances for "
|
||||
+ serviceId);
|
||||
}
|
||||
EurekaHttpResponse<Applications> response = client
|
||||
.getApplications(config.getRegion());
|
||||
List<ServiceInstance> instances = new ArrayList<>();
|
||||
if (!isSuccessful(response) || response.getEntity() == null) {
|
||||
return instances;
|
||||
}
|
||||
|
||||
Applications applications = response.getEntity();
|
||||
applications.shuffleInstances(config.shouldFilterOnlyUpInstances());
|
||||
List<InstanceInfo> infos = applications
|
||||
.getInstancesByVirtualHostName(serviceId);
|
||||
for (InstanceInfo info : infos) {
|
||||
instances.add(new EurekaServiceInstance(info));
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("eurekaConfigServerInstanceProvider found " + infos.size()
|
||||
+ " instance(s) for " + serviceId + ", " + instances);
|
||||
}
|
||||
return instances;
|
||||
};
|
||||
}
|
||||
|
||||
private static final class HostnameBasedUrlRandomizer
|
||||
implements EndpointUtils.ServiceUrlRandomizer {
|
||||
|
||||
private final String hostname;
|
||||
|
||||
private HostnameBasedUrlRandomizer(String hostname) {
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void randomize(List<String> urlList) {
|
||||
int listSize = 0;
|
||||
if (urlList != null) {
|
||||
listSize = urlList.size();
|
||||
}
|
||||
if (!StringUtils.hasText(hostname) || listSize == 0) {
|
||||
return;
|
||||
}
|
||||
// Find the hashcode of the instance hostname and use it to find an entry
|
||||
// and then arrange the rest of the entries after this entry.
|
||||
int instanceHashcode = hostname.hashCode();
|
||||
if (instanceHashcode < 0) {
|
||||
instanceHashcode = instanceHashcode * -1;
|
||||
}
|
||||
int backupInstance = instanceHashcode % listSize;
|
||||
for (int i = 0; i < backupInstance; i++) {
|
||||
String zone = urlList.remove(0);
|
||||
urlList.add(zone);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(
|
||||
name = "org.springframework.web.reactive.function.client.WebClient")
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
|
||||
havingValue = "true")
|
||||
@ImportAutoConfiguration({ CodecsAutoConfiguration.class,
|
||||
WebClientAutoConfiguration.class })
|
||||
protected static class WebClientConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(EurekaHttpClient.class)
|
||||
public WebClientEurekaHttpClient configDiscoveryWebClientEurekaHttpClient(
|
||||
EurekaClientConfigBean config, ObjectProvider<WebClient.Builder> builder,
|
||||
Environment env) {
|
||||
return (WebClientEurekaHttpClient) new WebClientTransportClientFactory(
|
||||
builder::getIfAvailable)
|
||||
.newClient(new DefaultEndpoint(getEurekaUrl(config, env)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2019 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 javax.annotation.PostConstruct;
|
||||
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
/**
|
||||
* Bootstrap configuration for a config client that wants to lookup the config server via
|
||||
* discovery.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConditionalOnBean({ EurekaDiscoveryClientConfiguration.class })
|
||||
@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", matchIfMissing = false)
|
||||
public class EurekaDiscoveryClientConfigServiceAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
if (this.context.getParent() != null) {
|
||||
if (this.context.getBeanNamesForType(EurekaClient.class).length > 0
|
||||
&& this.context.getParent()
|
||||
.getBeanNamesForType(EurekaClient.class).length > 0) {
|
||||
// If the parent has a EurekaClient as well it should be shutdown, so the
|
||||
// local one can register accurate instance info
|
||||
this.context.getParent().getBean(EurekaClient.class).shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2019 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 org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.config.client.ConfigServicePropertySourceLocator;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Eureka-specific helper for config client that wants to lookup the config server via
|
||||
* discovery.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConditionalOnClass(ConfigServicePropertySourceLocator.class)
|
||||
@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", matchIfMissing = false)
|
||||
@Configuration
|
||||
@Import({ EurekaDiscoveryClientConfiguration.class, // this emulates
|
||||
// @EnableDiscoveryClient, the import
|
||||
// selector doesn't run before the
|
||||
// bootstrap phase
|
||||
EurekaClientAutoConfiguration.class })
|
||||
public class EurekaDiscoveryClientConfigServiceBootstrapConfiguration {
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2020 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.
|
||||
|
||||
+5
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2020 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.
|
||||
@@ -62,6 +62,10 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
}
|
||||
}
|
||||
|
||||
public String getServiceUrl() {
|
||||
return this.serviceUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Void> register(InstanceInfo info) {
|
||||
String urlPath = serviceUrl + "apps/" + info.getAppName();
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2020 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.
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2020 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,7 +39,7 @@ import com.netflix.discovery.shared.transport.EurekaHttpClient;
|
||||
import com.netflix.discovery.shared.transport.TransportClientFactory;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.client.support.BasicAuthorizationInterceptor;
|
||||
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
@@ -66,7 +66,7 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
if (serviceURI.getUserInfo() != null) {
|
||||
String[] credentials = serviceURI.getUserInfo().split(":");
|
||||
if (credentials.length == 2) {
|
||||
restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor(
|
||||
restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(
|
||||
credentials[0], credentials[1]));
|
||||
}
|
||||
}
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2017-2020 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.http;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
|
||||
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
* @author Haytham Mohamed
|
||||
*/
|
||||
public class WebClientDiscoveryClientOptionalArgs
|
||||
extends AbstractDiscoveryClientOptionalArgs<Void> {
|
||||
|
||||
@Deprecated
|
||||
public WebClientDiscoveryClientOptionalArgs() {
|
||||
this(WebClient::builder);
|
||||
}
|
||||
|
||||
public WebClientDiscoveryClientOptionalArgs(Supplier<WebClient.Builder> builder) {
|
||||
setTransportClientFactories(new WebClientTransportClientFactories(builder));
|
||||
}
|
||||
|
||||
}
|
||||
+240
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Copyright 2017-2020 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.http;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
|
||||
import com.netflix.discovery.shared.Application;
|
||||
import com.netflix.discovery.shared.Applications;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpClient;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpResponse;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpResponse.EurekaHttpResponseBuilder;
|
||||
import com.netflix.discovery.util.StringUtil;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import static com.netflix.discovery.shared.transport.EurekaHttpResponse.anEurekaHttpResponse;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
* @author Haytham Mohamed
|
||||
*/
|
||||
public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private WebClient webClient;
|
||||
|
||||
public WebClientEurekaHttpClient(WebClient webClient) {
|
||||
this.webClient = webClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Void> register(InstanceInfo info) {
|
||||
return webClient.post().uri("apps/" + info.getAppName(), Void.class)
|
||||
.body(BodyInserters.fromValue(info))
|
||||
.header(HttpHeaders.ACCEPT_ENCODING, "gzip")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.exchange().map(response -> eurekaHttpResponse(response)).block();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Void> cancel(String appName, String id) {
|
||||
return webClient.delete().uri("apps/" + appName + '/' + id, Void.class).exchange()
|
||||
.map(response -> eurekaHttpResponse(response)).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() : "");
|
||||
|
||||
ClientResponse response = webClient.put().uri(urlPath, InstanceInfo.class)
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).exchange()
|
||||
.block();
|
||||
|
||||
EurekaHttpResponseBuilder<InstanceInfo> builder = anEurekaHttpResponse(
|
||||
statusCodeValueOf(response), InstanceInfo.class)
|
||||
.headers(headersOf(response));
|
||||
|
||||
InstanceInfo entity = response.toEntity(InstanceInfo.class).block().getBody();
|
||||
|
||||
if (entity != null) {
|
||||
builder.entity(entity);
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
|
||||
}
|
||||
|
||||
@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, Void.class)
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.exchange().map(response -> eurekaHttpResponse(response)).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, Void.class)
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.exchange().map(response -> eurekaHttpResponse(response)).block();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Applications> getApplications(String... regions) {
|
||||
return getApplicationsInternal("apps/", regions);
|
||||
}
|
||||
|
||||
private EurekaHttpResponse<Applications> getApplicationsInternal(String urlPath,
|
||||
String[] regions) {
|
||||
String url = urlPath;
|
||||
|
||||
if (regions != null && regions.length > 0) {
|
||||
url = url + (urlPath.contains("?") ? "&" : "?") + "regions="
|
||||
+ StringUtil.join(regions);
|
||||
}
|
||||
|
||||
ClientResponse response = webClient.get().uri(url, Applications.class)
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).exchange()
|
||||
.block();
|
||||
|
||||
int statusCode = statusCodeValueOf(response);
|
||||
|
||||
Applications body = response.toEntity(Applications.class).block().getBody();
|
||||
|
||||
return anEurekaHttpResponse(statusCode,
|
||||
statusCode == HttpStatus.OK.value() && body != null ? body : null)
|
||||
.headers(headersOf(response)).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Applications> getDelta(String... regions) {
|
||||
return getApplicationsInternal("apps/delta", regions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Applications> getVip(String vipAddress, String... regions) {
|
||||
return getApplicationsInternal("vips/" + vipAddress, regions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Applications> getSecureVip(String secureVipAddress,
|
||||
String... regions) {
|
||||
return getApplicationsInternal("svips/" + secureVipAddress, regions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Application> getApplication(String appName) {
|
||||
|
||||
ClientResponse response = webClient.get()
|
||||
.uri("apps/" + appName, Application.class)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).exchange()
|
||||
.block();
|
||||
|
||||
int statusCode = statusCodeValueOf(response);
|
||||
Application body = response.toEntity(Application.class).block().getBody();
|
||||
|
||||
Application application = statusCode == HttpStatus.OK.value() && body != null
|
||||
? body : null;
|
||||
|
||||
return anEurekaHttpResponse(statusCode, application).headers(headersOf(response))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<InstanceInfo> getInstance(String appName, String id) {
|
||||
return getInstanceInternal("apps/" + appName + '/' + id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<InstanceInfo> getInstance(String id) {
|
||||
return getInstanceInternal("instances/" + id);
|
||||
}
|
||||
|
||||
private EurekaHttpResponse<InstanceInfo> getInstanceInternal(String urlPath) {
|
||||
ClientResponse response = webClient.get().uri(urlPath, InstanceInfo.class)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).exchange()
|
||||
.block();
|
||||
|
||||
int statusCode = statusCodeValueOf(response);
|
||||
InstanceInfo body = response.toEntity(InstanceInfo.class).block().getBody();
|
||||
|
||||
return anEurekaHttpResponse(statusCode,
|
||||
statusCode == HttpStatus.OK.value() && body != null ? body : null)
|
||||
.headers(headersOf(response)).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
public WebClient getWebClient() {
|
||||
return this.webClient;
|
||||
}
|
||||
|
||||
private static Map<String, String> headersOf(ClientResponse response) {
|
||||
ClientResponse.Headers httpHeaders = response.headers();
|
||||
if (httpHeaders == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
HttpHeaders asHeaders = httpHeaders.asHttpHeaders();
|
||||
if (asHeaders == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
asHeaders.entrySet().stream().forEach(entry -> entry.getValue().stream()
|
||||
.forEach(v -> headers.put(entry.getKey(), v)));
|
||||
return headers;
|
||||
}
|
||||
|
||||
private int statusCodeValueOf(ClientResponse response) {
|
||||
return response.statusCode().value();
|
||||
}
|
||||
|
||||
private EurekaHttpResponse<Void> eurekaHttpResponse(ClientResponse response) {
|
||||
return anEurekaHttpResponse(statusCodeValueOf(response))
|
||||
.headers(headersOf(response)).build();
|
||||
}
|
||||
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2017-2020 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.http;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.shared.transport.TransportClientFactory;
|
||||
import com.netflix.discovery.shared.transport.jersey.EurekaJerseyClient;
|
||||
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
|
||||
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
* @author Haytham Mohamed
|
||||
*/
|
||||
public class WebClientTransportClientFactories implements TransportClientFactories<Void> {
|
||||
|
||||
private final Supplier<WebClient.Builder> builder;
|
||||
|
||||
public WebClientTransportClientFactories(Supplier<WebClient.Builder> builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportClientFactory newTransportClientFactory(
|
||||
Collection<Void> additionalFilters, EurekaJerseyClient providedJerseyClient) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportClientFactory newTransportClientFactory(
|
||||
EurekaClientConfig clientConfig, Collection<Void> additionalFilters,
|
||||
InstanceInfo myInstanceInfo) {
|
||||
return new WebClientTransportClientFactory(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportClientFactory newTransportClientFactory(
|
||||
final EurekaClientConfig clientConfig,
|
||||
final Collection<Void> additionalFilters, final InstanceInfo myInstanceInfo,
|
||||
final Optional<SSLContext> sslContext,
|
||||
final Optional<HostnameVerifier> hostnameVerifier) {
|
||||
return new WebClientTransportClientFactory(builder);
|
||||
}
|
||||
|
||||
}
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright 2017-2020 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.http;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.fasterxml.jackson.databind.BeanDescription;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
|
||||
import com.fasterxml.jackson.databind.SerializationConfig;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
|
||||
import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.converters.jackson.mixin.ApplicationsJsonMixIn;
|
||||
import com.netflix.discovery.converters.jackson.mixin.InstanceInfoJsonMixIn;
|
||||
import com.netflix.discovery.converters.jackson.serializer.InstanceInfoJsonBeanSerializer;
|
||||
import com.netflix.discovery.shared.Applications;
|
||||
import com.netflix.discovery.shared.resolver.EurekaEndpoint;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpClient;
|
||||
import com.netflix.discovery.shared.transport.TransportClientFactory;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.ClientCodecConfigurer;
|
||||
import org.springframework.http.codec.json.Jackson2JsonDecoder;
|
||||
import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Provides the custom {@link WebClient.Builder} required by the
|
||||
* {@link WebClientEurekaHttpClient}. Relies on Jackson for serialization and
|
||||
* deserialization.
|
||||
*
|
||||
* @author Daniel Lavoie
|
||||
* @author Haytham Mohamed
|
||||
*/
|
||||
public class WebClientTransportClientFactory implements TransportClientFactory {
|
||||
|
||||
private final Supplier<WebClient.Builder> builderSupplier;
|
||||
|
||||
@Deprecated
|
||||
public WebClientTransportClientFactory() {
|
||||
this(WebClient::builder);
|
||||
}
|
||||
|
||||
public WebClientTransportClientFactory(Supplier<WebClient.Builder> builderSupplier) {
|
||||
this.builderSupplier = builderSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpClient newClient(EurekaEndpoint endpoint) {
|
||||
// we want a copy to modify. Don't change the original
|
||||
WebClient.Builder builder = this.builderSupplier.get().clone();
|
||||
setUrl(builder, endpoint.getServiceUrl());
|
||||
setCodecs(builder);
|
||||
builder.filter(http4XxErrorExchangeFilterFunction());
|
||||
return new WebClientEurekaHttpClient(builder.build());
|
||||
}
|
||||
|
||||
private WebClient.Builder setUrl(WebClient.Builder builder, String serviceUrl) {
|
||||
String url = serviceUrl;
|
||||
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] + "@",
|
||||
"");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (URISyntaxException ignore) {
|
||||
}
|
||||
return builder.baseUrl(url);
|
||||
}
|
||||
|
||||
private void setCodecs(WebClient.Builder builder) {
|
||||
ObjectMapper objectMapper = objectMapper();
|
||||
builder.codecs(configurer -> {
|
||||
ClientCodecConfigurer.ClientDefaultCodecs defaults = configurer
|
||||
.defaultCodecs();
|
||||
defaults.jackson2JsonEncoder(
|
||||
new Jackson2JsonEncoder(objectMapper, MediaType.APPLICATION_JSON));
|
||||
defaults.jackson2JsonDecoder(
|
||||
new Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON));
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// Skip over 4xx http errors
|
||||
private ExchangeFilterFunction http4XxErrorExchangeFilterFunction() {
|
||||
return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
|
||||
// literally 400 pass the tests, not 4xxClientError
|
||||
if (clientResponse.statusCode().value() == 400) {
|
||||
ClientResponse newResponse = ClientResponse.from(clientResponse)
|
||||
.statusCode(HttpStatus.OK).build();
|
||||
newResponse.body(
|
||||
(clientHttpResponse, context) -> clientHttpResponse.getBody());
|
||||
return Mono.just(newResponse);
|
||||
}
|
||||
return Mono.just(clientResponse);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the serialization configurations required by the Eureka Server. JSON
|
||||
* content exchanged with eureka requires a root node matching the entity being
|
||||
* serialized or deserialized. Achieved with
|
||||
* {@link SerializationFeature#WRAP_ROOT_VALUE} and
|
||||
* {@link DeserializationFeature#UNWRAP_ROOT_VALUE}.
|
||||
* {@link PropertyNamingStrategy.SnakeCaseStrategy} is applied to the underlying
|
||||
* {@link ObjectMapper}.
|
||||
* @deprecated to be removed.
|
||||
* @return a {@link MappingJackson2HttpMessageConverter} object
|
||||
*/
|
||||
@Deprecated
|
||||
public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
|
||||
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
|
||||
converter.setObjectMapper(objectMapper());
|
||||
return converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the serialization configurations required by the Eureka Server. JSON
|
||||
* content exchanged with eureka requires a root node matching the entity being
|
||||
* serialized or deserialized. Achieved with
|
||||
* {@link SerializationFeature#WRAP_ROOT_VALUE} and
|
||||
* {@link DeserializationFeature#UNWRAP_ROOT_VALUE}.
|
||||
* {@link PropertyNamingStrategy.SnakeCaseStrategy} is applied to the underlying
|
||||
* {@link ObjectMapper}.
|
||||
* @return a {@link ObjectMapper} object
|
||||
*/
|
||||
private ObjectMapper objectMapper() {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
|
||||
|
||||
SimpleModule jsonModule = new SimpleModule();
|
||||
jsonModule.setSerializerModifier(createJsonSerializerModifier());
|
||||
objectMapper.registerModule(jsonModule);
|
||||
|
||||
objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
|
||||
objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
|
||||
objectMapper.addMixIn(Applications.class, ApplicationsJsonMixIn.class);
|
||||
objectMapper.addMixIn(InstanceInfo.class, InstanceInfoJsonMixIn.class);
|
||||
|
||||
return objectMapper;
|
||||
}
|
||||
|
||||
@Deprecated // reduce visibility in future release
|
||||
public static BeanSerializerModifier createJsonSerializerModifier() {
|
||||
return new BeanSerializerModifier() {
|
||||
@Override
|
||||
public JsonSerializer<?> modifySerializer(SerializationConfig config,
|
||||
BeanDescription beanDesc, JsonSerializer<?> serializer) {
|
||||
if (beanDesc.getBeanClass().isAssignableFrom(InstanceInfo.class)) {
|
||||
return new InstanceInfoJsonBeanSerializer(
|
||||
(BeanSerializerBase) serializer, false);
|
||||
}
|
||||
return serializer;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
}
|
||||
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2013-2020 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.loadbalancer;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import com.netflix.appinfo.EurekaInstanceConfig;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.cloud.loadbalancer.config.LoadBalancerZoneConfig;
|
||||
import org.springframework.cloud.netflix.ribbon.eureka.ZoneUtils;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.springframework.cloud.netflix.eureka.loadbalancer.LoadBalancerEurekaAutoConfiguration.LOADBALANCER_ZONE;
|
||||
|
||||
/**
|
||||
* A configuration for Spring Cloud LoadBalancer that retrieves client instance zone from
|
||||
* Eureka and sets it as a property. Based on
|
||||
* {@link EurekaLoadBalancerClientConfiguration}.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.2.1
|
||||
* @see EurekaLoadBalancerClientConfiguration
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnBean({ LoadBalancerZoneConfig.class, EurekaLoadBalancerProperties.class })
|
||||
public class EurekaLoadBalancerClientConfiguration {
|
||||
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(EurekaLoadBalancerClientConfiguration.class);
|
||||
|
||||
private final EurekaClientConfig clientConfig;
|
||||
|
||||
private final EurekaInstanceConfig eurekaConfig;
|
||||
|
||||
private final LoadBalancerZoneConfig zoneConfig;
|
||||
|
||||
private final EurekaLoadBalancerProperties eurekaLoadBalancerProperties;
|
||||
|
||||
public EurekaLoadBalancerClientConfiguration(
|
||||
@Autowired(required = false) EurekaClientConfig clientConfig,
|
||||
@Autowired(required = false) EurekaInstanceConfig eurekaInstanceConfig,
|
||||
LoadBalancerZoneConfig zoneConfig,
|
||||
EurekaLoadBalancerProperties eurekaLoadBalancerProperties) {
|
||||
this.clientConfig = clientConfig;
|
||||
this.eurekaConfig = eurekaInstanceConfig;
|
||||
this.zoneConfig = zoneConfig;
|
||||
this.eurekaLoadBalancerProperties = eurekaLoadBalancerProperties;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postprocess() {
|
||||
if (!StringUtils.isEmpty(zoneConfig.getZone())) {
|
||||
return;
|
||||
}
|
||||
String zone = getZoneFromEureka();
|
||||
if (!StringUtils.isEmpty(zone)) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Setting the value of '" + LOADBALANCER_ZONE + "' to " + zone);
|
||||
}
|
||||
zoneConfig.setZone(zone);
|
||||
}
|
||||
}
|
||||
|
||||
private String getZoneFromEureka() {
|
||||
String zone;
|
||||
boolean approximateZoneFromHostname = eurekaLoadBalancerProperties
|
||||
.isApproximateZoneFromHostname();
|
||||
if (approximateZoneFromHostname && eurekaConfig != null) {
|
||||
return ZoneUtils.extractApproximateZone(this.eurekaConfig.getHostName(false));
|
||||
}
|
||||
else {
|
||||
zone = eurekaConfig == null ? null
|
||||
: eurekaConfig.getMetadataMap().get("zone");
|
||||
if (StringUtils.isEmpty(zone)) {
|
||||
String[] zones = clientConfig
|
||||
.getAvailabilityZones(clientConfig.getRegion());
|
||||
// Pick the first one from the regions we want to connect to
|
||||
zone = zones != null && zones.length > 0 ? zones[0] : null;
|
||||
}
|
||||
return zone;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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.loadbalancer;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* A {@link ConfigurationProperties} bean for the Eureka-specific instrumentation of
|
||||
* Spring Cloud LoadBalancer.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.2.1
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.loadbalancer.eureka")
|
||||
public class EurekaLoadBalancerProperties {
|
||||
|
||||
/**
|
||||
* Used to determine whether we should try to get the `zone` value from host name.
|
||||
*/
|
||||
private boolean approximateZoneFromHostname = false;
|
||||
|
||||
public boolean isApproximateZoneFromHostname() {
|
||||
return approximateZoneFromHostname;
|
||||
}
|
||||
|
||||
public void setApproximateZoneFromHostname(boolean approximateZoneFromHostname) {
|
||||
this.approximateZoneFromHostname = approximateZoneFromHostname;
|
||||
}
|
||||
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2013-2020 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.loadbalancer;
|
||||
|
||||
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.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientConfigurationRegistrar;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
|
||||
import org.springframework.cloud.loadbalancer.config.LoadBalancerZoneConfig;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
* An Autoconfiguration that loads default config for Spring Cloud LoadBalancer clients.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.2.1
|
||||
* @see EurekaLoadBalancerClientConfiguration
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
@ConditionalOnClass(LoadBalancerClientConfigurationRegistrar.class)
|
||||
@LoadBalancerClients(defaultConfiguration = EurekaLoadBalancerClientConfiguration.class)
|
||||
@ConditionalOnProperty(name = "eureka.client.enabled", matchIfMissing = true)
|
||||
public class LoadBalancerEurekaAutoConfiguration {
|
||||
|
||||
/**
|
||||
* Spring Cloud LoadBalancer Zone property name.
|
||||
*/
|
||||
public static final String LOADBALANCER_ZONE = "spring.cloud.loadbalancer.zone";
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
EurekaLoadBalancerProperties eurekaLoadBalancerProperties() {
|
||||
return new EurekaLoadBalancerProperties();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
LoadBalancerZoneConfig zoneConfig(Environment environment) {
|
||||
return new LoadBalancerZoneConfig(environment.getProperty(LOADBALANCER_ZONE));
|
||||
}
|
||||
|
||||
}
|
||||
+9
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2020 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.
|
||||
@@ -123,7 +123,7 @@ public class DefaultManagementMetadataProvider implements ManagementMetadataProv
|
||||
String refinedContextPath = '/'
|
||||
+ StringUtils.trimLeadingCharacter(contextPath, '/');
|
||||
URL base = new URL(scheme, hostname, port, refinedContextPath);
|
||||
String refinedStatusPath = StringUtils.trimLeadingCharacter(statusPath, '/');
|
||||
String refinedStatusPath = refinedStatusPath(statusPath, contextPath);
|
||||
return new URL(base, refinedStatusPath).toString();
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
@@ -133,6 +133,13 @@ public class DefaultManagementMetadataProvider implements ManagementMetadataProv
|
||||
}
|
||||
}
|
||||
|
||||
private String refinedStatusPath(String statusPath, String contextPath) {
|
||||
if (statusPath.startsWith(contextPath) && !"/".equals(contextPath)) {
|
||||
statusPath = StringUtils.replace(statusPath, contextPath, "");
|
||||
}
|
||||
return StringUtils.trimLeadingCharacter(statusPath, '/');
|
||||
}
|
||||
|
||||
private String getErrorMessage(String scheme, String hostname, int port,
|
||||
String contextPath, String statusPath) {
|
||||
return String.format(
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2020 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.
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2019-2020 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.reactive;
|
||||
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.shared.Application;
|
||||
import com.netflix.discovery.shared.Applications;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaServiceInstance;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* A {@link ReactiveDiscoveryClient} implementation for Eureka.
|
||||
*
|
||||
* @author Tim Ysewyn
|
||||
*/
|
||||
public class EurekaReactiveDiscoveryClient implements ReactiveDiscoveryClient {
|
||||
|
||||
private final EurekaClient eurekaClient;
|
||||
|
||||
private final EurekaClientConfig clientConfig;
|
||||
|
||||
public EurekaReactiveDiscoveryClient(EurekaClient eurekaClient,
|
||||
EurekaClientConfig clientConfig) {
|
||||
this.eurekaClient = eurekaClient;
|
||||
this.clientConfig = clientConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Spring Cloud Eureka Reactive Discovery Client";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<ServiceInstance> getInstances(String serviceId) {
|
||||
return Flux
|
||||
.defer(() -> Flux.fromIterable(
|
||||
eurekaClient.getInstancesByVipAddress(serviceId, false)))
|
||||
.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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return clientConfig instanceof Ordered ? ((Ordered) clientConfig).getOrder()
|
||||
: ReactiveDiscoveryClient.DEFAULT_ORDER;
|
||||
}
|
||||
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2019-2020 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.reactive;
|
||||
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
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.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
|
||||
import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled;
|
||||
import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled;
|
||||
import org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration;
|
||||
import org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration;
|
||||
import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicatorProperties;
|
||||
import org.springframework.cloud.client.discovery.health.reactive.ReactiveDiscoveryClientHealthIndicator;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Configuration related to service discovery when using Netflix Eureka.
|
||||
*
|
||||
* @author Tim Ysewyn
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(EurekaClientConfig.class)
|
||||
@ConditionalOnDiscoveryEnabled
|
||||
@ConditionalOnReactiveDiscoveryEnabled
|
||||
@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
|
||||
@EnableConfigurationProperties
|
||||
@AutoConfigureAfter({ EurekaClientAutoConfiguration.class,
|
||||
ReactiveCompositeDiscoveryClientAutoConfiguration.class })
|
||||
@AutoConfigureBefore(ReactiveCommonsClientAutoConfiguration.class)
|
||||
@ImportAutoConfiguration(EurekaClientAutoConfiguration.class)
|
||||
public class EurekaReactiveDiscoveryClientConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EurekaReactiveDiscoveryClient eurekaReactiveDiscoveryClient(
|
||||
EurekaClient client, EurekaClientConfig clientConfig) {
|
||||
return new EurekaReactiveDiscoveryClient(client, clientConfig);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(
|
||||
name = "org.springframework.boot.actuate.health.ReactiveHealthIndicator")
|
||||
@ConditionalOnDiscoveryHealthIndicatorEnabled
|
||||
public ReactiveDiscoveryClientHealthIndicator eurekaReactiveDiscoveryClientHealthIndicator(
|
||||
EurekaReactiveDiscoveryClient client,
|
||||
DiscoveryClientHealthIndicatorProperties properties) {
|
||||
return new ReactiveDiscoveryClientHealthIndicator(client, properties);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
@@ -52,7 +52,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Dave Syer
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class EurekaRibbonClientConfiguration {
|
||||
|
||||
private static final Log log = LogFactory
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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,7 +29,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
* @author Dave Syer
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
@ConditionalOnRibbonAndEurekaEnabled
|
||||
@AutoConfigureAfter(RibbonAutoConfiguration.class)
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+6
@@ -17,6 +17,12 @@
|
||||
"name": "ribbon.eureka.enabled",
|
||||
"description": "Enables the use of Eureka with Ribbon.",
|
||||
"type": "java.lang.Boolean"
|
||||
},
|
||||
{
|
||||
"defaultValue": false,
|
||||
"name": "eureka.client.webclient.enabled",
|
||||
"description": "Enables the use of WebClient for Eureka HTTP Client.",
|
||||
"type": "java.lang.Boolean"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.netflix.eureka.config.EurekaClientConfigServerAutoConfiguration,\
|
||||
org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceAutoConfiguration,\
|
||||
org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration,\
|
||||
org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration,\
|
||||
org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,\
|
||||
org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration
|
||||
org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration,\
|
||||
org.springframework.cloud.netflix.eureka.reactive.EurekaReactiveDiscoveryClientConfiguration,\
|
||||
org.springframework.cloud.netflix.eureka.loadbalancer.LoadBalancerEurekaAutoConfiguration
|
||||
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceBootstrapConfiguration
|
||||
|
||||
org.springframework.cloud.netflix.eureka.config.EurekaConfigServerBootstrapConfiguration
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2019 the original author or authors.
|
||||
* Copyright 2015-2020 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.
|
||||
@@ -72,7 +72,7 @@ public class ConditionalOnRefreshScopeTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
protected static class Beans {
|
||||
|
||||
@Bean
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
@@ -33,18 +33,22 @@ import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicator;
|
||||
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
|
||||
import org.springframework.cloud.commons.util.UtilAutoConfiguration;
|
||||
import org.springframework.cloud.context.refresh.ContextRefresher;
|
||||
import org.springframework.cloud.context.scope.GenericScope;
|
||||
import org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration;
|
||||
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
@@ -63,6 +67,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.fail;
|
||||
* @author Spencer Gibb
|
||||
* @author Matt Jenkins
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Tim Ysewyn
|
||||
*/
|
||||
public class EurekaClientAutoConfigurationTests {
|
||||
|
||||
@@ -78,6 +83,7 @@ public class EurekaClientAutoConfigurationTests {
|
||||
private void setupContext(Class<?>... config) {
|
||||
ConfigurationPropertySources.attach(this.context.getEnvironment());
|
||||
this.context.register(PropertyPlaceholderAutoConfiguration.class,
|
||||
DiscoveryClientOptionalArgsConfiguration.class,
|
||||
EurekaDiscoveryClientConfiguration.class);
|
||||
for (Class<?> value : config) {
|
||||
this.context.register(value);
|
||||
@@ -319,6 +325,20 @@ public class EurekaClientAutoConfigurationTests {
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public 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);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context
|
||||
.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getHealthCheckUrl())
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl())
|
||||
.endsWith(":8989/servletContextPath/myHealthCheck");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusPageUrlPathAndManagementPortKabobCase() {
|
||||
TestPropertyValues
|
||||
@@ -583,6 +603,21 @@ public class EurekaClientAutoConfigurationTests {
|
||||
assertBeanNotPresent(EurekaDiscoveryClientConfiguration.Marker.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public 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);
|
||||
});
|
||||
}
|
||||
|
||||
private void assertBeanNotPresent(Class beanClass) {
|
||||
try {
|
||||
context.getBean(beanClass);
|
||||
@@ -622,7 +657,7 @@ public class EurekaClientAutoConfigurationTests {
|
||||
EurekaClient.class)).getTargetSource().getTarget();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
@Import({ UtilAutoConfiguration.class, EurekaClientAutoConfiguration.class })
|
||||
protected static class TestConfiguration {
|
||||
@@ -638,7 +673,8 @@ public class EurekaClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnMissingBean(value = EurekaClient.class,
|
||||
search = SearchStrategy.CURRENT)
|
||||
public EurekaClient eurekaClient(ApplicationInfoManager manager,
|
||||
EurekaClientConfig config, ApplicationContext context) {
|
||||
return new CloudEurekaClient(manager, config, null, context) {
|
||||
@@ -655,16 +691,9 @@ public class EurekaClientAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
protected static class MockClientConfiguration {
|
||||
|
||||
@Bean
|
||||
public MutableDiscoveryClientOptionalArgs mutableDiscoveryClientOptionalArgs() {
|
||||
MutableDiscoveryClientOptionalArgs args = new MutableDiscoveryClientOptionalArgs();
|
||||
args.setEurekaJerseyClient(jerseyClient());
|
||||
return args;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EurekaJerseyClient jerseyClient() {
|
||||
EurekaJerseyClient mock = Mockito.mock(EurekaJerseyClient.class);
|
||||
@@ -679,7 +708,7 @@ public class EurekaClientAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(AutoServiceRegistrationProperties.class)
|
||||
public static class AutoServiceRegistrationConfiguration {
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
@@ -129,7 +129,7 @@ public class EurekaClientConfigBeanTests {
|
||||
.getEurekaServerServiceUrls(myZone).toString();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(EurekaClientConfigBean.class)
|
||||
protected static class TestConfiguration {
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
@@ -263,7 +263,7 @@ public class EurekaInstanceConfigBeanTests {
|
||||
return this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
protected static class TestConfiguration {
|
||||
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2013-2020 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;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.Test;
|
||||
|
||||
public class EurekaServiceInstanceTests {
|
||||
|
||||
@Test
|
||||
public void getSchemeReturnsNonNull() {
|
||||
InstanceInfo instanceInfo = InstanceInfo.Builder.newBuilder().setAppName("test")
|
||||
.setHostName("myhost").setPort(8080).build();
|
||||
EurekaServiceInstance instance = new EurekaServiceInstance(instanceInfo);
|
||||
Assertions.assertThat(instance.getScheme()).isEqualTo("http");
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2020 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.
|
||||
@@ -72,7 +72,7 @@ public class InstanceInfoFactoryTests {
|
||||
return this.context.getBean(EurekaInstanceConfigBean.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
protected static class TestConfiguration {
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user