Consul + Thrift 搭建分布式微服务
最终项目工程结构
.
├── example.thrift
├── gen-java
│ └── com
│ └── kabai
│ └── thrift
│ ├── User.java
│ └── UserService.java
├── thrift.consumer
│ ├── pom.xml
│ └── src
│ └── main
│ ├── java
│ │ └── com
│ │ └── kabai
│ │ ├── ThriftClientApplication.java
│ │ ├── config
│ │ │ └── ThriftClientConfig.java
│ │ ├── controller
│ │ │ └── UserController.java
│ │ └── thrift
│ │ ├── User.java
│ │ └── UserService.java
│ └── resources
│ └── application.yml
└── thrift.provider
├── pom.xml
└── src
└── main
├── java
│ └── com
│ └── kabai
│ ├── ThriftServerApplication.java
│ ├── config
│ │ └── ThriftServerConfig.java
│ └── thrift
│ ├── User.java
│ ├── UserService.java
│ └── UserServiceImpl.java
└── resources
└── application.yml
准备工作
-
安装 Thrift 编译器:
- 你需要先安装 Thrift 编译器,以便将 Thrift IDL 文件编译为 Java 代码。
- 下载并安装: Thrift 安装指南
-
创建 Thrift IDL 文件:
-
定义服务接口和数据结构,例如创建一个文件
example.thrift:namespace java com.kabai.thrift struct User { 1: i32 id, 2: string name } service UserService { User getUserById(1: i32 id) }
-
编译 Thrift IDL 文件
-
在命令行运行 Thrift 编译器将 IDL 文件编译为 Java 代码:
thrift --gen java example.thrift这将生成一个
gen-java文件夹,包含所有生成的 Java 文件。
版本
我这里本地配置了两个版本,这里演示项目,需要用到jdk17,maven 3.9.7。
- jdk17
- maven 3.9.7
- Spring Boot 3.1.2
- Packaging jar
# 配置JDK路径
export JAVA_8_HOME=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home
export JAVA_17_HOME=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home
# 默认使用 JDK8
export JAVA_HOME=$JAVA_8_HOME
CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.
# 配置alias命令动态切换JDK版本
alias jdk8='export JAVA_HOME=$JAVA_8_HOME'
alias jdk17='export JAVA_HOME=$JAVA_17_HOME'
export JAVA_HOME
export CLASSPATH
# 配置maven路径
export MAVEN_3_6_1_HOME=/Users/mac/env/apache-maven-3.6.1
export MAVEN_3_9_7_HOME=/Users/mac/env/apache-maven-3.9.7
# 默认使用 3.6.1
export MAVEN_HOME=$MAVEN_3_6_1_HOME
export PATH=$MAVEN_HOME/bin:$PATH
# 配置alias命令动态切换MAVEN版本
alias mvn3.6='export MAVEN_HOME=$MAVEN_3_6_1_HOME && export PATH=$MAVEN_HOME/bin:${PATH//:$MAVEN_3_9_7_HOME\/bin/}'
alias mvn3.9='export MAVEN_HOME=$MAVEN_3_9_7_HOME && export PATH=$MAVEN_HOME/bin:${PATH//:$MAVEN_3_6_1_HOME\/bin/}'
# 导出MAVEN_HOME和PATH变量
export MAVEN_HOME
export PATH
步骤 1: 安装Consul配置中心
确保Consul安装并运行。你可以在本地或者服务器上安装并运行Consul,以下是一些基本步骤:
# 下载并解压Consul
wget https://releases.hashicorp.com/consul/1.10.3/consul_1.10.3_linux_amd64.zip
unzip consul_1.10.3_linux_amd64.zip
# 运行Consul
/root/consul agent -dev -client=0.0.0.0
步骤 2: 创建springboot项目 - 从springboot官网
-
thrift.provider
-
thrift.consumer
步骤 3: 创建服务提供者(thrift.provider)
接下来,我们创建一个服务提供者,它将向Consul注册自己的服务,并提供API服务。
- 创建一个新的Spring Boot应用程序。
package com.kabai;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ThriftServerApplication {
public static void main(String[] args) {
SpringApplication.run(ThriftServerApplication.class, args);
}
}
- 添加consul-discovery、libthrift和Spring Web的依赖到
pom.xml文件中。
- consul-discovery
- consul-config
- libthrift
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.14.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
<version>4.0.3</version>
</dependency>
- 完整pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.kabai</groupId>
<artifactId>thrift.provider</artifactId>
<version>1.0.0-RELEASE</version>
<name>thrift.provider</name>
<description>thrift.provider</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.14.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
<version>4.0.3</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2022.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 配置thrift-provider连接属性,以连接到Consul服务器。
spring:
application:
name: thrift-provider
cloud:
consul:
host: 140.143.xx.xx
port: 8500
discovery:
instance-id: thrift-provider-12345
service-name: thrift-provider
register: true
enabled: true
heartbeat:
enabled: true
config:
enabled: true
format: yaml
config:
import: "optional:consul:"
- 创建一个ThriftServerConfig配置类,配置Thrift。
package com.kabai.config;
import com.kabai.thrift.UserService;
import com.kabai.thrift.UserServiceImpl;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ThriftServerConfig {
@Bean
public TServer thriftServer(UserServiceImpl userService) throws Exception {
TServerTransport serverTransport = new TServerSocket(9090); // 使用独立的端口,例如9090
UserService.Processor<UserServiceImpl> processor = new UserService.Processor<>(userService);
TThreadPoolServer.Args args = new TThreadPoolServer.Args(serverTransport)
.processor(processor)
.protocolFactory(new TBinaryProtocol.Factory(true, true, Integer.MAX_VALUE, Integer.MAX_VALUE));
TServer server = new TThreadPoolServer(args);
new Thread(() -> server.serve()).start();
return server;
}
}
- 拷贝生成thrift文件到thrift.provider工程目录内
cd gen-java #进入生成的Thrift目录
cp -r ./ ../thrift.provider/src/main/java #拷贝进thrift.provider工程目录内
- 写你具体的逻辑实现
package com.kabai.thrift;
import org.apache.thrift.TException;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService.Iface {
@Override
public User getUserById(int id) throws TException {
User user = new User();
user.setId(id);
user.setName("User" + id);
return user;
}
}
步骤 4: 创建服务消费者(thrift.consumer)
最后,我们创建一个服务消费者,它将使用Feign来调用服务提供者的API。
- 创建一个新的Spring Boot应用程序。
package com.kabai;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ThriftClientApplication {
public static void main(String[] args) {
SpringApplication.run(ThriftClientApplication.class, args);
}
}
- 添加OpenFeign、Consul Discovery Client和Spring Web的依赖到
pom.xml文件中。
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.14.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
<version>4.0.3</version>
</dependency>
- 完整pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.kabai</groupId>
<artifactId>thrift.consumer</artifactId>
<version>1.0.0-RELEASE</version>
<name>thrift.consumer</name>
<description>thrift.consumer</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.14.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
<version>4.0.3</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2022.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 配置thrift-consumer连接属性,以连接到Consul服务器。
spring:
application:
name: thrift-consumer
cloud:
consul:
host: 140.143.xx.xx
port: 8500
discovery:
instance-id: thrift-consumer-67890
service-name: thrift-consumer
register: true
enabled: true
heartbeat:
enabled: true
config:
enabled: true
format: yaml
config:
import: "optional:consul:"
server:
port: 8280
- 创建一个ThriftClientConfig配置类,配置Thrift。
package com.kabai.config;
import com.kabai.thrift.UserService;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class ThriftClientConfig {
private final DiscoveryClient discoveryClient;
public ThriftClientConfig(DiscoveryClient discoveryClient) {
this.discoveryClient = discoveryClient;
}
@Bean
public UserService.Client userServiceClient() throws Exception {
List<ServiceInstance> instances = discoveryClient.getInstances("thrift-provider");
if (instances == null || instances.isEmpty()) {
throw new IllegalStateException("No instances of thrift-provider found");
}
ServiceInstance serviceInstance = instances.get(0);
TTransport transport = new TSocket(serviceInstance.getHost(), 9090); // 确保使用的是服务端配置的独立端口
transport.open();
TProtocol protocol = new TBinaryProtocol(transport, Integer.MAX_VALUE, Integer.MAX_VALUE);
return new UserService.Client(protocol);
}
}
- 拷贝生成thrift文件到thrift.consumer工程目录内
cd gen-java #进入生成的Thrift目录
cp -r ./ ../thrift.consumer/src/main/java #拷贝进thrift.consumer工程目录内
- 暴露一个HTTP接口 来调用
sayHello方法。
package com.kabai.controller;
import com.kabai.thrift.User;
import com.kabai.thrift.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserService.Client userServiceClient;
@GetMapping("/user/{id}")
public User getUserById(@PathVariable int id) {
try {
return userServiceClient.getUserById(id);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
项目启动
确认服务环境
- jdk:jdk17
- maven:3.9.4
依次启动
- Consul
- service-provider
- service-consumer
编译、打包、运行
- 运行Consul
/root/consul agent -dev -client=0.0.0.0
- thrift.provider
jdk17
mvn3.9
mvn spring-boot:run
- service.consumer
jdk17
mvn3.9
mvn spring-boot:run
Consul Dashboard
http://60.35.xx.xx:8500/ui
浏览器访问测试接口
http://localhost:8280/user/11