```
* Solon 对标 Spring Boot
* Solon Cloud 则对标 Spring Cloud
```

Solon Cloud 是一套接口定义与配置规范，相当于DDD里的防腐层。可为常见的分布式系统架构提供了一种简单且方便的编程模式，帮助开发人员构建有弹性的、可靠的、协调的应用程序。Solon Cloud 主要由三部份组成：

* 接口定义与配置规范
* 实现相关接口定义的各种插件（只要实现相关接口的 Solon 插件，即是 Solon Cloud 插件。）
* 以及通用客户端。


### 1、Solon Cloud 套件内容


#### 1.1、接口定义及配置规范清单

接口定义及配置规范，为第三方框架的适配与使用提供了统一模式

| 功能名称 | Solon Cloud | 接口定义 | 配置规范（具体暂略） | 
| -------- | -------- | -------- | -------- |
| 分布式注册与发现     | Solon Cloud Discovery     | CloudDiscoveryService  |  solon.cloud.@@.discovery  | 
| 分布式网关     |  Solon Cloud Gateway     | -  |  -  | 
| 分布式断路器     |  Solon Cloud Breaker     | CloudBreakerService |  solon.cloud.@@.breaker  | 
| 分布式配置     | Solon Cloud Config     | CloudConfigService |  solon.cloud.@@.config  | 
| 分布式跟踪     | Solon Cloud Trace     | CloudTraceService |  solon.cloud.@@.trace  | 
| 分布式监控     | Solon Cloud Metric     | CloudMetricService |  solon.cloud.@@.metric  | 
| 分布式事件总线     | Solon Cloud Event     |  CloudEventService |  solon.cloud.@@.event  | 
| 分布式任务     | Solon Cloud Job     |  CloudJobService |  solon.cloud.@@.job  | 
| 分布式ID     |  Solon Cloud Id     |  CloudIdService |  solon.cloud.@@.id   | 
| 分布式文件     | Solon Cloud File     |  CloudFileService |  solon.cloud.@@.file  | 
| 分布式名单     |  Solon Cloud List     | CloudListService |  solon.cloud.@@.list   | 
| 分布式锁     | Solon Cloud Lock     | CloudLockService |  solon.cloud.@@.lock  | 
| 分布式日志     |  Solon Cloud Logging     | CloudLogService |  solon.cloud.@@.log  | 


#### 1.2、通用客户端

通用客户端，提供了所有不同框架的统一使用界面，同时提供了自由手动操控的机制。当然，注解支持不会少！

```java 
//手动获取配置（不管背后是哪个配置框架，都是如此）
 Config val1 = CloudClient.config().pull(Solon.cfg().appGroup(), "demo.ds");
 
 //手动生成ID
 long val2 = CloudClient.id().generate();
 
 //手动发布事件（不管背后是哪个消息队列，都是如此）
 CloudClient.event().publish(new Event("demo.user.login","1"));
 
 //等...
```



### 2、快速概览


#### 2.1、Hello world 

一个普通的 rest api，输出 hello world

```java
@SolonMain
public class DemoApp {
    public static void main(String[] args) {
        Solon.start(DemoApp.class, args, app->{
          app.router().get("/", c -> c.output("Hello world!"));
        });
    }
}
```

#### 2.2、使用分布式配置服务


通过本地配置导入需要的分布式配置

```yaml
solon.app:
  group: "demo"
  name: "demoapp"

solon.cloud.water:
  server: "waterapi:9371"
  config:
    load: "demoapp.yml" #默认加载一个配置
```

或者，使用 @CloudConfig 注解生成Bean

```java
@Configuration
public class Config {
    @Bean
    public DataSource ds(@CloudConfig("demo.ds") HikariDataSource ds){
        return ds;
    }
}
```

#### 2.3、使用分布式注册与发现服务实现 Rpc 调用

服务端
```java
//
// 1.所有 remoting = true 的组件，即为 rpc 服务；
// 2.以 uri 的形式提供资源描述，以同时支持 rest api 和 rpc 两种模式（不要有相同的函数名出现）
//
@Mapping("/rpc/")
@Remoting
public class HelloServiceImpl implements HelloService{

    @Override
    public String hello(String name) {
        return null;
    }
}
```

客户端
```java
@Controller
public class HelloController {
    //注入Rpc服务代理（会自动通过发现服务获取服务集群）
    @NamiClient(name = "hellorpc", path = "/rpc/")
    HelloService helloService;
    
    public String hello(String name){
        return helloService.hello(name);
    }
}
```

#### 2.4、使用 Slf4j 日志接口，转发到分布式日志记录器

