# lix-rpc **Repository Path**: sclx/lix-rpc ## Basic Information - **Project Name**: lix-rpc - **Description**: 基于springcloud的feign分布式远程调用 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-04-26 - **Last Updated**: 2025-08-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # lix-rpc 一个基于 Spring Boot 和 OpenFeign 的现代化 RPC 框架,专注于多内容类型支持和文件流处理的微服务间远程调用解决方案。 ## 📖 项目概述 **lix-rpc** 是对 OpenFeign 的深度增强封装,通过注解驱动的方式提供强大的 RPC 功能,支持 JSON、文件上传下载、流式数据传输等多种内容类型,显著提升微服务开发效率。 ### 🌟 核心特性 - ✅ **多内容类型**: 支持 JSON、Multipart、OctetStream、TextPlain、XML 等多种数据格式 - ✅ **文件流处理**: 原生支持大文件上传下载和流式数据传输 - ✅ **智能调用**: 根据参数类型自动选择最优的调用方式和端点 - ✅ **注解驱动**: 通过 `@RpcService` 和 `@RpcClient` 注解简化开发 - ✅ **透明代理**: 客户端像调用本地方法一样调用远程服务 - ✅ **Spring 整合**: 深度集成 Spring 生态,支持依赖注入和 AOP - ✅ **服务发现**: 集成 Eureka 实现服务自动注册与发现 - ✅ **高性能**: Jackson 序列化,缓存优化,内存友好的流式处理 ## 🏗️ 架构设计 ### 整体架构 ``` ┌─────────────────┐ HTTP/多格式 ┌─────────────────┐ │ RPC Client │ ───────────────► │ RPC Server │ │ │ │ │ │ @RpcClient │ │ @RpcService │ │ 智能内容协商 │ │ 多端点处理 │ │ │ │ │ │ 自动生成代理 │ │ 统一分发调用 │ └─────────────────┘ └─────────────────┘ ▲ ▲ │ │ ┌─────────┐ ┌─────────┐ │Enhanced │ │Enhanced │ │ Feign │ │ RPC │ │ Client │ │Controller│ └─────────┘ └─────────┘ ``` ### 调用端点映射 ``` 客户端参数类型 → 服务端处理端点 ──────────────────────────────────────────── 普通对象 → /enhancedRpc/enhanced/dispatch MultipartFile → /enhancedRpc/upload InputStream/byte[] → /enhancedRpc/stream String (文本) → /enhancedRpc/text ``` ## 📁 模块结构 ``` lix-rpc/ ├── lix-rpc-platform/ # 🔥 核心 RPC 框架(仅增强实现) │ ├── lix-rpc-platform-common/ # 公共组件和注解 │ ├── lix-rpc-platform-server/ # 服务端增强处理器 │ └── lix-rpc-platform-client/ # 客户端智能代理 ├── lix-rpc-interfaces/ # 服务接口定义 ├── lix-rpc-server/ # 服务提供者示例 ├── lix-rpc-client/ # 服务消费者示例 ├── lix-rpc-eureka/ # 注册中心 ├── lix-rpc-gateway/ # 服务网关 ├── lix-rpc-oauth2/ # 认证授权 └── lix-rpc-commons/ # 通用工具 ``` ## 🚀 快速开始 ### 1. 定义服务接口 ```java // 多功能服务接口 public interface EnhancedFileService { // JSON 对象调用 String processData(DataObject data); // 文件上传 String uploadFile(MultipartFile file, String description); // 文件下载 byte[] downloadFile(String fileName); // 流式数据处理 byte[] processStream(InputStream inputStream, String operation); // 文本处理 String processText(String content); } ``` ### 2. 实现服务提供者 ```java // 启动类 @SpringBootApplication @EnableEurekaClient @EnableRpcServer("com.example.service") public class ServerApplication { public static void main(String[] args) { SpringApplication.run(ServerApplication.class, args); } } // 服务实现(支持多种内容类型) @RpcService( value = "enhancedFileService", contentTypes = { RpcService.ContentType.JSON, RpcService.ContentType.MULTIPART, RpcService.ContentType.OCTET_STREAM, RpcService.ContentType.TEXT_PLAIN }, enableStreaming = true ) @Service public class EnhancedFileServiceImpl implements EnhancedFileService { @Override public String uploadFile(MultipartFile file, String description) { // 自动处理文件上传,支持大文件 return "文件上传成功: " + file.getOriginalFilename(); } @Override public byte[] downloadFile(String fileName) { // 返回文件字节数据,自动使用流式传输 return loadFileAsBytes(fileName); } @Override public byte[] processStream(InputStream inputStream, String operation) { // 流式数据处理,内存友好 return processStreamData(inputStream, operation); } @Override public String processText(String content) { // 纯文本处理 return "处理结果: " + content.toUpperCase(); } } ``` ### 3. 实现服务消费者 ```java // 启动类 @SpringBootApplication @EnableEurekaClient @EnableRpcClient("com.example.controller") public class ClientApplication { public static void main(String[] args) { SpringApplication.run(ClientApplication.class, args); } } // 服务消费(智能内容协商) @RestController public class EnhancedTestController { @RpcClient( serverName = "file-service", contentTypes = { RpcService.ContentType.JSON, RpcService.ContentType.MULTIPART, RpcService.ContentType.OCTET_STREAM, RpcService.ContentType.TEXT_PLAIN }, maxFileSize = 50 * 1024 * 1024 // 50MB ) private EnhancedFileService enhancedFileService; // 文件上传 - 自动使用 multipart/form-data @PostMapping("/upload") public String upload(@RequestParam MultipartFile file) { return enhancedFileService.uploadFile(file, "客户端上传"); } // 文件下载 - 自动处理二进制响应 @GetMapping("/download") public ResponseEntity download(@RequestParam String fileName) { byte[] data = enhancedFileService.downloadFile(fileName); return ResponseEntity.ok() .header("Content-Disposition", "attachment; filename=\"" + fileName + "\"") .body(data); } // 流式处理 - 自动使用 application/octet-stream @PostMapping("/stream") public byte[] processStream(@RequestBody byte[] data, @RequestParam String operation) { InputStream inputStream = new ByteArrayInputStream(data); return enhancedFileService.processStream(inputStream, operation); } } ``` ## 🔧 核心组件详解 ### 📋 lix-rpc-platform-common **职责**: 提供 RPC 框架的基础设施和公共组件 #### 核心注解 ```java // 服务端注解 - 支持多内容类型 @RpcService( value = "serviceName", contentTypes = { RpcService.ContentType.JSON, // application/json RpcService.ContentType.MULTIPART, // multipart/form-data RpcService.ContentType.OCTET_STREAM,// application/octet-stream RpcService.ContentType.TEXT_PLAIN, // text/plain RpcService.ContentType.XML // application/xml }, enableStreaming = true ) // 客户端注解 - 智能内容协商 @RpcClient( serverName = "service-name", contentTypes = {RpcService.ContentType.JSON, RpcService.ContentType.MULTIPART}, maxFileSize = 50 * 1024 * 1024 // 最大文件大小 ) // 启用注解 @EnableRpcServer(value = "packages", enhanced = true) // 服务端 @EnableRpcClient(value = "packages", defaultEnhanced = false) // 客户端 ``` #### 增强数据传输对象 ```java // 增强请求对象 public class EnhancedRpcRequest { private String serviceClass; private String methodKey; private String parameters; private RpcService.ContentType contentType; private String requestId; private boolean streaming; private byte[] fileData; // 文件数据 private String fileName; // 文件名 private long fileSize; // 文件大小 // ... 更多属性 } // 增强响应对象 public class EnhancedRpcResponse { private String result; private Integer code; private Long cost; private String requestId; private RpcService.ContentType contentType; private byte[] fileData; // 返回文件数据 private String fileName; // 返回文件名 public boolean isFile() { // 是否为文件响应 return fileData != null && fileData.length > 0; } } ``` ### 🖥️ lix-rpc-platform-server **职责**: 服务端增强处理器,支持多端点和智能分发 #### 多端点架构 ```java @RestController @RequestMapping("/enhancedRpc") public class EnhancedRpcController { // 增强 JSON RPC 调用 @PostMapping("/enhanced/dispatch") public ResponseEntity enhancedDispatch(@RequestBody EnhancedRpcRequest request) { // 统一处理 JSON 格式请求 } // 文件上传处理 @PostMapping("/upload") public ResponseEntity uploadDispatch( @RequestParam String serviceClass, @RequestParam String methodKey, @RequestParam String parameters, @RequestParam MultipartFile file) { // 专门处理文件上传 } // 流式数据处理 @PostMapping("/stream") public ResponseEntity streamDispatch( @RequestParam String serviceClass, @RequestParam String methodKey, @RequestParam String parameters, HttpServletRequest request) { // 处理二进制流数据 } // 文本处理 @PostMapping("/text") public ResponseEntity textDispatch( @RequestParam String serviceClass, @RequestParam String methodKey, @RequestParam String parameters, @RequestBody String content) { // 处理纯文本数据 } } ``` #### 智能服务分发 ```java public class EnhancedRpcServerBeanProcessor { // 服务缓存 private static final Map> serviceCache = new HashMap<>(); private static final Map methodCache = new HashMap<>(); // 智能调用方法 public Object invoke(EnhancedRpcRequest request) { // 1. 从缓存获取服务类和方法 // 2. 根据内容类型进行参数转换 // 3. 反射调用目标方法 // 4. 智能处理返回结果 } } ``` ### 🌐 lix-rpc-platform-client **职责**: 客户端智能代理,根据参数类型自动选择调用方式 #### 智能代理架构 ```java public class EnhancedJDKRemoteServiceProxy implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) { // 智能检测参数类型 RpcService.ContentType contentType = detectContentType(method, args); // 根据内容类型选择调用方式 switch (contentType) { case MULTIPART: return invokeFileUpload(method, args); // 文件上传端点 case OCTET_STREAM: return invokeStreamCall(method, args); // 流式处理端点 case TEXT_PLAIN: return invokeTextCall(method, args); // 文本处理端点 default: return invokeJsonCall(method, args); // JSON 端点 } } private RpcService.ContentType detectContentType(Method method, Object[] args) { // 智能检测参数类型 for (Object arg : args) { if (arg instanceof MultipartFile) { return RpcService.ContentType.MULTIPART; } if (arg instanceof InputStream || arg instanceof byte[]) { return RpcService.ContentType.OCTET_STREAM; } } return RpcService.ContentType.JSON; } } ``` #### 增强 Feign 配置 ```java // 支持多种编码器的 Feign 客户端 public interface EnhancedRemoteInterface { // JSON 调用 @Headers("Content-Type: application/json;charset=UTF-8") @RequestLine("POST /enhancedRpc/enhanced/dispatch") ResponseEntity enhancedDispatch(@RequestBody EnhancedRpcRequest request); // 文件上传 @Headers("Content-Type: multipart/form-data") @RequestLine("POST /enhancedRpc/upload") ResponseEntity uploadDispatch( @Param("serviceClass") String serviceClass, @Param("methodKey") String methodKey, @Param("parameters") String parameters, @Param("file") feign.form.FormData file); // 流式数据 @Headers("Content-Type: application/octet-stream") @RequestLine("POST /enhancedRpc/stream") ResponseEntity streamDispatch(/*...*/); // 文本处理 @Headers("Content-Type: text/plain") @RequestLine("POST /enhancedRpc/text") ResponseEntity textDispatch(/*...*/); } ``` ## 🔄 完整调用链路 ### 启动流程 1. **服务端**: `@EnableRpcServer` → `EnhancedRpcServerBeanProcessor` → 扫描 `@RpcService` → 缓存服务和方法 → 注册多个控制器端点 2. **客户端**: `@EnableRpcClient` → `EnhancedRpcClientBeanProcessor` → 扫描 `@RpcClient` → 创建智能代理 → 配置增强 Feign 客户端 ### 运行时调用流程 ``` 客户端方法调用 ↓ 智能代理拦截 (EnhancedJDKRemoteServiceProxy) ↓ 参数类型检测 (detectContentType) ↓ 选择调用端点 (JSON/Upload/Stream/Text) ↓ 构造请求对象 (EnhancedRpcRequest) ↓ Feign 发送 HTTP 请求 ↓ 服务端控制器接收 (EnhancedRpcController) ↓ 智能分发调用 (EnhancedRpcServerBeanProcessor) ↓ 反射调用目标方法 ↓ 智能响应处理 (EnhancedRpcResponse) ↓ 客户端结果处理和反序列化 ``` ## 🎯 使用示例 ### 文件处理示例 ```java // 服务接口 public interface FileProcessService { String uploadDocument(MultipartFile file, String category); byte[] downloadDocument(String documentId); String convertDocument(InputStream docStream, String targetFormat); } // 服务实现 @RpcService( contentTypes = { RpcService.ContentType.JSON, RpcService.ContentType.MULTIPART, RpcService.ContentType.OCTET_STREAM }, enableStreaming = true ) public class FileProcessServiceImpl implements FileProcessService { @Override public String uploadDocument(MultipartFile file, String category) { // 自动处理 multipart/form-data 请求 String documentId = UUID.randomUUID().toString(); // 保存文件逻辑... return documentId; } @Override public byte[] downloadDocument(String documentId) { // 返回文件数据,自动使用 application/octet-stream return Files.readAllBytes(getDocumentPath(documentId)); } @Override public String convertDocument(InputStream docStream, String targetFormat) { // 处理二进制流,自动从 application/octet-stream 解析 return processConversion(docStream, targetFormat); } } // 客户端使用 @RestController public class DocumentController { @RpcClient( serverName = "file-process-service", maxFileSize = 100 * 1024 * 1024 // 100MB ) private FileProcessService fileProcessService; @PostMapping("/documents") public String uploadDocument(@RequestParam MultipartFile file, @RequestParam String category) { // 直接调用,框架自动处理文件上传 return fileProcessService.uploadDocument(file, category); } @GetMapping("/documents/{id}") public ResponseEntity downloadDocument(@PathVariable String id) { // 直接调用,框架自动处理文件下载 byte[] content = fileProcessService.downloadDocument(id); return ResponseEntity.ok() .header("Content-Type", "application/octet-stream") .body(content); } } ``` ### HTTP 直接调用示例 ```bash # 文件上传 curl -X POST http://localhost:8765/enhancedRpc/upload \ -F "serviceClass=com.example.FileProcessService" \ -F "methodKey=uploadDocument_MultipartFile_String" \ -F "parameters=[\"documents\"]" \ -F "file=@document.pdf" # 流式数据处理 curl -X POST http://localhost:8765/enhancedRpc/stream \ -H "Content-Type: application/octet-stream" \ --data-binary @data.bin \ -G -d "serviceClass=com.example.FileProcessService" \ -d "methodKey=convertDocument_InputStream_String" \ -d "parameters=[\"pdf\"]" ``` ## 🔧 技术栈 - **Spring Boot 2.0.6**: 应用框架 - **Spring Cloud Finchley.SR4**: 微服务套件 - **OpenFeign**: HTTP 客户端 - **Feign Form**: 文件上传支持 - **Jackson**: JSON 序列化(替代 FastJSON) - **Eureka**: 服务注册与发现 - **Maven**: 项目管理 ## 📦 依赖配置 ### 服务端依赖 ```xml cn.lix.sc lix-rpc-platform-server 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-web com.fasterxml.jackson.core jackson-databind ``` ### 客户端依赖 ```xml cn.lix.sc lix-rpc-platform-client 1.0-SNAPSHOT org.springframework.cloud spring-cloud-starter-openfeign io.github.openfeign.form feign-form 3.8.0 io.github.openfeign feign-jackson ``` ## 💡 设计亮点 1. **智能内容协商**: 根据参数类型自动选择最适合的传输方式和端点 2. **多端点架构**: 不同内容类型使用专门优化的处理端点 3. **流式处理**: 大文件和流数据的内存友好处理 4. **零配置**: 注解驱动,无需额外配置即可支持多种数据类型 5. **类型安全**: 基于接口定义,编译时类型检查 6. **性能优化**: 方法缓存、Jackson 序列化、智能路由 7. **向后兼容**: 平滑的架构演进,无需修改现有代码 8. **生产就绪**: 完整的错误处理、日志记录和监控支持 --- ## 🚀 开始使用 1. 引入相应的依赖 2. 在服务端添加 `@EnableRpcServer` 注解 3. 在客户端添加 `@EnableRpcClient` 注解 4. 使用 `@RpcService` 标记服务实现 5. 使用 `@RpcClient` 注入服务代理 6. 享受智能的多内容类型 RPC 调用! 更多详细示例和高级用法,请参考项目中的 `lix-rpc-server` 和 `lix-rpc-client` 模块。 --- ## 🔧 故障排除 ### 文件上传问题解决方案 如果遇到 `multipart boundary not found` 错误,原因可能是: #### 问题原因 1. **multipart boundary 丢失**: Feign 客户端没有正确设置 Content-Type 的 boundary 参数 2. **Header 配置冲突**: 硬编码的 Content-Type header 覆盖了 FormEncoder 自动生成的 boundary 3. **依赖版本不兼容**: feign-form 版本与 OpenFeign 版本不匹配 #### 解决方案 **1. 检查依赖配置** ```xml io.github.openfeign.form feign-form 3.8.0 io.github.openfeign feign-jackson ``` **2. Feign 接口配置(正确)** ```java // ❌ 错误:硬编码 Content-Type 会导致 boundary 丢失 @Headers("Content-Type: multipart/form-data") @RequestLine("POST /enhancedRpc/upload") ResponseEntity uploadDispatch(/*...*/); // ✅ 正确:让 FormEncoder 自动处理 boundary @RequestLine("POST /enhancedRpc/upload") ResponseEntity uploadDispatch(/*...*/); ``` **3. 服务端配置** ```java @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity uploadDispatch( @RequestParam("serviceClass") String serviceClass, @RequestParam("methodKey") String methodKey, @RequestParam(value = "beanName", required = false) String beanName, @RequestParam(value = "parameters", required = false) String parameters, @RequestParam("file") MultipartFile file) { // 处理逻辑 } ``` **4. Spring Boot 配置** ```yaml spring: servlet: multipart: enabled: true max-file-size: 50MB max-request-size: 55MB ``` **5. 调试技巧** ```java // 启用详细日志 logging: level: feign: DEBUG cn.lix.sc.rpc: DEBUG ``` #### 测试验证 ```bash # 直接 HTTP 测试 curl -X POST http://localhost:8765/enhancedRpc/upload \ -F "serviceClass=cn.lix.sc.rpc.service.demo.service.EnhancedFileService" \ -F "methodKey=uploadFile_MultipartFile_String" \ -F "beanName=enhancedFileService" \ -F "parameters=[\"测试描述\"]" \ -F "file=@test.txt" ``` ### 常见错误及解决方案 | 错误信息 | 原因 | 解决方案 | |---------|------|---------| | `multipart boundary not found` | Content-Type header 配置错误 | 移除硬编码的 multipart Content-Type | | `Request entity too large` | 文件大小超限 | 调整 `max-file-size` 配置 | | `Connection timeout` | 网络或服务响应超时 | 调整 `connectTimeout` 和 `readTimeout` | | `Method not supported` | HTTP 方法映射错误 | 检查 `@RequestLine` 配置 |