tio-boot spring-cloud
概述
- tio-boot 完全支持 spring-cloud
- 仅仅是 web 中间件使用 tio-boot-server,其他组件仍然是 spring-cloud
tio-boot, Spring Cloud, 和 Consul
整合 tio-boot, Spring Cloud, 和 Consul 实现服务注册与发现是一种提升微服务架构可靠性和灵活性的有效方法。本文档将详细介绍如何创建两个服务,spring-cloud-consul-product-service
和 spring-cloud-consul-order-service
,并通过 Consul 实现这两个服务的注册与发现。其中 product-service
提供接口,order-service
调用 product-service
的接口。
流程概述
- 启动 Consul: Consul 作为服务注册和服务发现的工具,可以通过简单的命令启动。
- 配置
product-service
: 包括 Maven 依赖配置、application 属性配置、启动类和相关组件的配置,确保服务可以正确注册到 Consul。 - 配置
order-service
: 类似于product-service
,配置相关依赖和属性,以及 RestTemplate 用于服务间的调用。 - 服务注册与发现: 服务启动后,会自动注册到 Consul,
order-service
可以通过 Consul 发现product-service
并进行调用。
启动 Consul
在开始之前,确保你有 Consul 环境,可以通过以下命令启动 Consul:
consul.exe agent -dev
product-service
- Maven 配置(pom.xml): 定义了项目的 Java 版本、依赖项(包括 Spring Boot、tio-boot、Spring Cloud Consul Discovery 等)。
pom.xml
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.1.6.RELEASE</spring-boot.version>
<tio-boot.version>1.8.7</tio-boot.version>
<main.class>demo.ProductApp</main.class>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-reactor-netty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>tio-boot</artifactId>
<version>${tio-boot.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>hotswap-classloader</artifactId>
<version>1.2.1</version>
</dependency>
<!-- SpringBoot集成Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!--SpringCloud提供的基于Consul的服务发现-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--actuator用于心跳检查-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Spring Boot -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<includeSystemScope>true</includeSystemScope>
<!--使该插件支持热启动 -->
<fork>true</fork>
<mainClass>${main.class}</mainClass>
</configuration>
<!-- 设置执行目标 -->
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 应用配置(application.yml): 指定了服务的端口、应用名称和 Consul 服务器的地址。
application.yml
server:
port: 8001 #端口
spring:
application:
#访问名称
name: consul-provider-product
cloud:
consul:
#服务地址
host: localhost
#服务端口
port: 8500
discovery:
service-name: ${spring.application.name}
app.properties
server.port=8001
app.properties 和 application.yml 都需要指定端口
- 启动类(ProductApp.java): 标记了 Spring Boot 应用、启用了服务发现,并导入了必要的配置。
package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Import;
import com.litongjava.jfinal.aop.annotation.AComponentScan;
import com.litongjava.tio.boot.spring.SpringBootArgs;
import com.litongjava.tio.boot.spring.TioBootServerAutoConfiguration;
@SpringBootApplication
@EnableDiscoveryClient
@AComponentScan
@Import(TioBootServerAutoConfiguration.class)
public class ProductApp {
public static void main(String[] args) {
long start = System.currentTimeMillis();
SpringBootArgs.set(ProductApp.class, args);
SpringApplication.run(ProductApp.class, args);
long end = System.currentTimeMillis();
System.out.println((end - start) + "(ms)");
}
}
- RestTemplate 配置(ApplicationContextConfig.java): 配置了 RestTemplate 并启用了负载均衡,使其可以通过服务名调用其他服务。
package demo.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import lombok.extern.slf4j.Slf4j;
@Configuration
@Slf4j
public class ApplicationContextConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
log.info("restTemplate:{}", restTemplate.toString());
return restTemplate;
}
}
- Tio-Boot 集成配置(SpringBeanContextConfig.java): 配置了 tio-boot 与 Spring 的集成。
package demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.jfinal.aop.AopManager;
import com.litongjava.jfinal.spring.SpringBeanContextUtils;
import lombok.extern.slf4j.Slf4j;
@Configuration
@Slf4j
public class SpringBeanContextConfig {
@Autowired
private ApplicationContext applicationContext;
@Bean(destroyMethod = "close")
@DependsOn("restTemplate")
public void myBean() {
log.info("add Autowired");
// 开启和spring的整合
AopManager.me().getAopFactory().setEnableWithSpring(true);
SpringBeanContextUtils.setContext(applicationContext);
// 让 tio-boot的bean支持Autowired注解
Aop.addFetchBeanAnnotation(Autowired.class);
}
}
- 健康控制器(ActuatorController.java): 定义了对外提供的 健康 接口。consul 会通过这个接口检查应用是否健康 ActuatorController
package demo.controller;
import java.util.HashMap;
import java.util.Map;
import com.litongjava.annotation.RequestPath;
@RequestPath("/actuator")
public class ActuatorController {
public Map<String, String> health() {
HashMap<String, String> hashMap = new HashMap<>(1);
hashMap.put("status", "up");
return hashMap;
}
}
- 业务控制器(ProductController.java): 定义了对外提供的 REST 接口。
package demo.controller;
import java.util.UUID;
import com.litongjava.annotation.RequestPath;
@RequestPath
public class ProductController {
@RequestPath("/product/consul")
public String paymentConsul() {
return "tio-boot with consul: " + UUID.randomUUID().toString();
}
}
order-service
与 product-service
配置类似,不同之处主要在于 OrderController.java
,在这里通过 RestTemplate
调用 product-service
提供的服务。
- pom.xml 和 product-service 相同
- 启动类 和 product-service 仅类名不同
- ApplicationContextConfig 和 product-service 相同
- SpringBeanContextConfig 和 product-service 相同
- ActuatorController 和 product-service 相同
- OrderController 调用 product-server
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;
import com.litongjava.jfinal.spring.SpringBeanContextUtils;
import com.litongjava.annotation.RequestPath;
import demo.service.UserService;
import lombok.extern.slf4j.Slf4j;
@RequestPath("/consumer")
@Slf4j
public class OrderController {
// consul服务中心的服务名称
public static final String INVOKE_URL = "http://consul-provider-product";
@Autowired
RestTemplate restTemplate;
public String getRestTemplate() {
return restTemplate.toString();
}
@RequestPath(value = "/payment/consul")
public String paymentInfo() {
log.info("restTemplate:{}", restTemplate.toString());
String result = restTemplate.getForObject(INVOKE_URL + "/product/consul", String.class);
return result;
}
}
测试服务调用
- 启动 Consul。
- 分别启动
product-service
和order-service
。 - 通过访问
order-service
的 APIhttp://127.0.0.1:8002/consumer/payment/consul测试调用product-service
是否成功。 显示如下说明调用成功
tio-boot with consul: c78c2ce5-fa6a-4218-94f2-add528f1e04d
源码地址
https://github.com/litongjava/java-ee-spring-cloud-study/tree/main/maven/spring-cloud-consul-study/spring-cloud-consul-tio-boot