Solon Cloud Log 强调语义标签。通过语议标签，对日志进行固定索引，进而实现更快的查询，或者关联查询。

```java
@Slf4j
public class LogController {
    @Mapping("/")
    public String hello(String name){
        //将元信息固化为 tag0 ... tag4；利于做日志索引
        TagsMDC.tag0("user_"+name); //相当于 MDC.put("tag0", "user_"+name);
        
        log.info("有用户来了");
        
        return name;
    }
}
```

注：也可以改用 `logback` 或 `log4j` 日志框架（已适配 cloud 添加器）

#### 2.5、使用分布式事件进行业务水平扩展

Solon Cloud Event 的两个特性说明：

1. 自守护模式，即失败后不断延时重发确保最终成功。此特性可支持SAGA分布式事务模型。
2. 多通道模式，即不同消息框架并存。此特性可按业务做不同安排，例如：业务消息用 RabbitMQ，IoT消息用 Mqtt。


例，发布事件

```java 
public class EventController {
    public void onUserRegistered(long user_id) {
        //用户注册完成后，发布一个事件
        //
        CloudClient.event().publish(
                new Event("user.registered", String.format("{\"user_id\":%d}", user_id)));
    }
}
```

订阅与消费事件

```java
@CloudEvent("user.registered")
public class EventListen implements CloudEventHandler {
    @Override
    public boolean handler(Event event) throws Throwable {
        //用户注册完成后，送个金币...
        //
        return true;
    }
}
```


#### 2.6、使用分布式名单做Ip或Token限制

```java
public class ListController {
    public void hello(Context ctx){
        String ip = IpUtils.getIP(ctx);
        
        if(CloudClient.list().inListOfIp("safelist", ip) == false){
            return;
        }
        
        //业务处理...
    }
}
```


#### 2.7、使用分布式融断器进行限流控制

添加配置（此配置可通过配置服务，动态更新）

```yml
solon.cloud.local:
  breaker:
    main: 100 #qps = 100

```

通过注解，添加埋点

```java
//此处的注解埋点，名称与配置的断路器名称须一一对应
@CloudBreaker("main")
@Controller
public class BreakerController {
    @Mapping("/breaker")
    public void breaker(){
        
    }
}
```


#### 2.8、使用分布式跟踪服务获取并传播TraceId

通过MDC传递给 slf4j MDC
```java
String traceId = CloudClient.trace().getTraceId();

MDC.put(CloudClient.trace().HEADER_TRACE_ID_NAME(), traceId);
```

通过Http Header 传给后Http节点

```java
HttpUtils.url("http://x.x.x.x")
  .headerAdd(CloudClient.trace().HEADER_TRACE_ID_NAME(), traceId).get();
```

等......（Solon Cloud Log 默认支持 CloudClient.trace() 接口）


#### 2.9、使用简单的分布式监控服务

```java
//监控服务的路径请求性能（后端实现的时候，可以进一步记录超5秒、超1秒的次数；以及典线图）
CloudClient.metric().addMeter("path", path, milliseconds);

//监控服务的路径请求出错次数
CloudClient.metric().addCount("path_err", path, 1);

//监控服务的运行时状态
CloudClient.metric().addGauge("service", "runtime", RuntimeStatus.now());
```

#### 2.10、使用分布式任务

```java
//注解模式 - Hander 风格（也可以用：Bean method 风格）
@CloudJob("JobHandlerDemo1")
public class JobHandlerDemo1 implements CloudJobHandler {
    @Override
    public void handle(Context ctx) throws Throwable {
        //任务处理
    }
}

//手动模式
CloudClient.job().register("JobHandlerDemo3","",c->{
    //任务处理 
});
```


#### 2.11、使用分布式ID，生成有序不重复ID

```java
long log_id = CloudClient.id().generate();
```

一般用于无逻辑性的ID生成，如：日志ID、事务ID、自增ID...

#### 2.12、使用分布式锁，对流量或资源进行控制

```java
if(CloudClient.lock().tryLock("user_"+user_id, 3)){
    //对一个用户尝试3秒的锁；3秒内不充行重复提交
}else{
    //请求太频繁了...
}
```

#### 2.13、使用分布式文件服务


```java
//使用分布式文件，存储用户扩展信息
CloudClient.file().put("solon/user_"+user_id, new Media("{name:noear}"));

//读取
Media data = CloudClient.file().get("solon/user_"+user_id);
```


#### 2.14、使用分布式网关服务


```yml
solon.cloud.gateway:
  routes:
    - id: demo
      target: "https://www.baidu.com" # 或 "lb://user-service"
      predicates:
        - "Path=/**"
```


