Compare commits

..
Author SHA1 Message Date
buildmaster 993f04a6c7 Update SNAPSHOT to 2.2.9.RELEASE 2021-07-06 14:36:22 +00:00
Chintan Radia e394c1227b Fix transfer encoding is set to chunked by settin entity contentLength to 0 for DELETE requests (#4002) 2021-06-15 11:10:51 +02:00
Alexander Kogut c1afe1d2a0 Handle special characters in TraceProxyRequestHelper (#3995) 2021-06-10 14:23:13 +02:00
Olga Maciaszek-Sharma 89c37a3842 Handle stopping instance (#3999)
* Fix for #1571

See https://github.com/spring-cloud/spring-cloud-netflix/issues/1571#issuecomment-351638405 for more information about the rational behind the changes.

Original contributor: Bertrand Renuart <bertrand.renuart@itma.lu>
2021-05-24 19:08:25 +02:00
Jay Bryant 17e72988dc Cherry pick 8ad6682836 2021-05-24 17:11:51 +02:00
Olga MaciaszekSharma 849f1e7e99 Fix doc. 2021-05-24 17:06:38 +02:00
Olga MaciaszekSharma 3f4c702aa5 Upgrade bcpkix to 1.68. 2021-05-24 14:04:51 +02:00
spencergibb 1bd64613d1 updates eureka to 1.10.14
Fixes gh-3994
2021-05-21 16:15:50 -04:00
Olga MaciaszekSharma 86101cd733 Switch from main to master. 2021-04-26 19:12:59 +02:00
Olga MaciaszekSharma a5734695b7 Revert "Switch to GH actions."
This reverts commit e839d1dfbd.
2021-04-26 19:05:25 +02:00
Olga MaciaszekSharma 14c7ac2dda Fix README generation.
# Conflicts:
#	docs/README.adoc
2021-04-26 19:00:10 +02:00
Olga MaciaszekSharma e839d1dfbd Switch to GH actions. 2021-04-26 18:44:52 +02:00
buildmaster c5268f0d89 Bumping versions to 2.2.9.BUILD-SNAPSHOT after release 2021-04-21 16:01:59 +00:00
buildmaster 2b33f7a8b6 Going back to snapshots 2021-04-21 16:01:59 +00:00
buildmaster 848bfab4ee Update SNAPSHOT to 2.2.8.RELEASE 2021-04-21 15:51:58 +00:00
buildmaster 4646484a30 Bumping versions 2021-04-20 21:20:11 +00:00
Olga MaciaszekSharma 6f1332ee72 Reformat. 2021-04-20 17:23:37 +02:00
Olga Maciaszek-Sharma bff9419201 Do not load RibbonAutoConfiguration when spring.cloud.loadbalancer.ribbon.enabled is false. (#3977) 2021-03-05 16:08:15 +01:00
Olga Maciaszek-Sharma 7b90195ee8 Upgrade SC Contract version in Hystrix-Contract. 2021-02-18 16:51:43 +01:00
Felipe Adorno df7ecf81c9 get timeout from property source (#3965)
I try solve the problem getting values from environment, if have any other way to do that please ping me.

Fixes #3786
2021-02-17 17:38:43 -05:00
buildmaster f2526d5e03 Bumping versions to 2.2.8.BUILD-SNAPSHOT after release 2021-02-11 14:05:01 +00:00
buildmaster 8e00d28bcc Going back to snapshots 2021-02-11 14:05:00 +00:00
buildmaster 92cb1a7aa0 Update SNAPSHOT to 2.2.7.RELEASE 2021-02-11 14:01:40 +00:00
Olga Maciaszek-Sharma 8ecb3dca51 Fix request verification (#3969)
* Add tests reproducing the issue.

* Strip `'` from path for route search.

* Add information on contributing, community support and commercial support to project site.

* Add checking for "#". Add logging.

* Add test.

* Revert "Add test."

This reverts commit 81875849

* Revert "Add checking for "#". Add logging."

This reverts commit 0232945a

* Verify for urls.

* Verify for encoded and double-encoded Strings.

* Verify insecure paths with `..\` and '..//'. Add more tests.
2021-02-11 11:58:55 +01:00
Olga Maciaszek-Sharma df64a02013 Use org security policy. 2021-01-22 10:15:20 +01:00
Olga Maciaszek-Sharma 74f7c0eefd Add information on contributing, community support and commercial support to project site. 2021-01-18 11:07:00 +01:00
spencergibb 4978f8f7de No longer manage xstream dependency version.
xstream is managed as a compile dependency eureka-client now, Spring Cloud Netflix no longer needs to manage it.

See #3955
2021-01-14 12:23:05 -05:00
Theo Sun 0b490f6d27 bump versions (#3955) 2021-01-14 11:51:19 -05:00
Olga Maciaszek-Sharma c6141c5b15 Add license link to the docs. 2021-01-14 16:03:01 +01:00
hrksingh 992269781a Update EurekaInstanceConfigBean.java (#3937)
Updated spelling mistake in Javadoc  from prference to preference

(cherry picked from commit 1d6a5876fb)
2021-01-11 15:42:35 +01:00
Olga Maciaszek-Sharma 4ec5556420 Upgrade xstream to 1.4.14. 2020-12-01 18:58:40 +01:00
Olga Maciaszek-Sharma 2fe021fbdb Switch to server.servlet.encoding.force. Fixes gh-3895. 2020-12-01 18:46:38 +01:00
Olga Maciaszek-Sharma a452c1d8e9 Upgrade Eureka to 1.10.10. 2020-12-01 18:33:49 +01:00
Olga Maciaszek-Sharma 3bf50f3ef5 Upgrade bcpkix-jdk15on. 2020-12-01 18:21:50 +01:00
buildmaster ab17bbfee2 Bumping versions to 2.2.7.BUILD-SNAPSHOT after release 2020-11-09 10:28:44 +00:00
buildmaster 7240308834 Going back to snapshots 2020-11-09 10:28:44 +00:00
buildmaster 53c5b4ba86 Update SNAPSHOT to 2.2.6.RELEASE 2020-11-09 10:24:42 +00:00
spencergibb ce82ea3b71 Updates equals() for events.
Fixes gh-3918
2020-11-02 12:57:46 -05:00
Olga Maciaszek-Sharma 08add768d0 Bump mockito-core to 3.6.0. 2020-10-30 17:14:44 +01:00
Olga Maciaszek-Sharma 4064646b39 Bump eureka to 1.10.7. 2020-10-30 16:53:31 +01:00
Olga Maciaszek-Sharma ce73a587f5 Handle nulls. Minor refactoring. 2020-10-30 16:08:24 +01:00
joyita07 78ca251e96 Added support for ReactiveHealthIndicator. (#3903) 2020-10-30 14:36:13 +01:00
Olga Maciaszek-Sharma 6ce8123be1 Upgrade eureka to 1.10.4. 2020-10-06 20:32:08 +02:00
Olga Maciaszek-Sharma d11f91cdb1 Upgrade mockito-core to 3.5.13. 2020-10-06 20:06:08 +02:00
Olga Maciaszek-Sharma 57053ed7eb Upgrade xstream to 1.4.13. 2020-10-06 19:46:21 +02:00
Olga Maciaszek-Sharma 0297304397 Upgrade bcpkix-jdk15on to 1.66. 2020-10-06 19:23:15 +02:00
Olga Maciaszek-Sharma 4bdb799c8c Revert "Upgrade wro4j to 1.9.0."
This reverts commit 6e70f55049.
2020-10-06 18:36:18 +02:00
Olga Maciaszek-Sharma 6e70f55049 Upgrade wro4j to 1.9.0. 2020-10-06 18:13:48 +02:00
Olga Maciaszek-Sharma be57fe3d8b Upgrade jquery to 3.5.1. 2020-10-06 18:03:38 +02:00
Olga Maciaszek-Sharma 931cca4f44 Upgrade eureka-jersey to 1.19.4. 2020-10-06 17:43:46 +02:00
Olga Maciaszek-Sharma 0d7c73c583 Set errexit output (#3894) 2020-09-22 14:48:02 +02:00
spencergibb d498a6e091 Updates spring-cloud-contract to 2.2.4.RELEASE 2020-09-01 19:15:25 -04:00
buildmaster 34ede67962 Bumping versions to 2.2.6.BUILD-SNAPSHOT after release 2020-08-28 19:53:11 +00:00
buildmaster 24e842cfdd Going back to snapshots 2020-08-28 19:53:10 +00:00
buildmaster a1a9d8c599 Update SNAPSHOT to 2.2.5.RELEASE 2020-08-28 19:46:50 +00:00
Haytham Mohamed c5e8b66368 upgrade jquery from version 3.4.1 to 3.5.1 fixes gh-3843 (#3854)
fixes gh-3843
2020-08-28 12:37:40 -04:00
Ryan Baxter 88985f33af Merge branch 'jialindai-2.2.x' into 2.2.x 2020-08-24 16:12:25 -04:00
Ryan Baxter eeaeeb3e6f Code review changes 2020-08-24 16:11:59 -04:00
JiaLin a3436d08eb Use common TLS classes 2020-08-23 15:53:14 +08:00
JiaLin 5f3f35fd68 merge changes from upstream 2020-08-19 00:20:44 +08:00
spencergibb 23d15f70bc Updates s-c-build to 2.3.2.BUILD-SNAPSHOT 2020-08-03 13:00:36 -04:00
JiaLin 072418826e Update spring-cloud-netflix.adoc 2020-08-01 22:19:48 +08:00
JiaLin cbc914259b add client side TLS support 2020-08-01 21:55:32 +08:00
buildmaster 896b33c109 Bumping versions to 2.2.5.BUILD-SNAPSHOT after release 2020-07-31 20:37:36 +00:00
buildmaster a826a960e6 Going back to snapshots 2020-07-31 20:37:36 +00:00
buildmaster a579eb4594 Update SNAPSHOT to 2.2.4.RELEASE 2020-07-31 20:33:25 +00:00
Ryan Baxter 624bbc8b50 add allow list for proxy.stream endpoint 2020-07-30 15:15:09 -04:00
Samuel Renier 4de8761123 Updates eureka.version to 1.9.25
fixes gh-3839
2020-07-28 16:09:29 -04:00
spencergibb 8d5a3f8ec1 Updates WebClientEurekaHttpClient to use auto configured WebClient.
This allows it to take advantage of settings that are auto-configured such as spring.codec.*.

Fixes gh-3819
2020-07-28 15:57:51 -04:00
spencergibb f6120d525f Adds test to verify on("load",
See gh-3817
2020-07-28 15:29:07 -04:00
MadeInChina 4bf57b9cd2 Fix spring-cloud-starter-hystrix-dashboard jquery3.4.1 usage error (#3816) (#3817) 2020-07-28 15:21:19 -04:00
spencergibb 3bd44d69ca Updates to include dns discovery for config server bootstrap.
Fixes gh-3827
2020-07-22 18:20:03 -04:00
Rafael Renan Pacheco 6506e03bcf Adds missing eureka.client.enabled property condition
Fixes gh-3814
Fixes gh-3823
2020-06-17 17:07:32 -04:00
slamhan 443628827e Deduplicates context path in health-check-url
fixes gh-3809
2020-06-17 16:33:08 -04:00
spencergibb 85261361d7 Makes WebClient opt in in eureka config server bootstrap.
Fixes gh-3822
2020-06-17 13:09:39 -04:00
Marcin Grzejszczak 34a07a15e2 Migrated to docs.spring.io & updated sc-build 2020-06-04 15:45:36 +02:00
buildmaster 21b8599be5 Bumping versions to 2.2.4.BUILD-SNAPSHOT after release 2020-05-28 17:39:17 +00:00
buildmaster a8539b33db Going back to snapshots 2020-05-28 17:39:17 +00:00
buildmaster 5d983b082e Update SNAPSHOT to 2.2.3.RELEASE 2020-05-28 17:34:08 +00:00
spencergibb e556ccc7ed Moves DiscoveryClientOptionalArgsConfiguration to auto-configuration.
Throws an error if eureka.client.webclient.enabled is true and webflux is not on the classpath.
2020-05-15 18:24:49 -04:00
spencergibb 529b7ae12a Uses RestTemplateEurekaHttpClient if webflux not on classpath
See gh-3795
2020-05-15 11:11:38 -04:00
spencergibb a18479da64 Ignores .sdkmanrc 2020-05-15 11:10:39 -04:00
Spencer Gibb 8d19948f4b Uses http to look up config server from eureka (#3796)
This eliminates the oddness of having multiple discovery client beans and related behavior and simplifies bootstrap significantly.

Moves to ConfigServerInstanceProvider.Function for config client bootstrap.

Removes conditions for dealing with DiscoverClient in parent context.

Updates tests to reflect the new reality of no DiscoveryClient in bootstrap.

Renames config bootstrap to EurekaConfigServerBootstrapConfiguration

Fixes gh-3795

See https://github.com/spring-cloud/spring-cloud-gateway/issues/1514
2020-05-14 15:04:30 -04:00
Spencer Gibb 182951a0d5 Updates to eureka v1.9.21
fixes gh-3787
2020-05-01 10:46:10 -04:00
Olga Maciaszek-Sharma 0783016676 Fix failing checkstyle. 2020-04-23 16:49:09 +02:00
Olga Maciaszek-Sharma c36743de83 Update license comments. 2020-04-23 14:59:09 +02:00
Haytham Mohamed 297f8950b1 Merge pull request #3779 from Haybu/enh-2.2.x/issue-3737
Adds opt-in webclient support for eureka client
2020-04-22 14:31:23 -05:00
Haytham Mohamed 849642ff84 define eureka.client.webclient.enabled in the manual properties metadata json file 2020-04-20 15:41:53 -05:00
Haytham Mohamed dff3b91bef ready for submission 2020-04-17 02:10:31 -05:00
Haytham Mohamed 7db58f7d16 update tests 2020-04-17 01:43:03 -05:00
Haytham Mohamed e820a484d6 add WebClient as opt-in option 2020-04-16 23:44:32 -05:00
XiaoZiShan 2afba0977f 😀typo I found reading zuul source code (#3776)
a little excited but seeing the current module into the maintenance phase and not knowing if it will be merged, I would like to be involved in the spring community to contribute.
2020-04-15 20:25:46 +02:00
Olga Maciaszek-Sharma 61d2f956e3 Remove superfluous directive. Fixes gh-3756. 2020-04-14 21:38:46 +02:00
Olga Maciaszek-Sharma 17b9002fef Upgrade jQuery. Fixes gh-3773. 2020-04-10 17:35:43 +02:00
Eduard Wirch d6f375490a Fix circular dependency in ZuulProxyAutoConfiguration (#3769)
ZuulProxyAutoConfiguration declared a ServiceRouteMapper bean and required it for a field injection at the same time.

Fixes gh-3733
2020-04-07 15:20:07 -04:00
Spencer Gibb bee39ec1bf Updates eureka to 1.9.19
fixes gh-3770
2020-04-07 15:19:33 -04:00
Spencer Gibb 0dc755518c Adds maintenance mode info for concurrency-limits module.
see gh-3767
2020-04-07 11:46:48 -04:00
Spencer Gibb ad3f2cb53a Deprecates concurrency-limits module.
fixes gh-3767
2020-04-07 11:31:44 -04:00
Spencer Gibb 74f9fd4f9d bumps build to 2.3.0.BUILD-SNAPSHOT 2020-03-19 10:59:24 -04:00
Spencer Gibb c69a3eed70 Makes springClientFactory conditional on missing bean 2020-03-18 18:20:38 -04:00
Spencer Gibb 0c12ec9132 Adds validation starter 2020-03-18 18:05:38 -04:00
Spencer Gibb 2f6f0a0f05 Fixes assertion to use valid class 2020-03-18 18:03:21 -04:00
Spencer Gibb c0174be906 bumps build to 2.2.4.BUILD-SNAPSHOT 2020-03-18 18:00:49 -04:00
Spencer Gibb 7e96ed15f2 Updates docs branches 2020-03-06 12:42:52 -05:00
Spencer Gibb 1b07143fde Removes management of spring-cloud-netflix-hystrix-contract
spring-cloud-netflix-hystrix-contract is not a published artifact and can make validating the bom more complicated than needed.

Fixes gh-3740
2020-03-04 17:46:57 -05:00
buildmaster ea31d78891 Bumping versions to 2.2.3.BUILD-SNAPSHOT after release 2020-03-04 16:14:34 +00:00
buildmaster 492731632c Going back to snapshots 2020-03-04 16:14:33 +00:00
buildmaster 551fecde83 Update SNAPSHOT to 2.2.2.RELEASE 2020-03-04 16:05:27 +00:00
Spencer Gibb aed8d19aea Updates contract version to 2.2.1.RELEASE 2020-02-04 18:23:35 -05:00
Olga Maciaszek-Sharma ff6b50d0a8 Adjust to changes in commons. 2020-02-04 19:40:28 +01:00
Spencer Gibb 3cb98b70ce Updates eureka to 1.9.17
Doesn't shutdown servo for AbstractDocumentationTests.

fixes gh-3743
2020-01-29 12:17:00 -05:00
Spencer Gibb d1ffc8d72e Revert "Updates eureka to 1.9.17"
This reverts commit 49f88c4e
2020-01-27 15:42:45 -05:00
Spencer Gibb 49f88c4e7c Updates eureka to 1.9.17
fixes gh-3743
2020-01-27 14:14:03 -05:00
Spencer Gibb 53bffa7f04 formatting 2020-01-27 12:26:33 -05:00
Spencer Gibb 8e1ada2b3d formatting 2020-01-27 12:26:17 -05:00
Spencer Gibb 4122aadb73 Removes implementation in preference of parent class 2020-01-27 12:24:42 -05:00
Spencer Gibb 92c0c7d503 Merge branch '2.1.x' into 2.2.x 2020-01-27 12:24:15 -05:00
Dmitrii_Priporov 34b1a07124 Implements ServiceInstance.getScheme() using InstanceInfo.
fixes gh-3727
2020-01-27 12:24:07 -05:00
Spencer Gibb ae637ab3e5 Implements getScheme 2020-01-27 12:23:41 -05:00
Spencer Gibb 2cd7e41c05 Merge branch '2.1.x' into 2.2.x 2020-01-27 11:30:32 -05:00
Flora KALISA cf95248c37 Documents defaultZone case sensitivity
Fixes gh-3695
2020-01-27 11:29:33 -05:00
buildmaster b904eaa886 Bumping versions 2020-01-21 13:55:23 +00:00
Spencer Gibb 3455489f47 Migrates deprecations 2020-01-17 17:58:31 -05:00
buildmaster af919cac66 Bumping versions 2020-01-15 17:47:08 +00:00
Eric Bussieres ead46658c0 Fix for customizer not applied (#3722)
* Fix for customizer not applied when circuit breaker are created in advance

* Checkstyle
2020-01-14 13:34:04 -05:00
buildmaster 732f7d40ea Bumping versions 2020-01-14 17:46:24 +00:00
Spencer Gibb 67444a07c2 Merge branch '2.1.x' 2020-01-13 20:36:16 -05:00
OLPMO a6da307048 Optimize some code (#3693)
* Optimize some code

* fix error of ImportOrder
2020-01-13 20:32:00 -05:00
Andrew McCallum 55dabe8e6b Fix Apache HTTP client typos (#3687) 2020-01-13 18:38:46 -05:00
LiangYong 7e82a47dd3 fixed #3692 issue (#3728)
* fixed #3692 issue

fixed #3692  : Ribbon not getting list of servers from properties with lazy initialization

* Fixeds #3692 issue & add add test

* fix check style failed
2020-01-10 17:18:35 +01:00
fecqs c56e4a35d5 Fixes misspelling in sagan index 2020-01-06 20:32:01 -05:00
buildmaster 02f3bb8bba Bumping versions 2019-12-20 17:46:33 +00:00
buildmaster a4fc71a5b1 Bumping versions to 2.2.2.BUILD-SNAPSHOT after release 2019-12-20 12:36:13 +00:00
buildmaster a33387faa6 Going back to snapshots 2019-12-20 12:36:13 +00:00
buildmaster ec087d0747 Update SNAPSHOT to 2.2.1.RELEASE 2019-12-20 12:31:01 +00:00
Olga Maciaszek-Sharma 23659f8aea Gh 3718 add zoned loadbalancer instrumentation (#3720)
* Add instrumentation for zoned LoadBalancer.

* Add documentation.

* Fix after review.

* Fix after review.
2019-12-19 17:46:50 +01:00
Spencer Gibb b51a15c3f2 ignores .flattened-pom.xml 2019-12-17 17:49:38 -05:00
Spencer Gibb dc30eb2073 removes .flattened-pom.xml 2019-12-17 17:49:03 -05:00
Deepika Mohan c6b8873f0c Fix typo: clas -> class (#3710) 2019-12-16 16:45:52 +01:00
buildmaster 78cce48aa1 Bumping versions 2019-11-26 17:45:50 +00:00
buildmaster 73c40cf561 Bumping versions to 2.2.1.BUILD-SNAPSHOT after release 2019-11-26 10:03:40 +00:00
buildmaster a10d7b69d4 Going back to snapshots 2019-11-26 10:03:40 +00:00
buildmaster 4164297a89 Update SNAPSHOT to 2.2.0.RELEASE 2019-11-26 09:57:00 +00:00
buildmaster 56534dba1c Bumping versions 2019-11-22 17:45:45 +00:00
buildmaster f50e3d60a9 Bumping versions 2019-11-20 17:45:30 +00:00
Ryan Baxter e31d478c11 Update issue templates 2019-11-19 16:25:35 -05:00
Ryan Baxter 0fa901f6bc Create security.md 2019-11-19 16:24:32 -05:00
buildmaster 23366ac178 Bumping versions to 2.1.5.BUILD-SNAPSHOT after release 2019-11-18 14:58:44 +00:00
buildmaster 6fc234494a Going back to snapshots 2019-11-18 14:58:44 +00:00
buildmaster fdbbc6b7e7 Update SNAPSHOT to 2.1.4.RELEASE 2019-11-18 14:53:27 +00:00
Ryan Baxter 67fd109d68 Merge branch 'master' of github.com:spring-cloud/spring-cloud-netflix 2019-11-13 19:38:36 -05:00
Ryan Baxter 3ecf5a7420 Update configuration to use proxyBeanMethods=false. Fixes #3677 2019-11-13 19:38:30 -05:00
buildmaster 69f4c901a9 Going back to snapshots 2019-11-08 21:41:50 +00:00
buildmaster 3130493a3c Update SNAPSHOT to 2.2.0.RC2 2019-11-08 21:38:52 +00:00
buildmaster 87529e0994 Bumping versions 2019-11-07 13:52:14 +00:00
Marcin Grzejszczak e8816398a8 Added maven flatten plugin 2019-11-07 14:37:26 +01:00
Dave Syer bb1269d635 Also add build helper config for contract tests 2019-11-06 09:43:26 +00:00
Dave Syer 38cec4e35d Fix some dependencies that show up in the wrong scope
Apparently you can build on the command line but Eclipse is fussy
now and wouldn't compile these projects without explicit
dependencies.
2019-11-06 09:43:26 +00:00
buildmaster 2b5d246725 Bumping versions 2019-11-05 17:47:29 +00:00
Ryan Baxter 9b2405f3eb Adding configuration metadata for spring cloud circuitbreaker 2019-11-04 16:28:31 -05:00
Ryan Baxter 4ca1901417 Fix command key configuration. Use id as command key and class as group key. 2019-10-31 16:43:41 -04:00
Ryan Baxter 2208011dd3 Add property to disable spring cloud circuit breaker for hystrix 2019-10-31 16:42:59 -04:00
Ryan Baxter 9a2b254d0c Merge remote-tracking branch 'origin/2.1.x' 2019-10-24 17:09:37 -04:00
Ryan Baxter 9103d95ebc removing resource class from circle config 2019-10-24 17:09:18 -04:00
buildmaster d74b319b44 Going back to snapshots 2019-10-24 20:39:42 +00:00
buildmaster 3d3d528e02 Update SNAPSHOT to 2.2.0.RC1 2019-10-24 20:36:47 +00:00
buildmaster 28326b506b Going back to snapshots 2019-10-03 19:22:30 +00:00
buildmaster 392565f395 Update SNAPSHOT to 2.2.0.M3 2019-10-03 19:19:39 +00:00
Tim Ysewyn 532a95e783 Added support for reactive service discovery 2019-10-02 16:40:51 +02:00
Ryan Baxter 5d09760b94 Applying #3407 to the 2.1.x branch 2019-10-01 19:27:17 -04:00
Spencer Gibb ac60c28baa Updates to use "components" rather than "details"
See https://github.com/spring-projects/spring-boot/issues/17929
2019-09-30 13:17:07 -04:00
Olga Maciaszek-Sharma 40ec6066c1 Merge 2.1.x. 2019-09-26 16:34:04 +02:00
Olga Maciaszek-Sharma d0c5bede65 Gh 3464 upgrade scc new (#3667)
* Upgrade Spring Cloud Contract version to 2.1.3.RELEASE.

* Gh 3409 turbine stream test (#3665)

* Add stream-test-support.

* Fix condition.

* Remove outdated workaround.

(cherry picked from commit 24f5e0b043)
2019-09-26 16:13:45 +02:00
OLPMO bd6005e23d Optimize code of eureka (#3660)
* Optimize code of eureka

* Merge newest code

* fix checkstyle bug
2019-09-26 14:07:49 +02:00
buildmaster e8ff2ebaf8 Bumping versions 2019-09-25 17:45:22 +00:00
Olga Maciaszek-Sharma 24f5e0b043 Gh 3409 turbine stream test (#3665)
* Add stream-test-support.

* Fix condition.

* Remove outdated workaround.
2019-09-25 19:32:09 +02:00
Spencer Gibb 8eb843c951 Updates health check handler to use new StatusAggregator 2019-09-25 12:59:39 -04:00
Spencer Gibb 543ab09012 polish 2019-09-25 12:59:11 -04:00
Ryan Baxter 7389f25f1c Merge remote-tracking branch 'origin/2.1.x' 2019-09-19 16:43:33 -04:00
Ryan Baxter ac9f021b92 Fix RestTemplateEurekaHttpClient status update endpoint. Fixes #3571 (#3657) 2019-09-19 16:42:37 -04:00
Spencer Gibb b0b5459adb removes useless comments 2019-09-18 13:31:27 -04:00
Olga Maciaszek-Sharma 669ce753b2 Merge branch '2.1.x'
# Conflicts:
#	docs/pom.xml
#	pom.xml
#	spring-cloud-netflix-archaius/pom.xml
#	spring-cloud-netflix-concurrency-limits/pom.xml
#	spring-cloud-netflix-core/pom.xml
#	spring-cloud-netflix-dependencies/pom.xml
#	spring-cloud-netflix-eureka-client/pom.xml
#	spring-cloud-netflix-eureka-server/pom.xml
#	spring-cloud-netflix-hystrix-contract/pom.xml
#	spring-cloud-netflix-hystrix-dashboard/pom.xml
#	spring-cloud-netflix-hystrix-stream/pom.xml
#	spring-cloud-netflix-hystrix/pom.xml
#	spring-cloud-netflix-ribbon/pom.xml
#	spring-cloud-netflix-sidecar/pom.xml
#	spring-cloud-netflix-turbine-stream/pom.xml
#	spring-cloud-netflix-turbine/pom.xml
#	spring-cloud-netflix-zuul/pom.xml
#	spring-cloud-starter-netflix/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-archaius/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-eureka-client/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-eureka-server/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-hystrix-dashboard/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-hystrix/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-ribbon/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-turbine-stream/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-turbine/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-zuul/pom.xml
2019-09-18 13:40:33 +02:00
Olga Maciaszek-Sharma a7655046b9 Remove spring.provides. 2019-09-18 13:38:49 +02:00
buildmaster 7dbac954d1 Bumping versions 2019-09-16 17:45:17 +00:00
Rafał Żukowski 828bc82363 ConditionalOnMissingBean on formBodyWrapperFilter, debugFilter… (#3609) 2019-09-16 12:26:08 -04:00
Olga Maciaszek-Sharma e8b50d80ed Update docs. (#3650) 2019-09-13 17:09:01 +02:00
Olga Maciaszek-Sharma 181d210aa5 Add Spring Cloud LoadBalancer starter to Eureka starters. Fixes gh-3646. (#3647) 2019-09-11 12:48:46 +02:00
buildmaster 6e487520ed Bumping versions to 2.1.4.BUILD-SNAPSHOT after release 2019-09-09 19:06:23 +00:00
buildmaster 6e4334ac52 Going back to snapshots 2019-09-09 19:06:23 +00:00
buildmaster 924c889c31 Update SNAPSHOT to 2.1.3.RELEASE 2019-09-09 18:54:26 +00:00
Spencer Gibb d4db93a86a Merge branch '2.1.x' 2019-09-04 15:54:32 -04:00
Spencer Gibb 4953b3ccdc Upgrades eureka to 1.9.13 and excludes compactmap.
fixes gh-3636
2019-09-04 15:53:58 -04:00
Ryan Baxter 438d3f9b0e Fromatting 2019-09-03 16:57:48 -04:00
Ryan Baxter d5de0fc55c Merge remote-tracking branch 'origin/2.1.x' 2019-09-03 16:18:00 -04:00
Ryan Baxter 9c24024bc9 Updating readme with note about building spring-cloud-netflix-hystrix-contract. Fixes #3497 2019-09-03 16:17:32 -04:00
Spencer Gibb 388faaa8e5 Removes okhttp3 again after added back in older branch. 2019-09-03 14:36:27 -04:00
Ryan Baxter b386a78dae Merge remote-tracking branch 'origin/2.1.x' 2019-09-03 10:56:45 -04:00
Denys Ivano 0ea0472b4f Re-create connection manager on "zuul.host.*" property change (#3407)
* Re-create connection manager on "zuul.host.*" property change 

Fixes #3406

* Wrap connectionManager.shutdown() in try/catch block. Polishing
2019-09-03 10:55:47 -04:00
Spencer Gibb af8978a886 Moves okhttp3 dep mgmt back to bom 2019-08-30 14:53:11 -04:00
Spencer Gibb 6d74bebf66 Removes dependency management for okhttp3 2019-08-29 12:22:29 -04:00
Spencer Gibb a99b5d66ca Merge branch '2.1.x' 2019-08-29 12:17:02 -04:00
Spencer Gibb 3c9de171c7 Moves non-netflix dependencies out of bom into root pom.
fixes gh-3639
2019-08-29 12:14:59 -04:00
Ryan Baxter b0e694601e Merge remote-tracking branch 'origin/2.1.x' 2019-08-28 20:18:54 -04:00
emilnkrastev 0e90beeb01 Initialize remoteRegionAppWhitelist with default value (#3634) 2019-08-28 20:18:17 -04:00
Ryan Baxter e160395978 Separated circuitbreaker auto config to its own file 2019-08-28 13:57:09 -04:00
Ryan Baxter 46c25b38d7 Adding spring cloud circuitbreaker hystrix implementation 2019-08-27 20:14:16 -04:00
buildmaster 455c60c15c Going back to snapshots 2019-08-14 14:55:06 +00:00
buildmaster 00b419be94 Update SNAPSHOT to 2.2.0.M2 2019-08-14 14:51:52 +00:00
Spencer Gibb df33d0bd07 Merge branch '2.1.x' 2019-08-01 17:02:03 -04:00
Yuxin Bai df37357316 set replication client filters in RefreshablePeerEurekaNodes (#3610)
fixes gh-3554
2019-08-01 17:00:48 -04:00
Marcin Grzejszczak 9d40b5dc4e Added symbolic link of index.adoc 2019-07-29 14:33:54 +02:00
Marcin Grzejszczak ec28a40f90 Added symbolic link of index.adoc 2019-07-29 14:33:48 +02:00
buildmaster b8fb056981 Going back to snapshots 2019-07-03 18:03:09 +00:00
buildmaster b0ace4774e Update SNAPSHOT to 2.2.0.M1 2019-07-03 18:00:04 +00:00
Ryan Baxter 34c96c99cf Merge remote-tracking branch 'origin/2.1.x' 2019-07-03 11:27:08 -04:00
Ryan Baxter 54bd12c7c2 Separate and fix tests in SidecarApplicationTests (#3585)
* Separate and fix tests in SidecarApplicationTests.  Fixes #3584

* Renaming classes so they end in Tests
2019-07-03 11:17:27 -04:00
Spencer Gibb f29ea94f6e Bumps to 2.1.3.BUILD-SNAPSHOT and build to 2.1.7 2019-06-21 12:11:45 -04:00
Dave Syer 5741326cb5 Add jaxb-runtime to eureka server starter
See https://github.com/spring-io/start.spring.io/issues/119
2019-06-21 11:31:22 -04:00
buildmaster 609c66c2f0 Bumping versions to 2.1.4.BUILD-SNAPSHOT after release 2019-06-20 16:56:25 +00:00
buildmaster 58643b0aae Going back to snapshots 2019-06-20 16:56:24 +00:00
buildmaster d20f70a0c3 Update SNAPSHOT to 2.1.2.RELEASE 2019-06-20 16:48:20 +00:00
Greg Adams c24e7e05bf conditional sidecar autoconfig EurekaInstanceConfigBean (#3568)
fix for gh-3545
2019-06-17 20:43:08 -04:00
Spencer Gibb fd710d8a7d Merge branch '2.1.x' 2019-06-13 20:10:40 -04:00
Spencer Gibb b6814e1133 Updates eureka to 1.9.12 2019-06-13 20:07:23 -04:00
Spencer Gibb 62deb59314 Rename freemarker templates to ftlh
fixes gh-3566
2019-06-13 19:51:37 -04:00
Spencer Gibb 925f460d64 Rename freemarker templates to ftlh
fixes gh-3566
2019-06-13 19:38:07 -04:00
buildmaster 232bff2041 Bumping versions to 2.1.3.BUILD-SNAPSHOT after release 2019-06-11 19:08:47 +00:00
buildmaster e9b1dcd2fd Going back to snapshots 2019-06-11 19:08:47 +00:00
buildmaster 42a8855370 Update SNAPSHOT to 2.1.2.RELEASE 2019-06-11 18:59:05 +00:00
Spencer Gibb 6c2359a0ca Merge branch '2.1.x' 2019-06-10 12:33:50 -04:00
Spencer Gibb 3770d6c14f Updates eureka to 1.9.10
fixes gh-3553
2019-06-10 12:33:30 -04:00
Spencer Gibb 571d1b7bb7 Merge branch '2.1.x' 2019-06-05 15:44:45 -04:00
Spencer Gibb b975b31d97 Merge branch '2.0.x' into 2.1.x 2019-06-05 15:44:18 -04:00
Chris White 4145df96dc Filter WebServerInitializedEvent for web-only. (#3514)
Filter WebServerInitializedEvent for web-only, excluding management.

Fixes gh-2732
2019-06-05 14:35:49 -04:00
PeichengLiu c01d9e6b59 fix a syntax error in the document (#3525) 2019-06-03 10:18:48 -04:00
Ryan Baxter 609b4f5838 Moving to Horsham 2019-05-29 11:25:41 -04:00
Olga Maciaszek-Sharma 23e1c36462 Reformat with the newest Spring javaformat plugin version 2019-05-29 16:35:22 +02:00
Olga Maciaszek-Sharma 4d765b37bb Merge branch '2.1.x' 2019-05-29 16:22:15 +02:00
HeemangHan e0d8cc5469 fix typo (#3543) 2019-05-29 16:21:13 +02:00
Siavash Shaghafi e606cc527e adds caution about property name case-sensitivity (#3533)
* adds caution about property name case-sensitivity

* applies review suggestion
2019-05-23 13:55:27 +02:00
Ryan Baxter 4403e1c8ff Merge remote-tracking branch 'origin/2.1.x' 2019-05-21 13:00:16 -04:00
Ryan Baxter fbb59f8d0a Merge remote-tracking branch 'origin/2.0.x' into 2.1.x 2019-05-21 12:59:48 -04:00
Ryan Baxter 066ffa3fea Merge branch 'aftersss-2.0.x.fix' into 2.0.x 2019-05-21 12:45:21 -04:00
Ryan Baxter fe3dfcc4e8 Polishing documentation 2019-05-21 12:44:30 -04:00
Ryan Baxter a2ee96ebb9 Merge branch '2.0.x.fix' of https://github.com/aftersss/spring-cloud-netflix into aftersss-2.0.x.fix 2019-05-21 11:10:07 -04:00
Ryan Baxter 0b0f5d2334 Merge branch 'master' of github.com:spring-cloud/spring-cloud-netflix 2019-05-21 11:09:30 -04:00
Ryan Baxter 25cd7a5810 Formatting changes 2019-05-21 11:09:18 -04:00
Dave Syer 7aab07365d Add jaxb-runtime to eureka server starter
See https://github.com/spring-io/start.spring.io/issues/119
2019-05-20 10:40:35 +01:00
Dave Syer 6acaa9be8b Update xstream to latest patch level 2019-05-13 13:52:10 +01:00
Dave Syer 11a9819e3b Tweak test to work with Java 12
Also some format changes (checkstyle/Boot plugin)
2019-05-13 10:57:55 +01:00
Dave Syer 4997b69433 Remove deprecated class usage 2019-05-13 09:14:23 +01:00
Dave Syer e2f1f368b5 Make http trace filter bean injection conditional
Recent changes in Spring Boot have meant that there is no longer
an httpTraceFilter bean by default. We can just make it conditional.

Fixes gh-3528
2019-05-13 09:04:55 +01:00
Ryan Baxter 7ea5c3a32f Merge remote-tracking branch 'origin/2.1.x' 2019-05-10 14:23:30 -04:00
Ryan Baxter bd46dc4233 Merge remote-tracking branch 'origin/2.0.x' into 2.1.x 2019-05-10 14:22:52 -04:00
Ryan Baxter cc12f2e82f Cleanup ThreadLocal in SendResponseFilter. Fixes #2283 (#3530) 2019-05-10 13:52:45 -04:00
wenqi.huang 2bbb537b17 Add some documentation about the property eureka.client.refresh.enable 2019-05-03 10:52:54 +08:00
wenqi.huang 84ccefcd4a Add some documentation about the property eureka.client.refresh.enable 2019-05-03 10:42:40 +08:00
Marcin Grzejszczak 03b1e326ce Added sagan pages; fixes gh-3521 2019-04-29 13:21:56 +04:00
Spencer Gibb 7449915919 Bumps to Germantown 2019-04-25 10:28:47 +02:00
wenqi.huang 7fd55be4b3 Add more tests for @ConditionalOnRefreshScope 2019-04-11 18:28:09 +08:00
wenqi.huang ffebfebe31 Add more tests for @ConditionalOnRefreshScope 2019-04-11 18:02:24 +08:00
wenqi.huang bf1cc4d270 Give users a choice to determine whether the EurekaClient instance can be refreshed or not. 2019-04-11 17:19:50 +08:00
Ryan Baxter 0e66862cbb Merge remote-tracking branch 'origin/2.1.x' 2019-04-10 20:29:34 -04:00
Ryan Baxter df8083fb23 Merge remote-tracking branch 'origin/2.0.x' into 2.1.x 2019-04-10 20:28:01 -04:00
Craig Andrews 33113beca8 Do not set the Content-Encoding when ungzipping (#3421)
If the original request has Accept-Encoding not set, the origin response may still be gzipped.
In that case (in which Zuul unzips the response), it must not set the Content-Encoding response header.
2019-04-10 19:42:47 -04:00
Spencer Gibb ee9c704a4c Fixes change in framework api 2019-04-05 11:34:26 -04:00
Spencer Gibb 105f8d85b3 adds checkstyle suppressions. 2019-04-05 11:22:53 -04:00
Ryan Baxter cc6ec1572b Merge branch 'spring-operator-polish-urls-remaining-master' 2019-03-28 20:12:30 -04:00
Ryan Baxter 37d39617bf Fixing tests 2019-03-28 20:12:03 -04:00
Ryan Baxter 3c92af4a06 Merge branch 'polish-urls-remaining-master' of https://github.com/spring-operator/spring-cloud-netflix into spring-operator-polish-urls-remaining-master 2019-03-28 16:16:27 -04:00
Ryan Baxter 2f8a750a13 Merge branch 'spring-operator-polish-urls-remaining-2.0.x' into 2.0.x 2019-03-28 12:30:01 -04:00
Ryan Baxter 35fa602286 Fixing broken tests 2019-03-28 12:29:49 -04:00
Ryan Baxter 4d9a4ea3f6 Merge branch 'polish-urls-remaining-2.0.x' of https://github.com/spring-operator/spring-cloud-netflix into spring-operator-polish-urls-remaining-2.0.x 2019-03-28 12:02:08 -04:00
Ryan Baxter e3993945eb Merge branch '2.1.x' of github.com:spring-cloud/spring-cloud-netflix into 2.1.x 2019-03-28 12:00:03 -04:00
Ryan Baxter 71e1e06faf Merge branch 'spring-operator-polish-urls-remaining-2.1.x' into 2.1.x 2019-03-28 11:59:14 -04:00
Ryan Baxter 6d77a2e25a Fixing broken tests 2019-03-28 11:58:51 -04:00
Spring Operator 0cdf207631 URL Cleanup (#3470)
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* [ ] http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd with 2 occurrences migrated to:
  https://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd ([https](https://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd) result 200).
* [ ] http://repo.spring.io/libs-milestone-local with 2 occurrences migrated to:
  https://repo.spring.io/libs-milestone-local ([https](https://repo.spring.io/libs-milestone-local) result 302).
* [ ] http://repo.spring.io/libs-snapshot-local with 2 occurrences migrated to:
  https://repo.spring.io/libs-snapshot-local ([https](https://repo.spring.io/libs-snapshot-local) result 302).
* [ ] http://repo.spring.io/release with 1 occurrences migrated to:
  https://repo.spring.io/release ([https](https://repo.spring.io/release) result 302).

# Ignored
These URLs were intentionally ignored.

* http://maven.apache.org/POM/4.0.0 with 50 occurrences
* http://www.isdc.ro/wro with 1 occurrences
* http://www.w3.org/2000/svg with 2 occurrences
* http://www.w3.org/2001/XMLSchema-instance with 25 occurrences
2019-03-26 11:53:21 -04:00
Spring Operator 3c0c452628 URL Cleanup (#3448)
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* [ ] http://www.apache.org/licenses/ with 1 occurrences migrated to:
  https://www.apache.org/licenses/ ([https](https://www.apache.org/licenses/) result 200).
* [ ] http://www.apache.org/licenses/LICENSE-2.0 with 362 occurrences migrated to:
  https://www.apache.org/licenses/LICENSE-2.0 ([https](https://www.apache.org/licenses/LICENSE-2.0) result 200).
2019-03-26 11:51:33 -04:00
Spring Operator eff47e0464 URL Cleanup (#3441)
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed But Review Recommended
These URLs were fixed, but the https status was not OK. However, the https status was the same as the http request or http redirected to an https URL, so they were migrated. Your review is recommended.

* http://www.puppycrawl.com/dtds/suppressions_1_1.dtd (404) with 1 occurrences migrated to:
  https://www.puppycrawl.com/dtds/suppressions_1_1.dtd ([https](https://www.puppycrawl.com/dtds/suppressions_1_1.dtd) result 404).

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* http://maven.apache.org/xsd/maven-4.0.0.xsd with 27 occurrences migrated to:
  https://maven.apache.org/xsd/maven-4.0.0.xsd ([https](https://maven.apache.org/xsd/maven-4.0.0.xsd) result 200).

# Ignored
These URLs were intentionally ignored.

* http://maven.apache.org/POM/4.0.0 with 54 occurrences
* http://www.isdc.ro/wro with 1 occurrences
* http://www.w3.org/2001/XMLSchema-instance with 27 occurrences
2019-03-26 11:50:20 -04:00
Spring Operator 70aadd2280 URL Cleanup (#3471)
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed But Review Recommended
These URLs were fixed, but the https status was not OK. However, the https status was the same as the http request or http redirected to an https URL, so they were migrated. Your review is recommended.

* [ ] http://www.puppycrawl.com/dtds/suppressions_1_1.dtd (404) with 1 occurrences migrated to:
  https://www.puppycrawl.com/dtds/suppressions_1_1.dtd ([https](https://www.puppycrawl.com/dtds/suppressions_1_1.dtd) result 404).

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* [ ] http://maven.apache.org/xsd/maven-4.0.0.xsd with 27 occurrences migrated to:
  https://maven.apache.org/xsd/maven-4.0.0.xsd ([https](https://maven.apache.org/xsd/maven-4.0.0.xsd) result 200).
* [ ] http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd with 2 occurrences migrated to:
  https://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd ([https](https://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd) result 200).

# Ignored
These URLs were intentionally ignored.

* http://maven.apache.org/POM/4.0.0 with 54 occurrences
* http://www.isdc.ro/wro with 1 occurrences
* http://www.w3.org/2000/svg with 2 occurrences
* http://www.w3.org/2001/XMLSchema-instance with 27 occurrences
2019-03-26 11:47:06 -04:00
Spring Operator f7cb82abb5 URL Cleanup
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# HTTP URLs that Could Not Be Fixed
These URLs were unable to be fixed. Please review them to see if they can be manually resolved.

* [ ] http://conor.cc (200) with 4 occurrences could not be migrated:
   ([https](https://conor.cc) result SSLProtocolException).
* [ ] http://richclarkdesign.com (200) with 1 occurrences could not be migrated:
   ([https](https://richclarkdesign.com) result SSLHandshakeException).
* [ ] http://tinysort.sjeiti.com/ (200) with 1 occurrences could not be migrated:
   ([https](https://tinysort.sjeiti.com/) result SSLException).
* [ ] http://unknown-origin.com (200) with 1 occurrences could not be migrated:
   ([https](https://unknown-origin.com) result AnnotatedConnectException).
* [ ] http://www.sjeiti.com/ (301) with 1 occurrences could not be migrated:
   ([https](https://www.sjeiti.com/) result SSLException).
* [ ] http://foo.com (301) with 1 occurrences could not be migrated:
   ([https](https://foo.com) result SSLHandshakeException).

# Fixed URLs

## Fixed But Review Recommended
These URLs were fixed, but the https status was not OK. However, the https status was the same as the http request or http redirected to an https URL, so they were migrated. Your review is recommended.

* [ ] http://ejohn.org/ (301) with 1 occurrences migrated to:
  https://johnresig.com/ ([https](https://ejohn.org/) result ClosedChannelException).
* [ ] http://ejohn.org/blog/javascript-micro-templating/ (301) with 1 occurrences migrated to:
  https://johnresig.com/blog/javascript-micro-templating/ ([https](https://ejohn.org/blog/javascript-micro-templating/) result ClosedChannelException).
* [ ] http://example3.com/ (302) with 1 occurrences migrated to:
  https://www.hugedomains.com/domain_profile.cfm?d=example3&e=com ([https](https://example3.com/) result ConnectTimeoutException).
* [ ] http://example3.com (302) with 2 occurrences migrated to:
  https://www.hugedomains.com/domain_profile.cfm?d=example3&e=com ([https](https://example3.com) result ConnectTimeoutException).
* [ ] http://192.168.13.90:9999/actuator/health (ConnectTimeoutException) with 1 occurrences migrated to:
  https://192.168.13.90:9999/actuator/health ([https](https://192.168.13.90:9999/actuator/health) result ConnectTimeoutException).
* [ ] http://192.168.13.90:9999/actuator/info (ConnectTimeoutException) with 1 occurrences migrated to:
  https://192.168.13.90:9999/actuator/info ([https](https://192.168.13.90:9999/actuator/info) result ConnectTimeoutException).
* [ ] http://www.w3.org/TR/html4/loose.dtd (ReadTimeoutException) with 1 occurrences migrated to:
  https://www.w3.org/TR/html4/loose.dtd ([https](https://www.w3.org/TR/html4/loose.dtd) result ReadTimeoutException).
* [ ] http://allowed-origin.com (UnknownHostException) with 2 occurrences migrated to:
  https://allowed-origin.com ([https](https://allowed-origin.com) result UnknownHostException).
* [ ] http://compose.docker.io/ (UnknownHostException) with 2 occurrences migrated to:
  https://compose.docker.io/ ([https](https://compose.docker.io/) result UnknownHostException).
* [ ] http://custom-example.com (UnknownHostException) with 1 occurrences migrated to:
  https://custom-example.com ([https](https://custom-example.com) result UnknownHostException).
* [ ] http://custom-example.com/ (UnknownHostException) with 1 occurrences migrated to:
  https://custom-example.com/ ([https](https://custom-example.com/) result UnknownHostException).
* [ ] http://earlymade.com (UnknownHostException) with 4 occurrences migrated to:
  https://earlymade.com ([https](https://earlymade.com) result UnknownHostException).
* [ ] http://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/ (UnknownHostException) with 1 occurrences migrated to:
  https://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/ ([https](https://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/) result UnknownHostException).
* [ ] http://example.com,http://example2.com (UnknownHostException) with 2 occurrences migrated to:
  https://example.com,http://example2.com ([https](https://example.com,https://example2.com) result UnknownHostException).
* [ ] http://example1.com,http://example2.com (UnknownHostException) with 1 occurrences migrated to:
  https://example1.com,http://example2.com ([https](https://example1.com,https://example2.com) result UnknownHostException).
* [ ] http://first.example.com (UnknownHostException) with 1 occurrences migrated to:
  https://first.example.com ([https](https://first.example.com) result UnknownHostException).
* [ ] http://hostname:port/turbine/turbine.stream (UnknownHostException) with 1 occurrences migrated to:
  https://hostname:port/turbine/turbine.stream ([https](https://hostname:port/turbine/turbine.stream) result UnknownHostException).
* [ ] http://hystrix-app:port/actuator/hystrix.stream (UnknownHostException) with 1 occurrences migrated to:
  https://hystrix-app:port/actuator/hystrix.stream ([https](https://hystrix-app:port/actuator/hystrix.stream) result UnknownHostException).
* [ ] http://legacy.example.com (UnknownHostException) with 1 occurrences migrated to:
  https://legacy.example.com ([https](https://legacy.example.com) result UnknownHostException).
* [ ] http://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME ([https](https://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream ([https](https://my.turbine.sever:8989/turbine.stream) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream?cluster=customers (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream?cluster=customers ([https](https://my.turbine.sever:8989/turbine.stream?cluster=customers) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream?cluster=default (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream?cluster=default ([https](https://my.turbine.sever:8989/turbine.stream?cluster=default) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream?cluster=products (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream?cluster=products ([https](https://my.turbine.sever:8989/turbine.stream?cluster=products) result UnknownHostException).
* [ ] http://sidecar.local.spring.io:5678/configserver/default-master.yml (UnknownHostException) with 1 occurrences migrated to:
  https://sidecar.local.spring.io:5678/configserver/default-master.yml ([https](https://sidecar.local.spring.io:5678/configserver/default-master.yml) result UnknownHostException).
* [ ] http://turbine-hostname:port/turbine.stream (UnknownHostException) with 1 occurrences migrated to:
  https://turbine-hostname:port/turbine.stream ([https](https://turbine-hostname:port/turbine.stream) result UnknownHostException).
* [ ] http://turbine-hostname:port/turbine.stream?cluster= (UnknownHostException) with 1 occurrences migrated to:
  https://turbine-hostname:port/turbine.stream?cluster= ([https](https://turbine-hostname:port/turbine.stream?cluster=) result UnknownHostException).
* [ ] http://user2:pwd2@test2.com (UnknownHostException) with 1 occurrences migrated to:
  https://user2:pwd2@test2.com ([https](https://user2:pwd2@test2.com) result UnknownHostException).
* [ ] http://user:foo@example.com:80/eureka (UnknownHostException) with 1 occurrences migrated to:
  https://user:foo@example.com:80/eureka ([https](https://user:foo@example.com:80/eureka) result UnknownHostException).
* [ ] http://user:pwd@test1.com (UnknownHostException) with 1 occurrences migrated to:
  https://user:pwd@test1.com ([https](https://user:pwd@test1.com) result UnknownHostException).
* [ ] http://example.com/users_service (404) with 1 occurrences migrated to:
  https://example.com/users_service ([https](https://example.com/users_service) result 404).
* [ ] http://www.puppycrawl.com/dtds/suppressions_1_1.dtd (404) with 1 occurrences migrated to:
  https://www.puppycrawl.com/dtds/suppressions_1_1.dtd ([https](https://www.puppycrawl.com/dtds/suppressions_1_1.dtd) result 404).

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* [ ] http://asciidoctor.org with 1 occurrences migrated to:
  https://asciidoctor.org ([https](https://asciidoctor.org) result 200).
* [ ] http://example.com with 15 occurrences migrated to:
  https://example.com ([https](https://example.com) result 200).
* [ ] http://example.com/ with 5 occurrences migrated to:
  https://example.com/ ([https](https://example.com/) result 200).
* [ ] http://github.com/ with 1 occurrences migrated to:
  https://github.com/ ([https](https://github.com/) result 200).
* [ ] http://hello.com with 3 occurrences migrated to:
  https://hello.com ([https](https://hello.com) result 200).
* [ ] http://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html with 1 occurrences migrated to:
  https://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html ([https](https://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html) result 200).
* [ ] http://martinfowler.com/bliki/CircuitBreaker.html with 1 occurrences migrated to:
  https://martinfowler.com/bliki/CircuitBreaker.html ([https](https://martinfowler.com/bliki/CircuitBreaker.html) result 200).
* [ ] http://projects.spring.io/spring-cloud/ with 6 occurrences migrated to:
  https://projects.spring.io/spring-cloud/ ([https](https://projects.spring.io/spring-cloud/) result 200).
* [ ] http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html with 3 occurrences migrated to:
  https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html ([https](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) result 200).
* [ ] http://www.gnu.org/licenses/gpl.html with 1 occurrences migrated to:
  https://www.gnu.org/licenses/gpl.html ([https](https://www.gnu.org/licenses/gpl.html) result 200).
* [ ] http://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146/27 with 1 occurrences migrated to:
  https://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146/27 ([https](https://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146/27) result 200).
* [ ] http://commons.apache.org/proper/commons-configuration with 1 occurrences migrated to:
  https://commons.apache.org/proper/commons-configuration ([https](https://commons.apache.org/proper/commons-configuration) result 301).
* [ ] http://creativecommons.org/licenses/MIT/ with 4 occurrences migrated to:
  https://creativecommons.org/licenses/MIT/ ([https](https://creativecommons.org/licenses/MIT/) result 301).
* [ ] http://plugins.jetbrains.com/plugin/6546 with 3 occurrences migrated to:
  https://plugins.jetbrains.com/plugin/6546 ([https](https://plugins.jetbrains.com/plugin/6546) result 301).
* [ ] http://raw.github.com/ with 1 occurrences migrated to:
  https://raw.github.com/ ([https](https://raw.github.com/) result 301).
* [ ] http://service.com with 3 occurrences migrated to:
  https://service.com ([https](https://service.com) result 301).
* [ ] http://www.opensource.org/licenses/mit-license.php with 1 occurrences migrated to:
  https://www.opensource.org/licenses/mit-license.php ([https](https://www.opensource.org/licenses/mit-license.php) result 301).
* [ ] http://eclipse.org with 2 occurrences migrated to:
  https://eclipse.org ([https](https://eclipse.org) result 302).
* [ ] http://eclipse.org/m2e/ with 4 occurrences migrated to:
  https://eclipse.org/m2e/ ([https](https://eclipse.org/m2e/) result 302).
* [ ] http://example2.com/ with 1 occurrences migrated to:
  https://example2.com/ ([https](https://example2.com/) result 302).
* [ ] http://simplegrid.info with 4 occurrences migrated to:
  https://simplegrid.info ([https](https://simplegrid.info) result 302).
* [ ] http://simplegrid.info/ with 1 occurrences migrated to:
  https://simplegrid.info/ ([https](https://simplegrid.info/) result 302).
* [ ] http://www.springsource.com/developer/sts with 2 occurrences migrated to:
  https://www.springsource.com/developer/sts ([https](https://www.springsource.com/developer/sts) result 302).

# Ignored
These URLs were intentionally ignored.

* http://%s:%s with 1 occurrences
* http://badClients/good with 1 occurrences
* http://badClients/null with 1 occurrences
* http://badClients/ping with 1 occurrences
* http://badClients/timeout with 1 occurrences
* http://bar with 1 occurrences
* http://defaul-host3:8678/eureka/,http://defaul-host4:8678/eureka/ with 1 occurrences
* http://defaul-host4:8678/eureka/ with 2 occurrences
* http://defaul-host5:8678/eureka/ with 2 occurrences
* http://defaul-host6:8678/eureka/ with 2 occurrences
* http://default-host1:8678/eureka/ with 2 occurrences
* http://default-host2:8678/eureka/ with 2 occurrences
* http://default-host3:8678/eureka/ with 2 occurrences
* http://foo with 5 occurrences
* http://foo/ with 2 occurrences
* http://foo/%20bar with 1 occurrences
* http://foo/%20bar?hello=1+2 with 2 occurrences
* http://foo:7001/ with 1 occurrences
* http://foo:7777/ with 1 occurrences
* http://host/doStuff with 1 occurrences
* http://host:7777/Management/health with 1 occurrences
* http://host:7777/Management/info with 1 occurrences
* http://host:7777/Server/Management/health with 1 occurrences
* http://host:7777/Server/Management/info with 1 occurrences
* http://host:7777/Server/health with 1 occurrences
* http://host:7777/Server/info with 1 occurrences
* http://host:7777/health with 1 occurrences
* http://host:7777/info with 1 occurrences
* http://host:8888/Management/health with 3 occurrences
* http://host:8888/Management/info with 3 occurrences
* http://host:8888/health with 2 occurrences
* http://host:8888/info with 2 occurrences
* http://localhost with 135 occurrences
* http://localhost/ with 2 occurrences
* http://localhost/info with 1 occurrences
* http://localhost/ping with 2 occurrences
* http://localhost/status with 1 occurrences
* http://localhost:%d/lazy/sample with 1 occurrences
* http://localhost:%d/service/redirectedUri with 1 occurrences
* http://localhost:5678/configserver with 1 occurrences
* http://localhost:5678/customers with 1 occurrences
* http://localhost:5678/hosts/ with 1 occurrences
* http://localhost:7777/local with 4 occurrences
* http://localhost:8000/health.json with 1 occurrences
* http://localhost:8000/src/test/resources/health.json with 1 occurrences
* http://localhost:8080 with 2 occurrences
* http://localhost:8081 with 3 occurrences
* http://localhost:8383/turbine.stream?cluster=RACES with 1 occurrences
* http://localhost:8383/turbine.stream?cluster=WEB with 1 occurrences
* http://localhost:8678/eureka/ with 1 occurrences
* http://localhost:8761 with 2 occurrences
* http://localhost:8761/eureka/ with 5 occurrences
* http://localhost:9000 with 2 occurrences
* http://mhhost2:0/foo/health with 2 occurrences
* http://mhhost2:0/foo/info with 2 occurrences
* http://myhost2:9000 with 1 occurrences
* http://myhost:8080 with 1 occurrences
* http://myhost:8989 with 1 occurrences
* http://myhost:9000 with 1 occurrences
* http://myservice with 1 occurrences
* http://peer1/eureka/ with 1 occurrences
* http://peer1/eureka/,http://peer2/eureka/,http://peer3/eureka/ with 1 occurrences
* http://peer2/eureka/ with 1 occurrences
* http://region1-zone-host:8678/eureka/ with 2 occurrences
* http://region2-zone-host:8678/eureka/ with 2 occurrences
* http://region4-zone-host:8678/eureka/ with 2 occurrences
* http://simple/ with 1 occurrences
* http://simple/emptypost with 1 occurrences
* http://simple/header with 1 occurrences
* http://simple/path/ with 2 occurrences
* http://simple/post with 1 occurrences
* http://simple/request?param= with 1 occurrences
* http://simple_bad with 1 occurrences
* http://test1.com with 1 occurrences
* http://test1.com,http://test2.com with 1 occurrences
* http://test1.com,http://user2:pwd2@test2.com with 1 occurrences
* http://test2.com with 1 occurrences
* http://test3.com,http://test4.com with 1 occurrences
* http://test3.com,http://user4:pwd4@test4.com with 1 occurrences
* http://test:test@localhost:8761 with 1 occurrences
* http://test@localhost:8761 with 1 occurrences
* http://testService with 1 occurrences
* http://user:password@localhost:8761/eureka with 1 occurrences
* http://user:password@localhost:8761/eureka/ with 1 occurrences
2019-03-26 03:43:54 -05:00
Spring Operator 7ec928600d URL Cleanup
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# HTTP URLs that Could Not Be Fixed
These URLs were unable to be fixed. Please review them to see if they can be manually resolved.

* [ ] http://conor.cc (200) with 4 occurrences could not be migrated:
   ([https](https://conor.cc) result SSLProtocolException).
* [ ] http://richclarkdesign.com (200) with 1 occurrences could not be migrated:
   ([https](https://richclarkdesign.com) result SSLHandshakeException).
* [ ] http://tinysort.sjeiti.com/ (200) with 1 occurrences could not be migrated:
   ([https](https://tinysort.sjeiti.com/) result SSLException).
* [ ] http://unknown-origin.com (200) with 1 occurrences could not be migrated:
   ([https](https://unknown-origin.com) result AnnotatedConnectException).
* [ ] http://www.sjeiti.com/ (301) with 1 occurrences could not be migrated:
   ([https](https://www.sjeiti.com/) result SSLException).
* [ ] http://foo.com (301) with 1 occurrences could not be migrated:
   ([https](https://foo.com) result SSLHandshakeException).

# Fixed URLs

## Fixed But Review Recommended
These URLs were fixed, but the https status was not OK. However, the https status was the same as the http request or http redirected to an https URL, so they were migrated. Your review is recommended.

* [ ] http://ejohn.org/ (301) with 1 occurrences migrated to:
  https://johnresig.com/ ([https](https://ejohn.org/) result ClosedChannelException).
* [ ] http://ejohn.org/blog/javascript-micro-templating/ (301) with 1 occurrences migrated to:
  https://johnresig.com/blog/javascript-micro-templating/ ([https](https://ejohn.org/blog/javascript-micro-templating/) result ClosedChannelException).
* [ ] http://example3.com/ (302) with 1 occurrences migrated to:
  https://www.hugedomains.com/domain_profile.cfm?d=example3&e=com ([https](https://example3.com/) result ConnectTimeoutException).
* [ ] http://example3.com (302) with 2 occurrences migrated to:
  https://www.hugedomains.com/domain_profile.cfm?d=example3&e=com ([https](https://example3.com) result ConnectTimeoutException).
* [ ] http://192.168.13.90:9999/actuator/health (ConnectTimeoutException) with 1 occurrences migrated to:
  https://192.168.13.90:9999/actuator/health ([https](https://192.168.13.90:9999/actuator/health) result ConnectTimeoutException).
* [ ] http://192.168.13.90:9999/actuator/info (ConnectTimeoutException) with 1 occurrences migrated to:
  https://192.168.13.90:9999/actuator/info ([https](https://192.168.13.90:9999/actuator/info) result ConnectTimeoutException).
* [ ] http://www.w3.org/TR/html4/loose.dtd (ReadTimeoutException) with 1 occurrences migrated to:
  https://www.w3.org/TR/html4/loose.dtd ([https](https://www.w3.org/TR/html4/loose.dtd) result ReadTimeoutException).
* [ ] http://allowed-origin.com (UnknownHostException) with 2 occurrences migrated to:
  https://allowed-origin.com ([https](https://allowed-origin.com) result UnknownHostException).
* [ ] http://compose.docker.io/ (UnknownHostException) with 2 occurrences migrated to:
  https://compose.docker.io/ ([https](https://compose.docker.io/) result UnknownHostException).
* [ ] http://custom-example.com (UnknownHostException) with 1 occurrences migrated to:
  https://custom-example.com ([https](https://custom-example.com) result UnknownHostException).
* [ ] http://custom-example.com/ (UnknownHostException) with 1 occurrences migrated to:
  https://custom-example.com/ ([https](https://custom-example.com/) result UnknownHostException).
* [ ] http://earlymade.com (UnknownHostException) with 4 occurrences migrated to:
  https://earlymade.com ([https](https://earlymade.com) result UnknownHostException).
* [ ] http://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/ (UnknownHostException) with 1 occurrences migrated to:
  https://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/ ([https](https://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/) result UnknownHostException).
* [ ] http://example.com,http://example2.com (UnknownHostException) with 2 occurrences migrated to:
  https://example.com,http://example2.com ([https](https://example.com,https://example2.com) result UnknownHostException).
* [ ] http://example1.com,http://example2.com (UnknownHostException) with 1 occurrences migrated to:
  https://example1.com,http://example2.com ([https](https://example1.com,https://example2.com) result UnknownHostException).
* [ ] http://first.example.com (UnknownHostException) with 1 occurrences migrated to:
  https://first.example.com ([https](https://first.example.com) result UnknownHostException).
* [ ] http://hostname:port/turbine/turbine.stream (UnknownHostException) with 1 occurrences migrated to:
  https://hostname:port/turbine/turbine.stream ([https](https://hostname:port/turbine/turbine.stream) result UnknownHostException).
* [ ] http://hystrix-app:port/actuator/hystrix.stream (UnknownHostException) with 1 occurrences migrated to:
  https://hystrix-app:port/actuator/hystrix.stream ([https](https://hystrix-app:port/actuator/hystrix.stream) result UnknownHostException).
* [ ] http://legacy.example.com (UnknownHostException) with 1 occurrences migrated to:
  https://legacy.example.com ([https](https://legacy.example.com) result UnknownHostException).
* [ ] http://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME ([https](https://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream ([https](https://my.turbine.sever:8989/turbine.stream) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream?cluster=customers (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream?cluster=customers ([https](https://my.turbine.sever:8989/turbine.stream?cluster=customers) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream?cluster=default (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream?cluster=default ([https](https://my.turbine.sever:8989/turbine.stream?cluster=default) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream?cluster=products (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream?cluster=products ([https](https://my.turbine.sever:8989/turbine.stream?cluster=products) result UnknownHostException).
* [ ] http://sidecar.local.spring.io:5678/configserver/default-master.yml (UnknownHostException) with 1 occurrences migrated to:
  https://sidecar.local.spring.io:5678/configserver/default-master.yml ([https](https://sidecar.local.spring.io:5678/configserver/default-master.yml) result UnknownHostException).
* [ ] http://turbine-hostname:port/turbine.stream (UnknownHostException) with 1 occurrences migrated to:
  https://turbine-hostname:port/turbine.stream ([https](https://turbine-hostname:port/turbine.stream) result UnknownHostException).
* [ ] http://turbine-hostname:port/turbine.stream?cluster= (UnknownHostException) with 1 occurrences migrated to:
  https://turbine-hostname:port/turbine.stream?cluster= ([https](https://turbine-hostname:port/turbine.stream?cluster=) result UnknownHostException).
* [ ] http://user2:pwd2@test2.com (UnknownHostException) with 1 occurrences migrated to:
  https://user2:pwd2@test2.com ([https](https://user2:pwd2@test2.com) result UnknownHostException).
* [ ] http://user:foo@example.com:80/eureka (UnknownHostException) with 1 occurrences migrated to:
  https://user:foo@example.com:80/eureka ([https](https://user:foo@example.com:80/eureka) result UnknownHostException).
* [ ] http://user:pwd@test1.com (UnknownHostException) with 1 occurrences migrated to:
  https://user:pwd@test1.com ([https](https://user:pwd@test1.com) result UnknownHostException).
* [ ] http://example.com/users_service (404) with 1 occurrences migrated to:
  https://example.com/users_service ([https](https://example.com/users_service) result 404).
* [ ] http://www.puppycrawl.com/dtds/suppressions_1_1.dtd (404) with 1 occurrences migrated to:
  https://www.puppycrawl.com/dtds/suppressions_1_1.dtd ([https](https://www.puppycrawl.com/dtds/suppressions_1_1.dtd) result 404).

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* [ ] http://asciidoctor.org with 1 occurrences migrated to:
  https://asciidoctor.org ([https](https://asciidoctor.org) result 200).
* [ ] http://example.com with 15 occurrences migrated to:
  https://example.com ([https](https://example.com) result 200).
* [ ] http://example.com/ with 5 occurrences migrated to:
  https://example.com/ ([https](https://example.com/) result 200).
* [ ] http://github.com/ with 1 occurrences migrated to:
  https://github.com/ ([https](https://github.com/) result 200).
* [ ] http://hello.com with 3 occurrences migrated to:
  https://hello.com ([https](https://hello.com) result 200).
* [ ] http://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html with 1 occurrences migrated to:
  https://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html ([https](https://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html) result 200).
* [ ] http://martinfowler.com/bliki/CircuitBreaker.html with 1 occurrences migrated to:
  https://martinfowler.com/bliki/CircuitBreaker.html ([https](https://martinfowler.com/bliki/CircuitBreaker.html) result 200).
* [ ] http://projects.spring.io/spring-cloud/ with 6 occurrences migrated to:
  https://projects.spring.io/spring-cloud/ ([https](https://projects.spring.io/spring-cloud/) result 200).
* [ ] http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html with 3 occurrences migrated to:
  https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html ([https](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) result 200).
* [ ] http://www.gnu.org/licenses/gpl.html with 1 occurrences migrated to:
  https://www.gnu.org/licenses/gpl.html ([https](https://www.gnu.org/licenses/gpl.html) result 200).
* [ ] http://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146/27 with 1 occurrences migrated to:
  https://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146/27 ([https](https://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146/27) result 200).
* [ ] http://commons.apache.org/proper/commons-configuration with 1 occurrences migrated to:
  https://commons.apache.org/proper/commons-configuration ([https](https://commons.apache.org/proper/commons-configuration) result 301).
* [ ] http://creativecommons.org/licenses/MIT/ with 4 occurrences migrated to:
  https://creativecommons.org/licenses/MIT/ ([https](https://creativecommons.org/licenses/MIT/) result 301).
* [ ] http://plugins.jetbrains.com/plugin/6546 with 3 occurrences migrated to:
  https://plugins.jetbrains.com/plugin/6546 ([https](https://plugins.jetbrains.com/plugin/6546) result 301).
* [ ] http://raw.github.com/ with 1 occurrences migrated to:
  https://raw.github.com/ ([https](https://raw.github.com/) result 301).
* [ ] http://service.com with 3 occurrences migrated to:
  https://service.com ([https](https://service.com) result 301).
* [ ] http://www.opensource.org/licenses/mit-license.php with 1 occurrences migrated to:
  https://www.opensource.org/licenses/mit-license.php ([https](https://www.opensource.org/licenses/mit-license.php) result 301).
* [ ] http://eclipse.org with 2 occurrences migrated to:
  https://eclipse.org ([https](https://eclipse.org) result 302).
* [ ] http://eclipse.org/m2e/ with 4 occurrences migrated to:
  https://eclipse.org/m2e/ ([https](https://eclipse.org/m2e/) result 302).
* [ ] http://example2.com/ with 1 occurrences migrated to:
  https://example2.com/ ([https](https://example2.com/) result 302).
* [ ] http://simplegrid.info with 4 occurrences migrated to:
  https://simplegrid.info ([https](https://simplegrid.info) result 302).
* [ ] http://simplegrid.info/ with 1 occurrences migrated to:
  https://simplegrid.info/ ([https](https://simplegrid.info/) result 302).
* [ ] http://www.springsource.com/developer/sts with 2 occurrences migrated to:
  https://www.springsource.com/developer/sts ([https](https://www.springsource.com/developer/sts) result 302).

# Ignored
These URLs were intentionally ignored.

* http://%s:%s with 1 occurrences
* http://badClients/good with 1 occurrences
* http://badClients/null with 1 occurrences
* http://badClients/ping with 1 occurrences
* http://badClients/timeout with 1 occurrences
* http://bar with 1 occurrences
* http://defaul-host3:8678/eureka/,http://defaul-host4:8678/eureka/ with 1 occurrences
* http://defaul-host4:8678/eureka/ with 2 occurrences
* http://defaul-host5:8678/eureka/ with 2 occurrences
* http://defaul-host6:8678/eureka/ with 2 occurrences
* http://default-host1:8678/eureka/ with 2 occurrences
* http://default-host2:8678/eureka/ with 2 occurrences
* http://default-host3:8678/eureka/ with 2 occurrences
* http://foo with 5 occurrences
* http://foo/ with 2 occurrences
* http://foo/%20bar with 1 occurrences
* http://foo/%20bar?hello=1+2 with 2 occurrences
* http://foo:7001/ with 1 occurrences
* http://foo:7777/ with 1 occurrences
* http://host/doStuff with 1 occurrences
* http://host:7777/Management/health with 1 occurrences
* http://host:7777/Management/info with 1 occurrences
* http://host:7777/Server/Management/health with 1 occurrences
* http://host:7777/Server/Management/info with 1 occurrences
* http://host:7777/Server/health with 1 occurrences
* http://host:7777/Server/info with 1 occurrences
* http://host:7777/health with 1 occurrences
* http://host:7777/info with 1 occurrences
* http://host:8888/Management/health with 3 occurrences
* http://host:8888/Management/info with 3 occurrences
* http://host:8888/health with 2 occurrences
* http://host:8888/info with 2 occurrences
* http://localhost with 133 occurrences
* http://localhost/ with 2 occurrences
* http://localhost/info with 1 occurrences
* http://localhost/ping with 2 occurrences
* http://localhost/status with 1 occurrences
* http://localhost:%d/lazy/sample with 1 occurrences
* http://localhost:%d/service/redirectedUri with 1 occurrences
* http://localhost:5678/configserver with 1 occurrences
* http://localhost:5678/customers with 1 occurrences
* http://localhost:5678/hosts/ with 1 occurrences
* http://localhost:7777/local with 4 occurrences
* http://localhost:8000/health.json with 1 occurrences
* http://localhost:8000/src/test/resources/health.json with 1 occurrences
* http://localhost:8080 with 2 occurrences
* http://localhost:8081 with 3 occurrences
* http://localhost:8383/turbine.stream?cluster=RACES with 1 occurrences
* http://localhost:8383/turbine.stream?cluster=WEB with 1 occurrences
* http://localhost:8678/eureka/ with 1 occurrences
* http://localhost:8761 with 2 occurrences
* http://localhost:8761/eureka/ with 5 occurrences
* http://localhost:9000 with 2 occurrences
* http://mhhost2:0/foo/health with 2 occurrences
* http://mhhost2:0/foo/info with 2 occurrences
* http://myhost2:9000 with 1 occurrences
* http://myhost:8080 with 1 occurrences
* http://myhost:8989 with 1 occurrences
* http://myhost:9000 with 1 occurrences
* http://myservice with 1 occurrences
* http://peer1/eureka/ with 1 occurrences
* http://peer1/eureka/,http://peer2/eureka/,http://peer3/eureka/ with 1 occurrences
* http://peer2/eureka/ with 1 occurrences
* http://region1-zone-host:8678/eureka/ with 2 occurrences
* http://region2-zone-host:8678/eureka/ with 2 occurrences
* http://region4-zone-host:8678/eureka/ with 2 occurrences
* http://simple/ with 1 occurrences
* http://simple/emptypost with 1 occurrences
* http://simple/header with 1 occurrences
* http://simple/path/ with 2 occurrences
* http://simple/post with 1 occurrences
* http://simple/request?param= with 1 occurrences
* http://simple_bad with 1 occurrences
* http://test1.com with 1 occurrences
* http://test1.com,http://test2.com with 1 occurrences
* http://test1.com,http://user2:pwd2@test2.com with 1 occurrences
* http://test2.com with 1 occurrences
* http://test3.com,http://test4.com with 1 occurrences
* http://test3.com,http://user4:pwd4@test4.com with 1 occurrences
* http://test:test@localhost:8761 with 1 occurrences
* http://test@localhost:8761 with 1 occurrences
* http://testService with 1 occurrences
* http://user:password@localhost:8761/eureka with 1 occurrences
* http://user:password@localhost:8761/eureka/ with 1 occurrences
2019-03-26 03:43:44 -05:00
Ryan Baxter 743f6079a1 Downgrading contract version 2019-03-25 19:53:04 -04:00
Ryan Baxter fb9f72d17b Updating dependencies 2019-03-25 16:25:14 -04:00
Spring Operator bb56c8a98c URL Cleanup (#3452)
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* [ ] http://www.apache.org/licenses/ with 1 occurrences migrated to:
  https://www.apache.org/licenses/ ([https](https://www.apache.org/licenses/) result 200).
* [ ] http://www.apache.org/licenses/LICENSE-2.0 with 414 occurrences migrated to:
  https://www.apache.org/licenses/LICENSE-2.0 ([https](https://www.apache.org/licenses/LICENSE-2.0) result 200).
2019-03-25 09:32:57 -04:00
Spring Operator c1771dce56 URL Cleanup (#3451)
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* [ ] http://www.apache.org/licenses/ with 1 occurrences migrated to:
  https://www.apache.org/licenses/ ([https](https://www.apache.org/licenses/) result 200).
* [ ] http://www.apache.org/licenses/LICENSE-2.0 with 414 occurrences migrated to:
  https://www.apache.org/licenses/LICENSE-2.0 ([https](https://www.apache.org/licenses/LICENSE-2.0) result 200).
2019-03-21 20:29:33 -04:00
Spring Operator 88b71f05fa URL Cleanup
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# HTTP URLs that Could Not Be Fixed
These URLs were unable to be fixed. Please review them to see if they can be manually resolved.

* [ ] http://conor.cc (200) with 4 occurrences could not be migrated:
   ([https](https://conor.cc) result SSLProtocolException).
* [ ] http://richclarkdesign.com (200) with 1 occurrences could not be migrated:
   ([https](https://richclarkdesign.com) result SSLHandshakeException).
* [ ] http://tinysort.sjeiti.com/ (200) with 1 occurrences could not be migrated:
   ([https](https://tinysort.sjeiti.com/) result SSLException).
* [ ] http://unknown-origin.com (200) with 1 occurrences could not be migrated:
   ([https](https://unknown-origin.com) result AnnotatedConnectException).
* [ ] http://www.sjeiti.com/ (301) with 1 occurrences could not be migrated:
   ([https](https://www.sjeiti.com/) result SSLException).
* [ ] http://foo.com (301) with 1 occurrences could not be migrated:
   ([https](https://foo.com) result SSLHandshakeException).

# Fixed URLs

## Fixed But Review Recommended
These URLs were fixed, but the https status was not OK. However, the https status was the same as the http request or http redirected to an https URL, so they were migrated. Your review is recommended.

* [ ] http://ejohn.org/ (301) with 1 occurrences migrated to:
  https://johnresig.com/ ([https](https://ejohn.org/) result ClosedChannelException).
* [ ] http://ejohn.org/blog/javascript-micro-templating/ (301) with 1 occurrences migrated to:
  https://johnresig.com/blog/javascript-micro-templating/ ([https](https://ejohn.org/blog/javascript-micro-templating/) result ClosedChannelException).
* [ ] http://example3.com/ (302) with 1 occurrences migrated to:
  https://www.hugedomains.com/domain_profile.cfm?d=example3&e=com ([https](https://example3.com/) result ConnectTimeoutException).
* [ ] http://example3.com (302) with 2 occurrences migrated to:
  https://www.hugedomains.com/domain_profile.cfm?d=example3&e=com ([https](https://example3.com) result ConnectTimeoutException).
* [ ] http://192.168.13.90:9999/actuator/health (ConnectTimeoutException) with 1 occurrences migrated to:
  https://192.168.13.90:9999/actuator/health ([https](https://192.168.13.90:9999/actuator/health) result ConnectTimeoutException).
* [ ] http://192.168.13.90:9999/actuator/info (ConnectTimeoutException) with 1 occurrences migrated to:
  https://192.168.13.90:9999/actuator/info ([https](https://192.168.13.90:9999/actuator/info) result ConnectTimeoutException).
* [ ] http://www.w3.org/TR/html4/loose.dtd (ReadTimeoutException) with 1 occurrences migrated to:
  https://www.w3.org/TR/html4/loose.dtd ([https](https://www.w3.org/TR/html4/loose.dtd) result SSLException).
* [ ] http://%s:%s (UnknownHostException) with 1 occurrences migrated to:
  https://%s:%s ([https](https://%s:%s) result UnknownHostException).
* [ ] http://allowed-origin.com (UnknownHostException) with 2 occurrences migrated to:
  https://allowed-origin.com ([https](https://allowed-origin.com) result UnknownHostException).
* [ ] http://badClients/good (UnknownHostException) with 1 occurrences migrated to:
  https://badClients/good ([https](https://badClients/good) result UnknownHostException).
* [ ] http://badClients/null (UnknownHostException) with 1 occurrences migrated to:
  https://badClients/null ([https](https://badClients/null) result UnknownHostException).
* [ ] http://badClients/ping (UnknownHostException) with 1 occurrences migrated to:
  https://badClients/ping ([https](https://badClients/ping) result UnknownHostException).
* [ ] http://badClients/timeout (UnknownHostException) with 1 occurrences migrated to:
  https://badClients/timeout ([https](https://badClients/timeout) result UnknownHostException).
* [ ] http://bar (UnknownHostException) with 1 occurrences migrated to:
  https://bar ([https](https://bar) result UnknownHostException).
* [ ] http://compose.docker.io/ (UnknownHostException) with 2 occurrences migrated to:
  https://compose.docker.io/ ([https](https://compose.docker.io/) result UnknownHostException).
* [ ] http://custom-example.com (UnknownHostException) with 1 occurrences migrated to:
  https://custom-example.com ([https](https://custom-example.com) result UnknownHostException).
* [ ] http://custom-example.com/ (UnknownHostException) with 1 occurrences migrated to:
  https://custom-example.com/ ([https](https://custom-example.com/) result UnknownHostException).
* [ ] http://defaul-host3:8678/eureka/,http://defaul-host4:8678/eureka/ (UnknownHostException) with 1 occurrences migrated to:
  https://defaul-host3:8678/eureka/,http://defaul-host4:8678/eureka/ ([https](https://defaul-host3:8678/eureka/,https://defaul-host4:8678/eureka/) result UnknownHostException).
* [ ] http://defaul-host4:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://defaul-host4:8678/eureka/ ([https](https://defaul-host4:8678/eureka/) result UnknownHostException).
* [ ] http://defaul-host5:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://defaul-host5:8678/eureka/ ([https](https://defaul-host5:8678/eureka/) result UnknownHostException).
* [ ] http://defaul-host6:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://defaul-host6:8678/eureka/ ([https](https://defaul-host6:8678/eureka/) result UnknownHostException).
* [ ] http://default-host1:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://default-host1:8678/eureka/ ([https](https://default-host1:8678/eureka/) result UnknownHostException).
* [ ] http://default-host2:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://default-host2:8678/eureka/ ([https](https://default-host2:8678/eureka/) result UnknownHostException).
* [ ] http://default-host3:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://default-host3:8678/eureka/ ([https](https://default-host3:8678/eureka/) result UnknownHostException).
* [ ] http://earlymade.com (UnknownHostException) with 4 occurrences migrated to:
  https://earlymade.com ([https](https://earlymade.com) result UnknownHostException).
* [ ] http://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/ (UnknownHostException) with 1 occurrences migrated to:
  https://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/ ([https](https://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/) result UnknownHostException).
* [ ] http://example.com,http://example2.com (UnknownHostException) with 2 occurrences migrated to:
  https://example.com,http://example2.com ([https](https://example.com,https://example2.com) result UnknownHostException).
* [ ] http://example1.com,http://example2.com (UnknownHostException) with 1 occurrences migrated to:
  https://example1.com,http://example2.com ([https](https://example1.com,https://example2.com) result UnknownHostException).
* [ ] http://first.example.com (UnknownHostException) with 1 occurrences migrated to:
  https://first.example.com ([https](https://first.example.com) result UnknownHostException).
* [ ] http://foo (UnknownHostException) with 5 occurrences migrated to:
  https://foo ([https](https://foo) result UnknownHostException).
* [ ] http://foo/ (UnknownHostException) with 2 occurrences migrated to:
  https://foo/ ([https](https://foo/) result UnknownHostException).
* [ ] http://foo/%20bar (UnknownHostException) with 1 occurrences migrated to:
  https://foo/%20bar ([https](https://foo/%20bar) result UnknownHostException).
* [ ] http://foo/%20bar?hello=1+2 (UnknownHostException) with 2 occurrences migrated to:
  https://foo/%20bar?hello=1+2 ([https](https://foo/%20bar?hello=1+2) result UnknownHostException).
* [ ] http://foo:7001/ (UnknownHostException) with 1 occurrences migrated to:
  https://foo:7001/ ([https](https://foo:7001/) result UnknownHostException).
* [ ] http://foo:7777/ (UnknownHostException) with 1 occurrences migrated to:
  https://foo:7777/ ([https](https://foo:7777/) result UnknownHostException).
* [ ] http://host/doStuff (UnknownHostException) with 1 occurrences migrated to:
  https://host/doStuff ([https](https://host/doStuff) result UnknownHostException).
* [ ] http://host:7777/Management/health (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/Management/health ([https](https://host:7777/Management/health) result UnknownHostException).
* [ ] http://host:7777/Management/info (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/Management/info ([https](https://host:7777/Management/info) result UnknownHostException).
* [ ] http://host:7777/Server/Management/health (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/Server/Management/health ([https](https://host:7777/Server/Management/health) result UnknownHostException).
* [ ] http://host:7777/Server/Management/info (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/Server/Management/info ([https](https://host:7777/Server/Management/info) result UnknownHostException).
* [ ] http://host:7777/Server/health (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/Server/health ([https](https://host:7777/Server/health) result UnknownHostException).
* [ ] http://host:7777/Server/info (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/Server/info ([https](https://host:7777/Server/info) result UnknownHostException).
* [ ] http://host:7777/health (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/health ([https](https://host:7777/health) result UnknownHostException).
* [ ] http://host:7777/info (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/info ([https](https://host:7777/info) result UnknownHostException).
* [ ] http://host:8888/Management/health (UnknownHostException) with 3 occurrences migrated to:
  https://host:8888/Management/health ([https](https://host:8888/Management/health) result UnknownHostException).
* [ ] http://host:8888/Management/info (UnknownHostException) with 3 occurrences migrated to:
  https://host:8888/Management/info ([https](https://host:8888/Management/info) result UnknownHostException).
* [ ] http://host:8888/health (UnknownHostException) with 2 occurrences migrated to:
  https://host:8888/health ([https](https://host:8888/health) result UnknownHostException).
* [ ] http://host:8888/info (UnknownHostException) with 2 occurrences migrated to:
  https://host:8888/info ([https](https://host:8888/info) result UnknownHostException).
* [ ] http://hostname:port/turbine/turbine.stream (UnknownHostException) with 1 occurrences migrated to:
  https://hostname:port/turbine/turbine.stream ([https](https://hostname:port/turbine/turbine.stream) result UnknownHostException).
* [ ] http://hystrix-app:port/actuator/hystrix.stream (UnknownHostException) with 1 occurrences migrated to:
  https://hystrix-app:port/actuator/hystrix.stream ([https](https://hystrix-app:port/actuator/hystrix.stream) result UnknownHostException).
* [ ] http://legacy.example.com (UnknownHostException) with 1 occurrences migrated to:
  https://legacy.example.com ([https](https://legacy.example.com) result UnknownHostException).
* [ ] http://mhhost2:0/foo/health (UnknownHostException) with 2 occurrences migrated to:
  https://mhhost2:0/foo/health ([https](https://mhhost2:0/foo/health) result UnknownHostException).
* [ ] http://mhhost2:0/foo/info (UnknownHostException) with 2 occurrences migrated to:
  https://mhhost2:0/foo/info ([https](https://mhhost2:0/foo/info) result UnknownHostException).
* [ ] http://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME ([https](https://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream ([https](https://my.turbine.sever:8989/turbine.stream) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream?cluster=customers (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream?cluster=customers ([https](https://my.turbine.sever:8989/turbine.stream?cluster=customers) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream?cluster=default (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream?cluster=default ([https](https://my.turbine.sever:8989/turbine.stream?cluster=default) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream?cluster=products (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream?cluster=products ([https](https://my.turbine.sever:8989/turbine.stream?cluster=products) result UnknownHostException).
* [ ] http://myhost2:9000 (UnknownHostException) with 1 occurrences migrated to:
  https://myhost2:9000 ([https](https://myhost2:9000) result UnknownHostException).
* [ ] http://myhost:8080 (UnknownHostException) with 1 occurrences migrated to:
  https://myhost:8080 ([https](https://myhost:8080) result UnknownHostException).
* [ ] http://myhost:8989 (UnknownHostException) with 1 occurrences migrated to:
  https://myhost:8989 ([https](https://myhost:8989) result UnknownHostException).
* [ ] http://myhost:9000 (UnknownHostException) with 1 occurrences migrated to:
  https://myhost:9000 ([https](https://myhost:9000) result UnknownHostException).
* [ ] http://myservice (UnknownHostException) with 1 occurrences migrated to:
  https://myservice ([https](https://myservice) result UnknownHostException).
* [ ] http://peer1/eureka/ (UnknownHostException) with 1 occurrences migrated to:
  https://peer1/eureka/ ([https](https://peer1/eureka/) result UnknownHostException).
* [ ] http://peer1/eureka/,http://peer2/eureka/,http://peer3/eureka/ (UnknownHostException) with 1 occurrences migrated to:
  https://peer1/eureka/,http://peer2/eureka/,http://peer3/eureka/ ([https](https://peer1/eureka/,https://peer2/eureka/,https://peer3/eureka/) result UnknownHostException).
* [ ] http://peer2/eureka/ (UnknownHostException) with 1 occurrences migrated to:
  https://peer2/eureka/ ([https](https://peer2/eureka/) result UnknownHostException).
* [ ] http://region1-zone-host:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://region1-zone-host:8678/eureka/ ([https](https://region1-zone-host:8678/eureka/) result UnknownHostException).
* [ ] http://region2-zone-host:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://region2-zone-host:8678/eureka/ ([https](https://region2-zone-host:8678/eureka/) result UnknownHostException).
* [ ] http://region4-zone-host:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://region4-zone-host:8678/eureka/ ([https](https://region4-zone-host:8678/eureka/) result UnknownHostException).
* [ ] http://sidecar.local.spring.io:5678/configserver/default-master.yml (UnknownHostException) with 1 occurrences migrated to:
  https://sidecar.local.spring.io:5678/configserver/default-master.yml ([https](https://sidecar.local.spring.io:5678/configserver/default-master.yml) result UnknownHostException).
* [ ] http://simple/ (UnknownHostException) with 1 occurrences migrated to:
  https://simple/ ([https](https://simple/) result UnknownHostException).
* [ ] http://simple/emptypost (UnknownHostException) with 1 occurrences migrated to:
  https://simple/emptypost ([https](https://simple/emptypost) result UnknownHostException).
* [ ] http://simple/header (UnknownHostException) with 1 occurrences migrated to:
  https://simple/header ([https](https://simple/header) result UnknownHostException).
* [ ] http://simple/path/ (UnknownHostException) with 2 occurrences migrated to:
  https://simple/path/ ([https](https://simple/path/) result UnknownHostException).
* [ ] http://simple/post (UnknownHostException) with 1 occurrences migrated to:
  https://simple/post ([https](https://simple/post) result UnknownHostException).
* [ ] http://simple/request?param= (UnknownHostException) with 1 occurrences migrated to:
  https://simple/request?param= ([https](https://simple/request?param=) result UnknownHostException).
* [ ] http://simple_bad (UnknownHostException) with 1 occurrences migrated to:
  https://simple_bad ([https](https://simple_bad) result UnknownHostException).
* [ ] http://turbine-hostname:port/turbine.stream (UnknownHostException) with 1 occurrences migrated to:
  https://turbine-hostname:port/turbine.stream ([https](https://turbine-hostname:port/turbine.stream) result UnknownHostException).
* [ ] http://turbine-hostname:port/turbine.stream?cluster= (UnknownHostException) with 1 occurrences migrated to:
  https://turbine-hostname:port/turbine.stream?cluster= ([https](https://turbine-hostname:port/turbine.stream?cluster=) result UnknownHostException).
* [ ] http://user2:pwd2@test2.com (UnknownHostException) with 1 occurrences migrated to:
  https://user2:pwd2@test2.com ([https](https://user2:pwd2@test2.com) result UnknownHostException).
* [ ] http://user:foo@example.com:80/eureka (UnknownHostException) with 1 occurrences migrated to:
  https://user:foo@example.com:80/eureka ([https](https://user:foo@example.com:80/eureka) result UnknownHostException).
* [ ] http://user:password@localhost:8761/eureka (UnknownHostException) with 1 occurrences migrated to:
  https://user:password@localhost:8761/eureka ([https](https://user:password@localhost:8761/eureka) result UnknownHostException).
* [ ] http://user:password@localhost:8761/eureka/ (UnknownHostException) with 1 occurrences migrated to:
  https://user:password@localhost:8761/eureka/ ([https](https://user:password@localhost:8761/eureka/) result UnknownHostException).
* [ ] http://user:pwd@test1.com (UnknownHostException) with 1 occurrences migrated to:
  https://user:pwd@test1.com ([https](https://user:pwd@test1.com) result UnknownHostException).
* [ ] http://www.puppycrawl.com/dtds/suppressions_1_1.dtd (404) with 1 occurrences migrated to:
  https://www.puppycrawl.com/dtds/suppressions_1_1.dtd ([https](https://www.puppycrawl.com/dtds/suppressions_1_1.dtd) result 404).

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* [ ] http://asciidoctor.org with 1 occurrences migrated to:
  https://asciidoctor.org ([https](https://asciidoctor.org) result 200).
* [ ] http://example.com with 15 occurrences migrated to:
  https://example.com ([https](https://example.com) result 200).
* [ ] http://example.com/ with 5 occurrences migrated to:
  https://example.com/ ([https](https://example.com/) result 200).
* [ ] http://example.com/users_service with 1 occurrences migrated to:
  https://example.com/users_service ([https](https://example.com/users_service) result 200).
* [ ] http://github.com/ with 1 occurrences migrated to:
  https://github.com/ ([https](https://github.com/) result 200).
* [ ] http://hello.com with 3 occurrences migrated to:
  https://hello.com ([https](https://hello.com) result 200).
* [ ] http://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html with 1 occurrences migrated to:
  https://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html ([https](https://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html) result 200).
* [ ] http://martinfowler.com/bliki/CircuitBreaker.html with 1 occurrences migrated to:
  https://martinfowler.com/bliki/CircuitBreaker.html ([https](https://martinfowler.com/bliki/CircuitBreaker.html) result 200).
* [ ] http://projects.spring.io/spring-cloud/ with 6 occurrences migrated to:
  https://projects.spring.io/spring-cloud/ ([https](https://projects.spring.io/spring-cloud/) result 200).
* [ ] http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html with 3 occurrences migrated to:
  https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html ([https](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) result 200).
* [ ] http://www.gnu.org/licenses/gpl.html with 1 occurrences migrated to:
  https://www.gnu.org/licenses/gpl.html ([https](https://www.gnu.org/licenses/gpl.html) result 200).
* [ ] http://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146/27 with 1 occurrences migrated to:
  https://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146/27 ([https](https://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146/27) result 200).
* [ ] http://commons.apache.org/proper/commons-configuration with 1 occurrences migrated to:
  https://commons.apache.org/proper/commons-configuration ([https](https://commons.apache.org/proper/commons-configuration) result 301).
* [ ] http://creativecommons.org/licenses/MIT/ with 4 occurrences migrated to:
  https://creativecommons.org/licenses/MIT/ ([https](https://creativecommons.org/licenses/MIT/) result 301).
* [ ] http://plugins.jetbrains.com/plugin/6546 with 3 occurrences migrated to:
  https://plugins.jetbrains.com/plugin/6546 ([https](https://plugins.jetbrains.com/plugin/6546) result 301).
* [ ] http://raw.github.com/ with 1 occurrences migrated to:
  https://raw.github.com/ ([https](https://raw.github.com/) result 301).
* [ ] http://service.com with 3 occurrences migrated to:
  https://service.com ([https](https://service.com) result 301).
* [ ] http://www.opensource.org/licenses/mit-license.php with 1 occurrences migrated to:
  https://www.opensource.org/licenses/mit-license.php ([https](https://www.opensource.org/licenses/mit-license.php) result 301).
* [ ] http://eclipse.org with 2 occurrences migrated to:
  https://eclipse.org ([https](https://eclipse.org) result 302).
* [ ] http://eclipse.org/m2e/ with 4 occurrences migrated to:
  https://eclipse.org/m2e/ ([https](https://eclipse.org/m2e/) result 302).
* [ ] http://example2.com/ with 1 occurrences migrated to:
  https://example2.com/ ([https](https://example2.com/) result 302).
* [ ] http://simplegrid.info with 4 occurrences migrated to:
  https://simplegrid.info ([https](https://simplegrid.info) result 302).
* [ ] http://simplegrid.info/ with 1 occurrences migrated to:
  https://simplegrid.info/ ([https](https://simplegrid.info/) result 302).
* [ ] http://www.springsource.com/developer/sts with 2 occurrences migrated to:
  https://www.springsource.com/developer/sts ([https](https://www.springsource.com/developer/sts) result 302).

# Ignored
These URLs were intentionally ignored.

* http://localhost with 135 occurrences
* http://localhost/ with 2 occurrences
* http://localhost/info with 1 occurrences
* http://localhost/ping with 2 occurrences
* http://localhost/status with 1 occurrences
* http://localhost:%d/lazy/sample with 1 occurrences
* http://localhost:%d/service/redirectedUri with 1 occurrences
* http://localhost:5678/configserver with 1 occurrences
* http://localhost:5678/customers with 1 occurrences
* http://localhost:5678/hosts/ with 1 occurrences
* http://localhost:7777/local with 4 occurrences
* http://localhost:8000/health.json with 1 occurrences
* http://localhost:8000/src/test/resources/health.json with 1 occurrences
* http://localhost:8080 with 2 occurrences
* http://localhost:8081 with 3 occurrences
* http://localhost:8383/turbine.stream?cluster=RACES with 1 occurrences
* http://localhost:8383/turbine.stream?cluster=WEB with 1 occurrences
* http://localhost:8678/eureka/ with 1 occurrences
* http://localhost:8761 with 2 occurrences
* http://localhost:8761/eureka/ with 5 occurrences
* http://localhost:9000 with 2 occurrences
* http://test1.com with 1 occurrences
* http://test1.com,http://test2.com with 1 occurrences
* http://test1.com,http://user2:pwd2@test2.com with 1 occurrences
* http://test2.com with 1 occurrences
* http://test3.com,http://test4.com with 1 occurrences
* http://test3.com,http://user4:pwd4@test4.com with 1 occurrences
* http://test:test@localhost:8761 with 1 occurrences
* http://test@localhost:8761 with 1 occurrences
* http://testService with 1 occurrences
2019-03-20 15:47:00 -05:00
Craig Andrews 52e4f5ea59 Set traceRequestBody to false by default (#3439)
traceRequestBody requires the body to be buffered which reduces performance and can be problematic, such as when used in combination with `zuul.use-filter=true` and `zuul.servlet-path=/` See https://github.com/spring-cloud/spring-cloud-netflix/issues/3418

traceRequestBody should only be set when logging the request body is actually necessary.
2019-03-19 14:51:42 -04:00
Spring Operator 21e7cca37f URL Cleanup (#3427)
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed Success 
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* http://maven.apache.org/xsd/maven-4.0.0.xsd with 25 occurrences migrated to:  
  https://maven.apache.org/xsd/maven-4.0.0.xsd ([https](https://maven.apache.org/xsd/maven-4.0.0.xsd) result 200).
* http://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch with 1 occurrences migrated to:  
  https://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch ([https](https://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch) result 200).
* http://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin with 1 occurrences migrated to:  
  https://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin ([https](https://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin) result 200).
* http://www.apache.org/licenses/LICENSE-2.0 with 2 occurrences migrated to:  
  https://www.apache.org/licenses/LICENSE-2.0 ([https](https://www.apache.org/licenses/LICENSE-2.0) result 200).

# Ignored
These URLs were intentionally ignored.

* http://maven.apache.org/POM/4.0.0 with 50 occurrences
* http://www.w3.org/2001/XMLSchema-instance with 25 occurrences
2019-03-16 11:58:09 -04:00
Spring Operator 77b8965e29 URL Cleanup (#3411)
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed Success 
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* http://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch migrated to:  
  https://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch ([https](https://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch) result 200).
* http://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin migrated to:  
  https://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin ([https](https://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin) result 200).
* http://www.apache.org/licenses/LICENSE-2.0 migrated to:  
  https://www.apache.org/licenses/LICENSE-2.0 ([https](https://www.apache.org/licenses/LICENSE-2.0) result 200).

# Ignored
These URLs were intentionally ignored.

* http://maven.apache.org/POM/4.0.0
* http://maven.apache.org/xsd/maven-4.0.0.xsd
* http://www.w3.org/2001/XMLSchema-instance
2019-03-11 18:58:19 -04:00
Ryan Baxter 0791a02223 Ignore failing test 2019-03-07 16:17:51 -05:00
Ryan Baxter 8fdc6f0898 Fix health check handler so it is compatible with boot 2.2.0 2019-03-07 16:17:26 -05:00
Marcin Grzejszczak 3d5484e410 Hoxton 2019-03-07 18:12:01 +01:00
Marcin Grzejszczak d289dabfff HTTP to HTTPS 2019-03-07 13:52:09 +01:00
buildmaster 9f766ff4cd Bumping versions to 2.1.2.BUILD-SNAPSHOT after release 2019-03-05 17:29:50 +00:00
buildmaster ed46ed8ca8 Going back to snapshots 2019-03-05 17:29:50 +00:00
buildmaster 87001cd4fe Update SNAPSHOT to 2.1.1.RELEASE 2019-03-05 16:35:33 +00:00
Ryan Baxter 88d4de73c2 Fix potential NPE when extracting data from query params. Fixes #3405 2019-03-04 19:51:16 -05:00
Ryan Baxter 435e94c3f5 Change property name. Fixes #3393 2019-02-27 20:15:25 -05:00
buildmaster 54128d620c Bumping versions to 2.0.4.BUILD-SNAPSHOT after release 2019-02-22 15:45:51 +00:00
buildmaster 08f8ff9ab6 Going back to snapshots 2019-02-22 15:45:51 +00:00
buildmaster b654016e73 Update SNAPSHOT to 2.0.3.RELEASE 2019-02-22 15:38:58 +00:00
Ryan Baxter 53ede01f5e Merge remote-tracking branch 'origin/2.0.x' 2019-02-22 07:49:29 -05:00
Ryan Baxter f55c95b5f3 Fix encoding when retryring requests (#3398) 2019-02-22 07:36:33 -05:00
Olga Maciaszek-Sharma 62363587e0 Merge branch '2.0.x'
# Conflicts:
#	docs/README.adoc
#	pom.xml
#	spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java
#	spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java
#	spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/ConditionalOnRibbonAndEurekaEnabled.java
#	spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfigurationTests.java
2019-02-17 18:48:50 +01:00
Olga Maciaszek-Sharma b6f32d1044 Merge branch '2.0.x'
# Conflicts:
#	docs/README.adoc
#	pom.xml
#	spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java
#	spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java
#	spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/ConditionalOnRibbonAndEurekaEnabled.java
#	spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfigurationTests.java
2019-02-17 18:47:28 +01:00
Olga Maciaszek-Sharma 80af1ddcf5 Make spring.cloud.discovery.enabled work as eureka.client.enabled (#3390)
* Make spring.cloud.discovery.enabled work as eureka.client.enabled

* Switch to using `ConditionalOnDiscoveryEnabled`. Add info in docs.
2019-02-17 17:37:42 +01:00
Spencer Gibb 2b241232da Updates concurrency-limits to v0.1.12 2019-02-15 16:43:48 -05:00
Spencer Gibb 5824f38184 Ignores test 2019-02-15 16:43:28 -05:00
buildmaster 921d1dbae5 Bumping versions 2019-02-14 17:43:06 +00:00
Spencer Gibb b0f43cef69 Updates eureka server java 11 dependencies.
fixes gh-3391
2019-02-14 12:40:42 -05:00
Ryan Baxter 1cf6375ae6 Merge remote-tracking branch 'origin/2.0.x' 2019-02-13 15:52:22 -06:00
周立 8a01660f6b fix SidecarController's broken link. (#3381)
fix SidecarController's broken link.
2019-02-13 15:51:10 -06:00
Olga Maciaszek-Sharma 8c4d6a55a7 Set failsOnError to true. (#3386) 2019-02-12 13:37:39 +01:00
davids-backbase c8e9ad92a9 Use server.servlet.context-path instead of server.context-path for prefix to health check and info URLs (#3382) 2019-02-08 11:40:27 -05:00
Olga Maciaszek-Sharma 805818941c Fix and enforce checkstyle (#3380)
* Checkstyle improvements.

* Checkstyle improvements.

* Checkstyle improvements.

* Finish checkstyle cleanup. Turn failOnError on.

* Fix incorrect final class
2019-02-07 22:16:44 +01:00
Ryan Baxter b0335afd69 Merge remote-tracking branch 'origin/2.0.x' 2019-02-04 10:00:29 -05:00
Pan Li ebfc626538 Fix defect of hystrix stream queue configuration (#3374)
* Support 2 config format send-rate and sendRate.
* If both given, send-rate will be ignore.
Fixes #3359
2019-02-04 09:59:56 -05:00
Dmitrii Priporov 33b84b15e1 Issue-3305. Way to set securePortEnabled option for sidecar (#3356)
* added securePortEnabled option for sidecar
Fixes #3305
2019-02-01 12:23:16 -05:00
Spencer Gibb 273626208b Update to Netflix/concurrency-limits v0.1.10
fixes gh-3369
2019-01-31 13:58:03 -05:00
buildmaster 1026bee78d Bumping versions 2019-01-25 13:17:06 +00:00
buildmaster 20e04bf8e6 Bumping versions to 2.1.1.BUILD-SNAPSHOT after release 2019-01-22 18:20:04 +00:00
buildmaster 589bf3868d Going back to snapshots 2019-01-22 18:20:03 +00:00
buildmaster 50be967c05 Update SNAPSHOT to 2.1.0.RELEASE 2019-01-22 18:10:57 +00:00
Spencer Gibb 5ecd0842ce Merge branch '2.0.x' 2019-01-18 15:56:34 -05:00
Spencer Gibb 567ebda132 Adds ability to get keep alive time from a string.
fixes gh-3038
2019-01-18 15:49:43 -05:00
Spencer Gibb f524c3bb2a Updates stubrunner to 2.0.2.RELEASE 2019-01-18 15:49:43 -05:00
Spencer Gibb 38b8182259 Bumps spring cloud build to 2.1.2.BUILD-SNAPSHOT 2019-01-12 13:03:55 -05:00
Spencer Gibb e460b94b90 Moves Maintenance Mode section to file and includes it in readme 2019-01-07 15:50:15 -05:00
Ryan Baxter 7c6be558f9 Merge remote-tracking branch 'origin/2.0.x' 2019-01-07 10:22:51 -05:00
Ryan Baxter 67f472771e Decode query params in RequestContentDataExtractor (#3321)
* Decode query params in RequestContentDataExtractor.  Fixes #3300
2019-01-07 10:21:15 -05:00
buildmaster 4f316bd4b4 Bumping versions 2019-01-03 17:01:13 +00:00
buildmaster cdaf03ce09 Going back to snapshots 2018-12-20 21:09:55 +00:00
561 changed files with 19281 additions and 10304 deletions
-1
View File
@@ -10,7 +10,6 @@ jobs:
branches:
ignore:
- gh-pages # list of branches to ignore
resource_class: large
steps:
- checkout
- restore_cache:
+16
View File
@@ -0,0 +1,16 @@
root=true
[*.java]
indent_style = tab
indent_size = 4
continuation_indent_size = 8
[*.groovy]
indent_style = tab
indent_size = 4
continuation_indent_size = 8
[*.xml]
indent_style = tab
indent_size = 4
continuation_indent_size = 8
+6 -6
View File
@@ -3,7 +3,7 @@
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
tracker for issues and merging pull requests into main. If you want
to contribute even something trivial please do not hesitate, but
follow the guidelines below.
@@ -17,7 +17,7 @@ given the ability to merge pull requests.
## Code of Conduct
This project adheres to the Contributor Covenant [code of
conduct](https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc). By participating, you are expected to uphold this code. Please report
conduct](https://github.com/spring-cloud/spring-cloud-build/blob/main/docs/src/main/asciidoc/code-of-conduct.adoc). By participating, you are expected to uphold this code. Please report
unacceptable behavior to spring-code-of-conduct@pivotal.io.
## Code Conventions and Housekeeping
@@ -27,8 +27,8 @@ added after the original pull request but before a merge.
* Use the Spring Framework code format conventions. If you use Eclipse
you can import formatter settings using the
`eclipse-code-formatter.xml` file from the
[Spring Cloud Build](https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml) project. If using IntelliJ, you can use the
[Eclipse Code Formatter Plugin](http://plugins.jetbrains.com/plugin/6546) to import the same file.
[Spring Cloud Build](https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/main/spring-cloud-dependencies-parent/eclipse-code-formatter.xml) project. If using IntelliJ, you can use the
[Eclipse Code Formatter Plugin](https://plugins.jetbrains.com/plugin/6546) to import the same file.
* Make sure all new `.java` files to have a simple Javadoc class comment with at least an
`@author` tag identifying you, and preferably at least a paragraph on what the class is
for.
@@ -38,8 +38,8 @@ added after the original pull request but before a merge.
than cosmetic changes).
* Add some Javadocs and, if you change the namespace, some XSD doc elements.
* A few unit tests would help a lot as well -- someone has to do it.
* If no-one else is using your branch, please rebase it against the current master (or
* If no-one else is using your branch, please rebase it against the current main (or
other target branch in the main project).
* When writing a commit message please follow [these conventions](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html),
* When writing a commit message please follow [these conventions](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html),
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).
+17
View File
@@ -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.
+20
View File
@@ -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.
+3
View File
@@ -18,3 +18,6 @@ _site/
.shelf
*.swp
*.swo
.vscode/
.flattened-pom.xml
.sdkmanrc
+1 -4
View File
@@ -7,7 +7,7 @@ to you 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
http://www.apache.org/licenses/LICENSE-2.0
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
@@ -17,9 +17,6 @@ specific language governing permissions and limitations
under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
+5 -5
View File
@@ -21,7 +21,7 @@
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>http://repo.spring.io/libs-snapshot-local</url>
<url>https://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
@@ -29,7 +29,7 @@
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/libs-milestone-local</url>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
@@ -37,7 +37,7 @@
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>http://repo.spring.io/release</url>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
@@ -47,7 +47,7 @@
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>http://repo.spring.io/libs-snapshot-local</url>
<url>https://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
@@ -55,7 +55,7 @@
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/libs-milestone-local</url>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
-11
View File
@@ -1,11 +0,0 @@
require 'asciidoctor'
require 'erb'
options = {:mkdirs => true, :safe => :unsafe, :attributes => ['linkcss', 'allow-uri-read']}
guard 'shell' do
watch(/^docs\/[A-Z-a-z][^#]*\.adoc$/) {|m|
Asciidoctor.load_file('docs/src/main/asciidoc/README.adoc', :to_file => './README.adoc', safe: :safe, parse: false, attributes: 'allow-uri-read')
Asciidoctor.render_file('docs/src/main/asciidoc/spring-cloud-netflix.adoc', options.merge(:to_dir => 'target/generated-docs'))
}
end
+2 -2
View File
@@ -1,7 +1,7 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
@@ -193,7 +193,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
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,
+235 -11
View File
@@ -1,10 +1,47 @@
// 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.
////
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"]
: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/main.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/main"]
image::https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/main/graph/badge.svg["Codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/main"]
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 +60,46 @@ 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
Placing a module in maintenance mode means that the Spring Cloud team will no longer be adding new features to the module.
We will fix blocker bugs and security issues, and we will also consider and review small pull requests from the community.
We intend to continue to support these modules for a period of at least a year from the general availability
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
* spring-cloud-netflix-hystrix
* spring-cloud-netflix-ribbon
* spring-cloud-netflix-turbine-stream
* spring-cloud-netflix-turbine
* spring-cloud-netflix-zuul
NOTE: This does not include the Eureka modules.
== Building
:jdkversion: 1.8
@@ -60,7 +137,7 @@ credentials and you already have those.
The projects that require middleware generally include a
`docker-compose.yml`, so consider using
http://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,
@@ -82,13 +159,18 @@ a modified file in the correct place. Just commit it and push the change.
=== Working with the code
If you don't have an IDE preference we would recommend that you use
http://www.springsource.com/developer/sts[Spring Tools Suite] or
http://eclipse.org[Eclipse] when working with the code. We use the
http://eclipse.org/m2e/[m2eclipse] eclipse plugin for maven support. Other IDEs and tools
https://www.springsource.com/developer/sts[Spring Tools Suite] or
https://eclipse.org[Eclipse] when working with the code. We use the
https://eclipse.org/m2e/[m2eclipse] eclipse plugin for maven support. Other IDEs and tools
should also work without issue as long as they use Maven 3.3.3 or better.
==== 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 http://eclipse.org/m2e/[m2eclipse] eclipse plugin when working with
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
marketplace".
@@ -115,8 +197,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
@@ -145,7 +232,7 @@ added after the original pull request but before a merge.
`eclipse-code-formatter.xml` file from the
https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml[Spring
Cloud Build] project. If using IntelliJ, you can use the
http://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter
https://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter
Plugin] to import the same file.
* Make sure all new `.java` files to have a simple Javadoc class comment with at least an
`@author` tag identifying you, and preferably at least a paragraph on what the class is
@@ -158,6 +245,143 @@ added after the original pull request but before a merge.
* A few unit tests would help a lot as well -- someone has to do it.
* If no-one else is using your branch, please rebase it against the current master (or
other target branch in the main project).
* When writing a commit message please follow http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions],
* 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.
== License
The project license file is available https://raw.githubusercontent.com/spring-cloud/spring-cloud-netflix/main/LICENSE.txt[here].
+1 -1
View File
@@ -1,4 +1,4 @@
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
/* Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Remove the comments around the @import statement below when using this as a custom stylesheet */
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic|Noto+Serif:400,400italic,700,700italic|Droid+Sans+Mono:400";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
-163
View File
@@ -1,163 +0,0 @@
// Do not edit this file (e.g. go instead to src/main/asciidoc)
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"]
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
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
* 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
* 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
== Building
:jdkversion: 1.8
=== Basic Compile and Test
To build the source you will need to install JDK {jdkversion}.
Spring Cloud uses Maven for most build-related activities, and you
should be able to get off the ground quite quickly by cloning the
project you are interested in and typing
----
$ ./mvnw install
----
NOTE: You can also install Maven (>=3.3.3) yourself and run the `mvn` command
in place of `./mvnw` in the examples below. If you do that you also
might need to add `-P spring` if your local Maven settings do not
contain repository declarations for spring pre-release artifacts.
NOTE: Be aware that you might need to increase the amount of memory
available to Maven by setting a `MAVEN_OPTS` environment variable with
a value like `-Xmx512m -XX:MaxPermSize=128m`. We try to cover this in
the `.mvn` configuration, so if you find you have to do it to make a
build succeed, please raise a ticket to get the settings added to
source control.
For hints on how to build the project look in `.travis.yml` if there
is one. There should be a "script" and maybe "install" command. Also
look at the "services" section to see if any services need to be
running locally (e.g. mongo or rabbit). Ignore the git-related bits
that you might find in "before_install" since they're related to setting git
credentials and you already have those.
The projects that require middleware generally include a
`docker-compose.yml`, so consider using
http://compose.docker.io/[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,
rabbit and redis.
NOTE: If all else fails, build with the command from `.travis.yml` (usually
`./mvnw install`).
=== Documentation
The spring-cloud-build module has a "docs" profile, and if you switch
that on it will try to build asciidoc sources from
`src/main/asciidoc`. As part of that process it will look for a
`README.adoc` and process it by loading all the includes, but not
parsing or rendering it, just copying it to `${main.basedir}`
(defaults to `${basedir}`, i.e. the root of the project). If there are
any changes in the README it will then show up after a Maven build as
a modified file in the correct place. Just commit it and push the change.
=== Working with the code
If you don't have an IDE preference we would recommend that you use
http://www.springsource.com/developer/sts[Spring Tools Suite] or
http://eclipse.org[Eclipse] when working with the code. We use the
http://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.
==== Importing into eclipse with m2eclipse
We recommend the http://eclipse.org/m2e/[m2eclipse] eclipse plugin when working with
eclipse. If you don't already have m2eclipse installed it is available from the "eclipse
marketplace".
NOTE: Older versions of m2e do not support Maven 3.3, so once the
projects are imported into Eclipse you will also need to tell
m2eclipse to use the right profile for the projects. If you
see many different errors related to the POMs in the projects, check
that you have an up to date installation. If you can't upgrade m2e,
add the "spring" profile to your `settings.xml`. Alternatively you can
copy the repository settings from the "spring" profile of the parent
pom into your `settings.xml`.
==== Importing into eclipse without m2eclipse
If you prefer not to use m2eclipse you can generate eclipse project metadata using the
following command:
[indent=0]
----
$ ./mvnw eclipse:eclipse
----
The generated eclipse projects can be imported by selecting `import existing projects`
from the `file` menu.
== Contributing
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
to contribute even something trivial please do not hesitate, but
follow the guidelines below.
=== Sign the Contributor License Agreement
Before we accept a non-trivial patch or pull request we will need you to sign the
https://cla.pivotal.io/sign/spring[Contributor License Agreement].
Signing the contributor's agreement does not grant anyone commit rights to the main
repository, but it does mean that we can accept your contributions, and you will get an
author credit if we do. Active contributors might be asked to join the core team, and
given the ability to merge pull requests.
=== Code of Conduct
This project adheres to the Contributor Covenant https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc[code of
conduct]. By participating, you are expected to uphold this code. Please report
unacceptable behavior to spring-code-of-conduct@pivotal.io.
=== Code Conventions and Housekeeping
None of these is essential for a pull request, but they will all help. They can also be
added after the original pull request but before a merge.
* Use the Spring Framework code format conventions. If you use Eclipse
you can import formatter settings using the
`eclipse-code-formatter.xml` file from the
https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml[Spring
Cloud Build] project. If using IntelliJ, you can use the
http://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter
Plugin] to import the same file.
* Make sure all new `.java` files to have a simple Javadoc class comment with at least an
`@author` tag identifying you, and preferably at least a paragraph on what the class is
for.
* Add the ASF license header comment to all new `.java` files (copy from existing files
in the project)
* Add yourself as an `@author` to the .java files that you modify substantially (more
than cosmetic changes).
* Add some Javadocs and, if you change the namespace, some XSD doc elements.
* A few unit tests would help a lot as well -- someone has to do it.
* If no-one else is using your branch, please rebase it against the current master (or
other target branch in the main project).
* When writing a commit message please follow http://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).
+57 -24
View File
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
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>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>2.1.0.RC3</version>
<version>2.2.9.RELEASE</version>
</parent>
<artifactId>spring-cloud-netflix-docs</artifactId>
<packaging>pom</packaging>
@@ -13,45 +13,78 @@
<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>
<main.basedir>${basedir}/..</main.basedir>
<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>
+15 -4
View File
@@ -1,5 +1,7 @@
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"]
include::_attributes.adoc[]
image::https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/main.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/main"]
image::https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/main/graph/badge.svg["Codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/main"]
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"]
@@ -15,10 +17,19 @@ include::intro.adoc[]
* 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
include::maintenance-mode.adoc[]
== Building
include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/building-jdk8.adoc[]
include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/main/docs/src/main/asciidoc/building-jdk8.adoc[]
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
include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/contributing.adoc[]
include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/main/docs/src/main/asciidoc/contributing.adoc[]
== License
The project license file is available https://raw.githubusercontent.com/spring-cloud/spring-cloud-netflix/main/LICENSE.txt[here].
+15
View File
@@ -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
+27
View File
@@ -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.
|===
+14
View File
@@ -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[]
+7 -7
View File
@@ -39,8 +39,8 @@ function check_if_anything_to_sync() {
}
function retrieve_current_branch() {
# Code getting the name of the current branch. For master we want to publish as we did until now
# http://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch
# Code getting the name of the current branch. For main we want to publish as we did until now
# https://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch
# If there is a branch already passed will reuse it - otherwise will try to find it
CURRENT_BRANCH=${BRANCH}
if [[ -z "${CURRENT_BRANCH}" ]] ; then
@@ -134,8 +134,8 @@ function add_docs_from_target() {
# Copies the docs by using the retrieved properties from Maven build
function copy_docs_for_current_version() {
if [[ "${CURRENT_BRANCH}" == "master" ]] ; then
echo -e "Current branch is master - will copy the current docs only to the root folder"
if [[ "${CURRENT_BRANCH}" == "main" ]] ; then
echo -e "Current branch is main - will copy the current docs only to the root folder"
for f in docs/target/generated-docs/*; do
file=${f#docs/target/generated-docs/*}
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then
@@ -147,7 +147,7 @@ function copy_docs_for_current_version() {
COMMIT_CHANGES="yes"
else
echo -e "Current branch is [${CURRENT_BRANCH}]"
# http://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin
# https://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin
if [[ ",${WHITELISTED_BRANCHES_VALUE}," = *",${CURRENT_BRANCH},"* ]] ; then
mkdir -p ${ROOT_FOLDER}/${CURRENT_BRANCH}
echo -e "Branch [${CURRENT_BRANCH}] is whitelisted! Will copy the current docs to the [${CURRENT_BRANCH}] folder"
@@ -216,7 +216,7 @@ function commit_changes_if_applicable() {
git commit -a -m "Sync docs from ${CURRENT_BRANCH} to gh-pages" && COMMIT_SUCCESSFUL="yes" || echo "Failed to commit changes"
# Uncomment the following push if you want to auto push to
# the gh-pages branch whenever you commit to master locally.
# the gh-pages branch whenever you commit to main locally.
# This is a little extreme. Use with care!
###################################################################
if [[ "${COMMIT_SUCCESSFUL}" == "yes" ]] ; then
@@ -249,7 +249,7 @@ The idea of this script is to update gh-pages branch with the generated docs. Wi
the script will work in the following manner:
- if there's no gh-pages / target for docs module then the script ends
- for master branch the generated docs are copied to the root of gh-pages branch
- for main branch the generated docs are copied to the root of gh-pages branch
- for any other branch (if that branch is whitelisted) a subfolder with branch name is created
and docs are copied there
- if the version switch is passed (-v) then a tag with (v) prefix will be retrieved and a folder
+1
View File
@@ -0,0 +1 @@
spring-cloud-netflix.adoc
+2
View File
@@ -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
@@ -0,0 +1,25 @@
include::_attributes.adoc[]
== Modules In Maintenance Mode
Placing a module in maintenance mode means that the Spring Cloud team will no longer be adding new features to the module.
We will fix blocker bugs and security issues, and we will also consider and review small pull requests from the community.
We intend to continue to support these modules for a period of at least a year from the general availability
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
* spring-cloud-netflix-hystrix
* spring-cloud-netflix-ribbon
* spring-cloud-netflix-turbine-stream
* spring-cloud-netflix-turbine
* spring-cloud-netflix-zuul
NOTE: This does not include the Eureka modules.
+55
View File
@@ -0,0 +1,55 @@
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`.
## Contributing
We welcome contributions. You can read more on how to contribute to the project https://github.com/spring-cloud/spring-cloud-netflix#contributing[here].
## Community Support
* You can report issues through https://github.com/spring-cloud/spring-cloud-netflix/issues[Github].
* We monitor https://stackoverflow.com/[StackOverflow] for questions with the `spring-cloud-netflix` tag.
* You can contact our team at https://gitter.im/spring-cloud/spring-cloud[Gitter].
## Commercial Support
Commercial Support is provided as part of the https://spring.io/support[VMware Spring Runtime] offering.
@@ -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");
}
----
====
+135 -77
View File
@@ -1,10 +1,14 @@
:github-tag: master
include::_attributes.adoc[]
:github-tag: main
:github-repo: spring-cloud/spring-cloud-netflix
:github-raw: http://raw.github.com/{github-repo}/{github-tag}
:github-code: http://github.com/{github-repo}/tree/{github-tag}
:github-raw: https://raw.github.com/{github-repo}/{github-tag}
:github-code: https://github.com/{github-repo}/tree/{github-tag}
:all: {asterisk}{asterisk}
:nofooter:
:branch: master
:branch: main
= Spring Cloud Netflix
*{spring-cloud-version}*
@@ -23,7 +27,7 @@ The server can be configured and deployed to be highly available, with each serv
=== How to Include Eureka Client
To include the Eureka Client in your project, use the starter with a group ID of `org.springframework.cloud` and an artifact ID of `spring-cloud-starter-netflix-eureka-client`.
See the http://projects.spring.io/spring-cloud/[Spring Cloud Project page] for details on setting up your build system with the current Spring Cloud Release Train.
See the https://projects.spring.io/spring-cloud/[Spring Cloud Project page] for details on setting up your build system with the current Spring Cloud Release Train.
=== Registering with Eureka
@@ -63,7 +67,9 @@ eureka:
defaultZone: http://localhost:8761/eureka/
----
In the preceding example, "defaultZone" is a magic string fallback value that provides the service URL for any client that does not express a preference (in other words, it is a useful default).
In the preceding example, `defaultZone` is a magic string fallback value that provides the service URL for any client that does not express a preference (in other words, it is a useful default).
WARNING: The `defaultZone` property is case sensitive and requires camel case because the `serviceUrl` property is a `Map<String, String>`. Therefore, the `defaultZone` property does not follow the normal Spring Boot snake-case convention of `default-zone`.
The default application name (that is, the service ID), virtual host, and non-secure port (taken from the `Environment`) are `${spring.application.name}`, `${spring.application.name}` and `${server.port}`, respectively.
@@ -72,15 +78,35 @@ The instance behaviour is driven by `eureka.instance.*` configuration keys, but
See {github-code}/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java[EurekaInstanceConfigBean] and {github-code}/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientConfigBean.java[EurekaClientConfigBean] for more details on the configurable options.
To disable the Eureka Discovery Client, you can set `eureka.client.enabled` to `false`.
To disable the Eureka Discovery Client, you can set `eureka.client.enabled` to `false`. Eureka Discovery Client will also be disabled when `spring.cloud.discovery.enabled` is set to `false`.
=== 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.
When Eureka server requires client side certificate for authentication, the client side certificate and trust store can be configured via properties, as shown in following example:
.application.yml
[source,yaml]
----
eureka:
client:
tls:
enabled: true
key-store: <path-of-key-store>
key-store-type: PKCS12
key-store-password: <key-store-password>
key-password: <key-password>
trust-store: <path-of-trust-store>
trust-store-type: PKCS12
trust-store-password: <trust-store-password>
----
The `eureka.client.tls.enabled` needs to be true to enable Eureka client side TLS. When `eureka.client.tls.trust-store` is omitted, a JVM default trust store is used. The default value for `eureka.client.tls.key-store-type` and `eureka.client.tls.trust-store-type` is PKCS12. When password properties are omitted, empty password is assumed.
=== Status Page and Health Indicator
The status page and health indicators for a Eureka instance default to `/info` and `/health` respectively, which are the default locations of useful endpoints in a Spring Boot Actuator application.
@@ -200,7 +226,7 @@ public EurekaInstanceConfigBean eurekaInstanceConfig(InetUtils inetUtils) {
A vanilla Netflix Eureka instance is registered with an ID that is equal to its host name (that is, there is only one service per host).
Spring Cloud Eureka provides a sensible default, which is defined as follows:
`${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}}`
`${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}`
An example is `myhost:myappname:8080`.
@@ -324,6 +350,25 @@ eureka.instance.metadataMap.zone = zone2
eureka.client.preferSameZoneEureka = true
```
=== Refreshing Eureka Clients
By default, the `EurekaClient` bean is refreshable, meaning the Eureka client properties can be changed and refreshed.
When a refresh occurs clients will be unregistered from the Eureka server and there might be a brief moment of time
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
@@ -333,7 +378,7 @@ This section describes how to set up a Eureka server.
=== How to Include Eureka Server
To include Eureka Server in your project, use the starter with a group ID of `org.springframework.cloud` and an artifact ID of `spring-cloud-starter-netflix-eureka-server`.
See the http://projects.spring.io/spring-cloud/[Spring Cloud Project page] for details on setting up your build system with the current Spring Cloud Release Train.
See the https://projects.spring.io/spring-cloud/[Spring Cloud Project page] for details on setting up your build system with the current Spring Cloud Release Train.
NOTE: If your project already uses Thymeleaf as its template engine, the Freemarker templates of the Eureka server may not be loaded correctly. In this case it is necessary to configure the template loader manually:
@@ -443,7 +488,7 @@ eureka:
hostname: peer1
client:
serviceUrl:
defaultZone: http://peer2/eureka/
defaultZone: https://peer2/eureka/
---
spring:
@@ -453,7 +498,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.
@@ -472,7 +517,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:
@@ -534,6 +579,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
@@ -542,25 +615,18 @@ when running a Eureka server you must include these dependencies in your POM or
[source,xml,indent=0]
----
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</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 http://martinfowler.com/bliki/CircuitBreaker.html[circuit breaker pattern].
Netflix has created a library called https://github.com/Netflix/Hystrix[Hystrix] that implements the https://martinfowler.com/bliki/CircuitBreaker.html[circuit breaker pattern].
In a microservice architecture, it is common to have multiple layers of service calls, as shown in the following example:
.Microservice Graph
@@ -582,7 +648,7 @@ Fallbacks may be chained so that the first fallback makes some other business ca
To include Hystrix in your project, use the starter with a group ID of `org.springframework.cloud`
and a artifact ID of `spring-cloud-starter-netflix-hystrix`.
See the http://projects.spring.io/spring-cloud/[Spring Cloud Project page] for details on setting up your build system with the current Spring Cloud Release Train.
See the https://projects.spring.io/spring-cloud/[Spring Cloud Project page] for details on setting up your build system with the current Spring Cloud Release Train.
The following example shows a minimal Eureka server with a Hystrix circuit breaker:
@@ -699,7 +765,7 @@ be slightly more than three seconds.
=== How to Include the Hystrix Dashboard
To include the Hystrix Dashboard in your project, use the starter with a group ID of `org.springframework.cloud` and an artifact ID of `spring-cloud-starter-netflix-hystrix-dashboard`.
See the http://projects.spring.io/spring-cloud/[Spring Cloud Project page] for details on setting up your build system with the current Spring Cloud Release Train.
See the https://projects.spring.io/spring-cloud/[Spring Cloud Project page] for details on setting up your build system with the current Spring Cloud Release Train.
To run the Hystrix Dashboard, annotate your Spring Boot main class with `@EnableHystrixDashboard`.
Then visit `/hystrix` and point the dashboard to an individual instance's `/hystrix.stream` endpoint in a Hystrix client application.
@@ -707,6 +773,10 @@ Then visit `/hystrix` and point the dashboard to an individual instance's `/hyst
NOTE: When connecting to a `/hystrix.stream` endpoint that uses HTTPS, the certificate used by the server must be trusted by the JVM.
If the certificate is not trusted, you must import the certificate into the JVM in order for the Hystrix Dashboard to make a successful connection to the stream endpoint.
NOTE: In order to use the `/proxy.stream` endpoint you must configure a list of hosts to allow connections to. To set the
list of allowed hosts use `hystrix.dashboard.proxyStreamAllowList`. You can use an Ant-style pattern in the host name to
match against a wider range of host names.
=== Turbine
Looking at an individual instance's Hystrix data is not very useful in terms of the overall health of the system. https://github.com/Netflix/Turbine[Turbine] is an application that aggregates all of the relevant `/hystrix.stream` endpoints into a combined `/turbine.stream` for use in the Hystrix Dashboard.
@@ -731,7 +801,7 @@ eureka:
The `turbine.appConfig` configuration key is a list of Eureka serviceIds that turbine uses to lookup instances.
The turbine stream is then used in the Hystrix dashboard with a URL similar to the following:
`http://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME`
`https://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME`
The cluster parameter can be omitted if the name is `default`.
The `cluster` parameter must match an entry in `turbine.aggregator.clusterConfig`.
@@ -810,7 +880,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.
@@ -822,10 +892,10 @@ Unlike Turbine server, Turbine Stream uses eureka serviceIds as cluster names an
If Turbine Stream server is running on port 8989 on `my.turbine.server` and you have two eureka serviceIds `customers` and `products` in your environment, the following URLs will be available on your Turbine Stream server. `default` and empty cluster name will provide all metrics that Turbine Stream server receives.
----
http://my.turbine.sever:8989/turbine.stream?cluster=customers
http://my.turbine.sever:8989/turbine.stream?cluster=products
http://my.turbine.sever:8989/turbine.stream?cluster=default
http://my.turbine.sever:8989/turbine.stream
https://my.turbine.sever:8989/turbine.stream?cluster=customers
https://my.turbine.sever:8989/turbine.stream?cluster=products
https://my.turbine.sever:8989/turbine.stream?cluster=default
https://my.turbine.sever:8989/turbine.stream
----
So, you can use eureka serviceIds as cluster names for your Turbine dashboard (or any compatible dashboard).
@@ -850,7 +920,7 @@ This contains (amongst other things) an `ILoadBalancer`, a `RestClient`, and a `
=== How to Include Ribbon
To include Ribbon in your project, use the starter with a group ID of `org.springframework.cloud` and an artifact ID of `spring-cloud-starter-netflix-ribbon`.
See the http://projects.spring.io/spring-cloud/[Spring Cloud Project page] for details on setting up your build system with the current Spring Cloud Release Train.
See the https://projects.spring.io/spring-cloud/[Spring Cloud Project page] for details on setting up your build system with the current Spring Cloud Release Train.
=== Customizing the Ribbon Client
@@ -870,7 +940,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:
@@ -892,7 +962,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`.
@@ -903,7 +973,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]
----
@@ -991,7 +1061,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
}
}
@@ -1069,7 +1139,7 @@ If you do not put any value with `LOAD_BALANCER_KEY` in `RequestContext`, null i
https://github.com/Netflix/archaius[Archaius] is the Netflix client-side configuration library.
It is the library used by all of the Netflix OSS components for configuration.
Archaius is an extension of the http://commons.apache.org/proper/commons-configuration[Apache Commons Configuration] project.
Archaius is an extension of the https://commons.apache.org/proper/commons-configuration[Apache Commons Configuration] project.
It allows updates to configuration by either polling a source for changes or by letting a source push changes to the client.
Archaius uses Dynamic<Type>Property classes as handles to properties, as shown in the following example:
@@ -1098,7 +1168,7 @@ Routing is an integral part of a microservice architecture.
For example, `/` may be mapped to your web application, `/api/users` is mapped to the user service and `/api/shop` is mapped to the shop service.
https://github.com/Netflix/zuul[Zuul] is a JVM-based router and server-side load balancer from Netflix.
http://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146/27[Netflix uses Zuul] for the following:
https://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146/27[Netflix uses Zuul] for the following:
* Authentication
* Insights
@@ -1122,7 +1192,7 @@ NOTE: The default Hystrix isolation pattern (`ExecutionIsolationStrategy`) for a
=== How to Include Zuul
To include Zuul in your project, use the starter with a group ID of `org.springframework.cloud` and a artifact ID of `spring-cloud-starter-netflix-zuul`.
See the http://projects.spring.io/spring-cloud/[Spring Cloud Project page] for details on setting up your build system with the current Spring Cloud Release Train.
See the https://projects.spring.io/spring-cloud/[Spring Cloud Project page] for details on setting up your build system with the current Spring Cloud Release Train.
[[netflix-zuul-reverse-proxy]]
=== Embedded Zuul Reverse Proxy
@@ -1188,7 +1258,7 @@ The location of the back end can be specified as either a `serviceId` (for a ser
routes:
users:
path: /myusers/**
url: http://example.com/users_service
url: https://example.com/users_service
----
These simple url-routes do not get executed as a `HystrixCommand`, nor do they load-balance multiple URLs with Ribbon.
@@ -1215,7 +1285,7 @@ hystrix:
myusers-service:
ribbon:
NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList
listOfServers: http://example1.com,http://example2.com
listOfServers: https://example1.com,http://example2.com
ConnectTimeout: 1000
ReadTimeout: 3000
MaxTotalHttpConnections: 500
@@ -1330,7 +1400,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
@@ -1451,7 +1521,7 @@ The following example shows the configuration details for a "`strangle`" scenari
routes:
first:
path: /first/**
url: http://first.example.com
url: https://first.example.com
second:
path: /second/**
url: forward:/second
@@ -1460,7 +1530,7 @@ The following example shows the configuration details for a "`strangle`" scenari
url: forward:/3rd
legacy:
path: /**
url: http://legacy.example.com
url: https://legacy.example.com
----
In the preceding example, we are strangle the "`legacy`" application, which is mapped to all requests that do not match one of the other patterns.
@@ -1550,7 +1620,7 @@ The following example maps all paths in "/api/{all}" to the Zuul filter chain:
=== Disable Zuul Filters
Zuul for Spring Cloud comes with a number of `ZuulFilter` beans enabled by default in both proxy and server mode.
See https://github.com/spring-cloud/spring-cloud-netflix/tree/master/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters[the Zuul filters package] for the list of filters that you can enable.
See https://github.com/spring-cloud/spring-cloud-netflix/tree/main/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters[the Zuul filters package] for the list of filters that you can enable.
If you want to disable one, set `zuul.<SimpleClassName>.<filterType>.disable=true`.
By convention, the package after `filters` is the Zuul filter type.
For example to disable `org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter`, set `zuul.SendResponseFilter.post.disable=true`.
@@ -1721,13 +1791,13 @@ public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/path-1/**")
.allowedOrigins("http://allowed-origin.com")
.allowedOrigins("https://allowed-origin.com")
.allowedMethods("GET", "POST");
}
};
}
----
In the example above, we allow `GET` and `POST` methods from `http://allowed-origin.com` to send cross-origin requests to the endpoints starting with `path-1`.
In the example above, we allow `GET` and `POST` methods from `https://allowed-origin.com` to send cross-origin requests to the endpoints starting with `path-1`.
You can apply CORS configuration to a specific path pattern or globally for the whole application, using `/**` mapping.
You can customize properties: `allowedOrigins`,`allowedMethods`,`allowedHeaders`,`exposedHeaders`,`allowCredentials` and `maxAge` via this configuration.
@@ -1755,7 +1825,7 @@ This path can be changed with the `zuul.servlet-path` property.
To pass information between filters, Zuul uses a https://github.com/Netflix/zuul/blob/1.x/zuul-core/src/main/java/com/netflix/zuul/context/RequestContext.java[`RequestContext`].
Its data is held in a `ThreadLocal` specific to each request.
Information about where to route requests, errors, and the actual `HttpServletRequest` and `HttpServletResponse` are stored there.
The `RequestContext` extends `ConcurrentHashMap`, so anything can be stored in the context. https://github.com/spring-cloud/spring-cloud-netflix/blob/master/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/support/FilterConstants.java[`FilterConstants`] contains the keys used by the filters installed by Spring Cloud Netflix (more on these <<zuul-developer-guide-enable-filters,later>>).
The `RequestContext` extends `ConcurrentHashMap`, so anything can be stored in the context. https://github.com/spring-cloud/spring-cloud-netflix/blob/main/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/support/FilterConstants.java[`FilterConstants`] contains the keys used by the filters installed by Spring Cloud Netflix (more on these <<zuul-developer-guide-enable-filters,later>>).
==== `@EnableZuulProxy` vs. `@EnableZuulServer`
@@ -1772,7 +1842,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.
@@ -2016,6 +2086,7 @@ Run the resulting application on the same host as the non-JVM application.
To configure the side car, add `sidecar.port` and `sidecar.health-uri` to `application.yml`.
The `sidecar.port` property is the port on which the non-JVM application listens.
This is so the Sidecar can properly register the application with Eureka.
The `sidecar.secure-port-enabled` options provides a way to enable secure port for traffic.
The `sidecar.health-uri` is a URI accessible on the non-JVM application that mimics a Spring Boot health indicator.
It should return a JSON document that resembles the following:
@@ -2053,14 +2124,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
}
@@ -2076,7 +2147,7 @@ If the Config Server is registered with Eureka, the non-JVM application can acce
If the `serviceId` of the ConfigServer is `configserver` and the Sidecar is on port 5678, then it can be accessed at http://localhost:5678/configserver.
Non-JVM applications can take advantage of the Config Server's ability to return YAML documents.
For example, a call to http://sidecar.local.spring.io:5678/configserver/default-master.yml
For example, a call to https://sidecar.local.spring.io:5678/configserver/default-master.yml
might result in a YAML document resembling the following:
[source,yaml]
@@ -2132,6 +2203,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:
@@ -2155,33 +2228,18 @@ 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.
// TODO Can we provide a link to how to do so?
== Modules In Maintenance Mode
include::maintenance-mode.adoc[]
Placing a module in maintenance mode means that the Spring Cloud team will no longer be adding new features to the module.
We will fix blocker bugs and security issues, and we will also consider and review small pull requests from the community.
== Configuration properties
To see the list of all Spring Cloud Netflix related configuration properties please check link:appendix.html[the Appendix page].
We intend to continue to support these modules for a period of at least a year from the general availability
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-hystrix-contract
* spring-cloud-netflix-hystrix-dashboard
* spring-cloud-netflix-hystrix-stream
* spring-cloud-netflix-hystrix
* spring-cloud-netflix-ribbon
* spring-cloud-netflix-turbine-stream
* spring-cloud-netflix-turbine
* spring-cloud-netflix-zuul
NOTE: This does not include the Eureka or concurrency-limits modules.
Vendored
+1 -1
View File
@@ -8,7 +8,7 @@
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
# 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
Vendored
+1 -1
View File
@@ -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
+56 -7
View File
@@ -1,16 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
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.0.RC3</version>
<version>2.2.9.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.0.RC3</version>
<version>2.3.5.RELEASE</version>
<relativePath />
</parent>
<scm>
@@ -21,20 +21,25 @@
</scm>
<properties>
<bintray.package>netflix</bintray.package>
<spring-cloud-commons.version>2.1.0.RC2</spring-cloud-commons.version>
<spring-cloud-config.version>2.1.0.RC3</spring-cloud-config.version>
<spring-cloud-stream.version>Fishtown.RC4</spring-cloud-stream.version>
<spring-cloud-commons.version>2.2.9.RELEASE</spring-cloud-commons.version>
<spring-cloud-config.version>2.2.8.RELEASE</spring-cloud-config.version>
<spring-cloud-stream.version>Horsham.SR13</spring-cloud-stream.version>
<!-- Has to be a stable version (not one that depends on this version of netflix): -->
<donotreplacespring-cloud-contract.version>2.0.1.RELEASE</donotreplacespring-cloud-contract.version>
<donotreplacespring-cloud-contract.version>2.2.4.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>
<eureka-jersey.version>1.19.4</eureka-jersey.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>
@@ -61,6 +66,14 @@
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencyManagement>
@@ -130,8 +143,43 @@
</exclusions>
</dependency>
<!-- end archaius deps -->
<!-- Eureka core dep that is now optional -->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>${eureka-jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>${eureka-jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>${eureka-jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>${eureka-jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-apache-client4</artifactId>
<version>${eureka-jersey.version}</version>
</dependency>
<!-- end eureka deps -->
</dependencies>
</dependencyManagement>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
</plugin>
</plugins>
</reporting>
<modules>
<module>spring-cloud-netflix-dependencies</module>
<module>spring-cloud-netflix-archaius</module>
@@ -150,6 +198,7 @@
<module>spring-cloud-netflix-ribbon</module>
<module>spring-cloud-starter-netflix</module>
<module>spring-cloud-netflix-hystrix</module>
<module>spring-cloud-netflix-eureka-client-tls-tests</module>
<module>docs</module>
</modules>
<profiles>
+2
View File
@@ -1,4 +1,6 @@
#!/bin/bash
set -o errexit
(cd spring-cloud-netflix-hystrix-contract && ../mvnw clean install -B -Pdocs ${@})
./mvnw clean install -B -Pdocs ${@}
+2
View File
@@ -1,4 +1,6 @@
#!/bin/bash
set -o errexit
(cd spring-cloud-netflix-hystrix-contract && ../mvnw clean install -B -Pdocs -DskipTests)
./mvnw clean install -B -Pdocs -DskipTests -fae
+2 -2
View File
@@ -4,7 +4,7 @@ set -o errexit
mkdir -p target
SCRIPT_URL="https://raw.githubusercontent.com/spring-cloud-samples/brewery/master/runAcceptanceTests.sh"
SCRIPT_URL="https://raw.githubusercontent.com/spring-cloud-samples/brewery/main/runAcceptanceTests.sh"
AT_WHAT_TO_TEST="EUREKA"
cd target
@@ -18,7 +18,7 @@ echo "Killing all running apps"
./runAcceptanceTests.sh -t "${AT_WHAT_TO_TEST}" --killattheend
SCRIPT_URL="https://raw.githubusercontent.com/spring-cloud-samples/tests/master/scripts/runTests.sh"
SCRIPT_URL="https://raw.githubusercontent.com/spring-cloud-samples/tests/main/scripts/runTests.sh"
curl "${SCRIPT_URL}" --output runIntegrationTests.sh
+2 -2
View File
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
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>
<parent>
<artifactId>spring-cloud-netflix</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>2.1.0.RC3</version>
<version>2.2.9.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -24,6 +24,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.PreDestroy;
import com.netflix.config.AggregatedConfiguration;
import com.netflix.config.ConcurrentCompositeConfiguration;
import com.netflix.config.ConfigurationManager;
import com.netflix.config.DeploymentContext;
import com.netflix.config.DynamicProperty;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicURLConfiguration;
import org.apache.commons.configuration.AbstractConfiguration;
import org.apache.commons.configuration.ConfigurationBuilder;
import org.apache.commons.configuration.EnvironmentConfiguration;
@@ -32,8 +39,9 @@ import org.apache.commons.configuration.event.ConfigurationEvent;
import org.apache.commons.configuration.event.ConfigurationListener;
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;
@@ -43,19 +51,12 @@ 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;
import org.springframework.util.ReflectionUtils;
import com.netflix.config.AggregatedConfiguration;
import com.netflix.config.ConcurrentCompositeConfiguration;
import com.netflix.config.ConfigurationManager;
import com.netflix.config.DeploymentContext;
import com.netflix.config.DynamicProperty;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicURLConfiguration;
import static com.netflix.config.ConfigurationManager.APPLICATION_PROPERTIES;
import static com.netflix.config.ConfigurationManager.DISABLE_DEFAULT_ENV_CONFIG;
import static com.netflix.config.ConfigurationManager.DISABLE_DEFAULT_SYS_CONFIG;
@@ -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)
@@ -98,52 +101,21 @@ public class ArchaiusAutoConfiguration {
}
@Bean
public static ConfigurableEnvironmentConfiguration configurableEnvironmentConfiguration(ConfigurableEnvironment env,
ApplicationContext context) {
Map<String, AbstractConfiguration> abstractConfigurationMap = context.getBeansOfType(AbstractConfiguration.class);
List<AbstractConfiguration> externalConfigurations = new ArrayList<>(abstractConfigurationMap.values());
ConfigurableEnvironmentConfiguration envConfig = new ConfigurableEnvironmentConfiguration(env);
public static ConfigurableEnvironmentConfiguration configurableEnvironmentConfiguration(
ConfigurableEnvironment env, ApplicationContext context) {
Map<String, AbstractConfiguration> abstractConfigurationMap = context
.getBeansOfType(AbstractConfiguration.class);
List<AbstractConfiguration> externalConfigurations = new ArrayList<>(
abstractConfigurationMap.values());
ConfigurableEnvironmentConfiguration envConfig = new ConfigurableEnvironmentConfiguration(
env);
configureArchaius(envConfig, env, externalConfigurations);
return envConfig;
}
@Configuration
@ConditionalOnClass(Health.class)
protected static class ArchaiusEndpointConfiguration {
@Bean
@ConditionalOnEnabledEndpoint
protected ArchaiusEndpoint archaiusEndpoint() {
return new ArchaiusEndpoint();
}
}
@Configuration
@ConditionalOnProperty(value = "archaius.propagate.environmentChangedEvent", matchIfMissing = true)
@ConditionalOnClass(EnvironmentChangeEvent.class)
protected static class PropagateEventsConfiguration
implements ApplicationListener<EnvironmentChangeEvent> {
@Autowired
private Environment env;
@Override
public void onApplicationEvent(EnvironmentChangeEvent event) {
AbstractConfiguration manager = ConfigurationManager.getConfigInstance();
for (String key : event.getKeys()) {
for (ConfigurationListener listener : manager
.getConfigurationListeners()) {
Object source = event.getSource();
// TODO: Handle add vs set vs delete?
int type = AbstractConfiguration.EVENT_SET_PROPERTY;
String value = this.env.getProperty(key);
boolean beforeUpdate = false;
listener.configurationChanged(new ConfigurationEvent(source, type,
key, value, beforeUpdate));
}
}
}
}
protected static void configureArchaius(ConfigurableEnvironmentConfiguration envConfig, ConfigurableEnvironment env, List<AbstractConfiguration> externalConfigurations) {
protected static void configureArchaius(
ConfigurableEnvironmentConfiguration envConfig, ConfigurableEnvironment env,
List<AbstractConfiguration> externalConfigurations) {
if (initialized.compareAndSet(false, true)) {
String appName = env.getProperty("spring.application.name");
if (appName == null) {
@@ -196,7 +168,8 @@ public class ArchaiusAutoConfiguration {
}
}
private static void addArchaiusConfiguration(ConcurrentCompositeConfiguration config) {
private static void addArchaiusConfiguration(
ConcurrentCompositeConfiguration config) {
if (ConfigurationManager.isConfigurationInstalled()) {
AbstractConfiguration installedConfiguration = ConfigurationManager
.getConfigInstance();
@@ -224,4 +197,45 @@ public class ArchaiusAutoConfiguration {
ReflectionUtils.setField(field, null, value);
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Health.class)
protected static class ArchaiusEndpointConfiguration {
@Bean
@ConditionalOnAvailableEndpoint
protected ArchaiusEndpoint archaiusEndpoint() {
return new ArchaiusEndpoint();
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "archaius.propagate.environmentChangedEvent",
matchIfMissing = true)
@ConditionalOnClass(EnvironmentChangeEvent.class)
protected static class PropagateEventsConfiguration
implements ApplicationListener<EnvironmentChangeEvent> {
@Autowired
private Environment env;
@Override
public void onApplicationEvent(EnvironmentChangeEvent event) {
AbstractConfiguration manager = ConfigurationManager.getConfigInstance();
for (String key : event.getKeys()) {
for (ConfigurationListener listener : manager
.getConfigurationListeners()) {
Object source = event.getSource();
// TODO: Handle add vs set vs delete?
int type = AbstractConfiguration.EVENT_SET_PROPERTY;
String value = this.env.getProperty(key);
boolean beforeUpdate = false;
listener.configurationChanged(new ConfigurationEvent(source, type,
key, value, beforeUpdate));
}
}
}
}
}
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,24 +16,30 @@
package org.springframework.cloud.netflix.archaius;
import com.netflix.config.ConfigurationManager;
import org.apache.commons.configuration.AbstractConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import com.netflix.config.ConfigurationManager;
/**
* @author Dave Syer
*/
public class ArchaiusDelegatingProxyUtils {
public final class ArchaiusDelegatingProxyUtils {
private ArchaiusDelegatingProxyUtils() {
}
/**
* {@code ApplicationContext} class name.
*/
public static String APPLICATION_CONTEXT = ApplicationContext.class.getName();
public static <T> T getNamedInstance(Class<T> type, String name) {
ApplicationContext context = (ApplicationContext) ConfigurationManager
.getConfigInstance().getProperty(APPLICATION_CONTEXT);
return context != null && context.containsBean(name) ? context
.getBean(name, type) : null;
return context != null && context.containsBean(name) ? context.getBean(name, type)
: null;
}
public static <T> T getInstanceWithPrefix(Class<T> type, String prefix) {
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -20,17 +20,19 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import com.netflix.config.ConcurrentCompositeConfiguration;
import com.netflix.config.ConfigurationManager;
import org.apache.commons.configuration.AbstractConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.EnvironmentConfiguration;
import org.apache.commons.configuration.SystemConfiguration;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import com.netflix.config.ConcurrentCompositeConfiguration;
import com.netflix.config.ConfigurationManager;
/**
* An actuator endpoint that returns Archaius configuration.
*
* @author Dave Syer
*/
@Endpoint(id = "archaius")
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -23,6 +23,7 @@ import java.util.List;
import java.util.Map;
import org.apache.commons.configuration.AbstractConfiguration;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
@@ -31,6 +32,8 @@ import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
/**
* EnvironmentConfiguration wrapper class providing further configuration possibilities.
*
* @author Spencer Gibb
*/
public class ConfigurableEnvironmentConfiguration extends AbstractConfiguration {
@@ -64,7 +67,8 @@ public class ConfigurableEnvironmentConfiguration extends AbstractConfiguration
@Override
public Iterator<String> getKeys() {
List<String> result = new ArrayList<>();
for (Map.Entry<String, PropertySource<?>> entry : getPropertySources().entrySet()) {
for (Map.Entry<String, PropertySource<?>> entry : getPropertySources()
.entrySet()) {
PropertySource<?> source = entry.getValue();
if (source instanceof EnumerablePropertySource) {
EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source;
@@ -78,8 +82,9 @@ public class ConfigurableEnvironmentConfiguration extends AbstractConfiguration
private Map<String, PropertySource<?>> getPropertySources() {
Map<String, PropertySource<?>> map = new LinkedHashMap<>();
MutablePropertySources sources = (this.environment != null ? this.environment
.getPropertySources() : new StandardEnvironment().getPropertySources());
MutablePropertySources sources = (this.environment != null
? this.environment.getPropertySources()
: new StandardEnvironment().getPropertySources());
for (PropertySource<?> source : sources) {
extract("", map, source);
}
@@ -1,38 +1,35 @@
/*
* Copyright 2013-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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 java.util.Collections;
import com.netflix.config.ConfigurationManager;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicStringProperty;
import org.apache.commons.configuration.AbstractConfiguration;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.netflix.config.ConfigurationManager;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicStringProperty;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Dave Syer
@@ -40,6 +37,7 @@ import static org.junit.Assert.assertNull;
public class ArchaiusAutoConfigurationTests {
private AnnotationConfigApplicationContext context;
private Object propertyValue;
@After
@@ -55,24 +53,23 @@ public class ArchaiusAutoConfigurationTests {
ArchaiusAutoConfiguration.class);
AbstractConfiguration config = this.context
.getBean(ConfigurableEnvironmentConfiguration.class);
assertNotNull(config.getString("java.io.tmpdir"));
assertThat(config.getString("java.io.tmpdir")).isNotNull();
}
@Test
public void environmentChangeEventPropagated() {
this.context = new AnnotationConfigApplicationContext(
ArchaiusAutoConfiguration.class);
ConfigurationManager.getConfigInstance().addConfigurationListener(
event -> {
if (event.getPropertyName().equals("my.prop")) {
ArchaiusAutoConfigurationTests.this.propertyValue = event
.getPropertyValue();
}
});
ConfigurationManager.getConfigInstance().addConfigurationListener(event -> {
if (event.getPropertyName().equals("my.prop")) {
ArchaiusAutoConfigurationTests.this.propertyValue = event
.getPropertyValue();
}
});
TestPropertyValues.of("my.prop=my.newval").applyTo(this.context);
this.context.publishEvent(new EnvironmentChangeEvent(Collections
.singleton("my.prop")));
assertEquals("my.newval", this.propertyValue);
this.context.publishEvent(
new EnvironmentChangeEvent(Collections.singleton("my.prop")));
assertThat(this.propertyValue).isEqualTo("my.newval");
}
@Test
@@ -84,9 +81,9 @@ public class ArchaiusAutoConfigurationTests {
DynamicStringProperty staticProperty = DynamicPropertyFactory.getInstance()
.getStringProperty("archaius.file.property", null);
assertNull(dbProperty.getValue());
assertNotNull(staticProperty.getValue());
assertEquals("Static config file property", staticProperty.getValue());
assertThat(dbProperty.getValue()).isNull();
assertThat(staticProperty.getValue()).isNotNull();
assertThat(staticProperty.getValue()).isEqualTo("Static config file property");
}
@Test
@@ -100,12 +97,12 @@ public class ArchaiusAutoConfigurationTests {
DynamicStringProperty staticProperty = DynamicPropertyFactory.getInstance()
.getStringProperty("archaius.file.property", null);
assertNotNull(dbProperty.getValue());
assertNotNull(secondDbProperty.getValue());
assertNotNull(staticProperty.getValue());
assertEquals("this is a db property", dbProperty.getValue());
assertEquals("this is another db property", secondDbProperty.getValue());
assertEquals("Static config file property", staticProperty.getValue());
assertThat(dbProperty.getValue()).isNotNull();
assertThat(secondDbProperty.getValue()).isNotNull();
assertThat(staticProperty.getValue()).isNotNull();
assertThat(dbProperty.getValue()).isEqualTo("this is a db property");
assertThat(secondDbProperty.getValue()).isEqualTo("this is another db property");
assertThat(staticProperty.getValue()).isEqualTo("Static config file property");
}
}
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -18,14 +18,13 @@ package org.springframework.cloud.netflix.archaius;
import java.util.Map;
import org.junit.Test;
import org.springframework.core.env.StandardEnvironment;
import com.netflix.config.ConcurrentCompositeConfiguration;
import com.netflix.config.ConfigurationManager;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.springframework.core.env.StandardEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Dave Syer
@@ -37,7 +36,7 @@ public class ArchaiusEndpointTests {
@Test
public void detectsPropertiesWhenSet() {
ConfigurationManager.getConfigInstance().setProperty("foo", "bar");
assertTrue(this.endpoint.invoke().containsKey("foo"));
assertThat(this.endpoint.invoke().containsKey("foo")).isTrue();
}
@Test
@@ -46,12 +45,12 @@ public class ArchaiusEndpointTests {
ConfigurationManager.getConfigInstance());
ConfigurableEnvironmentConfiguration config = new ConfigurableEnvironmentConfiguration(
new StandardEnvironment());
assertTrue(config.containsKey("user.dir"));
assertThat(config.containsKey("user.dir")).isTrue();
composite.addConfiguration(config);
ConfigurationManager.getConfigInstance().setProperty("foo", "bar");
Map<String, Object> map = this.endpoint.invoke();
assertTrue(map.containsKey("foo"));
assertFalse(map.containsKey("user.dir"));
assertThat(map.containsKey("foo")).isTrue();
assertThat(map.containsKey("user.dir")).isFalse();
}
}
@@ -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 {
}
}
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,25 +16,25 @@
package org.springframework.cloud.netflix.archaius;
import com.netflix.config.ConcurrentMapConfiguration;
import org.apache.commons.configuration.AbstractConfiguration;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.netflix.config.ConcurrentMapConfiguration;
/**
* @author Alexandru-George Burghelea
*/
@Configuration
@Configuration(proxyBeanMethods = false)
public class TestArchaiusExternalConfiguration {
@Bean
@Qualifier("dynamicConfiguration")
public AbstractConfiguration createDynamicConfiguration() {
ConcurrentMapConfiguration config = new ConcurrentMapConfiguration();
config.addProperty("db.property","this is a db property");
config.addProperty("db.second.property","this is another db property");
config.addProperty("db.property", "this is a db property");
config.addProperty("db.second.property", "this is another db property");
return config;
}
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
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>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>2.1.0.RC3</version>
<version>2.2.9.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-concurrency-limits</artifactId>
@@ -1,18 +1,17 @@
/*
* Copyright 2013-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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.concurrency.limits.micrometer;
@@ -24,10 +23,18 @@ import io.micrometer.core.instrument.DistributionSummary;
import io.micrometer.core.instrument.MeterRegistry;
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;
//TODO: baseId?
// TODO: baseId?
public MicrometerMetricRegistry(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
@@ -40,7 +47,9 @@ public class MicrometerMetricRegistry implements MetricRegistry {
}
@Override
public void registerGauge(String id, Supplier<Number> supplier, String... tagNameValuePairs) {
public void registerGauge(String id, Supplier<Number> supplier,
String... tagNameValuePairs) {
this.meterRegistry.gauge(id, Tags.of(tagNameValuePairs), supplier.get());
}
}
}
@@ -1,18 +1,17 @@
/*
* Copyright 2013-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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.concurrency.limits.reactive;
@@ -25,6 +24,14 @@ import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
/**
* A {@link WebFilter} implementation providing the possibility to use Netflix
* {@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;
@@ -41,8 +48,9 @@ public class ConcurrencyLimitsWebFilter implements WebFilter {
.doOnError(throwable -> listener.onIgnore()))
.orElseGet(() -> {
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
//TODO: set body
// TODO: set body
return exchange.getResponse().setComplete();
});
}
}
@@ -1,44 +1,52 @@
/*
* Copyright 2013-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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.concurrency.limits.reactive;
import com.netflix.concurrency.limits.Limiter;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.WebFilter;
import java.util.function.Consumer;
@Configuration
import com.netflix.concurrency.limits.Limiter;
import reactor.core.publisher.Mono;
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.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.ServerWebExchange;
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
*/
@Deprecated
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.REACTIVE)
@ConditionalOnClass({WebFilter.class, Mono.class})
@ConditionalOnClass({ WebFilter.class, Mono.class })
public class ReactiveConcurrencyLimitsAutoConfiguration {
private final ObjectProvider<Consumer<ServerWebExchangeLimiterBuilder>> configurerProvider;
public ReactiveConcurrencyLimitsAutoConfiguration(ObjectProvider<Consumer<ServerWebExchangeLimiterBuilder>> configurerProvider) {
public ReactiveConcurrencyLimitsAutoConfiguration(
ObjectProvider<Consumer<ServerWebExchangeLimiterBuilder>> configurerProvider) {
this.configurerProvider = configurerProvider;
}
@@ -53,7 +61,9 @@ public class ReactiveConcurrencyLimitsAutoConfiguration {
}
@Bean
public ConcurrencyLimitsWebFilter concurrencyLimitsWebFilter(Limiter<ServerWebExchange> limiter) {
public ConcurrencyLimitsWebFilter concurrencyLimitsWebFilter(
Limiter<ServerWebExchange> limiter) {
return new ConcurrencyLimitsWebFilter(limiter);
}
}
}
@@ -1,23 +1,21 @@
/*
* Copyright 2013-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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.concurrency.limits.reactive;
import java.security.Principal;
import java.util.Optional;
import java.util.function.Function;
@@ -25,58 +23,75 @@ import com.netflix.concurrency.limits.limiter.AbstractPartitionedLimiter;
import org.springframework.web.server.ServerWebExchange;
public class ServerWebExchangeLimiterBuilder extends AbstractPartitionedLimiter.Builder<ServerWebExchangeLimiterBuilder, 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> {
/**
* Partition the limit by header
* Partition the limit by header.
* @param name header name
* @return Chainable builder
*/
public ServerWebExchangeLimiterBuilder partitionByHeader(String name) {
return partitionResolver(exchange -> exchange.getRequest().getHeaders().getFirst(name));
return partitionResolver(
exchange -> exchange.getRequest().getHeaders().getFirst(name));
}
/**
* Partition the limit by {@link Principal}. Percentages of the limit are partitioned to named
* groups. Group membership is derived from the provided mapping function.
* Partition the limit by {@link Principal}. Percentages of the limit are partitioned
* to named groups. Group membership is derived from the provided mapping function.
* @param principalToGroup Mapping function from {@link Principal} to a named group.
* @param configurer Configuration function though which group percentages may be specified
* Unspecified group values may only use excess capacity.
* @param configurer Configuration function though which group percentages may be
* specified Unspecified group values may only use excess capacity.
* @return Chainable builder
*/
/*public ServerWebExchangeLimiterBuilder partitionByUserPrincipal(Function<Principal, String> principalToGroup, Consumer<LookupPartitionStrategy.Builder<ServerWebExchange>> configurer) {
return partitionResolver(
exchange -> Optional.ofNullable(request.getUserPrincipal()).map(principalToGroup).orElse(null),
configurer);
}*/
/*
* public ServerWebExchangeLimiterBuilder partitionByUserPrincipal(Function<Principal,
* String> principalToGroup,
* Consumer<LookupPartitionStrategy.Builder<ServerWebExchange>> configurer) { return
* partitionResolver( exchange ->
* Optional.ofNullable(request.getUserPrincipal()).map(principalToGroup).orElse(null),
* configurer); }
*/
/**
* Partition the limit by request attribute
* Partition the limit by request attribute.
* @param name attribute name
* @return Chainable builder
*/
public ServerWebExchangeLimiterBuilder partitionByAttribute(String name) {
return partitionResolver( exchange -> exchange.getAttribute(name));
return partitionResolver(exchange -> exchange.getAttribute(name));
}
/**
* Partition the limit by request parameter
* Partition the limit by request parameter.
* @param name parameter name
* @return Chainable builder
*/
public ServerWebExchangeLimiterBuilder partitionByParameter(String name) {
return partitionResolver(exchange -> exchange.getRequest().getQueryParams().getFirst(name));
return partitionResolver(
exchange -> exchange.getRequest().getQueryParams().getFirst(name));
}
/**
* Partition the limit by the full path. Percentages of the limit are partitioned to named
* groups. Group membership is derived from the provided mapping function.
* Partition the limit by the full path. Percentages of the limit are partitioned to
* named groups. Group membership is derived from the provided mapping function.
* @param pathToGroup Mapping function from full path to a named group.
* @return Chainable builder
*/
public ServerWebExchangeLimiterBuilder partitionByPathInfo(Function<String, String> pathToGroup) {
return partitionResolver(
exchange -> {
//TODO: pathWithinApplication?
String path = exchange.getRequest().getPath().contextPath().value();
return Optional.ofNullable(path).map(pathToGroup).orElse(null);
});
public ServerWebExchangeLimiterBuilder partitionByPathInfo(
Function<String, String> pathToGroup) {
return partitionResolver(exchange -> {
// TODO: pathWithinApplication?
String path = exchange.getRequest().getPath().contextPath().value();
return Optional.ofNullable(path).map(pathToGroup).orElse(null);
});
}
@Override
@@ -1,18 +1,17 @@
/*
* Copyright 2013-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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.concurrency.limits.web;
@@ -30,6 +29,14 @@ import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* A {@link HandlerInterceptor} implementation providing the possibility to use Netflix
* {@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;
@@ -39,7 +46,8 @@ public class ConcurrencyLimitsHandlerInterceptor implements HandlerInterceptor {
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
Optional<Listener> listener = limiter.acquire(request);
if (listener.isPresent()) {
request.setAttribute("concurrency_limiter_listener", listener.get());
@@ -47,29 +55,36 @@ public class ConcurrencyLimitsHandlerInterceptor implements HandlerInterceptor {
}
try {
//TODO: headers with information?
/*response.sendError(HttpStatus.TOO_MANY_REQUESTS.value());
response.getWriter().print("Concurrency limit exceeded");*/
// TODO: headers with information?
/*
* response.sendError(HttpStatus.TOO_MANY_REQUESTS.value());
* response.getWriter().print("Concurrency limit exceeded");
*/
response.sendError(HttpStatus.TOO_MANY_REQUESTS.value(),
"Concurrency limit exceeded");
} catch (IOException e) {
}
catch (IOException e) {
// ignore
}
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
Listener listener = (Listener) request.getAttribute("concurrency_limiter_listener");
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
Listener listener = (Listener) request
.getAttribute("concurrency_limiter_listener");
if (listener != null) {
if (ex != null) {
listener.onIgnore();
} else {
}
else {
listener.onSuccess();
}
}
@@ -1,19 +1,19 @@
/*
* Copyright 2013-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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.concurrency.limits.web;
import java.util.function.Consumer;
@@ -35,14 +35,22 @@ import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
/**
* MVC autoconfiguration class for registering Netflix {@link Limiter} bean.
*
* @author Spencer Gibb
* @deprecated to be removed in 3.0.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({HttpServletRequest.class, HandlerInterceptor.class})
@ConditionalOnClass({ HttpServletRequest.class, HandlerInterceptor.class })
@Deprecated
public class MvcConcurrencyLimitsAutoConfiguration implements WebMvcConfigurer {
private final ObjectProvider<Consumer<ServletLimiterBuilder>> configurerProvider;
public MvcConcurrencyLimitsAutoConfiguration(ObjectProvider<Consumer<ServletLimiterBuilder>> configurerProvider) {
public MvcConcurrencyLimitsAutoConfiguration(
ObjectProvider<Consumer<ServletLimiterBuilder>> configurerProvider) {
this.configurerProvider = configurerProvider;
}
@@ -56,16 +64,17 @@ public class MvcConcurrencyLimitsAutoConfiguration implements WebMvcConfigurer {
return builder.build();
}
@Configuration
@Configuration(proxyBeanMethods = false)
protected static class HandlerInterceptorConfiguration implements WebMvcConfigurer {
@Autowired
private Limiter<HttpServletRequest> limiter;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new ConcurrencyLimitsHandlerInterceptor(limiter));
}
}
}
}
@@ -1,18 +1,17 @@
/*
* Copyright 2013-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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.concurrency.limits.micrometer;
@@ -26,6 +25,7 @@ import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class MicrometerMetricRegistryTests {
@Test
public void testGuage() {
MeterRegistry registry = new SimpleMeterRegistry();
@@ -39,7 +39,7 @@ public class MicrometerMetricRegistryTests {
}
@Test
@Ignore //FIXME: micrometer doesn't allow recreating a gauge
@Ignore // FIXME: micrometer doesn't allow recreating a gauge
public void testUnregister() {
MeterRegistry registry = new SimpleMeterRegistry();
MicrometerMetricRegistry metricRegistry = new MicrometerMetricRegistry(registry);
@@ -52,5 +52,5 @@ public class MicrometerMetricRegistryTests {
assertThat(bar.value()).isEqualTo(20.0);
}
}
}
@@ -1,18 +1,17 @@
/*
* Copyright 2013-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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.concurrency.limits.reactive;
@@ -37,7 +36,7 @@ import org.springframework.util.SocketUtils;
import org.springframework.web.reactive.function.client.WebClient;
@RunWith(ModifiedClassPathRunner.class)
@ClassPathExclusions({"spring-boot-starter-tomcat-*", "tomcat-embed-*"})
@ClassPathExclusions({ "spring-boot-starter-tomcat-*", "tomcat-embed-*" })
public class ConcurrencyLimitsWebFilterTests extends AbstractConcurrencyLimitsTests {
private int port;
@@ -45,7 +44,7 @@ public class ConcurrencyLimitsWebFilterTests extends AbstractConcurrencyLimitsTe
@Before
public void init() {
port = SocketUtils.findAvailableTcpPort();
client = WebClient.create("http://localhost:"+port);
client = WebClient.create("http://localhost:" + port);
}
@Test
@@ -53,7 +52,8 @@ public class ConcurrencyLimitsWebFilterTests extends AbstractConcurrencyLimitsTe
public void webFilterWorks() {
try (ConfigurableApplicationContext context = new SpringApplicationBuilder()
.properties("server.port="+port, "spring.main.web-application-type=reactive")
.properties("server.port=" + port,
"spring.main.web-application-type=reactive")
.sources(TestConfig.class).run()) {
assertLimiter(client);
@@ -67,9 +67,9 @@ public class ConcurrencyLimitsWebFilterTests extends AbstractConcurrencyLimitsTe
@Bean
public Consumer<ServerWebExchangeLimiterBuilder> limiterBuilderConfigurer() {
return limiterBuilder -> limiterBuilder
.limit(FixedLimit.of(1));
return limiterBuilder -> limiterBuilder.limit(FixedLimit.of(1));
}
}
}
@@ -1,18 +1,17 @@
/*
* Copyright 2013-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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.concurrency.limits.test;
@@ -39,26 +38,26 @@ public class AbstractConcurrencyLimitsTests {
Flux<Tuple2<String, HttpStatus>> flux = Flux.range(1, 100)
.flatMap(integer -> client.get().uri("/").exchange(), 4)
// .log("reqs", Level.INFO)
.flatMap(response -> response.bodyToMono(String.class)
.defaultIfEmpty("")
/*.log("body2mono", Level.INFO)*/
.flatMap(response -> response.bodyToMono(String.class).defaultIfEmpty("")
/* .log("body2mono", Level.INFO) */
.zipWith(Mono.just(response.statusCode())));
Responses responses = new Responses();
StepVerifier.create(flux)
.thenConsumeWhile(response -> true, response -> {
HttpStatus status = response.getT2();
if (status.equals(HttpStatus.OK)) {
responses.success.incrementAndGet();
} else if (status.equals(HttpStatus.TOO_MANY_REQUESTS)) {
responses.tooManyReqs.incrementAndGet();
String body = response.getT1();
//TODO: body from handler isn't coming thru
// assertThat(body).isEqualTo("Concurrency limit exceeded");
} else {
responses.other.incrementAndGet();
}
}).verifyComplete();
StepVerifier.create(flux).thenConsumeWhile(response -> true, response -> {
HttpStatus status = response.getT2();
if (status.equals(HttpStatus.OK)) {
responses.success.incrementAndGet();
}
else if (status.equals(HttpStatus.TOO_MANY_REQUESTS)) {
responses.tooManyReqs.incrementAndGet();
String body = response.getT1();
// TODO: body from handler isn't coming thru
// assertThat(body).isEqualTo("Concurrency limit exceeded");
}
else {
responses.other.incrementAndGet();
}
}).verifyComplete();
System.out.println("Responses: " + responses);
@@ -67,7 +66,7 @@ public class AbstractConcurrencyLimitsTests {
}
@Configuration
@Configuration(proxyBeanMethods = false)
@RestController
protected static class HelloControllerConfiguration {
@@ -75,5 +74,7 @@ public class AbstractConcurrencyLimitsTests {
public String get() {
return "Hello";
}
}
}
@@ -1,37 +1,37 @@
/*
* Copyright 2013-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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.concurrency.limits.test;
import org.springframework.core.style.ToStringCreator;
import java.util.concurrent.atomic.AtomicInteger;
import org.springframework.core.style.ToStringCreator;
public class Responses {
public AtomicInteger success = new AtomicInteger(0);
public AtomicInteger tooManyReqs = new AtomicInteger(0);
public AtomicInteger other = new AtomicInteger(0);
@Override
public String toString() {
return new ToStringCreator(this)
.append("success", success)
.append("tooManyReqs", tooManyReqs)
.append("other", other)
.toString();
return new ToStringCreator(this).append("success", success)
.append("tooManyReqs", tooManyReqs).append("other", other).toString();
}
}
@@ -1,18 +1,17 @@
/*
* Copyright 2013-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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.concurrency.limits.web;
@@ -38,15 +37,17 @@ 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)
public class ConcurrencyLimitsHandlerInterceptorTests extends AbstractConcurrencyLimitsTests {
@SpringBootTest(properties = "logging.level.reactor.netty=DEBUG",
webEnvironment = RANDOM_PORT)
public class ConcurrencyLimitsHandlerInterceptorTests
extends AbstractConcurrencyLimitsTests {
@LocalServerPort
public int port;
@Before
public void init() {
client = WebClient.create("http://localhost:"+port);
client = WebClient.create("http://localhost:" + port);
}
@Test
@@ -61,9 +62,9 @@ public class ConcurrencyLimitsHandlerInterceptorTests extends AbstractConcurrenc
@Bean
public Consumer<ServletLimiterBuilder> limiterBuilderConfigurer() {
return servletLimiterBuilder -> servletLimiterBuilder
.limit(FixedLimit.of(1));
return servletLimiterBuilder -> servletLimiterBuilder.limit(FixedLimit.of(1));
}
}
}
+2 -2
View File
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
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>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>2.1.0.RC3</version>
<version>2.2.9.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-core</artifactId>
@@ -1,11 +1,11 @@
/*
* Copyright 2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -18,21 +18,25 @@ package org.springframework.cloud.netflix.core;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.Configuration;
/**
* @author Olga Maciaszek-Sharma
* @since 2.1.0
* @deprecated Module spring-cloud-netflix-core is deprecated as of 2.1.0, use spring-cloud-netflix-hystrix instead.
* @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 {
private static final Log LOG = LogFactory.getLog(CoreAutoConfiguration.class);
private static final Log LOG = LogFactory.getLog(CoreAutoConfiguration.class);
public CoreAutoConfiguration() {
LOG.warn(
"This module is deprecated. It will be removed in the next major release. "
+ "Please use spring-cloud-netflix-hystrix instead.");
}
public CoreAutoConfiguration() {
LOG.warn("This module is deprecated. It will be removed in the next major release. " +
"Please use spring-cloud-netflix-hystrix instead.");
}
}
+14 -66
View File
@@ -1,32 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
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>
<parent>
<artifactId>spring-cloud-dependencies-parent</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>2.1.0.RC3</version>
<version>2.3.5.RELEASE</version>
<relativePath/>
</parent>
<artifactId>spring-cloud-netflix-dependencies</artifactId>
<version>2.1.0.RC3</version>
<version>2.2.9.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.6</concurrency-limits.version>
<eureka.version>1.9.8</eureka.version>
<archaius.version>0.7.7</archaius.version>
<concurrency-limits.version>0.1.12</concurrency-limits.version>
<eureka.version>1.10.14</eureka.version>
<eventbus.version>0.3.0</eventbus.version>
<hystrix.version>1.5.18</hystrix.version>
<ribbon.version>2.3.0</ribbon.version>
<servo.version>0.12.21</servo.version>
<zuul.version>1.3.1</zuul.version>
<rxjava.version>1.2.0</rxjava.version>
<rxjava-reactive-streams.version>1.2.1</rxjava-reactive-streams.version>
<turbine.version>1.0.0</turbine.version>
<eureka-jersey.version>1.19.1</eureka-jersey.version>
<xstream.version>1.4.10</xstream.version>
<okhttp3.version>3.8.1</okhttp3.version>
</properties>
<dependencyManagement>
<dependencies>
@@ -60,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>
@@ -160,32 +151,6 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>${eureka-jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>${eureka-jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>${eureka-jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>${eureka-jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-apache-client4</artifactId>
<version>${eureka-jersey.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.concurrency-limits</groupId>
<artifactId>concurrency-limits-core</artifactId>
@@ -212,6 +177,10 @@
<artifactId>eureka-client</artifactId>
<version>${eureka.version}</version>
<exclusions>
<exclusion>
<groupId>com.github.vlsi.compactmap</groupId>
<artifactId>compactmap</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
@@ -269,12 +238,6 @@
</exclusion>
</exclusions>
</dependency>
<!-- Eureka core dep that is now optional -->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>${xstream.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
@@ -386,16 +349,6 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava</artifactId>
<version>${rxjava.version}</version>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava-reactive-streams</artifactId>
<version>${rxjava-reactive-streams.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.zuul</groupId>
<artifactId>zuul-core</artifactId>
@@ -412,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>
@@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>2.2.9.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-eureka-client-tls-tests</artifactId>
<packaging>jar</packaging>
<name>Spring Cloud Netflix Eureka Client TLS Tests</name>
<description>Spring Cloud Netflix Eureka Client TLS Tests</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.68</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,125 @@
/*
* Copyright 2018-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;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.util.SocketUtils;
public class AppRunner implements AutoCloseable {
private Class<?> appClass;
private Map<String, String> props;
private ConfigurableApplicationContext app;
public AppRunner(Class<?> appClass) {
this.appClass = appClass;
props = new LinkedHashMap<>();
}
public void property(String key, String value) {
props.put(key, value);
}
public void start() {
if (app == null) {
SpringApplicationBuilder builder = new SpringApplicationBuilder(appClass);
builder.properties("spring.jmx.enabled=false");
builder.properties(String.format("server.port=%d", availabeTcpPort()));
builder.properties(props());
app = builder.build().run();
}
}
private int availabeTcpPort() {
return SocketUtils.findAvailableTcpPort();
}
private String[] props() {
List<String> result = new ArrayList<>();
for (String key : props.keySet()) {
String value = props.get(key);
result.add(String.format("%s=%s", key, value));
}
return result.toArray(new String[0]);
}
public void stop() {
if (app != null) {
app.stop();
app = null;
}
}
public ConfigurableApplicationContext app() {
return app;
}
public String getProperty(String key) {
return app.getEnvironment().getProperty(key);
}
public <T> T getBean(Class<T> type) {
return app.getBean(type);
}
public ApplicationContext parent() {
return app.getParent();
}
public <T> Map<String, T> getParentBeans(Class<T> type) {
return parent().getBeansOfType(type);
}
public int port() {
if (app == null) {
throw new RuntimeException("App is not running.");
}
return app.getEnvironment().getProperty("server.port", Integer.class, -1);
}
public String root() {
if (app == null) {
throw new RuntimeException("App is not running.");
}
String protocol = tlsEnabled() ? "https" : "http";
return String.format("%s://localhost:%d/", protocol, port());
}
private boolean tlsEnabled() {
return app.getEnvironment().getProperty("server.ssl.enabled", Boolean.class,
false);
}
@Override
public void close() {
stop();
}
}
@@ -0,0 +1,93 @@
/*
* Copyright 2018-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;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import org.junit.BeforeClass;
public abstract class BaseCertTest {
protected static final String KEY_STORE_PASSWORD = "test-key-store-password";
protected static final String KEY_PASSWORD = "test-key-password";
protected static final String WRONG_PASSWORD = "test-wrong-password";
protected static File caCert;
protected static File wrongCaCert;
protected static File serverCert;
protected static File clientCert;
protected static File wrongClientCert;
protected BaseCertTest() {
}
@BeforeClass
public static void createCertificates() throws Exception {
KeyTool tool = new KeyTool();
KeyAndCert ca = tool.createCA("MyCA");
KeyAndCert server = ca.sign("server");
KeyAndCert client = ca.sign("client");
caCert = saveCert(ca);
serverCert = saveKeyAndCert(server);
clientCert = saveKeyAndCert(client);
KeyAndCert wrongCa = tool.createCA("WrongCA");
KeyAndCert wrongClient = wrongCa.sign("client");
wrongCaCert = saveCert(wrongCa);
wrongClientCert = saveKeyAndCert(wrongClient);
}
private static File saveKeyAndCert(KeyAndCert keyCert) throws Exception {
return saveKeyStore(keyCert.subject(),
() -> keyCert.storeKeyAndCert(KEY_PASSWORD));
}
private static File saveCert(KeyAndCert keyCert) throws Exception {
return saveKeyStore(keyCert.subject(), () -> keyCert.storeCert());
}
private static File saveKeyStore(String prefix, KeyStoreSupplier func)
throws Exception {
File result = File.createTempFile(prefix, ".p12");
result.deleteOnExit();
try (OutputStream output = new FileOutputStream(result)) {
KeyStore store = func.createKeyStore();
store.store(output, KEY_STORE_PASSWORD.toCharArray());
}
return result;
}
interface KeyStoreSupplier {
KeyStore createKeyStore() throws Exception;
}
}
@@ -0,0 +1,99 @@
/*
* Copyright 2018-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;
import java.io.File;
import java.util.function.BooleanSupplier;
import org.springframework.cloud.client.discovery.DiscoveryClient;
public class EurekaClientRunner extends AppRunner {
public EurekaClientRunner(Class<?> appClass, AppRunner server) {
super(appClass);
property("eureka.client.registerWithEureka", "false");
property("eureka.client.fetchRegistry", "true");
property("eureka.client.serviceUrl.defaultZone", server.root() + "eureka/");
property("eureka.client.refresh.enable", "true");
}
public EurekaClientRunner(Class<?> appClass, AppRunner server, String service) {
this(appClass, server);
property("eureka.client.registerWithEureka", "true");
property("spring.application.name", service);
}
public void enableTls() {
property("eureka.client.tls.enabled", "true");
}
public void disableTls() {
property("eureka.client.tls.enabled", "false");
}
public void setKeyStore(File keyStore, String keyStorePassword, String keyPassword) {
property("eureka.client.tls.key-store", pathOf(keyStore));
property("eureka.client.tls.key-store-password", keyStorePassword);
property("eureka.client.tls.key-password", keyPassword);
}
public void setKeyStore(File keyStore) {
property("eureka.client.tls.key-store", pathOf(keyStore));
}
public void setTrustStore(File trustStore, String password) {
property("eureka.client.tls.trust-store", pathOf(trustStore));
property("eureka.client.tls.trust-store-password", password);
}
public void setTrustStore(File trustStore) {
property("eureka.client.tls.trust-store", pathOf(trustStore));
}
private String pathOf(File file) {
return String.format("file:%s", file.getAbsolutePath());
}
public void waitServiceViaEureka(int seconds) {
assertInSeconds(() -> foundServiceViaEureka(), seconds);
}
private void assertInSeconds(BooleanSupplier assertion, int seconds) {
long start = System.currentTimeMillis();
long limit = 1000L * seconds;
long duration = 0;
do {
if (assertion.getAsBoolean()) {
return;
}
duration = System.currentTimeMillis() - start;
Thread.yield();
}
while (duration < limit);
throw new RuntimeException();
}
public boolean foundServiceViaEureka() {
DiscoveryClient discovery = getBean(DiscoveryClient.class);
return !discovery.getServices().isEmpty();
}
}
@@ -0,0 +1,158 @@
/*
* Copyright 2018-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;
import java.io.File;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
import static org.assertj.core.api.Assertions.assertThat;
public class EurekaClientTest extends BaseCertTest {
private static EurekaServerRunner server;
private static EurekaClientRunner service;
@BeforeClass
public static void setupAll() {
startEurekaServer();
startService();
waitForRegistration();
}
@AfterClass
public static void tearDownAll() {
stopService();
stopEurekaServer();
}
private static void startEurekaServer() {
server = new EurekaServerRunner(TestEurekaServer.class);
server.enableTls();
server.setKeyStore(serverCert, KEY_STORE_PASSWORD, "server", KEY_PASSWORD);
server.setTrustStore(caCert, KEY_STORE_PASSWORD);
server.start();
}
private static void stopEurekaServer() {
server.stop();
}
private static void startService() {
service = new EurekaClientRunner(TestApp.class, server, "testservice");
enableTlsClient(service);
service.start();
}
private static void stopService() {
service.stop();
}
private static void waitForRegistration() {
try (EurekaClientRunner client = createEurekaClient()) {
enableTlsClient(client);
client.start();
client.waitServiceViaEureka(60);
}
}
private static EurekaClientRunner createEurekaClient() {
return new EurekaClientRunner(TestApp.class, server);
}
private static void enableTlsClient(EurekaClientRunner runner) {
runner.enableTls();
runner.setKeyStore(clientCert, KEY_STORE_PASSWORD, KEY_PASSWORD);
runner.setTrustStore(caCert, KEY_STORE_PASSWORD);
}
/**
* Already proved this in waitForRegistration(). Keep this Test to express test
* purpose explicitly.
*/
@Test
public void clientCertCanWork() {
}
@Test
public void noCertCannotWork() {
try (EurekaClientRunner client = createEurekaClient()) {
client.disableTls();
client.start();
assertThat(client.foundServiceViaEureka()).isFalse();
}
}
@Test
public void wrongCertCannotWork() {
try (EurekaClientRunner client = createEurekaClient()) {
enableTlsClient(client);
client.setKeyStore(wrongClientCert);
client.start();
assertThat(client.foundServiceViaEureka()).isFalse();
}
}
@Test(expected = BeanCreationException.class)
public void wrongPasswordCauseFailure() {
EurekaClientRunner client = createEurekaClient();
enableTlsClient(client);
client.setKeyStore(clientCert, WRONG_PASSWORD, WRONG_PASSWORD);
client.start();
}
@Test(expected = BeanCreationException.class)
public void nonExistKeyStoreCauseFailure() {
EurekaClientRunner client = createEurekaClient();
enableTlsClient(client);
client.setKeyStore(new File("nonExistFile"));
client.start();
}
@Test
public void wrongTrustStoreCannotWork() {
try (EurekaClientRunner client = createEurekaClient()) {
enableTlsClient(client);
client.setTrustStore(wrongCaCert);
client.start();
assertThat(client.foundServiceViaEureka()).isFalse();
}
}
@SpringBootConfiguration
@EnableAutoConfiguration
public static class TestApp {
}
@SpringBootConfiguration
@EnableAutoConfiguration
@EnableEurekaServer
public static class TestEurekaServer {
}
}
@@ -0,0 +1,56 @@
/*
* Copyright 2018-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;
import java.io.File;
public class EurekaServerRunner extends AppRunner {
public EurekaServerRunner(Class<?> appClass) {
super(appClass);
property("eureka.client.registerWithEureka", "false");
property("eureka.client.fetchRegistry", "false");
property("eureka.server.waitTimeInMsWhenSyncEmpty", "0");
property("eureka.client.refresh.enable", "true");
}
public void enableTls() {
property("server.ssl.enabled", "true");
property("server.ssl.client-auth", "need");
}
public void setKeyStore(File keyStore, String keyStorePassword, String key,
String keyPassword) {
property("server.ssl.key-store", pathOf(keyStore));
property("server.ssl.key-store-type", "PKCS12");
property("server.ssl.key-store-password", keyStorePassword);
property("server.ssl.key-alias", key);
property("server.ssl.key-password", keyPassword);
}
public void setTrustStore(File trustStore, String password) {
property("server.ssl.trust-store", pathOf(trustStore));
property("server.ssl.trust-store-type", "PKCS12");
property("server.ssl.trust-store-password", password);
}
private String pathOf(File file) {
return String.format("file:%s", file.getAbsolutePath());
}
}
@@ -0,0 +1,94 @@
/*
* Copyright 2018-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;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
public class KeyAndCert {
private KeyPair keyPair;
private X509Certificate certificate;
public KeyAndCert(KeyPair keyPair, X509Certificate certificate) {
this.keyPair = keyPair;
this.certificate = certificate;
}
public KeyPair keyPair() {
return keyPair;
}
public PublicKey publicKey() {
return keyPair.getPublic();
}
public PrivateKey privateKey() {
return keyPair.getPrivate();
}
public X509Certificate certificate() {
return certificate;
}
public String subject() {
String dn = certificate.getSubjectDN().getName();
int index = dn.indexOf('=');
return dn.substring(index + 1);
}
public KeyAndCert sign(String subject) throws Exception {
KeyTool tool = new KeyTool();
return tool.signCertificate(subject, this);
}
public KeyAndCert sign(KeyPair keyPair, String subject) throws Exception {
KeyTool tool = new KeyTool();
return tool.signCertificate(keyPair, subject, this);
}
public KeyStore storeKeyAndCert(String keyPassword) throws Exception {
KeyStore result = KeyStore.getInstance("PKCS12");
result.load(null);
result.setKeyEntry(subject(), keyPair.getPrivate(), keyPassword.toCharArray(),
certChain());
return result;
}
private Certificate[] certChain() {
return new Certificate[] { certificate() };
}
public KeyStore storeCert() throws Exception {
return storeCert("PKCS12");
}
public KeyStore storeCert(String storeType) throws Exception {
KeyStore result = KeyStore.getInstance(storeType);
result.load(null);
result.setCertificateEntry(subject(), certificate());
return result;
}
}
@@ -0,0 +1,126 @@
/*
* Copyright 2018-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;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Date;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
public class KeyTool {
private static final long ONE_DAY = 1000L * 60L * 60L * 24L;
private static final long TEN_YEARS = ONE_DAY * 365L * 10L;
public KeyAndCert createCA(String ca) throws Exception {
KeyPair keyPair = createKeyPair();
X509Certificate certificate = createCert(keyPair, ca);
return new KeyAndCert(keyPair, certificate);
}
public KeyAndCert signCertificate(String subject, KeyAndCert signer)
throws Exception {
return signCertificate(createKeyPair(), subject, signer);
}
public KeyAndCert signCertificate(KeyPair keyPair, String subject, KeyAndCert signer)
throws Exception {
X509Certificate certificate = createCert(keyPair.getPublic(), signer.privateKey(),
signer.subject(), subject);
KeyAndCert result = new KeyAndCert(keyPair, certificate);
return result;
}
public KeyPair createKeyPair() throws Exception {
return createKeyPair(1024);
}
public KeyPair createKeyPair(int keySize) throws Exception {
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
gen.initialize(keySize, new SecureRandom());
return gen.generateKeyPair();
}
public X509Certificate createCert(KeyPair keyPair, String ca) throws Exception {
JcaX509v3CertificateBuilder builder = certBuilder(keyPair.getPublic(), ca, ca);
builder.addExtension(Extension.keyUsage, true,
new KeyUsage(KeyUsage.keyCertSign));
builder.addExtension(Extension.basicConstraints, false,
new BasicConstraints(true));
return signCert(builder, keyPair.getPrivate());
}
public X509Certificate createCert(PublicKey publicKey, PrivateKey privateKey,
String issuer, String subject) throws Exception {
JcaX509v3CertificateBuilder builder = certBuilder(publicKey, issuer, subject);
builder.addExtension(Extension.keyUsage, true,
new KeyUsage(KeyUsage.digitalSignature));
builder.addExtension(Extension.basicConstraints, false,
new BasicConstraints(false));
GeneralName[] names = new GeneralName[] {
new GeneralName(GeneralName.dNSName, "localhost") };
builder.addExtension(Extension.subjectAlternativeName, false,
GeneralNames.getInstance(new DERSequence(names)));
return signCert(builder, privateKey);
}
private JcaX509v3CertificateBuilder certBuilder(PublicKey publicKey, String issuer,
String subject) {
X500Name issuerName = new X500Name(String.format("dc=%s", issuer));
X500Name subjectName = new X500Name(String.format("dc=%s", subject));
long now = System.currentTimeMillis();
BigInteger serialNum = BigInteger.valueOf(now);
Date notBefore = new Date(now - ONE_DAY);
Date notAfter = new Date(now + TEN_YEARS);
return new JcaX509v3CertificateBuilder(issuerName, serialNum, notBefore, notAfter,
subjectName, publicKey);
}
private X509Certificate signCert(JcaX509v3CertificateBuilder builder,
PrivateKey privateKey) throws Exception {
ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA")
.build(privateKey);
X509CertificateHolder holder = builder.build(signer);
return new JcaX509CertificateConverter().getCertificate(holder);
}
}
+22 -7
View File
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
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>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>2.1.0.RC3</version>
<version>2.2.9.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>
@@ -62,11 +72,6 @@
<optional>true</optional>
</dependency>
<!-- Eureka core deps that are now optional -->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-apache-client4</artifactId>
@@ -82,6 +87,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 +137,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,11 +1,11 @@
/*
* Copyright 2013-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -20,13 +20,6 @@ import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpStatus;
import org.springframework.util.ReflectionUtils;
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
@@ -35,35 +28,47 @@ import com.netflix.discovery.DiscoveryClient;
import com.netflix.discovery.EurekaClientConfig;
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.cloud.client.discovery.event.HeartbeatEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpStatus;
import org.springframework.util.ReflectionUtils;
/**
* Subclass of {@link DiscoveryClient} that sends a {@link HeartbeatEvent} when
* {@link CloudEurekaClient#onCacheRefreshed()} is called.
*
* @author Spencer Gibb
*/
public class CloudEurekaClient extends DiscoveryClient {
private static final Log log = LogFactory.getLog(CloudEurekaClient.class);
private final AtomicLong cacheRefreshedCount = new AtomicLong(0);
private ApplicationEventPublisher publisher;
private Field eurekaTransportField;
private ApplicationInfoManager applicationInfoManager;
private AtomicReference<EurekaHttpClient> eurekaHttpClient = new AtomicReference<>();
public CloudEurekaClient(ApplicationInfoManager applicationInfoManager,
EurekaClientConfig config, ApplicationEventPublisher publisher) {
EurekaClientConfig config, ApplicationEventPublisher publisher) {
this(applicationInfoManager, config, null, publisher);
}
public CloudEurekaClient(ApplicationInfoManager applicationInfoManager,
EurekaClientConfig config,
AbstractDiscoveryClientOptionalArgs<?> args,
ApplicationEventPublisher publisher) {
EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs<?> args,
ApplicationEventPublisher publisher) {
super(applicationInfoManager, config, args);
this.applicationInfoManager = applicationInfoManager;
this.publisher = publisher;
this.eurekaTransportField = ReflectionUtils.findField(DiscoveryClient.class, "eurekaTransport");
this.eurekaTransportField = ReflectionUtils.findField(DiscoveryClient.class,
"eurekaTransport");
ReflectionUtils.makeAccessible(this.eurekaTransportField);
}
@@ -76,7 +81,8 @@ public class CloudEurekaClient extends DiscoveryClient {
}
public InstanceInfo getInstanceInfo(String appname, String instanceId) {
EurekaHttpResponse<InstanceInfo> response = getEurekaHttpClient().getInstance(appname, instanceId);
EurekaHttpResponse<InstanceInfo> response = getEurekaHttpClient()
.getInstance(appname, instanceId);
HttpStatus httpStatus = HttpStatus.valueOf(response.getStatusCode());
if (httpStatus.is2xxSuccessful() && response.getEntity() != null) {
return response.getEntity();
@@ -88,10 +94,13 @@ public class CloudEurekaClient extends DiscoveryClient {
if (this.eurekaHttpClient.get() == null) {
try {
Object eurekaTransport = this.eurekaTransportField.get(this);
Field registrationClientField = ReflectionUtils.findField(eurekaTransport.getClass(), "registrationClient");
Field registrationClientField = ReflectionUtils
.findField(eurekaTransport.getClass(), "registrationClient");
ReflectionUtils.makeAccessible(registrationClientField);
this.eurekaHttpClient.compareAndSet(null, (EurekaHttpClient) registrationClientField.get(eurekaTransport));
} catch (IllegalAccessException e) {
this.eurekaHttpClient.compareAndSet(null,
(EurekaHttpClient) registrationClientField.get(eurekaTransport));
}
catch (IllegalAccessException e) {
log.error("error getting EurekaHttpClient", e);
}
}
@@ -99,17 +108,20 @@ public class CloudEurekaClient extends DiscoveryClient {
}
public void setStatus(InstanceStatus newStatus, InstanceInfo info) {
getEurekaHttpClient().statusUpdate(info.getAppName(), info.getId(), newStatus, info);
getEurekaHttpClient().statusUpdate(info.getAppName(), info.getId(), newStatus,
info);
}
@Override
protected void onCacheRefreshed() {
super.onCacheRefreshed();
if (this.cacheRefreshedCount != null) { //might be called during construction and will be null
if (this.cacheRefreshedCount != null) { // might be called during construction and
// will be null
long newCount = this.cacheRefreshedCount.incrementAndGet();
log.trace("onCacheRefreshed called with count: " + newCount);
this.publisher.publishEvent(new HeartbeatEvent(this, newCount));
}
}
}
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -23,7 +23,11 @@ import com.netflix.appinfo.InstanceInfo;
* @author Spencer Gibb
*/
public interface CloudEurekaInstanceConfig extends EurekaInstanceConfig {
void setNonSecurePort(int port);
void setSecurePort(int securePort);
InstanceInfo.InstanceStatus getInitialStatus();
}
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,10 +16,10 @@
package org.springframework.cloud.netflix.eureka;
import com.netflix.discovery.shared.transport.EurekaTransportConfig;
import java.util.Objects;
import com.netflix.discovery.shared.transport.EurekaTransportConfig;
/**
* @author Spencer Gibb
* @author Gregor Zurowski
@@ -162,21 +162,27 @@ public class CloudEurekaTransportConfig implements EurekaTransportConfig {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
CloudEurekaTransportConfig that = (CloudEurekaTransportConfig) o;
return sessionedClientReconnectIntervalSeconds == that.sessionedClientReconnectIntervalSeconds &&
Double.compare(retryableClientQuarantineRefreshPercentage, that.retryableClientQuarantineRefreshPercentage) == 0 &&
bootstrapResolverRefreshIntervalSeconds == that.bootstrapResolverRefreshIntervalSeconds &&
applicationsResolverDataStalenessThresholdSeconds == that.applicationsResolverDataStalenessThresholdSeconds &&
asyncResolverRefreshIntervalMs == that.asyncResolverRefreshIntervalMs &&
asyncResolverWarmUpTimeoutMs == that.asyncResolverWarmUpTimeoutMs &&
asyncExecutorThreadPoolSize == that.asyncExecutorThreadPoolSize &&
Objects.equals(readClusterVip, that.readClusterVip) &&
Objects.equals(writeClusterVip, that.writeClusterVip) &&
bootstrapResolverForQuery == that.bootstrapResolverForQuery &&
Objects.equals(bootstrapResolverStrategy, that.bootstrapResolverStrategy) &&
applicationsResolverUseIp == that.applicationsResolverUseIp;
return sessionedClientReconnectIntervalSeconds == that.sessionedClientReconnectIntervalSeconds
&& Double.compare(retryableClientQuarantineRefreshPercentage,
that.retryableClientQuarantineRefreshPercentage) == 0
&& bootstrapResolverRefreshIntervalSeconds == that.bootstrapResolverRefreshIntervalSeconds
&& applicationsResolverDataStalenessThresholdSeconds == that.applicationsResolverDataStalenessThresholdSeconds
&& asyncResolverRefreshIntervalMs == that.asyncResolverRefreshIntervalMs
&& asyncResolverWarmUpTimeoutMs == that.asyncResolverWarmUpTimeoutMs
&& asyncExecutorThreadPoolSize == that.asyncExecutorThreadPoolSize
&& Objects.equals(readClusterVip, that.readClusterVip)
&& Objects.equals(writeClusterVip, that.writeClusterVip)
&& bootstrapResolverForQuery == that.bootstrapResolverForQuery
&& Objects.equals(bootstrapResolverStrategy,
that.bootstrapResolverStrategy)
&& applicationsResolverUseIp == that.applicationsResolverUseIp;
}
@Override
@@ -194,18 +200,27 @@ public class CloudEurekaTransportConfig implements EurekaTransportConfig {
@Override
public String toString() {
return new StringBuilder("CloudEurekaTransportConfig{")
.append("sessionedClientReconnectIntervalSeconds=").append(sessionedClientReconnectIntervalSeconds).append(", ")
.append("retryableClientQuarantineRefreshPercentage=").append(retryableClientQuarantineRefreshPercentage).append(", ")
.append("bootstrapResolverRefreshIntervalSeconds=").append(bootstrapResolverRefreshIntervalSeconds).append(", ")
.append("applicationsResolverDataStalenessThresholdSeconds=").append(applicationsResolverDataStalenessThresholdSeconds).append(", ")
.append("asyncResolverRefreshIntervalMs=").append(asyncResolverRefreshIntervalMs).append(", ")
.append("asyncResolverWarmUpTimeoutMs=").append(asyncResolverWarmUpTimeoutMs).append(", ")
.append("asyncExecutorThreadPoolSize=").append(asyncExecutorThreadPoolSize).append(", ")
.append("sessionedClientReconnectIntervalSeconds=")
.append(sessionedClientReconnectIntervalSeconds).append(", ")
.append("retryableClientQuarantineRefreshPercentage=")
.append(retryableClientQuarantineRefreshPercentage).append(", ")
.append("bootstrapResolverRefreshIntervalSeconds=")
.append(bootstrapResolverRefreshIntervalSeconds).append(", ")
.append("applicationsResolverDataStalenessThresholdSeconds=")
.append(applicationsResolverDataStalenessThresholdSeconds).append(", ")
.append("asyncResolverRefreshIntervalMs=")
.append(asyncResolverRefreshIntervalMs).append(", ")
.append("asyncResolverWarmUpTimeoutMs=")
.append(asyncResolverWarmUpTimeoutMs).append(", ")
.append("asyncExecutorThreadPoolSize=")
.append(asyncExecutorThreadPoolSize).append(", ")
.append("readClusterVip='").append(readClusterVip).append("', ")
.append("writeClusterVip='").append(writeClusterVip).append("', ")
.append("bootstrapResolverForQuery=").append(bootstrapResolverForQuery).append(", ")
.append("bootstrapResolverStrategy='").append(bootstrapResolverStrategy).append("', ")
.append("applicationsResolverUseIp=").append(applicationsResolverUseIp).append(", ").append("}")
.toString();
.append("bootstrapResolverForQuery=").append(bootstrapResolverForQuery)
.append(", ").append("bootstrapResolverStrategy='")
.append(bootstrapResolverStrategy).append("', ")
.append("applicationsResolverUseIp=").append(applicationsResolverUseIp)
.append(", ").append("}").toString();
}
}
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -1,11 +1,11 @@
/*
* Copyright 2013-2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -23,6 +23,14 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Map;
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaClientConfig;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
@@ -40,14 +48,13 @@ import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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;
@@ -59,19 +66,10 @@ 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;
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaClientConfig;
import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceId;
/**
@@ -81,18 +79,21 @@ import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceI
* @author Matt Jenkins
* @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.autoconfigure.RefreshAutoConfiguration",
@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"})
"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration" })
public class EurekaClientAutoConfiguration {
private ConfigurableEnvironment env;
@@ -107,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
@@ -129,20 +125,26 @@ 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) {
ManagementMetadataProvider managementMetadataProvider) {
String hostname = getProperty("eureka.instance.hostname");
boolean preferIpAddress = Boolean.parseBoolean(getProperty("eureka.instance.prefer-ip-address"));
boolean preferIpAddress = Boolean
.parseBoolean(getProperty("eureka.instance.prefer-ip-address"));
String ipAddress = getProperty("eureka.instance.ip-address");
boolean isSecurePortEnabled = Boolean.parseBoolean(getProperty("eureka.instance.secure-port-enabled"));
boolean isSecurePortEnabled = Boolean
.parseBoolean(getProperty("eureka.instance.secure-port-enabled"));
String serverContextPath = env.getProperty("server.context-path", "/");
int serverPort = Integer.valueOf(env.getProperty("server.port", env.getProperty("port", "8080")));
String serverContextPath = env.getProperty("server.servlet.context-path", "/");
int serverPort = Integer.parseInt(
env.getProperty("server.port", env.getProperty("port", "8080")));
Integer managementPort = env.getProperty("management.server.port", Integer.class);// nullable. should be wrapped into optional
String managementContextPath = env.getProperty("management.server.servlet.context-path");// nullable. should be wrapped into optional
Integer jmxPort = env.getProperty("com.sun.management.jmxremote.port", Integer.class);//nullable
Integer managementPort = env.getProperty("management.server.port", Integer.class);
String managementContextPath = env
.getProperty("management.server.servlet.context-path");
Integer jmxPort = env.getProperty("com.sun.management.jmxremote.port",
Integer.class);
EurekaInstanceConfigBean instance = new EurekaInstanceConfigBean(inetUtils);
instance.setNonSecurePort(serverPort);
@@ -153,7 +155,7 @@ public class EurekaClientAutoConfiguration {
instance.setIpAddress(ipAddress);
}
if(isSecurePortEnabled) {
if (isSecurePortEnabled) {
instance.setSecurePort(serverPort);
}
@@ -173,23 +175,25 @@ public class EurekaClientAutoConfiguration {
ManagementMetadata metadata = managementMetadataProvider.get(instance, serverPort,
serverContextPath, managementContextPath, managementPort);
if(metadata != null) {
if (metadata != null) {
instance.setStatusPageUrl(metadata.getStatusPageUrl());
instance.setHealthCheckUrl(metadata.getHealthCheckUrl());
if(instance.isSecurePortEnabled()) {
if (instance.isSecurePortEnabled()) {
instance.setSecureHealthCheckUrl(metadata.getSecureHealthCheckUrl());
}
Map<String, String> metadataMap = instance.getMetadataMap();
if (metadataMap.get("management.port") == null) {
metadataMap.put("management.port", String.valueOf(metadata.getManagementPort()));
}
} else {
//without the metadata the status and health check URLs will not be set
//and the status page and health check url paths will not include the
//context path so set them here
if(StringUtils.hasText(managementContextPath)) {
instance.setHealthCheckUrlPath(managementContextPath + instance.getHealthCheckUrlPath());
instance.setStatusPageUrlPath(managementContextPath + instance.getStatusPageUrlPath());
metadataMap.computeIfAbsent("management.port",
k -> String.valueOf(metadata.getManagementPort()));
}
else {
// without the metadata the status and health check URLs will not be set
// and the status page and health check url paths will not include the
// context path so set them here
if (StringUtils.hasText(managementContextPath)) {
instance.setHealthCheckUrlPath(
managementContextPath + instance.getHealthCheckUrlPath());
instance.setStatusPageUrlPath(
managementContextPath + instance.getStatusPageUrlPath());
}
}
@@ -204,36 +208,37 @@ public class EurekaClientAutoConfiguration {
}
}
@Bean
public DiscoveryClient discoveryClient(EurekaClient client, EurekaClientConfig clientConfig) {
return new EurekaDiscoveryClient(client, clientConfig);
}
@Bean
public EurekaServiceRegistry eurekaServiceRegistry() {
return new EurekaServiceRegistry();
}
// @Bean
// @ConditionalOnBean(AutoServiceRegistrationProperties.class)
// @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
// public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient, CloudEurekaInstanceConfig instanceConfig, ApplicationInfoManager applicationInfoManager, ObjectProvider<HealthCheckHandler> healthCheckHandler) {
// return EurekaRegistration.builder(instanceConfig)
// .with(applicationInfoManager)
// .with(eurekaClient)
// .with(healthCheckHandler)
// .build();
// }
// @Bean
// @ConditionalOnBean(AutoServiceRegistrationProperties.class)
// @ConditionalOnProperty(value =
// "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
// public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient,
// CloudEurekaInstanceConfig instanceConfig, ApplicationInfoManager
// applicationInfoManager, ObjectProvider<HealthCheckHandler> healthCheckHandler) {
// return EurekaRegistration.builder(instanceConfig)
// .with(applicationInfoManager)
// .with(eurekaClient)
// .with(healthCheckHandler)
// .build();
// }
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry registry,
EurekaRegistration registration) {
@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 {
@@ -244,14 +249,17 @@ public class EurekaClientAutoConfiguration {
private AbstractDiscoveryClientOptionalArgs<?> optionalArgs;
@Bean(destroyMethod = "shutdown")
@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config) {
@ConditionalOnMissingBean(value = EurekaClient.class,
search = SearchStrategy.CURRENT)
public EurekaClient eurekaClient(ApplicationInfoManager manager,
EurekaClientConfig config) {
return new CloudEurekaClient(manager, config, this.optionalArgs,
this.context);
}
@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);
@@ -260,20 +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) {
return EurekaRegistration.builder(instanceConfig)
.with(applicationInfoManager)
.with(eurekaClient)
.with(healthCheckHandler)
.build();
CloudEurekaInstanceConfig instanceConfig,
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 {
@@ -284,32 +292,40 @@ 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, EurekaClientConfig config, EurekaInstanceConfig instance,
@Autowired(required = false) HealthCheckHandler healthCheckHandler) {
//If we use the proxy of the ApplicationInfoManager we could run into a problem
//when shutdown is called on the CloudEurekaClient where the ApplicationInfoManager bean is
//requested but wont be allowed because we are shutting down. To avoid this we use the
//object directly.
public EurekaClient eurekaClient(ApplicationInfoManager manager,
EurekaClientConfig config, EurekaInstanceConfig instance,
@Autowired(required = false) HealthCheckHandler healthCheckHandler) {
// If we use the proxy of the ApplicationInfoManager we could run into a
// problem
// when shutdown is called on the CloudEurekaClient where the
// ApplicationInfoManager bean is
// requested but wont be allowed because we are shutting down. To avoid this
// we use the
// object directly.
ApplicationInfoManager appManager;
if(AopUtils.isAopProxy(manager)) {
if (AopUtils.isAopProxy(manager)) {
appManager = ProxyUtils.getTargetObject(manager);
} else {
}
else {
appManager = manager;
}
CloudEurekaClient cloudEurekaClient = new CloudEurekaClient(appManager, config, this.optionalArgs,
this.context);
CloudEurekaClient cloudEurekaClient = new CloudEurekaClient(appManager,
config, this.optionalArgs, this.context);
cloudEurekaClient.registerHealthCheck(healthCheckHandler);
return cloudEurekaClient;
}
@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(EurekaInstanceConfig config) {
public ApplicationInfoManager eurekaApplicationInfoManager(
EurekaInstanceConfig config) {
InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);
return new ApplicationInfoManager(config, instanceInfo);
}
@@ -317,16 +333,15 @@ 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) {
return EurekaRegistration.builder(instanceConfig)
.with(applicationInfoManager)
.with(eurekaClient)
.with(healthCheckHandler)
.build();
CloudEurekaInstanceConfig instanceConfig,
ApplicationInfoManager applicationInfoManager, @Autowired(
required = false) ObjectProvider<HealthCheckHandler> healthCheckHandler) {
return EurekaRegistration.builder(instanceConfig).with(applicationInfoManager)
.with(eurekaClient).with(healthCheckHandler).build();
}
}
@@ -344,35 +359,48 @@ public class EurekaClientAutoConfiguration {
@Documented
@ConditionalOnClass(RefreshScope.class)
@ConditionalOnBean(RefreshAutoConfiguration.class)
@ConditionalOnProperty(value = "eureka.client.refresh.enable", havingValue = "true",
matchIfMissing = true)
@interface ConditionalOnRefreshScope {
}
private static class OnMissingRefreshScopeCondition extends AnyNestedCondition {
public OnMissingRefreshScopeCondition() {
OnMissingRefreshScopeCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnMissingClass("org.springframework.cloud.context.scope.refresh.RefreshScope")
static class MissingClass {
}
@ConditionalOnMissingBean(RefreshAutoConfiguration.class)
static class MissingScope {
}
@ConditionalOnProperty(value = "eureka.client.refresh.enable",
havingValue = "false")
static class OnPropertyDisabled {
}
}
@Configuration
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Health.class)
protected static class EurekaHealthIndicatorConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledHealthIndicator("eureka")
public EurekaHealthIndicator eurekaHealthIndicator(EurekaClient eurekaClient,
EurekaInstanceConfig instanceConfig, EurekaClientConfig clientConfig) {
EurekaInstanceConfig instanceConfig, EurekaClientConfig clientConfig) {
return new EurekaHealthIndicator(eurekaClient, instanceConfig, clientConfig);
}
}
}
@@ -1,18 +1,18 @@
/*
* Copyright 2013-2014 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
*
* http://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.
*/
* 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;
@@ -36,17 +36,28 @@ import org.springframework.util.StringUtils;
import static org.springframework.cloud.netflix.eureka.EurekaConstants.DEFAULT_PREFIX;
/**
* Eureka client configuration bean.
*
* @author Dave Syer
* @author Gregor Zurowski
*/
@ConfigurationProperties(EurekaClientConfigBean.PREFIX)
public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
/**
* Default prefix for Eureka client config properties.
*/
public static final String PREFIX = "eureka.client";
/**
* Default Eureka URL.
*/
public static final String DEFAULT_URL = "http://localhost:8761" + DEFAULT_PREFIX
+ "/";
/**
* Default availability zone if none is resolved based on region.
*/
public static final String DEFAULT_ZONE = "defaultZone";
private static final int MINUTES = 60;
@@ -76,7 +87,7 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
/**
* Indicates how long initially (in seconds) to replicate instance info to the eureka
* server
* server.
*/
private int initialInstanceInfoReplicationIntervalSeconds = 40;
@@ -191,7 +202,7 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
*
* 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
* the connection hanging in limbo.
*/
private int eurekaConnectionIdleTimeoutSeconds = 30;
@@ -202,7 +213,7 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
private String registryRefreshSingleVipAddress;
/**
* The thread pool size for the heartbeatExecutor to initialise with
* The thread pool size for the heartbeatExecutor to initialise with.
*/
private int heartbeatExecutorThreadPoolSize = 2;
@@ -213,7 +224,7 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
private int heartbeatExecutorExponentialBackOffBound = 10;
/**
* The thread pool size for the cacheRefreshExecutor to initialise with
* The thread pool size for the cacheRefreshExecutor to initialise with.
*/
private int cacheRefreshExecutorThreadPoolSize = 2;
@@ -230,7 +241,7 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
*
* Typically the eureka server URLs carry protocol,host,port,context and version
* information if any. Example:
* http://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/
* https://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/
*
* The changes are effective at runtime at the next service url refresh cycle as
* specified by eurekaServiceUrlPollIntervalSeconds.
@@ -349,8 +360,8 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
private String dollarReplacement = "_-";
/**
* Get a replacement string for underscore sign <code>_</code> during
* serializing/deserializing information in eureka server.
* Get a replacement string for underscore sign <code>_</code> during serializing/
* deserializing information in eureka server.
*/
private String escapeCharReplacement = "__";
@@ -363,40 +374,42 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
/**
* If set to true, local status updates via ApplicationInfoManager will trigger
* on-demand (but rate limited) register/updates to remote eureka servers
* on-demand (but rate limited) register/updates to remote eureka servers.
*/
private boolean onDemandUpdateStatusChange = true;
/**
* This is a transient config and once the latest codecs are stable, can be removed
* (as there will only be one)
* (as there will only be one).
*/
private String encoderName;
/**
* This is a transient config and once the latest codecs are stable, can be removed
* (as there will only be one)
* (as there will only be one).
*/
private String decoderName;
/**
* EurekaAccept name for client data accept
* EurekaAccept name for client data accept.
*/
private String clientDataAccept = EurekaAccept.full.name();
/**
* Indicates whether the client should explicitly unregister itself from the remote server
* on client shutdown.
* Indicates whether the client should explicitly unregister itself from the remote
* server on client shutdown.
*/
private boolean shouldUnregisterOnShutdown = true;
/**
* Indicates whether the client should enforce registration during initialization. Defaults to false.
* Indicates whether the client should enforce registration during initialization.
* Defaults to false.
*/
private boolean shouldEnforceRegistrationAtInit = false;
/**
* Order of the discovery client used by `CompositeDiscoveryClient` for sorting available clients.
* Order of the discovery client used by `CompositeDiscoveryClient` for sorting
* available clients.
*/
private int order = 0;
@@ -461,7 +474,8 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
serviceUrls = this.serviceUrl.get(DEFAULT_ZONE);
}
if (!StringUtils.isEmpty(serviceUrls)) {
final String[] serviceUrlsSplit = StringUtils.commaDelimitedListToStringArray(serviceUrls);
final String[] serviceUrlsSplit = StringUtils
.commaDelimitedListToStringArray(serviceUrls);
List<String> eurekaServiceUrls = new ArrayList<>(serviceUrlsSplit.length);
for (String eurekaServiceUrl : serviceUrlsSplit) {
if (!endsWithSlash(eurekaServiceUrl)) {
@@ -915,7 +929,8 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
return shouldEnforceRegistrationAtInit;
}
public void setShouldEnforceRegistrationAtInit(boolean shouldEnforceRegistrationAtInit) {
public void setShouldEnforceRegistrationAtInit(
boolean shouldEnforceRegistrationAtInit) {
this.shouldEnforceRegistrationAtInit = shouldEnforceRegistrationAtInit;
}
@@ -930,56 +945,60 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
EurekaClientConfigBean that = (EurekaClientConfigBean) o;
return Objects.equals(propertyResolver, that.propertyResolver) &&
enabled == that.enabled &&
Objects.equals(transport, that.transport) &&
registryFetchIntervalSeconds == that.registryFetchIntervalSeconds &&
instanceInfoReplicationIntervalSeconds == that.instanceInfoReplicationIntervalSeconds &&
initialInstanceInfoReplicationIntervalSeconds == that.initialInstanceInfoReplicationIntervalSeconds &&
eurekaServiceUrlPollIntervalSeconds == that.eurekaServiceUrlPollIntervalSeconds &&
eurekaServerReadTimeoutSeconds == that.eurekaServerReadTimeoutSeconds &&
eurekaServerConnectTimeoutSeconds == that.eurekaServerConnectTimeoutSeconds &&
eurekaServerTotalConnections == that.eurekaServerTotalConnections &&
eurekaServerTotalConnectionsPerHost == that.eurekaServerTotalConnectionsPerHost &&
eurekaConnectionIdleTimeoutSeconds == that.eurekaConnectionIdleTimeoutSeconds &&
heartbeatExecutorThreadPoolSize == that.heartbeatExecutorThreadPoolSize &&
heartbeatExecutorExponentialBackOffBound == that.heartbeatExecutorExponentialBackOffBound &&
cacheRefreshExecutorThreadPoolSize == that.cacheRefreshExecutorThreadPoolSize &&
cacheRefreshExecutorExponentialBackOffBound == that.cacheRefreshExecutorExponentialBackOffBound &&
gZipContent == that.gZipContent &&
useDnsForFetchingServiceUrls == that.useDnsForFetchingServiceUrls &&
registerWithEureka == that.registerWithEureka &&
preferSameZoneEureka == that.preferSameZoneEureka &&
logDeltaDiff == that.logDeltaDiff &&
disableDelta == that.disableDelta &&
filterOnlyUpInstances == that.filterOnlyUpInstances &&
fetchRegistry == that.fetchRegistry &&
allowRedirects == that.allowRedirects &&
onDemandUpdateStatusChange == that.onDemandUpdateStatusChange &&
shouldUnregisterOnShutdown == that.shouldUnregisterOnShutdown &&
shouldEnforceRegistrationAtInit == that.shouldEnforceRegistrationAtInit &&
Objects.equals(proxyPort, that.proxyPort) &&
Objects.equals(proxyHost, that.proxyHost) &&
Objects.equals(proxyUserName, that.proxyUserName) &&
Objects.equals(proxyPassword, that.proxyPassword) &&
Objects.equals(backupRegistryImpl, that.backupRegistryImpl) &&
Objects.equals(eurekaServerURLContext, that.eurekaServerURLContext) &&
Objects.equals(eurekaServerPort, that.eurekaServerPort) &&
Objects.equals(eurekaServerDNSName, that.eurekaServerDNSName) &&
Objects.equals(region, that.region) &&
Objects.equals(registryRefreshSingleVipAddress, that.registryRefreshSingleVipAddress) &&
Objects.equals(serviceUrl, that.serviceUrl) &&
Objects.equals(fetchRemoteRegionsRegistry, that.fetchRemoteRegionsRegistry) &&
Objects.equals(availabilityZones, that.availabilityZones) &&
Objects.equals(dollarReplacement, that.dollarReplacement) &&
Objects.equals(escapeCharReplacement, that.escapeCharReplacement) &&
Objects.equals(encoderName, that.encoderName) &&
Objects.equals(decoderName, that.decoderName) &&
Objects.equals(clientDataAccept, that.clientDataAccept) &&
Objects.equals(order, that.order);
return Objects.equals(propertyResolver, that.propertyResolver)
&& enabled == that.enabled && Objects.equals(transport, that.transport)
&& registryFetchIntervalSeconds == that.registryFetchIntervalSeconds
&& instanceInfoReplicationIntervalSeconds == that.instanceInfoReplicationIntervalSeconds
&& initialInstanceInfoReplicationIntervalSeconds == that.initialInstanceInfoReplicationIntervalSeconds
&& eurekaServiceUrlPollIntervalSeconds == that.eurekaServiceUrlPollIntervalSeconds
&& eurekaServerReadTimeoutSeconds == that.eurekaServerReadTimeoutSeconds
&& eurekaServerConnectTimeoutSeconds == that.eurekaServerConnectTimeoutSeconds
&& eurekaServerTotalConnections == that.eurekaServerTotalConnections
&& eurekaServerTotalConnectionsPerHost == that.eurekaServerTotalConnectionsPerHost
&& eurekaConnectionIdleTimeoutSeconds == that.eurekaConnectionIdleTimeoutSeconds
&& heartbeatExecutorThreadPoolSize == that.heartbeatExecutorThreadPoolSize
&& heartbeatExecutorExponentialBackOffBound == that.heartbeatExecutorExponentialBackOffBound
&& cacheRefreshExecutorThreadPoolSize == that.cacheRefreshExecutorThreadPoolSize
&& cacheRefreshExecutorExponentialBackOffBound == that.cacheRefreshExecutorExponentialBackOffBound
&& gZipContent == that.gZipContent
&& useDnsForFetchingServiceUrls == that.useDnsForFetchingServiceUrls
&& registerWithEureka == that.registerWithEureka
&& preferSameZoneEureka == that.preferSameZoneEureka
&& logDeltaDiff == that.logDeltaDiff && disableDelta == that.disableDelta
&& filterOnlyUpInstances == that.filterOnlyUpInstances
&& fetchRegistry == that.fetchRegistry
&& allowRedirects == that.allowRedirects
&& onDemandUpdateStatusChange == that.onDemandUpdateStatusChange
&& shouldUnregisterOnShutdown == that.shouldUnregisterOnShutdown
&& shouldEnforceRegistrationAtInit == that.shouldEnforceRegistrationAtInit
&& Objects.equals(proxyPort, that.proxyPort)
&& Objects.equals(proxyHost, that.proxyHost)
&& Objects.equals(proxyUserName, that.proxyUserName)
&& Objects.equals(proxyPassword, that.proxyPassword)
&& Objects.equals(backupRegistryImpl, that.backupRegistryImpl)
&& Objects.equals(eurekaServerURLContext, that.eurekaServerURLContext)
&& Objects.equals(eurekaServerPort, that.eurekaServerPort)
&& Objects.equals(eurekaServerDNSName, that.eurekaServerDNSName)
&& Objects.equals(region, that.region)
&& Objects.equals(registryRefreshSingleVipAddress,
that.registryRefreshSingleVipAddress)
&& Objects.equals(serviceUrl, that.serviceUrl)
&& Objects.equals(fetchRemoteRegionsRegistry,
that.fetchRemoteRegionsRegistry)
&& Objects.equals(availabilityZones, that.availabilityZones)
&& Objects.equals(dollarReplacement, that.dollarReplacement)
&& Objects.equals(escapeCharReplacement, that.escapeCharReplacement)
&& Objects.equals(encoderName, that.encoderName)
&& Objects.equals(decoderName, that.decoderName)
&& Objects.equals(clientDataAccept, that.clientDataAccept)
&& Objects.equals(order, that.order);
}
@Override
@@ -1006,54 +1025,70 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
@Override
public String toString() {
return new StringBuilder("EurekaClientConfigBean{")
.append("propertyResolver=").append(propertyResolver).append(", ")
.append("enabled=").append(enabled).append(", ")
.append("transport=").append(transport).append(", ")
.append("registryFetchIntervalSeconds=").append(registryFetchIntervalSeconds).append(", ")
.append("instanceInfoReplicationIntervalSeconds=").append(instanceInfoReplicationIntervalSeconds).append(", ")
.append("initialInstanceInfoReplicationIntervalSeconds=").append(initialInstanceInfoReplicationIntervalSeconds).append(", ")
.append("eurekaServiceUrlPollIntervalSeconds=").append(eurekaServiceUrlPollIntervalSeconds).append(", ")
return new StringBuilder("EurekaClientConfigBean{").append("propertyResolver=")
.append(propertyResolver).append(", ").append("enabled=").append(enabled)
.append(", ").append("transport=").append(transport).append(", ")
.append("registryFetchIntervalSeconds=")
.append(registryFetchIntervalSeconds).append(", ")
.append("instanceInfoReplicationIntervalSeconds=")
.append(instanceInfoReplicationIntervalSeconds).append(", ")
.append("initialInstanceInfoReplicationIntervalSeconds=")
.append(initialInstanceInfoReplicationIntervalSeconds).append(", ")
.append("eurekaServiceUrlPollIntervalSeconds=")
.append(eurekaServiceUrlPollIntervalSeconds).append(", ")
.append("proxyPort='").append(proxyPort).append("', ")
.append("proxyHost='").append(proxyHost).append("', ")
.append("proxyUserName='").append(proxyUserName).append("', ")
.append("proxyPassword='").append(proxyPassword).append("', ")
.append("eurekaServerReadTimeoutSeconds=").append(eurekaServerReadTimeoutSeconds).append(", ")
.append("eurekaServerConnectTimeoutSeconds=").append(eurekaServerConnectTimeoutSeconds).append(", ")
.append("eurekaServerReadTimeoutSeconds=")
.append(eurekaServerReadTimeoutSeconds).append(", ")
.append("eurekaServerConnectTimeoutSeconds=")
.append(eurekaServerConnectTimeoutSeconds).append(", ")
.append("backupRegistryImpl='").append(backupRegistryImpl).append("', ")
.append("eurekaServerTotalConnections=").append(eurekaServerTotalConnections).append(", ")
.append("eurekaServerTotalConnectionsPerHost=").append(eurekaServerTotalConnectionsPerHost).append(", ")
.append("eurekaServerURLContext='").append(eurekaServerURLContext).append("', ")
.append("eurekaServerPort='").append(eurekaServerPort).append("', ")
.append("eurekaServerDNSName='").append(eurekaServerDNSName).append("', ")
.append("region='").append(region).append("', ")
.append("eurekaConnectionIdleTimeoutSeconds=").append(eurekaConnectionIdleTimeoutSeconds).append(", ")
.append("registryRefreshSingleVipAddress='").append(registryRefreshSingleVipAddress).append("', ")
.append("heartbeatExecutorThreadPoolSize=").append(heartbeatExecutorThreadPoolSize).append(", ")
.append("heartbeatExecutorExponentialBackOffBound=").append(heartbeatExecutorExponentialBackOffBound).append(", ")
.append("cacheRefreshExecutorThreadPoolSize=").append(cacheRefreshExecutorThreadPoolSize).append(", ")
.append("cacheRefreshExecutorExponentialBackOffBound=").append(cacheRefreshExecutorExponentialBackOffBound).append(", ")
.append("eurekaServerTotalConnections=")
.append(eurekaServerTotalConnections).append(", ")
.append("eurekaServerTotalConnectionsPerHost=")
.append(eurekaServerTotalConnectionsPerHost).append(", ")
.append("eurekaServerURLContext='").append(eurekaServerURLContext)
.append("', ").append("eurekaServerPort='").append(eurekaServerPort)
.append("', ").append("eurekaServerDNSName='").append(eurekaServerDNSName)
.append("', ").append("region='").append(region).append("', ")
.append("eurekaConnectionIdleTimeoutSeconds=")
.append(eurekaConnectionIdleTimeoutSeconds).append(", ")
.append("registryRefreshSingleVipAddress='")
.append(registryRefreshSingleVipAddress).append("', ")
.append("heartbeatExecutorThreadPoolSize=")
.append(heartbeatExecutorThreadPoolSize).append(", ")
.append("heartbeatExecutorExponentialBackOffBound=")
.append(heartbeatExecutorExponentialBackOffBound).append(", ")
.append("cacheRefreshExecutorThreadPoolSize=")
.append(cacheRefreshExecutorThreadPoolSize).append(", ")
.append("cacheRefreshExecutorExponentialBackOffBound=")
.append(cacheRefreshExecutorExponentialBackOffBound).append(", ")
.append("serviceUrl=").append(serviceUrl).append(", ")
.append("gZipContent=").append(gZipContent).append(", ")
.append("useDnsForFetchingServiceUrls=").append(useDnsForFetchingServiceUrls).append(", ")
.append("useDnsForFetchingServiceUrls=")
.append(useDnsForFetchingServiceUrls).append(", ")
.append("registerWithEureka=").append(registerWithEureka).append(", ")
.append("preferSameZoneEureka=").append(preferSameZoneEureka).append(", ")
.append("logDeltaDiff=").append(logDeltaDiff).append(", ")
.append("disableDelta=").append(disableDelta).append(", ")
.append("fetchRemoteRegionsRegistry='").append(fetchRemoteRegionsRegistry).append("', ")
.append("availabilityZones=").append(availabilityZones).append(", ")
.append("filterOnlyUpInstances=").append(filterOnlyUpInstances).append(", ")
.append("fetchRegistry=").append(fetchRegistry).append(", ")
.append("dollarReplacement='").append(dollarReplacement).append("', ")
.append("escapeCharReplacement='").append(escapeCharReplacement).append("', ")
.append("allowRedirects=").append(allowRedirects).append(", ")
.append("onDemandUpdateStatusChange=").append(onDemandUpdateStatusChange).append(", ")
.append("encoderName='").append(encoderName).append("', ")
.append("decoderName='").append(decoderName).append("', ")
.append("clientDataAccept='").append(clientDataAccept).append("', ")
.append("shouldUnregisterOnShutdown='").append(shouldUnregisterOnShutdown).append("', ")
.append("shouldEnforceRegistrationAtInit='").append(shouldEnforceRegistrationAtInit).append("', ")
.append("order='").append(order).append("'}")
.toString();
.append("fetchRemoteRegionsRegistry='").append(fetchRemoteRegionsRegistry)
.append("', ").append("availabilityZones=").append(availabilityZones)
.append(", ").append("filterOnlyUpInstances=")
.append(filterOnlyUpInstances).append(", ").append("fetchRegistry=")
.append(fetchRegistry).append(", ").append("dollarReplacement='")
.append(dollarReplacement).append("', ").append("escapeCharReplacement='")
.append(escapeCharReplacement).append("', ").append("allowRedirects=")
.append(allowRedirects).append(", ").append("onDemandUpdateStatusChange=")
.append(onDemandUpdateStatusChange).append(", ").append("encoderName='")
.append(encoderName).append("', ").append("decoderName='")
.append(decoderName).append("', ").append("clientDataAccept='")
.append(clientDataAccept).append("', ")
.append("shouldUnregisterOnShutdown='").append(shouldUnregisterOnShutdown)
.append("shouldEnforceRegistrationAtInit='")
.append(shouldEnforceRegistrationAtInit).append("', ").append("order='")
.append(order).append("'}").toString();
}
}
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -17,10 +17,15 @@
package org.springframework.cloud.netflix.eureka;
/**
* Class containing Eureka-specific constants.
*
* @author Spencer Gibb
*/
public class EurekaConstants {
public final class EurekaConstants {
/**
* Default Eureka prefix.
*/
public static final String DEFAULT_PREFIX = "/eureka";
private EurekaConstants() {
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -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,23 +27,25 @@ 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.
*
* @author Spencer Gibb
* @author Tim Ysewyn
*/
public class EurekaDiscoveryClient implements DiscoveryClient {
/**
* Client description {@link String}.
*/
public static final String DESCRIPTION = "Spring Cloud Eureka Discovery Client";
private final EurekaClient eurekaClient;
private final EurekaClientConfig clientConfig;
@Deprecated
@@ -53,7 +53,8 @@ public class EurekaDiscoveryClient implements DiscoveryClient {
this(eurekaClient, eurekaClient.getEurekaClientConfig());
}
public EurekaDiscoveryClient(EurekaClient eurekaClient, EurekaClientConfig clientConfig) {
public EurekaDiscoveryClient(EurekaClient eurekaClient,
EurekaClientConfig clientConfig) {
this.clientConfig = clientConfig;
this.eurekaClient = eurekaClient;
}
@@ -74,58 +75,6 @@ public class EurekaDiscoveryClient implements DiscoveryClient {
return instances;
}
public static 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 List<String> getServices() {
Applications applications = this.eurekaClient.getApplications();
@@ -146,6 +95,26 @@ public class EurekaDiscoveryClient implements DiscoveryClient {
@Override
public int getOrder() {
return clientConfig instanceof Ordered ? ((Ordered) clientConfig).getOrder() : DiscoveryClient.DEFAULT_ORDER;
return clientConfig instanceof Ordered ? ((Ordered) clientConfig).getOrder()
: DiscoveryClient.DEFAULT_ORDER;
}
/**
* 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}.
*/
@Deprecated
public static class EurekaServiceInstance
extends org.springframework.cloud.netflix.eureka.EurekaServiceInstance {
public EurekaServiceInstance(InstanceInfo instance) {
super(instance);
}
}
}
@@ -1,18 +1,17 @@
/*
* Copyright 2013-2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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;
@@ -22,12 +21,14 @@ 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;
import org.springframework.context.ApplicationListener;
@@ -39,23 +40,65 @@ import org.springframework.context.annotation.Configuration;
* @author Spencer Gibb
* @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 {
class Marker {}
/**
* 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
@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 StatusAggregator statusAggregator = new SimpleStatusAggregator();
@Bean
@ConditionalOnMissingBean(HealthCheckHandler.class)
public EurekaHealthCheckHandler eurekaHealthCheckHandler() {
return new EurekaHealthCheckHandler(this.statusAggregator);
}
}
/**
* Deprecated in favor of auto configuration order.
*
* @deprecated in favor of auto configuration order.
*/
@Deprecated
class Marker {
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RefreshScopeRefreshedEvent.class)
protected static class EurekaClientConfigurationRefresher implements ApplicationListener<RefreshScopeRefreshedEvent> {
protected static class EurekaClientConfigurationRefresher
implements ApplicationListener<RefreshScopeRefreshedEvent> {
@Autowired(required = false)
private EurekaClient eurekaClient;
@@ -64,9 +107,9 @@ public class EurekaDiscoveryClientConfiguration {
private EurekaAutoServiceRegistration autoRegistration;
public void onApplicationEvent(RefreshScopeRefreshedEvent event) {
//This will force the creation of the EurkaClient bean if not already created
//to make sure the client will be reregistered after a refresh event
if(eurekaClient != null) {
// This will force the creation of the EurkaClient bean if not already created
// to make sure the client will be reregistered after a refresh event
if (eurekaClient != null) {
eurekaClient.getApplications();
}
if (autoRegistration != null) {
@@ -75,20 +118,7 @@ public class EurekaDiscoveryClientConfiguration {
this.autoRegistration.start();
}
}
}
@Configuration
@ConditionalOnProperty(value = "eureka.client.healthcheck.enabled", matchIfMissing = false)
protected static class EurekaHealthCheckHandlerConfiguration {
@Autowired(required = false)
private HealthAggregator healthAggregator = new OrderedHealthAggregator();
@Bean
@ConditionalOnMissingBean(HealthCheckHandler.class)
public EurekaHealthCheckHandler eurekaHealthCheckHandler() {
return new EurekaHealthCheckHandler(this.healthAggregator);
}
}
}
@@ -1,11 +1,11 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2021 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
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -17,93 +17,236 @@
package org.springframework.cloud.netflix.eureka;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import reactor.core.publisher.Mono;
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.ReactiveHealthIndicator;
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;
import org.springframework.context.Lifecycle;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
import static com.netflix.appinfo.InstanceInfo.InstanceStatus;
/**
* A Eureka health checker, maps the application status into {@link InstanceStatus}
* that will be propagated to Eureka registry.
* A Eureka health checker, maps the application status into {@link InstanceStatus} that
* will be propagated to Eureka registry.
*
* On each heartbeat Eureka performs the health check invoking registered {@link HealthCheckHandler}. By default this
* implementation will perform aggregation of all registered {@link HealthIndicator}
* through registered {@link HealthAggregator}.
* On each heartbeat Eureka performs the health check invoking registered
* {@link HealthCheckHandler}. By default this implementation will perform aggregation of
* all registered {@link HealthIndicator} through registered {@link HealthAggregator}.
*
* A {@code null} status is returned when the application context is closed (or in the
* process of being closed). This prevents Eureka from updating the health status and only
* consider the status present in the current InstanceInfo.
*
* @author Jakub Narloch
* @author Spencer Gibb
* @author Nowrin Anwar Joyita
* @author Bertrand Renuart
* @see HealthCheckHandler
* @see StatusAggregator
* @see HealthAggregator
*/
public class EurekaHealthCheckHandler implements HealthCheckHandler, ApplicationContextAware, InitializingBean {
public class EurekaHealthCheckHandler implements HealthCheckHandler,
ApplicationContextAware, InitializingBean, Ordered, Lifecycle {
private static final Map<Status, InstanceInfo.InstanceStatus> STATUS_MAPPING =
new HashMap<Status, InstanceInfo.InstanceStatus>() {{
put(Status.UNKNOWN, InstanceStatus.UNKNOWN);
put(Status.OUT_OF_SERVICE, InstanceStatus.OUT_OF_SERVICE);
put(Status.DOWN, InstanceStatus.DOWN);
put(Status.UP, InstanceStatus.UP);
}};
private static final Map<Status, InstanceInfo.InstanceStatus> STATUS_MAPPING = new HashMap<Status, InstanceInfo.InstanceStatus>() {
{
put(Status.UNKNOWN, InstanceStatus.UNKNOWN);
put(Status.OUT_OF_SERVICE, InstanceStatus.OUT_OF_SERVICE);
put(Status.DOWN, InstanceStatus.DOWN);
put(Status.UP, InstanceStatus.UP);
}
};
private final CompositeHealthIndicator healthIndicator;
private StatusAggregator statusAggregator;
private ApplicationContext applicationContext;
/**
* {@code true} until the context is stopped.
*/
private boolean running = true;
private Map<String, HealthIndicator> healthIndicators;
private Map<String, ReactiveHealthIndicator> reactiveHealthIndicators = new HashMap<>();
@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;
healthIndicatorRegistryFactory = new HealthIndicatorRegistryFactory();
healthIndicator = new CompositeHealthIndicator(this.healthAggregator,
new DefaultHealthIndicatorRegistry());
}
public EurekaHealthCheckHandler(StatusAggregator statusAggregator) {
this.statusAggregator = statusAggregator;
Assert.notNull(statusAggregator, "StatusAggregator must not be null");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void afterPropertiesSet() throws Exception {
final Map<String, HealthIndicator> healthIndicators = applicationContext.getBeansOfType(HealthIndicator.class);
final Map<String, HealthIndicator> healthIndicators = applicationContext
.getBeansOfType(HealthIndicator.class);
this.healthIndicators = new HashMap<>();
final Map<String, ReactiveHealthIndicator> reactiveHealthIndicators = applicationContext
.getBeansOfType(ReactiveHealthIndicator.class);
if (statusAggregator != null) {
populateHealthIndicators(healthIndicators);
populateReactiveHealthIndicators(reactiveHealthIndicators);
}
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
//otherwise there is a never ending cycle of down. See gh-643
// 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 DiscoveryCompositeHealthIndicator) {
DiscoveryCompositeHealthIndicator indicator = (DiscoveryCompositeHealthIndicator) entry.getValue();
for (DiscoveryCompositeHealthIndicator.Holder holder : indicator.getHealthIndicators()) {
DiscoveryCompositeHealthIndicator indicator = (DiscoveryCompositeHealthIndicator) entry
.getValue();
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());
}
}
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());
}
}
}
void populateReactiveHealthIndicators(
Map<String, ReactiveHealthIndicator> reactiveHealthIndicators) {
for (Map.Entry<String, ReactiveHealthIndicator> entry : reactiveHealthIndicators
.entrySet()) {
this.reactiveHealthIndicators.put(entry.getKey(), entry.getValue());
}
}
@Override
public InstanceStatus getStatus(InstanceStatus instanceStatus) {
return getHealthStatus();
if (running) {
return getHealthStatus();
}
else {
// Return nothing if the context is not running, so the status held by the
// InstanceInfo remains unchanged.
// See gh-1571
return null;
}
}
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 = new HashSet<>();
if (healthIndicators != null) {
statusSet.addAll(
healthIndicators.values().stream().map(HealthIndicator::health)
.map(Health::getStatus).collect(Collectors.toSet()));
}
if (reactiveHealthIndicators != null) {
statusSet.addAll(reactiveHealthIndicators.values().stream()
.map(ReactiveHealthIndicator::health).map(Mono::block)
.filter(Objects::nonNull).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;
@@ -111,7 +254,34 @@ public class EurekaHealthCheckHandler implements HealthCheckHandler, Application
return STATUS_MAPPING.get(status);
}
@Deprecated
protected CompositeHealthIndicator getHealthIndicator() {
return healthIndicator;
}
@Override
public int getOrder() {
// registered with a high order priority so the close() method is invoked early
// and *BEFORE* EurekaAutoServiceRegistration
// (must be in effect when the registration is closed and the eureka replication
// triggered -> health check handler is
// consulted at that moment)
return Ordered.HIGHEST_PRECEDENCE;
}
@Override
public void start() {
running = true;
}
@Override
public void stop() {
running = false;
}
@Override
public boolean isRunning() {
return true;
}
}
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -20,13 +20,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.springframework.aop.support.AopUtils;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.Health.Builder;
import org.springframework.boot.actuate.health.Status;
import org.springframework.cloud.client.discovery.health.DiscoveryHealthIndicator;
import org.springframework.cloud.util.ProxyUtils;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.discovery.DiscoveryClient;
import com.netflix.discovery.EurekaClient;
@@ -34,6 +27,13 @@ import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
import org.springframework.aop.support.AopUtils;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.Health.Builder;
import org.springframework.boot.actuate.health.Status;
import org.springframework.cloud.client.discovery.health.DiscoveryHealthIndicator;
import org.springframework.cloud.util.ProxyUtils;
/**
* @author Dave Syer
*/
@@ -67,8 +67,7 @@ public class EurekaHealthIndicator implements DiscoveryHealthIndicator {
}
private Status getStatus(Builder builder) {
Status status = new Status(
this.eurekaClient.getInstanceRemoteStatus().toString(),
Status status = new Status(this.eurekaClient.getInstanceRemoteStatus().toString(),
"Remote status from Eureka server");
DiscoveryClient discoveryClient = getDiscoveryClient();
if (discoveryClient != null && clientConfig.shouldFetchRegistry()) {
@@ -93,10 +92,11 @@ public class EurekaHealthIndicator implements DiscoveryHealthIndicator {
private DiscoveryClient getDiscoveryClient() {
DiscoveryClient discoveryClient = null;
if(AopUtils.isAopProxy(eurekaClient)) {
if (AopUtils.isAopProxy(eurekaClient)) {
discoveryClient = ProxyUtils.getTargetObject(eurekaClient);
} else if(DiscoveryClient.class.isInstance(eurekaClient)) {
discoveryClient = (DiscoveryClient)eurekaClient;
}
else if (DiscoveryClient.class.isInstance(eurekaClient)) {
discoveryClient = (DiscoveryClient) eurekaClient;
}
return discoveryClient;
}
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -21,6 +21,10 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import com.netflix.appinfo.DataCenterInfo;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import com.netflix.appinfo.MyDataCenterInfo;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.commons.util.InetUtils.HostInfo;
@@ -28,10 +32,6 @@ import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import com.netflix.appinfo.DataCenterInfo;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import com.netflix.appinfo.MyDataCenterInfo;
/**
* @author Dave Syer
* @author Spencer Gibb
@@ -39,7 +39,8 @@ import com.netflix.appinfo.MyDataCenterInfo;
* @author Gregor Zurowski
*/
@ConfigurationProperties("eureka.instance")
public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, EnvironmentAware {
public class EurekaInstanceConfigBean
implements CloudEurekaInstanceConfig, EnvironmentAware {
private static final String UNKNOWN = "unknown";
@@ -48,7 +49,7 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, Envi
private InetUtils inetUtils;
/**
* Default prefix for actuator endpoints
* Default prefix for actuator endpoints.
*/
private String actuatorPrefix = "/actuator";
@@ -265,7 +266,7 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, Envi
/**
* Flag to say that, when guessing a hostname, the IP address of the server should be
* used in prference to the hostname reported by the OS.
* used in preference to the hostname reported by the OS.
*/
private boolean preferIpAddress = false;
@@ -275,6 +276,7 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, Envi
private InstanceStatus initialStatus = InstanceStatus.UP;
private String[] defaultAddressResolutionOrder = new String[0];
private Environment environment;
public String getHostname() {
@@ -327,8 +329,10 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, Envi
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
// set some defaults from the environment, but allow the defaults to use relaxed binding
String springAppName = this.environment.getProperty("spring.application.name", "");
// set some defaults from the environment, but allow the defaults to use relaxed
// binding
String springAppName = this.environment.getProperty("spring.application.name",
"");
if (StringUtils.hasText(springAppName)) {
setAppname(springAppName);
setVirtualHostName(springAppName);
@@ -567,40 +571,44 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, Envi
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
EurekaInstanceConfigBean that = (EurekaInstanceConfigBean) o;
return Objects.equals(hostInfo, that.hostInfo) &&
Objects.equals(inetUtils, that.inetUtils) &&
Objects.equals(appname, that.appname) &&
Objects.equals(appGroupName, that.appGroupName) &&
instanceEnabledOnit == that.instanceEnabledOnit &&
nonSecurePort == that.nonSecurePort &&
securePort == that.securePort &&
nonSecurePortEnabled == that.nonSecurePortEnabled &&
securePortEnabled == that.securePortEnabled &&
leaseRenewalIntervalInSeconds == that.leaseRenewalIntervalInSeconds &&
leaseExpirationDurationInSeconds == that.leaseExpirationDurationInSeconds &&
Objects.equals(virtualHostName, that.virtualHostName) &&
Objects.equals(instanceId, that.instanceId) &&
Objects.equals(secureVirtualHostName, that.secureVirtualHostName) &&
Objects.equals(aSGName, that.aSGName) &&
Objects.equals(metadataMap, that.metadataMap) &&
Objects.equals(dataCenterInfo, that.dataCenterInfo) &&
Objects.equals(ipAddress, that.ipAddress) &&
Objects.equals(statusPageUrlPath, that.statusPageUrlPath) &&
Objects.equals(statusPageUrl, that.statusPageUrl) &&
Objects.equals(homePageUrlPath, that.homePageUrlPath) &&
Objects.equals(homePageUrl, that.homePageUrl) &&
Objects.equals(healthCheckUrlPath, that.healthCheckUrlPath) &&
Objects.equals(healthCheckUrl, that.healthCheckUrl) &&
Objects.equals(secureHealthCheckUrl, that.secureHealthCheckUrl) &&
Objects.equals(namespace, that.namespace) &&
Objects.equals(hostname, that.hostname) &&
preferIpAddress == that.preferIpAddress &&
Objects.equals(initialStatus, that.initialStatus) &&
Arrays.equals(defaultAddressResolutionOrder, that.defaultAddressResolutionOrder) &&
Objects.equals(environment, that.environment);
return Objects.equals(hostInfo, that.hostInfo)
&& Objects.equals(inetUtils, that.inetUtils)
&& Objects.equals(appname, that.appname)
&& Objects.equals(appGroupName, that.appGroupName)
&& instanceEnabledOnit == that.instanceEnabledOnit
&& nonSecurePort == that.nonSecurePort && securePort == that.securePort
&& nonSecurePortEnabled == that.nonSecurePortEnabled
&& securePortEnabled == that.securePortEnabled
&& leaseRenewalIntervalInSeconds == that.leaseRenewalIntervalInSeconds
&& leaseExpirationDurationInSeconds == that.leaseExpirationDurationInSeconds
&& Objects.equals(virtualHostName, that.virtualHostName)
&& Objects.equals(instanceId, that.instanceId)
&& Objects.equals(secureVirtualHostName, that.secureVirtualHostName)
&& Objects.equals(aSGName, that.aSGName)
&& Objects.equals(metadataMap, that.metadataMap)
&& Objects.equals(dataCenterInfo, that.dataCenterInfo)
&& Objects.equals(ipAddress, that.ipAddress)
&& Objects.equals(statusPageUrlPath, that.statusPageUrlPath)
&& Objects.equals(statusPageUrl, that.statusPageUrl)
&& Objects.equals(homePageUrlPath, that.homePageUrlPath)
&& Objects.equals(homePageUrl, that.homePageUrl)
&& Objects.equals(healthCheckUrlPath, that.healthCheckUrlPath)
&& Objects.equals(healthCheckUrl, that.healthCheckUrl)
&& Objects.equals(secureHealthCheckUrl, that.secureHealthCheckUrl)
&& Objects.equals(namespace, that.namespace)
&& Objects.equals(hostname, that.hostname)
&& preferIpAddress == that.preferIpAddress
&& Objects.equals(initialStatus, that.initialStatus)
&& Arrays.equals(defaultAddressResolutionOrder,
that.defaultAddressResolutionOrder)
&& Objects.equals(environment, that.environment);
}
@Override
@@ -612,27 +620,29 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, Envi
secureVirtualHostName, aSGName, metadataMap, dataCenterInfo, ipAddress,
statusPageUrlPath, statusPageUrl, homePageUrlPath, homePageUrl,
healthCheckUrlPath, healthCheckUrl, secureHealthCheckUrl, namespace,
hostname, preferIpAddress, initialStatus, defaultAddressResolutionOrder, environment);
hostname, preferIpAddress, initialStatus, defaultAddressResolutionOrder,
environment);
}
@Override
public String toString() {
return new StringBuilder("EurekaInstanceConfigBean{")
.append("hostInfo=").append(hostInfo).append(", ")
.append("inetUtils=").append(inetUtils).append(", ")
.append("appname='").append(appname).append("', ")
return new StringBuilder("EurekaInstanceConfigBean{").append("hostInfo=")
.append(hostInfo).append(", ").append("inetUtils=").append(inetUtils)
.append(", ").append("appname='").append(appname).append("', ")
.append("appGroupName='").append(appGroupName).append("', ")
.append("instanceEnabledOnit=").append(instanceEnabledOnit).append(", ")
.append("nonSecurePort=").append(nonSecurePort).append(", ")
.append("securePort=").append(securePort).append(", ")
.append("nonSecurePortEnabled=").append(nonSecurePortEnabled).append(", ")
.append("securePortEnabled=").append(securePortEnabled).append(", ")
.append("leaseRenewalIntervalInSeconds=").append(leaseRenewalIntervalInSeconds).append(", ")
.append("leaseExpirationDurationInSeconds=").append(leaseExpirationDurationInSeconds).append(", ")
.append("leaseRenewalIntervalInSeconds=")
.append(leaseRenewalIntervalInSeconds).append(", ")
.append("leaseExpirationDurationInSeconds=")
.append(leaseExpirationDurationInSeconds).append(", ")
.append("virtualHostName='").append(virtualHostName).append("', ")
.append("instanceId='").append(instanceId).append("', ")
.append("secureVirtualHostName='").append(secureVirtualHostName).append("', ")
.append("aSGName='").append(aSGName).append("', ")
.append("secureVirtualHostName='").append(secureVirtualHostName)
.append("', ").append("aSGName='").append(aSGName).append("', ")
.append("metadataMap=").append(metadataMap).append(", ")
.append("dataCenterInfo=").append(dataCenterInfo).append(", ")
.append("ipAddress='").append(ipAddress).append("', ")
@@ -642,13 +652,15 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, Envi
.append("homePageUrl='").append(homePageUrl).append("', ")
.append("healthCheckUrlPath='").append(healthCheckUrlPath).append("', ")
.append("healthCheckUrl='").append(healthCheckUrl).append("', ")
.append("secureHealthCheckUrl='").append(secureHealthCheckUrl).append("', ")
.append("namespace='").append(namespace).append("', ")
.append("secureHealthCheckUrl='").append(secureHealthCheckUrl)
.append("', ").append("namespace='").append(namespace).append("', ")
.append("hostname='").append(hostname).append("', ")
.append("preferIpAddress=").append(preferIpAddress).append(", ")
.append("initialStatus=").append(initialStatus).append(", ")
.append("defaultAddressResolutionOrder=").append(Arrays.toString(defaultAddressResolutionOrder)).append(", ")
.append("defaultAddressResolutionOrder=")
.append(Arrays.toString(defaultAddressResolutionOrder)).append(", ")
.append("environment=").append(environment).append(", ").append("}")
.toString();
}
}
@@ -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,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -25,7 +25,8 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* See com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider
* See com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider.
*
* @author Spencer Gibb
*/
public class InstanceInfoFactory {
@@ -95,4 +96,5 @@ public class InstanceInfoFactory {
instanceInfo.setLeaseInfo(leaseInfoBuilder.build());
return instanceInfo;
}
}
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -1,11 +1,11 @@
/*
* Copyright 2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,33 +16,119 @@
package org.springframework.cloud.netflix.eureka.config;
import java.io.IOException;
import java.security.GeneralSecurityException;
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.beans.factory.annotation.Autowired;
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.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.configuration.SSLContextFactory;
import org.springframework.cloud.configuration.TlsProperties;
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 com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
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
@ConfigurationProperties("eureka.client.tls")
public TlsProperties tlsProperties() {
return new TlsProperties();
}
@Bean
@ConditionalOnMissingClass("com.sun.jersey.api.client.filter.ClientFilter")
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs() {
return new RestTemplateDiscoveryClientOptionalArgs();
@ConditionalOnMissingBean(value = { AbstractDiscoveryClientOptionalArgs.class },
search = SearchStrategy.CURRENT)
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
matchIfMissing = true, havingValue = "false")
public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs(
TlsProperties tlsProperties) throws GeneralSecurityException, IOException {
logger.info("Eureka HTTP Client uses RestTemplate.");
RestTemplateDiscoveryClientOptionalArgs result = new RestTemplateDiscoveryClientOptionalArgs();
setupTLS(result, tlsProperties);
return result;
}
@Bean
@ConditionalOnClass(name = "com.sun.jersey.api.client.filter.ClientFilter")
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
public MutableDiscoveryClientOptionalArgs discoveryClientOptionalArgs() {
return new MutableDiscoveryClientOptionalArgs();
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class,
search = SearchStrategy.CURRENT)
public MutableDiscoveryClientOptionalArgs discoveryClientOptionalArgs(
TlsProperties tlsProperties) throws GeneralSecurityException, IOException {
logger.info("Eureka HTTP Client uses Jersey");
MutableDiscoveryClientOptionalArgs result = new MutableDiscoveryClientOptionalArgs();
setupTLS(result, tlsProperties);
return result;
}
private static void setupTLS(AbstractDiscoveryClientOptionalArgs<?> args,
TlsProperties properties) throws GeneralSecurityException, IOException {
if (properties.isEnabled()) {
SSLContextFactory factory = new SSLContextFactory(properties);
args.setSSLContext(factory.createSSLContext());
}
}
@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 {
@Autowired
private TlsProperties tlsProperties;
@Bean
@ConditionalOnMissingBean(
value = { AbstractDiscoveryClientOptionalArgs.class,
RestTemplateDiscoveryClientOptionalArgs.class },
search = SearchStrategy.CURRENT)
public WebClientDiscoveryClientOptionalArgs webClientDiscoveryClientOptionalArgs(
ObjectProvider<WebClient.Builder> builder)
throws GeneralSecurityException, IOException {
logger.info("Eureka HTTP Client uses WebClient.");
WebClientDiscoveryClientOptionalArgs result = new WebClientDiscoveryClientOptionalArgs(
builder::getIfAvailable);
setupTLS(result, tlsProperties);
return result;
}
}
@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.");
}
}
}
@@ -1,11 +1,11 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -18,6 +18,9 @@ package org.springframework.cloud.netflix.eureka.config;
import javax.annotation.PostConstruct;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.discovery.EurekaClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -26,15 +29,12 @@ import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.discovery.EurekaClient;
/**
* Extra configuration for config server if it happens to be a Eureka instance.
*
* @author Dave Syer
*/
@Configuration
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnClass({ EurekaInstanceConfigBean.class, EurekaClient.class,
ConfigServerProperties.class })
@@ -52,7 +52,8 @@ public class EurekaClientConfigServerAutoConfiguration {
return;
}
String prefix = this.server.getPrefix();
if (StringUtils.hasText(prefix) && !StringUtils.hasText(this.instance.getMetadataMap().get("configPath"))) {
if (StringUtils.hasText(prefix) && !StringUtils
.hasText(this.instance.getMetadataMap().get("configPath"))) {
this.instance.getMetadataMap().put("configPath", prefix);
}
}
@@ -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)));
}
}
}
@@ -1,55 +0,0 @@
/*
* Copyright 2013-2014 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
*
* http://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 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;
import com.netflix.discovery.EurekaClient;
/**
* 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();
}
}
}
}
@@ -1,39 +0,0 @@
/*
* Copyright 2013-2014 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
*
* http://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 {
}
@@ -0,0 +1,32 @@
/*
* 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.config;
import org.springframework.cloud.configuration.TlsProperties;
/**
* Eureka client TLS properties.
*/
public class EurekaTlsProperties extends TlsProperties {
/**
* Prefix for Eureka client TLS properties.
*/
public static final String PREFIX = "eureka.client.tls";
}
@@ -1,11 +1,11 @@
/*
* Copyright 2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -26,7 +26,7 @@ import com.netflix.discovery.shared.Applications;
/**
* A simple wrapper class for {@link Applications} that insure proprer Jackson
* serialization through the JsonPropert overwrites.
*
*
* @author Daniel Lavoie
*/
public class EurekaApplications extends com.netflix.discovery.shared.Applications {
@@ -37,4 +37,5 @@ public class EurekaApplications extends com.netflix.discovery.shared.Application
@JsonProperty("application") List<Application> registeredApplications) {
super(appsHashCode, versionDelta, registeredApplications);
}
}
}
@@ -1,11 +1,11 @@
/*
* Copyright 2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -23,7 +23,9 @@ import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
*/
public class RestTemplateDiscoveryClientOptionalArgs
extends AbstractDiscoveryClientOptionalArgs<Void> {
public RestTemplateDiscoveryClientOptionalArgs() {
setTransportClientFactories(new RestTemplateTransportClientFactories());
}
}
@@ -1,11 +1,11 @@
/*
* Copyright 2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,24 +16,12 @@
package org.springframework.cloud.netflix.eureka.http;
import static com.netflix.discovery.shared.transport.EurekaHttpResponse.anEurekaHttpResponse;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import com.netflix.discovery.shared.Application;
@@ -42,6 +30,18 @@ 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.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import static com.netflix.discovery.shared.transport.EurekaHttpResponse.anEurekaHttpResponse;
/**
* @author Daniel Lavoie
@@ -51,16 +51,21 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
protected final Log logger = LogFactory.getLog(getClass());
private RestTemplate restTemplate;
private String serviceUrl;
public RestTemplateEurekaHttpClient(RestTemplate restTemplate, String serviceUrl) {
this.restTemplate = restTemplate;
this.serviceUrl = serviceUrl;
if (!serviceUrl.endsWith("/")) {
this.serviceUrl = this.serviceUrl+"/";
this.serviceUrl = this.serviceUrl + "/";
}
}
public String getServiceUrl() {
return this.serviceUrl;
}
@Override
public EurekaHttpResponse<Void> register(InstanceInfo info) {
String urlPath = serviceUrl + "apps/" + info.getAppName();
@@ -102,8 +107,9 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
response.getStatusCodeValue(), InstanceInfo.class)
.headers(headersOf(response));
if (response.hasBody())
if (response.hasBody()) {
eurekaResponseBuilder.entity(response.getBody());
}
return eurekaResponseBuilder.build();
}
@@ -111,7 +117,7 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
@Override
public EurekaHttpResponse<Void> statusUpdate(String appName, String id,
InstanceStatus newStatus, InstanceInfo info) {
String urlPath = serviceUrl + "apps/" + appName + '/' + id + "?status="
String urlPath = serviceUrl + "apps/" + appName + '/' + id + "/status?value="
+ newStatus.name() + "&lastDirtyTimestamp="
+ info.getLastDirtyTimestamp().toString();
@@ -228,4 +234,5 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
}
return headers;
}
}
@@ -1,11 +1,11 @@
/*
* Copyright 2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -19,15 +19,15 @@ package org.springframework.cloud.netflix.eureka.http;
import java.util.Collection;
import java.util.Optional;
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 javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
/**
* @author Daniel Lavoie
*/
@@ -48,11 +48,12 @@ public class RestTemplateTransportClientFactories
}
@Override
public TransportClientFactory newTransportClientFactory(final EurekaClientConfig clientConfig,
final Collection<Void> additionalFilters,
final InstanceInfo myInstanceInfo,
final Optional<SSLContext> sslContext,
final Optional<HostnameVerifier> hostnameVerifier) {
public TransportClientFactory newTransportClientFactory(
final EurekaClientConfig clientConfig,
final Collection<Void> additionalFilters, final InstanceInfo myInstanceInfo,
final Optional<SSLContext> sslContext,
final Optional<HostnameVerifier> hostnameVerifier) {
return new RestTemplateTransportClientFactory();
}
}
@@ -1,11 +1,11 @@
/*
* Copyright 2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -19,12 +19,6 @@ package org.springframework.cloud.netflix.eureka.http;
import java.net.URI;
import java.net.URISyntaxException;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.support.BasicAuthorizationInterceptor;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonSerializer;
@@ -44,11 +38,17 @@ import com.netflix.discovery.shared.resolver.EurekaEndpoint;
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.BasicAuthenticationInterceptor;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
/**
* Provides the custom {@link RestTemplate} required by the
* {@link RestTemplateEurekaHttpClient}. Relies on Jackson for serialization and
* deserialization.
*
*
* @author Daniel Lavoie
*/
public class RestTemplateTransportClientFactory implements TransportClientFactory {
@@ -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]));
}
}
@@ -76,7 +76,7 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
}
restTemplate.getMessageConverters().add(0, mappingJacksonHttpMessageConverter());
restTemplate.setErrorHandler(new ErrorHanlder());
restTemplate.setErrorHandler(new ErrorHandler());
return restTemplate;
}
@@ -85,13 +85,11 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
* 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. Achived with
* {@link SerializationFeature.WRAP_ROOT_VALUE} and
* {@link DeserializationFeature.UNWRAP_ROOT_VALUE}.
* {@link SerializationFeature#WRAP_ROOT_VALUE} and
* {@link DeserializationFeature#UNWRAP_ROOT_VALUE}.
* {@link PropertyNamingStrategy.SnakeCaseStrategy} is applied to the underlying
* {@link ObjectMapper}.
*
*
* @return
* @return a {@link MappingJackson2HttpMessageConverter} object
*/
public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
@@ -99,34 +97,49 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE));
SimpleModule jsonModule = new SimpleModule();
jsonModule.setSerializerModifier(createJsonSerializerModifier());//keyFormatter, compact));
jsonModule.setSerializerModifier(createJsonSerializerModifier()); // keyFormatter,
// compact));
converter.getObjectMapper().registerModule(jsonModule);
converter.getObjectMapper().configure(SerializationFeature.WRAP_ROOT_VALUE, true);
converter.getObjectMapper().configure(DeserializationFeature.UNWRAP_ROOT_VALUE,
true);
converter.getObjectMapper().addMixIn(Applications.class, ApplicationsJsonMixIn.class);
converter.getObjectMapper().addMixIn(InstanceInfo.class, InstanceInfoJsonMixIn.class);
// converter.getObjectMapper().addMixIn(DataCenterInfo.class, DataCenterInfoXmlMixIn.class);
// converter.getObjectMapper().addMixIn(InstanceInfo.PortWrapper.class, PortWrapperXmlMixIn.class);
// converter.getObjectMapper().addMixIn(Application.class, ApplicationXmlMixIn.class);
// converter.getObjectMapper().addMixIn(Applications.class, ApplicationsXmlMixIn.class);
converter.getObjectMapper().addMixIn(Applications.class,
ApplicationsJsonMixIn.class);
converter.getObjectMapper().addMixIn(InstanceInfo.class,
InstanceInfoJsonMixIn.class);
// converter.getObjectMapper().addMixIn(DataCenterInfo.class,
// DataCenterInfoXmlMixIn.class);
// converter.getObjectMapper().addMixIn(InstanceInfo.PortWrapper.class,
// PortWrapperXmlMixIn.class);
// converter.getObjectMapper().addMixIn(Application.class,
// ApplicationXmlMixIn.class);
// converter.getObjectMapper().addMixIn(Applications.class,
// ApplicationsXmlMixIn.class);
return converter;
}
public static BeanSerializerModifier createJsonSerializerModifier() {//final KeyFormatter keyFormatter, final boolean compactMode) {
public static BeanSerializerModifier createJsonSerializerModifier() { // final
// KeyFormatter
// keyFormatter,
// final
// boolean
// compactMode)
// {
return new BeanSerializerModifier() {
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config,
BeanDescription beanDesc, JsonSerializer<?> serializer) {
/*if (beanDesc.getBeanClass().isAssignableFrom(Applications.class)) {
return new ApplicationsJsonBeanSerializer((BeanSerializerBase) serializer, keyFormatter);
}*/
BeanDescription beanDesc, JsonSerializer<?> serializer) {
/*
* if (beanDesc.getBeanClass().isAssignableFrom(Applications.class)) {
* return new ApplicationsJsonBeanSerializer((BeanSerializerBase)
* serializer, keyFormatter); }
*/
if (beanDesc.getBeanClass().isAssignableFrom(InstanceInfo.class)) {
return new InstanceInfoJsonBeanSerializer((BeanSerializerBase) serializer, false);
return new InstanceInfoJsonBeanSerializer(
(BeanSerializerBase) serializer, false);
}
return serializer;
}
@@ -137,20 +150,22 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
public void shutdown() {
}
class ErrorHanlder extends DefaultResponseErrorHandler {
class ErrorHandler extends DefaultResponseErrorHandler {
@Override
protected boolean hasError(HttpStatus statusCode) {
/**
* When the Eureka server restarts and a client tries to sent a heartbeat the server
* will respond with a 404. By default RestTemplate will throw an exception in this case.
* What we want is to return the 404 to the upstream code so it will send another registration
* request to the server.
* When the Eureka server restarts and a client tries to sent a heartbeat the
* server will respond with a 404. By default RestTemplate will throw an
* exception in this case. What we want is to return the 404 to the upstream
* code so it will send another registration request to the server.
*/
if(statusCode.is4xxClientError()) {
if (statusCode.is4xxClientError()) {
return false;
}
return super.hasError(statusCode);
}
}
}
@@ -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));
}
}
@@ -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();
}
}
@@ -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);
}
}
@@ -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() {
}
}
@@ -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;
}
}
}
@@ -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;
}
}
@@ -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));
}
}
@@ -1,107 +1,150 @@
package org.springframework.cloud.netflix.eureka.metadata;
/*
* 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.
*/
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
import org.springframework.util.StringUtils;
package org.springframework.cloud.netflix.eureka.metadata;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
import org.springframework.util.StringUtils;
/**
* Default implementation of {@link DefaultManagementMetadataProvider}.
*
* @author Anastasiia Smirnova
*/
public class DefaultManagementMetadataProvider implements ManagementMetadataProvider {
private static final int RANDOM_PORT = 0;
private static final Log log = LogFactory.getLog(DefaultManagementMetadataProvider.class);
private static final int RANDOM_PORT = 0;
@Override
public ManagementMetadata get(EurekaInstanceConfigBean instance, int serverPort,
String serverContextPath, String managementContextPath,
Integer managementPort) {
private static final Log log = LogFactory
.getLog(DefaultManagementMetadataProvider.class);
@Override
public ManagementMetadata get(EurekaInstanceConfigBean instance, int serverPort,
String serverContextPath, String managementContextPath,
Integer managementPort) {
if (isRandom(managementPort)) {
return null;
}
if (managementPort == null && isRandom(serverPort)) {
return null;
}
String healthCheckUrl = getHealthCheckUrl(instance, serverPort, serverContextPath,
managementContextPath, managementPort, false);
String statusPageUrl = getStatusPageUrl(instance, serverPort, serverContextPath,
managementContextPath, managementPort);
String healthCheckUrl = getHealthCheckUrl(instance, serverPort, serverContextPath,
managementContextPath, managementPort, false);
String statusPageUrl = getStatusPageUrl(instance, serverPort, serverContextPath,
managementContextPath, managementPort);
ManagementMetadata metadata = new ManagementMetadata(healthCheckUrl, statusPageUrl, managementPort == null ? serverPort : managementPort);
if(instance.isSecurePortEnabled()) {
metadata.setSecureHealthCheckUrl(getHealthCheckUrl(instance, serverPort, serverContextPath,
managementContextPath, managementPort, true));
}
return metadata;
ManagementMetadata metadata = new ManagementMetadata(healthCheckUrl,
statusPageUrl, managementPort == null ? serverPort : managementPort);
if (instance.isSecurePortEnabled()) {
metadata.setSecureHealthCheckUrl(getHealthCheckUrl(instance, serverPort,
serverContextPath, managementContextPath, managementPort, true));
}
return metadata;
}
private boolean isRandom(Integer port) {
return port != null && port == RANDOM_PORT;
}
protected String getHealthCheckUrl(EurekaInstanceConfigBean instance, int serverPort, String serverContextPath,
String managementContextPath, Integer managementPort, boolean isSecure) {
String healthCheckUrlPath = instance.getHealthCheckUrlPath();
String healthCheckUrl = getUrl(instance, serverPort, serverContextPath, managementContextPath,
managementPort, healthCheckUrlPath, isSecure);
log.debug("Constructed eureka meta-data healthcheckUrl: " + healthCheckUrl);
return healthCheckUrl;
}
protected String getHealthCheckUrl(EurekaInstanceConfigBean instance, int serverPort,
String serverContextPath, String managementContextPath,
Integer managementPort, boolean isSecure) {
String healthCheckUrlPath = instance.getHealthCheckUrlPath();
String healthCheckUrl = getUrl(instance, serverPort, serverContextPath,
managementContextPath, managementPort, healthCheckUrlPath, isSecure);
log.debug("Constructed eureka meta-data healthcheckUrl: " + healthCheckUrl);
return healthCheckUrl;
}
public String getStatusPageUrl(EurekaInstanceConfigBean instance, int serverPort, String serverContextPath,
String managementContextPath, Integer managementPort) {
String statusPageUrlPath = instance.getStatusPageUrlPath();
String statusPageUrl = getUrl(instance, serverPort, serverContextPath, managementContextPath,
managementPort, statusPageUrlPath, false);
log.debug("Constructed eureka meta-data statusPageUrl: " + statusPageUrl);
return statusPageUrl;
}
public String getStatusPageUrl(EurekaInstanceConfigBean instance, int serverPort,
String serverContextPath, String managementContextPath,
Integer managementPort) {
String statusPageUrlPath = instance.getStatusPageUrlPath();
String statusPageUrl = getUrl(instance, serverPort, serverContextPath,
managementContextPath, managementPort, statusPageUrlPath, false);
log.debug("Constructed eureka meta-data statusPageUrl: " + statusPageUrl);
return statusPageUrl;
}
private String getUrl(EurekaInstanceConfigBean instance, int serverPort,
String serverContextPath, String managementContextPath,
Integer managementPort, String urlPath, boolean isSecure) {
managementContextPath = refineManagementContextPath(serverContextPath, managementContextPath, managementPort);
if (managementPort == null) {
managementPort = serverPort;
}
String scheme = isSecure ? "https" : "http";
return constructValidUrl(scheme, instance.getHostname(), managementPort, managementContextPath, urlPath);
}
private String getUrl(EurekaInstanceConfigBean instance, int serverPort,
String serverContextPath, String managementContextPath,
Integer managementPort, String urlPath, boolean isSecure) {
managementContextPath = refineManagementContextPath(serverContextPath,
managementContextPath, managementPort);
if (managementPort == null) {
managementPort = serverPort;
}
String scheme = isSecure ? "https" : "http";
return constructValidUrl(scheme, instance.getHostname(), managementPort,
managementContextPath, urlPath);
}
private String refineManagementContextPath(String serverContextPath, String managementContextPath,
Integer managementPort) {
// management context path is relative to server context path when no management port is set
if (managementContextPath != null && managementPort == null) {
return serverContextPath + managementContextPath;
}
if(managementContextPath != null) {
return managementContextPath;
}
if(managementPort != null) {
return "/";
}
return serverContextPath;
}
private String refineManagementContextPath(String serverContextPath,
String managementContextPath, Integer managementPort) {
// management context path is relative to server context path when no management
// port is set
if (managementContextPath != null && managementPort == null) {
return serverContextPath + managementContextPath;
}
if (managementContextPath != null) {
return managementContextPath;
}
if (managementPort != null) {
return "/";
}
return serverContextPath;
}
private String constructValidUrl(String scheme, String hostname, int port,
String contextPath, String statusPath) {
try {
if (!contextPath.endsWith("/")) {
contextPath = contextPath + "/";
}
String refinedContextPath = '/' + StringUtils.trimLeadingCharacter(contextPath, '/') ;
URL base = new URL(scheme, hostname, port, refinedContextPath);
String refinedStatusPath = StringUtils.trimLeadingCharacter(statusPath, '/');
return new URL(base, refinedStatusPath).toString();
} catch (MalformedURLException e) {
String message = getErrorMessage(scheme, hostname, port, contextPath, statusPath);
throw new IllegalStateException(message, e);
}
}
private String constructValidUrl(String scheme, String hostname, int port,
String contextPath, String statusPath) {
try {
if (!contextPath.endsWith("/")) {
contextPath = contextPath + "/";
}
String refinedContextPath = '/'
+ StringUtils.trimLeadingCharacter(contextPath, '/');
URL base = new URL(scheme, hostname, port, refinedContextPath);
String refinedStatusPath = refinedStatusPath(statusPath, contextPath);
return new URL(base, refinedStatusPath).toString();
}
catch (MalformedURLException e) {
String message = getErrorMessage(scheme, hostname, port, contextPath,
statusPath);
throw new IllegalStateException(message, e);
}
}
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(
"Failed to construct url for scheme: %s, hostName: %s port: %s contextPath: %s statusPath: %s",
scheme, hostname, port, contextPath, statusPath);
}
private String getErrorMessage(String scheme, String hostname, int port, String contextPath, String statusPath) {
return String.format("Failed to construct url for scheme: %s, hostName: %s port: %s contextPath: %s statusPath: %s",
scheme, hostname, port, contextPath, statusPath);
}
}
@@ -1,63 +1,94 @@
/*
* 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.metadata;
import java.util.Objects;
/**
* Stores management metadata for Eureka.
*
* @author Anastasiia Smirnova
* @author Ryan Baxter
*/
public class ManagementMetadata {
private final String healthCheckUrl;
private final String statusPageUrl;
private final Integer managementPort;
private String secureHealthCheckUrl;
private final String healthCheckUrl;
public ManagementMetadata(String healthCheckUrl, String statusPageUrl, Integer managementPort) {
this.healthCheckUrl = healthCheckUrl;
this.statusPageUrl = statusPageUrl;
this.managementPort = managementPort;
this.secureHealthCheckUrl = null;
}
private final String statusPageUrl;
public String getHealthCheckUrl() {
return healthCheckUrl;
}
private final Integer managementPort;
public String getStatusPageUrl() {
return statusPageUrl;
}
private String secureHealthCheckUrl;
public Integer getManagementPort() {
return managementPort;
}
public ManagementMetadata(String healthCheckUrl, String statusPageUrl,
Integer managementPort) {
this.healthCheckUrl = healthCheckUrl;
this.statusPageUrl = statusPageUrl;
this.managementPort = managementPort;
this.secureHealthCheckUrl = null;
}
public String getSecureHealthCheckUrl() {
return secureHealthCheckUrl;
}
public String getHealthCheckUrl() {
return healthCheckUrl;
}
public void setSecureHealthCheckUrl(String secureHealthCheckUrl) {
this.secureHealthCheckUrl = secureHealthCheckUrl;
}
public String getStatusPageUrl() {
return statusPageUrl;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ManagementMetadata that = (ManagementMetadata) o;
return Objects.equals(healthCheckUrl, that.healthCheckUrl) &&
Objects.equals(statusPageUrl, that.statusPageUrl) &&
Objects.equals(managementPort, that.managementPort);
}
public Integer getManagementPort() {
return managementPort;
}
@Override
public int hashCode() {
return Objects.hash(healthCheckUrl, statusPageUrl, managementPort);
}
public String getSecureHealthCheckUrl() {
return secureHealthCheckUrl;
}
public void setSecureHealthCheckUrl(String secureHealthCheckUrl) {
this.secureHealthCheckUrl = secureHealthCheckUrl;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ManagementMetadata that = (ManagementMetadata) o;
return Objects.equals(healthCheckUrl, that.healthCheckUrl)
&& Objects.equals(statusPageUrl, that.statusPageUrl)
&& Objects.equals(managementPort, that.managementPort);
}
@Override
public int hashCode() {
return Objects.hash(healthCheckUrl, statusPageUrl, managementPort);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("ManagementMetadata{");
sb.append("healthCheckUrl='").append(healthCheckUrl).append('\'');
sb.append(", statusPageUrl='").append(statusPageUrl).append('\'');
sb.append(", managementPort=").append(managementPort);
sb.append('}');
return sb.toString();
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("ManagementMetadata{");
sb.append("healthCheckUrl='").append(healthCheckUrl).append('\'');
sb.append(", statusPageUrl='").append(statusPageUrl).append('\'');
sb.append(", managementPort=").append(managementPort);
sb.append('}');
return sb.toString();
}
}

Some files were not shown because too many files have changed in this diff Show More