🔥 本地化模拟分布式能力的神器:Local-Solon-Cloud-Plugin
引言:统一的开发体验
在微服务架构日益普及的今天,开发人员经常面临一个困境:如何在本地开发环境中高效测试分布式服务功能?或者一套系统给不同的客户使用,有的需要单体部署,有的需要分布式部署,有的需要微服务部署。
传统做法,往往需要在本地搭建复杂的分布式环境,或者为不同部署方式编写不同的代码(要么用微服务方式开发,要么用单体方式开发)。Local-Solon-Cloud-Plugin 正是为解决这一痛点而生。
插件概述
核心定位
Local-Solon-Cloud-Plugin 是一个基于本地适配的 Solon Cloud 插件,它模拟实现了分布式系统的核心能力,却不需要真实的分布式环境。自 v1.11.2 版本开始提供支持,该插件覆盖了 Solon Cloud 所能提供的大部分接口能力。
核心价值
- 统一开发接口:所有项目使用相同的 Solon Cloud 接口进行开发
- 无缝环境切换:通过简单配置切换,即可在"本地单体服务"和"分布式服务"之间自由转换
- 降低测试复杂度:无需搭建复杂分布式环境即可测试分布式功能
应用场景示例
// 同一套代码,不同环境运行
// 本地开发:使用 local-solon-cloud-plugin
// 生产环境:切换为 water 或其它分布式实现
import org.noear.solon.cloud.annotation.CloudJob;
// 定时任务示例
@CloudJob(name = "demoJob", cron7x = "0 0 0 * * ?")
public void executeJob() {
// 本地开发时由插件调度
// 生产环境可由 Water 或 XXL-Job 调度
}
快速开始
添加依赖
<dependency>
<groupId>org.noear</groupId>
<artifactId>local-solon-cloud-plugin</artifactId>
<!-- 版本跟随 Solon 主版本 -->
</dependency>
基础配置
# app.yml
solon.app:
name: demoapp
group: demo
solon.cloud.local:
server: "./solon-cloud/" # 必须设置,也可以是资源目录
config:
load: "demoapp.yml" # 加载配置到应用属性
discovery:
service:
demoapp: # 添加本地服务发现
- "http://localhost:8081"
配置区别说明
- 体外目录(如
./solon-cloud/):支持文件上传功能 - 资源目录(如
classpath:META-INF/solon-cloud/):不支持文件上传
Solon Cloud 能力支持详情
| 云端能力接口 | 说明 | 本地模拟实现 | 备注 |
|---|---|---|---|
| CloudConfigService | 云端配置服务 | ✅ 支持 | 不支持 namespace;支持 group |
| CloudDiscoveryService | 云端注册与发现服务 | ✅ 支持 | 不支持 namespace;支持 group |
| CloudEventService | 云端事件服务 | ✅ 支持 | 不支持 namespace;支持 group |
| CloudFileService | 云端文件服务 | ✅ 支持 | 完整实现 |
| CloudI18nService | 云端国际化服务 | ✅ 支持 | 完整实现 |
| CloudJobService | 云端定时任务服务 | ✅ 支持 | 完整实现 |
| CloudListService | 云端名单列表服务 | ✅ 支持 | 完整实现 |
| CloudMetricService | 云端度量服务 | ⚠️ 空实现 | 仅保证接口调用不报错 |
| CloudTraceService | 云端链路跟踪服务 | ⚠️ 空实现 | 仅保证接口调用不报错 |
核心功能详解
1. 云端配置服务(本地模拟)
支持 YAML、Properties 格式,文件路径格式:config/{group}_{name}
配置加载方式:
# app.yml
solon.app:
name: demoapp
group: demo
solon.cloud.local:
server: "/data/demo/solon-cloud/"
config:
load: "demoapp.yml,demo-db.properties"
注解注入方式:
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.cloud.annotation.CloudConfig;
@Configuration
public class Config {
// 直接注入云端配置(已经 config.load 的配置)
@Bean
public DataSource initDbConfig(@Inject("${demo-db}") HikariDataSource ds) {
return ds;
}
// 动态获取云端配置(直接注入配置块)
@CloudConfig("test.yml")
private Properties testSettings;
}
2. 服务注册与发现(本地模拟)
在本地环境中模拟服务注册中心的功能:
solon.cloud.local:
discovery:
service:
user-service:
- "http://localhost:8081"
- "http://localhost:8082"
order-service:
- "http://localhost:8083"
可以通过环境配置,切换单体或分布式的配置需求。
3. 云端事件服务(本地模拟)
import org.noear.snack4.ONode;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.annotation.Post;
import org.noear.solon.cloud.CloudClient;
import org.noear.solon.cloud.model.Event;
// 发布事件
@Mapping("order")
@Controller
public class OrderController {
@Post
@Mapping("create")
public void createOrder(Order order) {
// 发布订单创建事件
CloudClient.event().publish(new Event("order.created", ONode.serialize(order)));
}
}
//------------------------------------
import org.noear.solon.cloud.CloudEventHandler;
import org.noear.solon.cloud.annotation.CloudEvent;
import org.noear.solon.cloud.model.Event;
// 订阅事件
@CloudEvent("order.created")
public class OrderEventHandler implements CloudEventHandler {
@Override
public boolean handle(Event event) throws Throwable {
// 处理订单创建事件
return false;
}
}
注意:本地模拟实现不支持事件持久化,重启后数据会丢失。生产环境建议使用消息队列适配框架。
4. 文件服务(本地模拟)
文件存储在 ${server}/file/ 目录下,支持标准文件操作接口。
5. 国际化服务(本地模拟)
文件格式:i18n/{group}_{name}-{locale}(不支持文件后缀)
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.cloud.impl.CloudI18nBundleFactory;
import org.noear.solon.i18n.I18nBundleFactory;
//注册国际化包工厂
@Configuration
public class DemoConfig {
@Bean
public I18nBundleFactory i18nBundleFactory(){
//将国际化服务,切换为云端接口
return new CloudI18nBundleFactory();
}
}
//使用 solon.i18n 接口
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.i18n.I18nService;
import java.util.Locale;
@Controller
public class DemoController{
I18nService i18nService = new I18nService("test-api");
@Mapping("/hello")
public String hello(Locale locale){
return i18nService.get(locale, "hello");
}
}
6. 定时任务调度(本地模拟)
import org.noear.solon.cloud.annotation.CloudJob;
@CloudJob(name = "dailyReport", cron7x = "0 0 2 * * ?")
public void generateDailyReport() {
// 每天凌晨2点执行
// 注意:时间到就会启动新的执行,不管上次是否完成
}
7. 名单服务(本地模拟)
支持IP白名单/黑名单等功能,JSON格式存储:list/{name}-{type}.json
实战示例
完整配置示例
solon:
app:
name: demoapp
group: demo
solon.cloud.local:
server: "./cloud-data/"
config:
load: "app.yml,db.yml"
refreshInterval: 10s # 配置刷新间隔
discovery:
service:
user-service:
- "http://localhost:8080"
product-service:
- "http://localhost:8081"
job:
enabled: true # 启用任务调度
event:
enabled: true # 启用事件调度
多环境切换配置(参考)
# 本地开发环境(使用本地模拟)
solon.cloud:
local:
enabled: true
server: "./solon-cloud-local/"
# 生产环境(使用真实的分布式服务)
# solon.cloud:
# water:
# server: "water-server:9371"
# config:
# load: "demoapp.yml"
注意事项
- 事件持久化:本地事件服务不支持持久化,重要业务场景需注意
- 性能监控:度量服务和跟踪服务为空实现,生产环境需要替换
- 集群特性:本地模拟不支持真正的集群特性,如分布式锁、Leader选举等
- 配置同步:多实例情况下,本地配置需要手动同步(也可以打包到 jar)
总结
Local-Solon-Cloud-Plugin 为 Solon Cloud 生态提供了一种优雅的解决方案,它让开发者在享受分布式架构优势的同时,避免了本地开发的复杂性。通过统一的接口设计和灵活的环境切换能力,该插件显著提升了开发效率,方便适应不同的客户需求。
无论是初创项目快速验证,还是大型项目的本地开发,Local-Solon-Cloud-Plugin 都是一个值得尝试的优秀工具。它的存在使得"一次编写,处处运行"的理念在分布式开发领域得以更好地实现。