├── .gitignore
├── LICENSE
├── README.md
├── api-gateway
└── zuul
│ ├── build.gradle
│ └── src
│ └── main
│ ├── java
│ └── com
│ │ └── example
│ │ └── ZuulApplication.java
│ └── resources
│ ├── application-docker.yml
│ └── application.yml
├── build.gradle
├── call-chain
├── README.md
├── zipkin-clients
│ ├── build.gradle
│ ├── zipkin-client
│ │ └── src
│ │ │ └── main
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── ZipkinClientApplication.java
│ │ │ └── resources
│ │ │ ├── application-docker.properties
│ │ │ └── application.properties
│ ├── zipkin-client0
│ │ └── src
│ │ │ └── main
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── ZipkinClientApplication0.java
│ │ │ └── resources
│ │ │ ├── application-docker.yml
│ │ │ └── application.yml
│ └── zipkin-client1
│ │ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── ZipkinClientApplication1.java
│ │ └── resources
│ │ ├── application-docker.yml
│ │ └── application.yml
└── zipkin-server
│ ├── build.gradle
│ └── src
│ └── main
│ ├── java
│ └── com
│ │ └── example
│ │ └── ZipkinServerApplication.java
│ └── resources
│ ├── application-docker.properties
│ └── application.properties
├── config
├── config-reader-with-bus
│ ├── SupportsRefreshingConfiguration.readMe
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── ConfigReaderWithBusApplication.java
│ │ └── resources
│ │ ├── bootstrap-docker.yml
│ │ └── bootstrap.yml
├── config-reader-with-bus0
│ ├── SupportsRefreshingConfiguration.readMe
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── ConfigReaderWithBusApplication0.java
│ │ └── resources
│ │ ├── bootstrap-docker.yml
│ │ └── bootstrap.yml
├── config-reader
│ ├── NoSupportsForRefreshingConfiguration.NotRecommendedForProduction.readMe
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── excample
│ │ │ └── ConfigReaderApplication.java
│ │ └── resources
│ │ ├── application-docker.yml
│ │ ├── application.yml
│ │ ├── bootstrap-docker.properties
│ │ └── bootstrap.properties
└── config-server
│ ├── build.gradle
│ └── src
│ └── main
│ ├── java
│ └── com
│ │ └── example
│ │ └── demo
│ │ └── ConfigServerApplication.java
│ └── resources
│ ├── application-docker.properties
│ └── application.properties
├── discovery
├── eureka-demo-client
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── EurekaDemoClientApplication.java
│ │ └── resources
│ │ ├── application-docker.yml
│ │ ├── application.yml
│ │ └── static
│ │ └── index.html
├── eureka-demo-client0
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── EurekaDemoClientApplication0.java
│ │ └── resources
│ │ ├── application-docker.yml
│ │ └── application.yml
└── eureka-server
│ ├── build.gradle
│ └── src
│ └── main
│ ├── java
│ └── com
│ │ └── example
│ │ └── EurekaServerApplication.java
│ └── resources
│ ├── application-docker.yml
│ └── application.yml
├── gradle.properties
├── routing
├── routing-feign
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ ├── CallServiceHi.java
│ │ │ ├── HiController.java
│ │ │ └── RoutingDemoFeignApplication.java
│ │ └── resources
│ │ ├── application-docker.yml
│ │ └── application.yml
└── routing-ribbon
│ ├── build.gradle
│ └── src
│ └── main
│ ├── java
│ └── com
│ │ └── example
│ │ └── routingribbon
│ │ ├── HelloController.java
│ │ ├── HelloService.java
│ │ └── RoutingRibbonApplication.java
│ └── resources
│ ├── application-docker.yml
│ └── application.yml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /build/
3 | !gradle/wrapper/gradle-wrapper.jar
4 |
5 | ### STS ###
6 | .apt_generated
7 | .classpath
8 | .factorypath
9 | .project
10 | .settings
11 | .springBeans
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | nbproject/private/
21 | build/
22 | nbbuild/
23 | dist/
24 | nbdist/
25 | .nb-gradle/
26 |
27 | ### java ###
28 | *.class
29 | out/
30 | *.jar
31 | *.war
32 |
33 | ### Mac OS ###
34 | .DS_Store
35 | docker
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # springcloud-quickstart
2 | 这是一个基于gradle构建工具的spring cloud微服务框架超级简单入门教程。
3 | spring cloud为开发人员提供了快速搭建分布式系统的一整套解决方案,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等。它可以直接在PC上使用Java的main方法运行集群。
4 | 另外说明spring cloud是基于springboot的,所以需要开发中对springboot有一定的了解。
5 | 本教程是教你如何使用spring cloud,以及构建镜像和本地单机运行集群,如果你需要学习更高级集群部署技术以及devops/CI/CD,比如docker swarm, kubernetes以及rancher等等,请点star给我继续补充的动力。
6 |
7 | **最近在推广我自己开源的生产级高性能响应式的微服务框架,学习成本相对springcloud低很多,有兴趣的可以关注一下**
8 | https://github.com/xiancloud/xian
9 |
10 | ## spring cloud依赖管理
11 | 1. 在/gradle.properties文件内申明gradle全局公共变量。我们主要用它来定义springCloud版本号,springboot版本号,以及其他一些公共变量
12 | ```properties
13 | ## dependency versions.
14 | springBootVersion=1.5.8.RELEASE
15 | springCloudVersion=Edgware.RELEASE
16 | ### docker configuration
17 | #gradle docker plugin version
18 | transmodeGradleDockerVersion=1.2
19 | #This configuration is for docker container environment to access the local machine host,in Chinese is "宿主机" ip.
20 | hostMachineIp=10.40.20.54
21 | ```
22 | 2. 在/build.gradle文件内申明springboot gradle插件
23 | ```gradle
24 | buildscript {
25 | repositories {
26 | maven { url "https://repo.spring.io/libs-milestone/" }
27 | jcenter()
28 | }
29 | dependencies {
30 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
31 | }
32 | }
33 | ```
34 | 3. 在/build.gradle文件内为所有gradle project引入springcloud公共依赖
35 | ```gradle
36 | allprojects {
37 | apply plugin: 'org.springframework.boot'
38 | repositories {
39 | maven { url "https://repo.spring.io/libs-milestone/" }
40 | jcenter()
41 | }
42 | dependencyManagement {
43 | imports {
44 | //spring bom helps us to declare dependencies without specifying version numbers.
45 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
46 | }
47 | }
48 | }
49 | ```
50 | 注意,上面imports的mavenBom非常重要,它帮我们管理了springCloud各种零散的jar包的版本。有了它,我们在对springCloud组件的依赖引入时,不需要指定具体的组件版本了,这简直是炒鸡方便啊。
51 |
52 | 4. /settings.gradle文件
53 | 它的作用是帮我们在IDE内自动组织项目结构(project structures)的,帮我们避开idea/eclipse内配置工程结构的复杂操作,有兴趣可以读一下源码。
54 |
55 | ## 服务注册中心/discovery/eureka-server
56 | 1. 本示例使用的是Spring Cloud Netflix Eureka ,eureka是一个服务注册和发现模块,公共依赖部分已经在根路径的build.gradle中给出,
57 | eureka-server模块自身依赖在/discovery/eureka-server/build.gradle文件配置如下:
58 | ```gradle
59 | dependencies {
60 | compile('org.springframework.cloud:spring-cloud-starter-eureka-server')
61 | }
62 | ```
63 | 2. eureka是一个高可用的组件,不依赖后端缓存,每一个实例注册之后需要向注册中心发送心跳,是在eureka-server的内存中完成的,在默认情况下erureka-server也是一个eureka client,必须要指定一个server地址。eureka-server的配置文件appication.yml:
64 | ```yml
65 | server:
66 | port: 8761
67 | eureka:
68 | instance:
69 | hostname: localhost
70 | client:
71 | registerWithEureka: false
72 | fetchRegistry: false
73 | service-url:
74 | defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
75 | ```
76 | 另请注意一点:很多网上的教程以及spring官方的教程上将'service-url'写成'serviceUrl'这是错误的!
77 | 3. eureka-server的springboot入口main application类:
78 | ```java
79 | @EnableEurekaServer
80 | @SpringBootApplication
81 | public class EurekaServerApplication {
82 | public static void main(String[] args) {
83 | SpringApplication.run(EurekaServerApplication.class, args);
84 | }
85 | }
86 | ```
87 | 启动这个main方法,然后访问 http://localhost:8761
88 | 代码详见/discovery/eureka-server模块。
89 | 4. eureka-client服务注册客户端(service provider)
90 | 服务提供方,比如一个微服务,作为eureka client身份可以将自己的信息注册到注册中心eureka-server内。
91 | /discovery/eureka-demo-client/build.gradle文件指定依赖如下:
92 | ```gradle
93 | dependencies {
94 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
95 | }
96 | ```
97 | springboot入口main类:com.example.EurekaDemoClientApplication.java
98 | ```java
99 | @SpringBootApplication
100 | @EnableDiscoveryClient
101 | @RestController
102 | public class EurekaDemoClientApplication {
103 | public static void main(String[] args) {
104 | SpringApplication.run(EurekaDemoClientApplication.class, args);
105 | }
106 | @Value("${server.port}")
107 | private int port;
108 |
109 | @RequestMapping("/hi")
110 | public String hi() {
111 | return "hi, my port=" + port;
112 | }
113 | }
114 | ```
115 | application.yml
116 | ```
117 | eureka:
118 | client:
119 | service-url:
120 | defaultZone: http://localhost:8761/eureka/
121 | server:
122 | port: 8763
123 | spring:
124 | application:
125 | name: eureka-demo-client
126 | ```
127 | 执行main方法启动springboot后,可以访问http://localhost:8763/hi 查看springboot restApi效果。
128 | 访问http://localhost:8761 (eureka-server控制台)查看服务注册效果。
129 | 依次类推,再启动另外一个/discovery/eureka-demo-client0,请再次查看服务注册效果。
130 |
131 | ### 服务路由和负载均衡/routing
132 | 以上/discovery/eureka-demo-client和/discovery/eureka-demo-client0我们可以把它看作是服务提供者service provider,这里开始定义服务消费者,即对服务提供者进行调用的的客户端。
133 | 当同一个微服务启动了多个副本节点后,我们对该服务的调用就需要一个负载均衡器来选择其中一个节点来进行调用,这就是springcloud-ribbon提供的功能。而feign则是对springcloud ribbon的一个封装,方便使用的。这里不深入介绍ribbon了,它本质就是一个借助服务注册发现实现的一个负载均衡器。
134 | 下面来分析feign源码:
135 | /routing/routing-feign/build.gradle
136 | ```gradle
137 | dependencies{
138 | compile "org.springframework.cloud:spring-cloud-starter-feign"
139 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
140 | }
141 | ```
142 | com.example.RoutingDemoFeignApplication.java
143 | ```java
144 | @SpringBootApplication
145 | @EnableDiscoveryClient
146 | @EnableFeignClients
147 | public class RoutingDemoFeignApplication {
148 | public static void main(String[] args) {
149 | SpringApplication.run(RoutingDemoFeignApplication.class, args);
150 | }
151 | }
152 | ```
153 | com.example.CallHiService.java接口,指明service provider微服务名: eureka-demo-client
154 | ```java
155 | @FeignClient(value = "eureka-demo-client")
156 | public interface CallServiceHi {
157 | @RequestMapping(value = "/hi", method = RequestMethod.GET)
158 | String sayHiFromClientOne(@RequestParam(value = "name") String name);
159 | }
160 | ```
161 | com.example.HiController.java 方便我们验证负载均衡结果:
162 | ```java
163 | @RestController
164 | public class HiController {
165 | @Autowired
166 | private CallServiceHi hiServiceCaller;
167 |
168 | @RequestMapping("hi")
169 | public String hi(@RequestParam String name) {
170 | return hiServiceCaller.sayHiFromClientOne(name);
171 | }
172 | }
173 | ```
174 | application.yml需要指明服务注册中心的地址,从而可以获取到所有目标节点信息,从而实现负载的功能
175 | ```yml
176 | eureka:
177 | client:
178 | service-url:
179 | defaultZone: http://localhost:8761/eureka/
180 | server:
181 | port: 8765
182 | spring:
183 | application:
184 | name: service-feign
185 | ```
186 | 运行main方法,启动springboot,然后请多次访问http://localhost:8765/hi?name=happyyangyuan 查看负载效果。
187 | 预期的输出结果轮流为:hi happyyangyuan, my port=8763 / hi happyyangyuan, my port=8762
188 |
189 | ### 调用链追踪/call-chain
190 | /call-chain内的demo展示的是使用Spring Cloud Sleuth实现的分布式系统的调用链追踪方案,它兼容支持了zipkin,只需要在build.gradle文件中引入相应的依赖即可。
191 | #### /call-chain/zipkin-server
192 | 顾名思义,就是springCloud Sleuth内置的zipkin-server集成,以来配置/call-chain/zipkin-server/build.gradle:
193 | ```gradle
194 | dependencies {
195 | compile "io.zipkin.java:zipkin-server"
196 | compile "io.zipkin.java:zipkin-autoconfigure-ui"
197 | }
198 | ```
199 | com.example.ZipkinServerApplication.java,注意加入@EnableZipkinServer注解:
200 | ```java
201 | @SpringBootApplication
202 | @EnableZipkinServer
203 | public class ZipkinServerApplication {
204 | public static void main(String[] args) {
205 | SpringApplication.run(ZipkinServerApplication.class, args);
206 | }
207 | }
208 | ```
209 | application.properties指明zipkin端口
210 | ```
211 | server.port=9411
212 | ```
213 | 执行com.example.ZipkinServerApplication.java的main方法启动,然后访问http://localhost:9411
214 | #### /call-chain/zipkin-clients调用链模拟
215 | 这里模拟调用链: zipkin-client --调用--> zipkin-client0 --调用--> zipkin-client1
216 | ##### /call-chain/zipkin-clients/build.gradle指定三个zipkinClients的公共依赖配置:
217 | ```gradle
218 | subprojects{
219 | dependencies {
220 | compile 'org.springframework.cloud:spring-cloud-starter-zipkin'
221 | /*这两个依赖已经被传递依赖了,因此不需要申明
222 | compile "org.springframework.cloud:spring-cloud-sleuth-zipkin-stream"
223 | compile "org.springframework.cloud:spring-cloud-starter-sleuth"*/
224 | compile "org.springframework.cloud:spring-cloud-starter-feign"
225 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
226 | }
227 | }
228 | ```
229 | 注意到,服务调用我们使用的的是feign客户端,并且引入了服务发现eureka客户端和zipkin客户端。
230 | ##### zipkin客户端配置
231 | 配置文件依然是/call-chain/zipkin-clients/zipkin-client/src/main/resources/application.properties
232 | ```
233 | server.port=8988
234 | spring.zipkin.base-url=http://localhost:9411
235 | spring.application.name=zipkin-client
236 | eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
237 | #The percentage of call-chaining messages to be sent to sleuth provider (zipkin for example).
238 | #Value range is 0.0~1.0, defaults to 0.1
239 | spring.sleuth.sampler.percentage=1
240 | ```
241 | 上面的配置文件,注意一下三点
242 | - 给定zipkin-server端地址:spring.zipkin.base-url=http://localhost:9411
243 | - 给定eureka-server地址:eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
244 | - 方便调试给定调用链追踪数据采用比例为100%,对应配置值为1,取值范围是0~1:spring.sleuth.sampler.percentage=1
245 | ##### zipkin客户端ZipkinClientApplication代码逻辑
246 | com.example.ZipkinClientApplication.java使用feign实现了对zipkin-client0的调用:
247 | ```java
248 | @SpringBootApplication
249 | @RestController
250 | @EnableDiscoveryClient
251 | @EnableFeignClients
252 | public class ZipkinClientApplication {
253 | public static void main(String[] args) {
254 | SpringApplication.run(ZipkinClientApplication.class, args);
255 | }
256 | @Autowired
257 | private FeignServiceInterface feignService;
258 | @RequestMapping(value = "/")
259 | public String home() {
260 | return feignService.callServiceFeign("no name");
261 | }
262 | @FeignClient(value = "zipkin-client0")
263 | public interface FeignServiceInterface {
264 | @RequestMapping(value = "/", method = RequestMethod.GET)
265 | String callServiceFeign(@RequestParam(value = "name") String name);
266 | }
267 | }
268 | ```
269 | 不知道你注意到没有,zipkin客户端激活功能不需要什么鬼类似“@EnableXxx”之类的注解,满足以下两点就可以激活zipkin客户端了数据采集了:
270 | - 配置zipkin-server访问地址
271 | - 引入zipkin 客户端依赖
272 | 就是这么简单!
273 | 其他两个zipkin-client0、zipkin-client1依次类推,我就不再粘贴代码了。
274 | #### 验证调用链看效果
275 | 启动zipkin-server、zipkin-client、zipkin-client0、zipkin-client1,启动方式你们都懂的。
276 | 然后访问http://localhost:8988 即可将调用链日志数据发送给zipkin-server,然后你再访问http://localhost:9411 查看调用链的展示。界面操作太简单,我就不贴图了。
277 |
278 | ### 集中配置管理/config
279 | 在实际微服务实现的分布式应用中,微服务数量是比较多的,节点数就更多了,我们不可能去每个节点里面去修改和维护那些配置文件的。我们需要一个统一的地方去定义和管理这些配置,springCloud Config提供了这样一个功能,我们只需要使用VCS版本管理控制系统比如git来维护一份统一配置,然后由springCloudConfig server读取这些配置,并可以提供给其他所有springCloudConfig Client来读取。使用VCS不仅可以让我们可以追溯所有的历史版本的配置文件,而且也实现了统一管理。
280 | #### config server
281 | demo在/config/config-server内
282 | 先引入config需要的依赖,build.gradle:
283 | ```gradle
284 | dependencies {
285 | compile('org.springframework.cloud:spring-cloud-config-server')
286 | }
287 | ```
288 | com.example.ConfigServerApplication.java加入@EnableConfigServer注解
289 | ```java
290 | @EnableConfigServer
291 | @SpringBootApplication
292 | public class ConfigServerApplication {
293 | public static void main(String[] args) {
294 | SpringApplication.run(ConfigServerApplication.class, args);
295 | }
296 | }
297 | ```
298 | application.properties:
299 | ```properties
300 | spring.application.name=config-server
301 | server.port=8888
302 | ##spring.cloud.config.server.git.uri
303 | # Please change the following configuration to point to your own configuration git repo url.
304 | spring.cloud.config.server.git.uri=https://github.com/happyyangyuan/springcloud-configuration.git
305 | # Local git repo url for test only.
306 | # spring.cloud.config.server.git.uri=${HOME}/ideaProjects/spring/configurations-demo-git
307 | # in case of the default /tmp dir deletion.
308 | spring.cloud.config.server.git.basedir=config-repo
309 | #Branch name for the repository.
310 | spring.cloud.config.label=master
311 | ```
312 | 这里配置文件注意几点:
313 | - 既可以使用远程git地址也可以使用本地git哦,比如你做测试做实验时。
314 | - linux系统内config server默认是将git文件缓存在在本地的/tmp路径内,但是许多Linux系统会定期清理/tmp文件的,导致配置失效。
315 |
316 | #### config client
317 | 在实际分布式应用里面,很多微服务应用都有自己独立的配置文件的,由于分布式应用比较分散,管理麻烦,因此我们可以考虑把微服务连接到spring cloud config server上,从config server读取集中配置。
318 | ##### 一个简单的config reader
319 | demo在 /config/config-reader路径内
320 | 依赖引入:
321 | ```build.gradle
322 | dependencies {
323 | compile "org.springframework.cloud:spring-cloud-starter-config"
324 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
325 | }
326 | ````
327 | bootstrap.properties
328 | ```properties
329 | spring.application.name=config-reader
330 | spring.cloud.config.label=master
331 | spring.cloud.config.profile=profileName
332 | spring.cloud.config.uri=http://localhost:8888/
333 | ```
334 | application.yml
335 | ```yml
336 | server:
337 | port: 8881
338 | eureka:
339 | client:
340 | service-url:
341 | defaultZone: http://localhost:8761/eureka/
342 | ```
343 | 注意事项:
344 | - spring.cloud.config.label=master配置是指定config客户端读取远程git哪个分支,如果不配置,就是读取config-server给定的默认分支了。
345 | - spring.cloud.config.profile=profileName是指定config客户端读取远程git内application-profileName.properties而文件配置的。
346 | - 如果找不到对应配置就会fall back到“通用层”配置文件。
347 | - bootstrap先于application配置加载,一些基础配置要放在bootstrap里面,基础配置如demo所示。
348 | com.example.ConfigReaderApplication.java
349 | ```java
350 | @SpringBootApplication
351 | @RestController
352 | @EnableDiscoveryClient
353 | public class ConfigReaderApplication {
354 | public static void main(String[] args) {
355 | SpringApplication.run(ConfigReaderApplication.class, args);
356 | }
357 | @Value("${message}")
358 | private String value;
359 | @RequestMapping(value = "/")
360 | public String read() {
361 | return value;
362 | }
363 | }
364 | ```
365 | 启动application,然后访问http://localhost:8881 查看效果吧。
366 |
367 | ##### spring cloud bus 消息总线
368 | 不知道你有没有发现,即使你把git内的配置修改了,以上config-reader是没法自动刷新配置的,必须重启服务才可以。spring cloud bus可以解决这个问题,让我们的配置可以动态刷新。
369 | 这里以/config/config-reader-with-bus为例来讲解。
370 | 引入依赖,build.gradle:
371 | ```gradle
372 | dependencies {
373 | compile "org.springframework.cloud:spring-cloud-starter-bus-amqp"
374 | compile "org.springframework.cloud:spring-cloud-starter-config"
375 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
376 | }
377 | ```
378 | 这里引入了一个spring-cloud-starter-bus-amqp,它是spring cloud bus规范的一种实现,基于amqp协议。接入我们比较熟悉的rabbitMQ队列服务。
379 | bootstrap.yml配置如下:
380 | ```yml
381 | server:
382 | port: 8882
383 | eureka:
384 | client:
385 | service-url:
386 | defaultZone: http://localhost:8761/eureka/
387 | spring:
388 | application:
389 | name: config-reader
390 | cloud:
391 | config:
392 | label: master
393 | profile: dev
394 | uri: http://localhost:8888/
395 | rabbitmq:
396 | host: yourRabbitMqHost
397 | port: 000 #yourRabbitPort
398 | username: rabbitUserName
399 | password: rabbitUserPwd
400 | management:
401 | security:
402 | enabled: false
403 | ```
404 | 注意事项:
405 | - rabbitmq客户端配置请自行填充以便你能完成本次demo效果测试。
406 | - management.security.enabled=false配置是为了方便我们后面测试的,后面详细说明。
407 | com.example.ConfigReaderWithBusApplication类
408 | ```java
409 | @SpringBootApplication
410 | @EnableDiscoveryClient
411 | @RestController
412 | @RefreshScope
413 | public class ConfigReaderWithBusApplication {
414 | public static void main(String[] args) {
415 | SpringApplication.run(ConfigReaderWithBusApplication.class, args);
416 | }
417 | /**
418 | * Waning: {@link RefreshScope} does not support private properties
419 | */
420 | @Value("${message}")
421 | String message;
422 | @RequestMapping("/")
423 | public String home() {
424 | return message;
425 | }
426 | }
427 | ```
428 | 注意事项:
429 | - @RefreshScope注解是必须的,否则无法实现动态刷新配置
430 | - @Value("${message}")注解的成员必须不能是private私有,否则无法刷新。这是我测试得到的结论,各位也可以自行验证一下。
431 |
432 | 启动application,然后访问http://localhost:8882 看看配置是否读取出来。然后修改你的git对应的配置文件,然后用postman/curl等http客户端工具调用如下API:http://localhost:8882/bus/refresh 触发配置更新,如果提示无权限调用此接口,可以配置为禁用management.security.enabled=false,然后再次访问http://localhost:8882 看看配置是否有更新。
433 | -/config/config-reader-with-bus0是另外一个config client的demo,它是用来验证一次刷新/bus/refresh则所有支持了消息总线的客户端都统一自动刷新配置的功能。亲,动手试试吧。
434 |
435 |
436 | ### 服务网关/api-gateway
437 | 本demo /api-gateway/zuul 展示的是使用spring cloud Zuul实现的网关服务。Zuul的主要功能是路由转发和过滤器,路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能。
438 | 依赖管理build.gradle:
439 | ```gradle
440 | dependencies {
441 | compile "org.springframework.cloud:spring-cloud-starter-zuul"
442 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
443 | }
444 | ```
445 | 注意这里,ribbon的依赖不需要加入,因为它会被zuul传递依赖得到,服务发现客户端依赖spring-cloud-starter-eureka必须要加入。
446 |
447 | application.yml
448 | ```yml
449 | server:
450 | port: 8769
451 | eureka:
452 | client:
453 | service-url:
454 | defaultZone: http://localhost:8761/eureka
455 | spring:
456 | application:
457 | name: zuul
458 | zuul:
459 | routes:
460 | api0:
461 | path: /api0/**
462 | serviceId: eureka-demo-client
463 | ```
464 | 根据配置的转发规则可以看到,对zuul的/api0/** 的请求将全部转发到服务eureka-demo-client上,我们可以在这里配置多个路由转发规则。
465 |
466 | com.example.ZuulApplication
467 | ```java
468 | @EnableDiscoveryClient
469 | @EnableZuulProxy
470 | @SpringBootApplication
471 | public class ZuulApplication {
472 | public static void main(String[] args) {
473 | SpringApplication.run(ZuulApplication.class, args);
474 | }
475 | }
476 | ```
477 | 启动ZuulApplication查看效果: http://localhost:8769/api0/hi?name=happyyangyuan
478 |
479 |
480 | ### 断路器 待补充
481 | 待补充
482 |
483 | ### 容器化运行方案
484 | 1. 先新建一个容器网络,以便多个容器(微服务)之间可以相互通信,命令为
485 | ```docker network create springcloud-quickstart```
486 | 2. 修改根路径内的gradle.properties文件中的"hostMachineIp"配置为宿主机IP地址,这很重要!
487 | 3. 在根目录执行gradle dockerBuild命令,构建完毕后,可使用docker images查看。
488 | 4. 由于几乎所有的其他微服务组件都依赖服务发现,因此先启动服务注册服务端,使用如下命令运行:
489 | ```docker run --network springcloud-quickstart -p 8761:8761 com.example/eureka-server:0.0.1-SNAPSHOT```
490 | 发现服务(eureka-server)需要端口暴露,以便我们可以在容器外面访问到它的控制台,地址是http://localhost:8761 ,建议端口映射与内部端口一致。
491 | 5. 启动其他服务,启动方式依次类推,除了zipkin-server和zuul网关,其他微服务组件是可以不暴露端口到外部的,列举几个关键节点启动命令。
492 | * zuul网关启动
493 | ```docker run --network springcloud-quickstart -p 8769:8769 com.example/zuul:0.0.1-SNAPSHOT```
494 | * zipkin调用链追踪
495 | ```docker run --network springcloud-quickstart -p 9411:9411 com.example/zipkin-server:0.0.1-SNAPSHOT```
496 | * 配置服务器启动
497 | ```docker run --network springcloud-quickstart -p 8888:8888 com.example/config-server:0.0.1-SNAPSHOT```
498 | * 其他
499 | ```docker run --network springcloud-quickstart com.example/:0.0.1-SNAPSHOT```
500 | ### 关于容器化构建的附加说明
501 | 1. gradle dockerBuild命令会遍历所有子project,并自动构建出所有微服务的镜像。我使用的是alpine+jre8,如果本地没有这个镜像,会从dockerHub下载alpine-jre基础镜像,第一次可能会比较久。alpine+jre整个基础镜像是80m左右,主要是jre比较大,再加上springCloud微服务的n多个jar包,最终应用镜像大小是120m左右。算是目前我能做到的最小的镜像。小归小,但是也有缺点:
502 | * alpine系统内置的不是我们熟悉的bash shell,而是ash shell。
503 | * 内置的jre,不提供jdk的很多调试命令,爱搞jvm调试的你们懂得。
504 | 2. 我们使用的是se.transmode.gradle:gradle-docker插件,有兴趣可以GitHub查看它的使用说明。
505 |
506 | **请按顺序学习,日后star数增加后我会补充更多细节...**
507 |
--------------------------------------------------------------------------------
/api-gateway/zuul/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 | compile "org.springframework.cloud:spring-cloud-starter-zuul"
3 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
4 | }
--------------------------------------------------------------------------------
/api-gateway/zuul/src/main/java/com/example/ZuulApplication.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
7 |
8 | /**
9 | * Created by happyyangyuan at 2017/11/27
10 | */
11 | @EnableDiscoveryClient
12 | @EnableZuulProxy
13 | @SpringBootApplication
14 | public class ZuulApplication {
15 | public static void main(String[] args) {
16 | SpringApplication.run(ZuulApplication.class, args);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/api-gateway/zuul/src/main/resources/application-docker.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://${HOST_MACHINE_IP}:8761/eureka
--------------------------------------------------------------------------------
/api-gateway/zuul/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8769
3 |
4 | eureka:
5 | client:
6 | service-url:
7 | defaultZone: http://localhost:8761/eureka
8 |
9 | spring:
10 | application:
11 | name: zuul
12 |
13 | zuul:
14 | routes:
15 | api0:
16 | path: /api0/**
17 | serviceId: eureka-demo-client
18 | # api1:
19 | # path: /api1/**
20 | # serviceId: eureka-demo-client0 there is no 'eureka-demo-client0' in the demo.
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
4 | maven { url "https://oss.sonatype.org/content/groups/public/" }
5 | maven { url "https://repo.spring.io/libs-milestone/" }
6 | jcenter()
7 | mavenCentral()
8 | }
9 | dependencies {
10 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
11 | classpath "se.transmode.gradle:gradle-docker:${transmodeGradleDockerVersion}"
12 | }
13 | }
14 | allprojects {
15 | apply plugin: 'java'
16 | apply plugin: 'org.springframework.boot'
17 | apply plugin: 'idea'
18 |
19 | group = 'com.example'
20 | version = '0.0.1-SNAPSHOT'
21 | sourceCompatibility = 1.8
22 |
23 | repositories {
24 | maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
25 | maven { url "https://oss.sonatype.org/content/groups/public/" }
26 | maven { url "https://repo.spring.io/libs-milestone/" }
27 | jcenter()
28 | mavenCentral()
29 | }
30 |
31 | dependencies {
32 | testCompile "org.springframework.boot:spring-boot-starter-test"
33 | }
34 |
35 | dependencyManagement {
36 | imports {
37 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
38 | }
39 | }
40 |
41 | if (project.subprojects) {
42 | bootRepackage {
43 | enabled = false
44 | }
45 | } else {
46 | apply plugin: 'docker'
47 | docker {
48 | maintainer = 'happyyangyuan '
49 | baseImage = 'openjdk:8-jre-alpine'
50 | }
51 | task dockerBuild(type: Docker, dependsOn: build) {
52 | applicationName = project.name
53 | addFile {
54 | from configurations.archives.artifacts.files
55 | into '/data/workspace/' + project.name
56 | }
57 | workingDir '/data/workspace/' + project.name
58 | setEnvironment('HOST_MACHINE_IP', hostMachineIp)
59 | defaultCommand(['java', '-jar', '-Dspring.profiles.active=docker', "${project.name}-${project.version}.jar"])
60 | }
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/call-chain/README.md:
--------------------------------------------------------------------------------
1 | This example demonstrates the following call chaining:
2 |
3 | zipkin-client --> zipkin-client0 --> zipkin-client1
4 |
5 | We use feign with service discovery to route requests to the destiny nodes.
6 | To run these zipkin-clients, the discovery eureka-server must be running.
--------------------------------------------------------------------------------
/call-chain/zipkin-clients/build.gradle:
--------------------------------------------------------------------------------
1 | subprojects{
2 | dependencies {
3 | compile 'org.springframework.cloud:spring-cloud-starter-zipkin'
4 | /*compile "org.springframework.cloud:spring-cloud-sleuth-zipkin-stream"*/
5 | /*compile "org.springframework.cloud:spring-cloud-starter-sleuth"*/
6 | compile "org.springframework.cloud:spring-cloud-starter-feign"
7 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
8 | }
9 | }
--------------------------------------------------------------------------------
/call-chain/zipkin-clients/zipkin-client/src/main/java/com/example/ZipkinClientApplication.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
7 | import org.springframework.cloud.netflix.feign.EnableFeignClients;
8 | import org.springframework.cloud.netflix.feign.FeignClient;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.RequestMethod;
11 | import org.springframework.web.bind.annotation.RequestParam;
12 | import org.springframework.web.bind.annotation.RestController;
13 |
14 | /**
15 | * Created by happyyangyuan at 2017/11/21
16 | */
17 | @SpringBootApplication
18 | @RestController
19 | @EnableDiscoveryClient
20 | @EnableFeignClients
21 | public class ZipkinClientApplication {
22 |
23 | public static void main(String[] args) {
24 | SpringApplication.run(ZipkinClientApplication.class, args);
25 | }
26 |
27 | @Autowired
28 | private FeignServiceInterface feignService;
29 |
30 | @RequestMapping(value = "/")
31 | public String home() {
32 | System.out.println("ZipkinClientApplication 00000000000000000");
33 | return feignService.callServiceFeign("no name");
34 | }
35 |
36 | @FeignClient(value = "zipkin-client0")
37 | public interface FeignServiceInterface {
38 | @RequestMapping(value = "/", method = RequestMethod.GET)
39 | String callServiceFeign(@RequestParam(value = "name") String name);
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/call-chain/zipkin-clients/zipkin-client/src/main/resources/application-docker.properties:
--------------------------------------------------------------------------------
1 | spring.zipkin.base-url=http://${HOST_MACHINE_IP}:9411
2 | eureka.client.service-url.defaultZone=http://${HOST_MACHINE_IP}:8761/eureka/
--------------------------------------------------------------------------------
/call-chain/zipkin-clients/zipkin-client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8988
2 | spring.zipkin.base-url=http://localhost:9411
3 | spring.application.name=zipkin-client
4 | eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
5 | #The percentage of call-chaining messages to be sent to sleuth provider (zipkin for example).
6 | #Value range is 0.0~1.0, defaults to 0.1
7 | spring.sleuth.sampler.percentage=1
--------------------------------------------------------------------------------
/call-chain/zipkin-clients/zipkin-client0/src/main/java/com/example/ZipkinClientApplication0.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
7 | import org.springframework.cloud.netflix.feign.EnableFeignClients;
8 | import org.springframework.cloud.netflix.feign.FeignClient;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.RequestParam;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | /**
14 | * Created by happyyangyuan at 2017/11/21
15 | */
16 | @EnableDiscoveryClient
17 | @EnableFeignClients
18 | @SpringBootApplication
19 | @RestController
20 | public class ZipkinClientApplication0 {
21 | public static void main(String[] args) {
22 | SpringApplication.run(ZipkinClientApplication0.class, args);
23 | }
24 |
25 | @Autowired
26 | ZipkinClientService1Interface zipkinClientService1;
27 |
28 | @RequestMapping("/")
29 | String home(@RequestParam("name") String name) {
30 | return zipkinClientService1.call(name);
31 | }
32 |
33 | @FeignClient("zipkin-client1")
34 | interface ZipkinClientService1Interface {
35 | @RequestMapping("/")
36 | String call(@RequestParam("name") String name);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/call-chain/zipkin-clients/zipkin-client0/src/main/resources/application-docker.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://${HOST_MACHINE_IP}:8761/eureka/
5 | spring:
6 | zipkin:
7 | base-url: http://${HOST_MACHINE_IP}:9411
--------------------------------------------------------------------------------
/call-chain/zipkin-clients/zipkin-client0/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://localhost:8761/eureka/
5 | server:
6 | port: 8989
7 | spring:
8 | application:
9 | name: zipkin-client0
10 | sleuth:
11 | sampler:
12 | percentage: 1
13 | zipkin:
14 | base-url: http://localhost:9411
--------------------------------------------------------------------------------
/call-chain/zipkin-clients/zipkin-client1/src/main/java/com/example/ZipkinClientApplication1.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 | import org.springframework.cloud.netflix.feign.EnableFeignClients;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.bind.annotation.RequestParam;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | /**
12 | * Created by happyyangyuan at 2017/11/21
13 | */
14 | @EnableDiscoveryClient
15 | @EnableFeignClients
16 | @SpringBootApplication
17 | @RestController
18 | public class ZipkinClientApplication1 {
19 | public static void main(String[] args) {
20 | SpringApplication.run(ZipkinClientApplication1.class, args);
21 | }
22 |
23 | @RequestMapping("/")
24 | String home(@RequestParam("name") String name) {
25 | System.out.println("00000000000000000 " + name);
26 | return "hello " + name;
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/call-chain/zipkin-clients/zipkin-client1/src/main/resources/application-docker.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://${HOST_MACHINE_IP}:8761/eureka/
5 | spring:
6 | zipkin:
7 | base-url: http://${HOST_MACHINE_IP}:9411
--------------------------------------------------------------------------------
/call-chain/zipkin-clients/zipkin-client1/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://localhost:8761/eureka/
5 | server:
6 | port: 8990
7 | spring:
8 | application:
9 | name: zipkin-client1
10 | sleuth:
11 | sampler:
12 | percentage: 1
13 | zipkin:
14 | base-url: http://localhost:9411
--------------------------------------------------------------------------------
/call-chain/zipkin-server/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 | compile "io.zipkin.java:zipkin-server"
3 | compile "io.zipkin.java:zipkin-autoconfigure-ui"
4 | }
--------------------------------------------------------------------------------
/call-chain/zipkin-server/src/main/java/com/example/ZipkinServerApplication.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import zipkin.server.EnableZipkinServer;
6 |
7 | /**
8 | * Created by happyyangyuan at 2017/11/21
9 | */
10 | @SpringBootApplication
11 | @EnableZipkinServer
12 | public class ZipkinServerApplication {
13 | public static void main(String[] args) {
14 | SpringApplication.run(ZipkinServerApplication.class, args);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/call-chain/zipkin-server/src/main/resources/application-docker.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyyangyuan/springcloud-quickstart/510e2ff5b4e8b34876a63dbfa0d35d6d910b1a0f/call-chain/zipkin-server/src/main/resources/application-docker.properties
--------------------------------------------------------------------------------
/call-chain/zipkin-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=9411
--------------------------------------------------------------------------------
/config/config-reader-with-bus/SupportsRefreshingConfiguration.readMe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyyangyuan/springcloud-quickstart/510e2ff5b4e8b34876a63dbfa0d35d6d910b1a0f/config/config-reader-with-bus/SupportsRefreshingConfiguration.readMe
--------------------------------------------------------------------------------
/config/config-reader-with-bus/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 | compile "org.springframework.cloud:spring-cloud-starter-bus-amqp"
3 | compile "org.springframework.cloud:spring-cloud-starter-config"
4 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
5 | /*
6 | compile "org.springframework.cloud:spring-retry"
7 | compile "org.springframework.cloud:spring-boot-starter-actuator"
8 | no need
9 | */
10 | }
--------------------------------------------------------------------------------
/config/config-reader-with-bus/src/main/java/com/example/ConfigReaderWithBusApplication.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
7 | import org.springframework.cloud.context.config.annotation.RefreshScope;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | /**
12 | * Created by happyyangyuan at 2017/11/21
13 | */
14 | @SpringBootApplication
15 | @EnableDiscoveryClient
16 | @RestController
17 | @RefreshScope
18 | public class ConfigReaderWithBusApplication {
19 | public static void main(String[] args) {
20 | SpringApplication.run(ConfigReaderWithBusApplication.class, args);
21 | }
22 |
23 | /**
24 | * Waning: {@link RefreshScope} does not support private properties
25 | */
26 | @Value("${message}")
27 | String message;
28 |
29 | @RequestMapping("/")
30 | public String home() {
31 | return message;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/config/config-reader-with-bus/src/main/resources/bootstrap-docker.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://${HOST_MACHINE_IP}:8761/eureka/
5 |
6 | spring:
7 | cloud:
8 | config:
9 | uri: http://${HOST_MACHINE_IP}:8888/
--------------------------------------------------------------------------------
/config/config-reader-with-bus/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8882
3 |
4 | eureka:
5 | client:
6 | service-url:
7 | defaultZone: http://localhost:8761/eureka/
8 |
9 | spring:
10 | application:
11 | name: config-reader
12 | cloud:
13 | config:
14 | label: master
15 | profile: dev
16 | uri: http://localhost:8888/
17 | rabbitmq:
18 | host: yourRabbitMqHost
19 | port: 000 #yourRabbitPort
20 | username: rabbitUserName
21 | password: rabbitUserPwd
22 | logging:
23 | level:
24 | org:
25 | springframework:
26 | cloud: DEBUG
27 | management:
28 | security:
29 | enabled: false
30 |
31 |
--------------------------------------------------------------------------------
/config/config-reader-with-bus0/SupportsRefreshingConfiguration.readMe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyyangyuan/springcloud-quickstart/510e2ff5b4e8b34876a63dbfa0d35d6d910b1a0f/config/config-reader-with-bus0/SupportsRefreshingConfiguration.readMe
--------------------------------------------------------------------------------
/config/config-reader-with-bus0/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 | compile "org.springframework.cloud:spring-cloud-starter-bus-amqp"
3 | compile "org.springframework.cloud:spring-cloud-starter-config"
4 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
5 | /*
6 | compile "org.springframework.cloud:spring-retry"
7 | compile "org.springframework.cloud:spring-boot-starter-actuator"
8 | no need
9 | */
10 | }
--------------------------------------------------------------------------------
/config/config-reader-with-bus0/src/main/java/com/example/ConfigReaderWithBusApplication0.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
7 | import org.springframework.cloud.context.config.annotation.RefreshScope;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | /**
12 | * Created by happyyangyuan at 2017/11/21
13 | */
14 | @SpringBootApplication
15 | @EnableDiscoveryClient
16 | @RestController
17 | @RefreshScope
18 | public class ConfigReaderWithBusApplication0 {
19 | public static void main(String[] args) {
20 | SpringApplication.run(ConfigReaderWithBusApplication0.class, args);
21 | }
22 |
23 | /**
24 | * Waning: {@link RefreshScope} does not support private properties
25 | */
26 | @Value("${message}")
27 | String message;
28 |
29 | @RequestMapping("/")
30 | public String home() {
31 | return message;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/config/config-reader-with-bus0/src/main/resources/bootstrap-docker.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://${HOST_MACHINE_IP}:8761/eureka/
5 |
6 | spring:
7 | cloud:
8 | config:
9 | uri: http://${HOST_MACHINE_IP}:8888/
--------------------------------------------------------------------------------
/config/config-reader-with-bus0/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8883
3 |
4 | eureka:
5 | client:
6 | service-url:
7 | defaultZone: http://localhost:8761/eureka/
8 |
9 | spring:
10 | application:
11 | name: config-reader
12 | cloud:
13 | config:
14 | label: master
15 | profile: dev
16 | uri: http://localhost:8888/
17 | rabbitmq:
18 | host: yourRabbitMqHost
19 | port: 000 #yourRabbitPort
20 | username: rabbitUserName
21 | password: rabbitUserPwd
22 | logging:
23 | level:
24 | org:
25 | springframework:
26 | cloud: DEBUG
27 | management:
28 | security:
29 | enabled: false
30 |
31 |
--------------------------------------------------------------------------------
/config/config-reader/NoSupportsForRefreshingConfiguration.NotRecommendedForProduction.readMe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyyangyuan/springcloud-quickstart/510e2ff5b4e8b34876a63dbfa0d35d6d910b1a0f/config/config-reader/NoSupportsForRefreshingConfiguration.NotRecommendedForProduction.readMe
--------------------------------------------------------------------------------
/config/config-reader/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 | compile "org.springframework.cloud:spring-cloud-starter-config"
3 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
4 | }
--------------------------------------------------------------------------------
/config/config-reader/src/main/java/com/excample/ConfigReaderApplication.java:
--------------------------------------------------------------------------------
1 | package com.excample;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.bind.annotation.RestController;
9 |
10 | /**
11 | * Created by happyyangyuan at 2017/11/20
12 | */
13 | @SpringBootApplication
14 | @RestController
15 | @EnableDiscoveryClient
16 | public class ConfigReaderApplication {
17 | public static void main(String[] args) {
18 | SpringApplication.run(ConfigReaderApplication.class, args);
19 | }
20 |
21 | @Value("${message}")
22 | private String value;
23 |
24 | @RequestMapping(value = "/")
25 | public String read() {
26 | return value;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/config/config-reader/src/main/resources/application-docker.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://${HOST_MACHINE_IP}:8761/eureka/
5 |
6 |
--------------------------------------------------------------------------------
/config/config-reader/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8881
3 |
4 | eureka:
5 | client:
6 | service-url:
7 | defaultZone: http://localhost:8761/eureka/
8 |
9 |
--------------------------------------------------------------------------------
/config/config-reader/src/main/resources/bootstrap-docker.properties:
--------------------------------------------------------------------------------
1 | spring.cloud.config.uri=http://${HOST_MACHINE_IP}:8888/
--------------------------------------------------------------------------------
/config/config-reader/src/main/resources/bootstrap.properties:
--------------------------------------------------------------------------------
1 | spring.application.name=config-reader
2 | spring.cloud.config.label=master
3 | spring.cloud.config.profile=dev
4 | spring.cloud.config.uri=http://localhost:8888/
5 | logging.level.org.springframework.cloud=DEBUG
--------------------------------------------------------------------------------
/config/config-server/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 | compile('org.springframework.cloud:spring-cloud-config-server')
3 | }
--------------------------------------------------------------------------------
/config/config-server/src/main/java/com/example/demo/ConfigServerApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.config.server.EnableConfigServer;
6 |
7 | @EnableConfigServer
8 | @SpringBootApplication
9 | public class ConfigServerApplication {
10 | public static void main(String[] args) {
11 | SpringApplication.run(ConfigServerApplication.class, args);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/config/config-server/src/main/resources/application-docker.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyyangyuan/springcloud-quickstart/510e2ff5b4e8b34876a63dbfa0d35d6d910b1a0f/config/config-server/src/main/resources/application-docker.properties
--------------------------------------------------------------------------------
/config/config-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.application.name=config-server
2 | server.port=8888
3 |
4 | ##spring.cloud.config.server.git.uri
5 | # Please change the following configuration to point to your own configuration git repo url.
6 | spring.cloud.config.server.git.uri=https://github.com/happyyangyuan/springcloud-configuration.git
7 |
8 | # Local git repo url for test only.
9 | # spring.cloud.config.server.git.uri=${HOME}/ideaProjects/spring/configurations-demo-git
10 |
11 | # in case of the default /tmp dir deletion.
12 | spring.cloud.config.server.git.basedir=config-repo
13 |
14 | #Branch name for the repository.
15 | spring.cloud.config.label=master
--------------------------------------------------------------------------------
/discovery/eureka-demo-client/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
3 | }
--------------------------------------------------------------------------------
/discovery/eureka-demo-client/src/main/java/com/example/EurekaDemoClientApplication.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.bind.annotation.RequestParam;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | /**
12 | * Created by happyyangyuan at 2017/11/20
13 | */
14 | @SpringBootApplication
15 | @EnableDiscoveryClient
16 | @RestController
17 | public class EurekaDemoClientApplication {
18 | public static void main(String[] args) {
19 | SpringApplication.run(EurekaDemoClientApplication.class, args);
20 | }
21 |
22 | @Value("${server.port}")
23 | private int port;
24 |
25 | @RequestMapping("hi")
26 | public String hi(@RequestParam(required = false) String name) {
27 | if (name == null)
28 | name = "Anonymous";
29 | return "hi " + name + ", my port=" + port;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/discovery/eureka-demo-client/src/main/resources/application-docker.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://${HOST_MACHINE_IP}:8761/eureka/
--------------------------------------------------------------------------------
/discovery/eureka-demo-client/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://localhost:8761/eureka/
5 | server:
6 | port: 8763
7 | spring:
8 | application:
9 | name: eureka-demo-client
10 |
--------------------------------------------------------------------------------
/discovery/eureka-demo-client/src/main/resources/static/index.html:
--------------------------------------------------------------------------------
1 |
2 | hello world.
3 | zh: 乱入一个静态页面,用来做测试的。
4 | en: Static page slips in for test.
5 |
--------------------------------------------------------------------------------
/discovery/eureka-demo-client0/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
3 | }
--------------------------------------------------------------------------------
/discovery/eureka-demo-client0/src/main/java/com/example/EurekaDemoClientApplication0.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.bind.annotation.RequestParam;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | /**
12 | * Created by happyyangyuan at 2017/11/20
13 | */
14 | @SpringBootApplication
15 | @EnableDiscoveryClient
16 | @RestController
17 | public class EurekaDemoClientApplication0 {
18 | public static void main(String[] args) {
19 | SpringApplication.run(EurekaDemoClientApplication0.class, args);
20 | }
21 |
22 | @Value("${server.port}")
23 | private int port;
24 |
25 | @RequestMapping("hi")
26 | public String hi(@RequestParam(required = false) String name) {
27 | if (name == null)
28 | name = "Anonymous";
29 | return "hi " + name + ", my port=" + port;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/discovery/eureka-demo-client0/src/main/resources/application-docker.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://${HOST_MACHINE_IP}:8761/eureka/
--------------------------------------------------------------------------------
/discovery/eureka-demo-client0/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://localhost:8761/eureka/
5 | server:
6 | port: 8762
7 | spring:
8 | application:
9 | name: eureka-demo-client
10 |
--------------------------------------------------------------------------------
/discovery/eureka-server/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 | compile('org.springframework.cloud:spring-cloud-starter-eureka-server')
3 | }
--------------------------------------------------------------------------------
/discovery/eureka-server/src/main/java/com/example/EurekaServerApplication.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
6 |
7 | /**
8 | * Created by happyyangyuan at 2017/11/18
9 | */
10 | @EnableEurekaServer
11 | @SpringBootApplication
12 | public class EurekaServerApplication {
13 | public static void main(String[] args) {
14 | SpringApplication.run(EurekaServerApplication.class, args);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/discovery/eureka-server/src/main/resources/application-docker.yml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyyangyuan/springcloud-quickstart/510e2ff5b4e8b34876a63dbfa0d35d6d910b1a0f/discovery/eureka-server/src/main/resources/application-docker.yml
--------------------------------------------------------------------------------
/discovery/eureka-server/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8761
3 |
4 | eureka:
5 | instance:
6 | hostname: localhost
7 | client:
8 | registerWithEureka: false
9 | fetchRegistry: false
10 | service-url:
11 | defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## dependency versions.
2 | springBootVersion=1.5.8.RELEASE
3 | springCloudVersion=Edgware.RELEASE
4 | ### docker configuration
5 | #gradle docker plugin version
6 | transmodeGradleDockerVersion=1.2
7 | #This configuration is for docker container environment to access the local machine host,in Chinese is "宿主机" ip.
8 | hostMachineIp=10.40.20.54
9 |
--------------------------------------------------------------------------------
/routing/routing-feign/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies{
2 | compile "org.springframework.cloud:spring-cloud-starter-feign"
3 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
4 | }
--------------------------------------------------------------------------------
/routing/routing-feign/src/main/java/com/example/CallServiceHi.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import org.springframework.cloud.netflix.feign.FeignClient;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.bind.annotation.RequestMethod;
6 | import org.springframework.web.bind.annotation.RequestParam;
7 |
8 | /**
9 | * Created by happyyangyuan at 2017/11/20
10 | */
11 | @FeignClient(value = "eureka-demo-client")
12 | public interface CallServiceHi {
13 | @RequestMapping(value = "/hi", method = RequestMethod.GET)
14 | String sayHiFromClientOne(@RequestParam(value = "name", required = false) String name);
15 | }
16 |
--------------------------------------------------------------------------------
/routing/routing-feign/src/main/java/com/example/HiController.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.bind.annotation.RequestParam;
6 | import org.springframework.web.bind.annotation.RestController;
7 |
8 | /**
9 | * Created by happyyangyuan at 2017/11/20
10 | */
11 | @RestController
12 | public class HiController {
13 | @Autowired
14 | private CallServiceHi hiServiceCaller;
15 |
16 | @RequestMapping("hi")
17 | public String hi(@RequestParam(required = false) String name) {
18 | return hiServiceCaller.sayHiFromClientOne(name);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/routing/routing-feign/src/main/java/com/example/RoutingDemoFeignApplication.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 | import org.springframework.cloud.netflix.feign.EnableFeignClients;
7 |
8 | /**
9 | * Created by happyyangyuan at 2017/11/20
10 | */
11 | @SpringBootApplication
12 | @EnableDiscoveryClient
13 | @EnableFeignClients
14 | public class RoutingDemoFeignApplication {
15 | public static void main(String[] args) {
16 | SpringApplication.run(RoutingDemoFeignApplication.class, args);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/routing/routing-feign/src/main/resources/application-docker.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://${HOST_MACHINE_IP}:8761/eureka/
--------------------------------------------------------------------------------
/routing/routing-feign/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://localhost:8761/eureka/
5 | server:
6 | port: 8765
7 | spring:
8 | application:
9 | name: service-feign
--------------------------------------------------------------------------------
/routing/routing-ribbon/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 | compile('org.springframework.cloud:spring-cloud-starter-ribbon')
3 | compile "org.springframework.cloud:spring-cloud-starter-eureka"
4 | }
5 |
--------------------------------------------------------------------------------
/routing/routing-ribbon/src/main/java/com/example/routingribbon/HelloController.java:
--------------------------------------------------------------------------------
1 | package com.example.routingribbon;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.bind.annotation.RequestParam;
6 | import org.springframework.web.bind.annotation.RestController;
7 |
8 | /**
9 | * Created by happyyangyuan at 2017/11/20
10 | */
11 | @RestController
12 | public class HelloController {
13 |
14 | private final HelloService helloService;
15 |
16 | @Autowired
17 | public HelloController(HelloService helloService) {
18 | this.helloService = helloService;
19 | }
20 |
21 | @RequestMapping(value = "/hi")
22 | public String hi(@RequestParam String name) {
23 | return helloService.hiService(name);
24 | }
25 |
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/routing/routing-ribbon/src/main/java/com/example/routingribbon/HelloService.java:
--------------------------------------------------------------------------------
1 | package com.example.routingribbon;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Service;
5 | import org.springframework.web.client.RestTemplate;
6 |
7 | /**
8 | * Created by happyyangyuan at 2017/11/20
9 | */
10 | @Service
11 | public class HelloService {
12 |
13 | @Autowired
14 | RestTemplate restTemplate;
15 |
16 | public String hiService(String name) {
17 | return restTemplate.getForObject("http://EUREKA-DEMO-CLIENT/hi?name=" + name, String.class);
18 | }
19 |
20 | }
--------------------------------------------------------------------------------
/routing/routing-ribbon/src/main/java/com/example/routingribbon/RoutingRibbonApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.routingribbon;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 | import org.springframework.cloud.client.loadbalancer.LoadBalanced;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.web.client.RestTemplate;
9 |
10 | @SpringBootApplication
11 | @EnableDiscoveryClient
12 | public class RoutingRibbonApplication {
13 |
14 | public static void main(String[] args) {
15 | SpringApplication.run(RoutingRibbonApplication.class, args);
16 | }
17 |
18 | @Bean
19 | @LoadBalanced
20 | RestTemplate restTemplate() {
21 | return new RestTemplate();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/routing/routing-ribbon/src/main/resources/application-docker.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://${HOST_MACHINE_IP}:8761/eureka/
--------------------------------------------------------------------------------
/routing/routing-ribbon/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | client:
3 | service-url:
4 | defaultZone: http://localhost:8761/eureka/
5 | server:
6 | port: 8764
7 | spring:
8 | application:
9 | name: service-ribbon
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /**
2 | * @author happyyangyuan created at 2017/11/22
3 | * Groovy script that includes modules automatically.
4 | */
5 | def dir = new File(settingsDir.toString())
6 | def projects = new HashSet()
7 | def projectSymbol = File.separator + 'src'
8 |
9 | dir.eachDirRecurse { subDir ->
10 | def subDirName = subDir.canonicalPath
11 | def isSubProject = true
12 | if (subDirName.endsWith(projectSymbol)) {
13 | for (String projectDir in projects) {
14 | if (subDirName.startsWith(projectDir)) {
15 | isSubProject = false
16 | break
17 | }
18 | }
19 | if (isSubProject) {
20 | projects << subDirName
21 | def lastIndex = subDirName.lastIndexOf(projectSymbol)
22 | def gradleModulePath = subDirName.substring(dir.canonicalPath.length(), lastIndex).replace(File.separator, ':')
23 | println "include " + gradleModulePath
24 | include gradleModulePath
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------