Skip to content

Commit 2646359

Browse files
author
litongjava
committed
tio-boot spring-cloud
1 parent 481587b commit 2646359

File tree

2 files changed

+388
-0
lines changed

2 files changed

+388
-0
lines changed

docs/.vuepress/config/sidebar-zh.json

+6
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@
168168
"collapsable": false,
169169
"children": ["25_性能测试/01.md"]
170170
},
171+
{
172+
"title": "26_spring-cloud",
173+
"collapsable": false,
174+
"children": ["26_spring-cloud/01.md"]
175+
},
176+
171177
{
172178
"title": "99_案例",
173179
"collapsable": false,

docs/zh/26_spring-cloud/01.md

+382
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,382 @@
1+
# tio-boot spring-cloud
2+
3+
## 概述
4+
5+
- tio-boot 完全支持 spring-cloud
6+
- 仅仅是 web 中间件使用 tio-boot-server,其他组件仍然是 spring-cloud
7+
8+
## tio-boot, Spring Cloud, 和 Consul
9+
10+
整合 tio-boot, Spring Cloud, 和 Consul 实现服务注册与发现是一种提升微服务架构可靠性和灵活性的有效方法。本文档将详细介绍如何创建两个服务,`spring-cloud-consul-product-service``spring-cloud-consul-order-service`,并通过 Consul 实现这两个服务的注册与发现。其中 `product-service` 提供接口,`order-service` 调用 `product-service` 的接口。
11+
12+
### 流程概述
13+
14+
1. **启动 Consul:** Consul 作为服务注册和服务发现的工具,可以通过简单的命令启动。
15+
2. **配置 `product-service`** 包括 Maven 依赖配置、application 属性配置、启动类和相关组件的配置,确保服务可以正确注册到 Consul。
16+
3. **配置 `order-service`** 类似于 `product-service`,配置相关依赖和属性,以及 RestTemplate 用于服务间的调用。
17+
4. **服务注册与发现:** 服务启动后,会自动注册到 Consul,`order-service` 可以通过 Consul 发现 `product-service` 并进行调用。
18+
19+
### 启动 Consul
20+
21+
在开始之前,确保你有 Consul 环境,可以通过以下命令启动 Consul:
22+
23+
```bash
24+
consul.exe agent -dev
25+
```
26+
27+
### `product-service`
28+
29+
1. **Maven 配置(pom.xml):** 定义了项目的 Java 版本、依赖项(包括 Spring Boot、tio-boot、Spring Cloud Consul Discovery 等)。
30+
31+
pom.xml
32+
33+
```
34+
<properties>
35+
<java.version>1.8</java.version>
36+
<maven.compiler.source>${java.version}</maven.compiler.source>
37+
<maven.compiler.target>${java.version}</maven.compiler.target>
38+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
39+
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
40+
<spring-boot.version>2.1.6.RELEASE</spring-boot.version>
41+
<tio-boot.version>1.3.9</tio-boot.version>
42+
<main.class>demo.ProductApp</main.class>
43+
</properties>
44+
45+
<dependencies>
46+
<dependency>
47+
<groupId>org.springframework.boot</groupId>
48+
<artifactId>spring-boot-starter-webflux</artifactId>
49+
<exclusions>
50+
<exclusion>
51+
<groupId>org.springframework.boot</groupId>
52+
<artifactId>spring-boot-starter-json</artifactId>
53+
</exclusion>
54+
<exclusion>
55+
<groupId>org.springframework.boot</groupId>
56+
<artifactId>spring-boot-starter-reactor-netty</artifactId>
57+
</exclusion>
58+
</exclusions>
59+
</dependency>
60+
61+
<dependency>
62+
<groupId>com.litongjava</groupId>
63+
<artifactId>tio-boot</artifactId>
64+
<version>${tio-boot.version}</version>
65+
</dependency>
66+
67+
68+
<dependency>
69+
<groupId>org.projectlombok</groupId>
70+
<artifactId>lombok</artifactId>
71+
<scope>provided</scope>
72+
</dependency>
73+
<dependency>
74+
<groupId>com.litongjava</groupId>
75+
<artifactId>hotswap-classloader</artifactId>
76+
<version>1.2.1</version>
77+
</dependency>
78+
79+
<!-- SpringBoot集成Test -->
80+
<dependency>
81+
<groupId>org.springframework.boot</groupId>
82+
<artifactId>spring-boot-starter-test</artifactId>
83+
<scope>test</scope>
84+
</dependency>
85+
86+
<dependency>
87+
<groupId>junit</groupId>
88+
<artifactId>junit</artifactId>
89+
<scope>test</scope>
90+
</dependency>
91+
92+
<!--SpringCloud提供的基于Consul的服务发现-->
93+
<dependency>
94+
<groupId>org.springframework.cloud</groupId>
95+
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
96+
</dependency>
97+
98+
<!--actuator用于心跳检查-->
99+
<dependency>
100+
<groupId>org.springframework.boot</groupId>
101+
<artifactId>spring-boot-starter-actuator</artifactId>
102+
</dependency>
103+
104+
</dependencies>
105+
106+
<build>
107+
<plugins>
108+
<!-- Spring Boot -->
109+
<plugin>
110+
<groupId>org.springframework.boot</groupId>
111+
<artifactId>spring-boot-maven-plugin</artifactId>
112+
<version>${spring-boot.version}</version>
113+
<configuration>
114+
<includeSystemScope>true</includeSystemScope>
115+
<!--使该插件支持热启动 -->
116+
<fork>true</fork>
117+
<mainClass>${main.class}</mainClass>
118+
</configuration>
119+
<!-- 设置执行目标 -->
120+
<executions>
121+
<execution>
122+
<goals>
123+
<goal>repackage</goal>
124+
</goals>
125+
</execution>
126+
</executions>
127+
</plugin>
128+
</plugins>
129+
</build>
130+
131+
<dependencyManagement>
132+
<dependencies>
133+
<dependency>
134+
<groupId>org.springframework.boot</groupId>
135+
<artifactId>spring-boot-dependencies</artifactId>
136+
<version>${spring-boot.version}</version>
137+
<type>pom</type>
138+
<scope>import</scope>
139+
</dependency>
140+
<dependency>
141+
<groupId>org.springframework.cloud</groupId>
142+
<artifactId>spring-cloud-dependencies</artifactId>
143+
<version>Greenwich.RELEASE</version>
144+
<type>pom</type>
145+
<scope>import</scope>
146+
</dependency>
147+
</dependencies>
148+
</dependencyManagement>
149+
```
150+
151+
2. **应用配置(application.yml):** 指定了服务的端口、应用名称和 Consul 服务器的地址。
152+
153+
application.yml
154+
155+
```
156+
server:
157+
port: 8001 #端口
158+
spring:
159+
application:
160+
#访问名称
161+
name: consul-provider-product
162+
cloud:
163+
consul:
164+
#服务地址
165+
host: localhost
166+
#服务端口
167+
port: 8500
168+
discovery:
169+
service-name: ${spring.application.name}
170+
171+
```
172+
173+
app.properties
174+
175+
```
176+
server.port=8001
177+
```
178+
179+
app.properties 和 application.yml 都需要指定端口
180+
181+
3. **启动类(ProductApp.java):** 标记了 Spring Boot 应用、启用了服务发现,并导入了必要的配置。
182+
183+
```
184+
package demo;
185+
186+
import org.springframework.boot.SpringApplication;
187+
import org.springframework.boot.autoconfigure.SpringBootApplication;
188+
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
189+
import org.springframework.context.annotation.Import;
190+
191+
import com.litongjava.jfinal.aop.annotation.AComponentScan;
192+
import com.litongjava.tio.boot.spring.SpringBootArgs;
193+
import com.litongjava.tio.boot.spring.TioBootServerAutoConfiguration;
194+
195+
@SpringBootApplication
196+
@EnableDiscoveryClient
197+
@AComponentScan
198+
@Import(TioBootServerAutoConfiguration.class)
199+
public class ProductApp {
200+
201+
public static void main(String[] args) {
202+
long start = System.currentTimeMillis();
203+
SpringBootArgs.set(ProductApp.class, args);
204+
SpringApplication.run(ProductApp.class, args);
205+
long end = System.currentTimeMillis();
206+
System.out.println((end - start) + "(ms)");
207+
}
208+
}
209+
210+
```
211+
212+
4. **RestTemplate 配置(ApplicationContextConfig.java):** 配置了 RestTemplate 并启用了负载均衡,使其可以通过服务名调用其他服务。
213+
214+
```
215+
package demo.config;
216+
217+
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
218+
import org.springframework.context.annotation.Bean;
219+
import org.springframework.context.annotation.Configuration;
220+
import org.springframework.web.client.RestTemplate;
221+
222+
import lombok.extern.slf4j.Slf4j;
223+
224+
@Configuration
225+
@Slf4j
226+
public class ApplicationContextConfig {
227+
228+
229+
@Bean
230+
@LoadBalanced
231+
public RestTemplate restTemplate() {
232+
RestTemplate restTemplate = new RestTemplate();
233+
log.info("restTemplate:{}", restTemplate.toString());
234+
return restTemplate;
235+
}
236+
}
237+
238+
```
239+
240+
5. **Tio-Boot 集成配置(SpringBeanContextConfig.java):** 配置了 tio-boot 与 Spring 的集成。
241+
242+
```
243+
package demo.config;
244+
245+
import org.springframework.beans.factory.annotation.Autowired;
246+
import org.springframework.context.ApplicationContext;
247+
import org.springframework.context.annotation.Bean;
248+
import org.springframework.context.annotation.Configuration;
249+
import org.springframework.context.annotation.DependsOn;
250+
251+
import com.litongjava.jfinal.aop.Aop;
252+
import com.litongjava.jfinal.aop.AopManager;
253+
import com.litongjava.jfinal.spring.SpringBeanContextUtils;
254+
255+
import lombok.extern.slf4j.Slf4j;
256+
257+
@Configuration
258+
@Slf4j
259+
public class SpringBeanContextConfig {
260+
261+
@Autowired
262+
private ApplicationContext applicationContext;
263+
264+
@Bean(destroyMethod = "close")
265+
@DependsOn("restTemplate")
266+
public void myBean() {
267+
log.info("add Autowired");
268+
// 开启和spring的整合
269+
AopManager.me().getAopFactory().setEnableWithSpring(true);
270+
SpringBeanContextUtils.setContext(applicationContext);
271+
// 让 tio-boot的bean支持Autowired注解
272+
Aop.addFetchBeanAnnotation(Autowired.class);
273+
}
274+
}
275+
276+
```
277+
278+
6. **健康控制器(ActuatorController.java):** 定义了对外提供的 健康 接口。consul 会通过这个接口检查应用是否健康
279+
ActuatorController
280+
281+
```
282+
package demo.controller;
283+
284+
import java.util.HashMap;
285+
import java.util.Map;
286+
287+
import com.litongjava.tio.http.server.annotation.RequestPath;
288+
289+
@RequestPath("/actuator")
290+
public class ActuatorController {
291+
public Map<String, String> health() {
292+
HashMap<String, String> hashMap = new HashMap<>(1);
293+
hashMap.put("status", "up");
294+
return hashMap;
295+
}
296+
297+
}
298+
299+
```
300+
301+
7. **业务控制器(ProductController.java):** 定义了对外提供的 REST 接口。
302+
303+
```
304+
package demo.controller;
305+
306+
import java.util.UUID;
307+
308+
import com.litongjava.tio.http.server.annotation.RequestPath;
309+
310+
@RequestPath
311+
public class ProductController {
312+
313+
@RequestPath("/product/consul")
314+
public String paymentConsul() {
315+
return "tio-boot with consul: " + UUID.randomUUID().toString();
316+
}
317+
}
318+
319+
```
320+
321+
### order-service
322+
323+
`product-service` 配置类似,不同之处主要在于 `OrderController.java`,在这里通过 `RestTemplate` 调用 `product-service` 提供的服务。
324+
325+
- pom.xml 和 product-service 相同
326+
- 启动类 和 product-service 仅类名不同
327+
- ApplicationContextConfig 和 product-service 相同
328+
- SpringBeanContextConfig 和 product-service 相同
329+
- ActuatorController 和 product-service 相同
330+
- OrderController 调用 product-server
331+
332+
```
333+
package demo.controller;
334+
335+
import org.springframework.beans.factory.annotation.Autowired;
336+
import org.springframework.web.bind.annotation.RequestMapping;
337+
import org.springframework.web.client.RestTemplate;
338+
339+
import com.litongjava.jfinal.spring.SpringBeanContextUtils;
340+
import com.litongjava.tio.http.server.annotation.RequestPath;
341+
342+
import demo.service.UserService;
343+
import lombok.extern.slf4j.Slf4j;
344+
345+
@RequestPath("/consumer")
346+
@Slf4j
347+
public class OrderController {
348+
349+
// consul服务中心的服务名称
350+
public static final String INVOKE_URL = "http://consul-provider-product";
351+
352+
@Autowired
353+
RestTemplate restTemplate;
354+
355+
public String getRestTemplate() {
356+
return restTemplate.toString();
357+
}
358+
359+
@RequestPath(value = "/payment/consul")
360+
public String paymentInfo() {
361+
log.info("restTemplate:{}", restTemplate.toString());
362+
String result = restTemplate.getForObject(INVOKE_URL + "/product/consul", String.class);
363+
return result;
364+
}
365+
}
366+
367+
```
368+
369+
### 测试服务调用
370+
371+
1. 启动 Consul。
372+
2. 分别启动 `product-service``order-service`
373+
3. 通过访问 `order-service` 的 APIhttp://127.0.0.1:8002/consumer/payment/consul测试调用 `product-service` 是否成功。
374+
显示如下说明调用成功
375+
376+
```
377+
tio-boot with consul: c78c2ce5-fa6a-4218-94f2-add528f1e04d
378+
```
379+
380+
### 源码地址
381+
382+
https://github.com/litongjava/java-ee-spring-cloud-study/tree/main/maven/spring-cloud-consul-study/spring-cloud-consul-tio-boot

0 commit comments

Comments
 (0)