zoukankan      html  css  js  c++  java
  • Solon Cloud 分布式服务开发套件清单,感觉受与 Spring Cloud 的不同

    Solon Cloud 是一系列的接口标准和配置规范。Solon Cloud 为常见的分布式系统模式提供了一种简单且方便的编程模式,帮助开发人员构建有弹性的、可靠的、协调的应用程序。Solon Cloud 构建于 Solon 之上,可使开发者很容易入手并快速应用于生产中。Solon Cloud 主要由三部份组成:接口定义与配置规范、实现相关接口定义的各种插件,以及通用客户端。

    Solon Cloud 非常容易实现与自研框架进行对接。只要实现相关接口定义,按规范配置的一个插件,即是一个 Solon Cloud 插件。

    Solon Cloud 项目源码:https://gitee.com/noear/solon

    Solon Cloud 示例源码:https://gitee.com/noear/solon_cloud_demo

    特点1:身材苗条

    最小的 Solon Cloud 开发单位只有5m(含 okhttp、mysql、redis、memcaced、HikariCP 等客户端或驱动)

    特点2:速度更快

    本机helloworld测试,Qps可达12万之多。可参考:《helloworld_wrk_test

    特点3:代码自由

    所有的能力可以用注解,也可以纯手写。按需而定,自由随心。

    建议

    让自己的单体应用,能多实例部署。就是分布式的良好开始......然后改用配置服务,然后增加事件驱动,按需拆分......慢慢来。

    一、Solon Cloud 套件内容

    (1)接口定义及配置规范清单

    接口定义及配置规范,可为不同的框架适配与使用提供了统一的模式

    功能名称 Solon Cloud 接口定义 配置规范(具体暂略)
    服务注册与发现 Solon Cloud Discovery CloudDiscoveryService solon.cloud.@@.discovery
    服务间调用方式 RPC or REST API or Event - -
    服务网关 Solon 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

    (2)现有适配插件清单

    插件 说明
    org.noear:consul-solon-plugin consul 适配插件(支持Solon cloud 配置服务、注册与发现服务)
    org.noear:nacos-solon-plugin nacos 适配插件(支持Solon cloud 配置服务、注册与发现服务)
    org.noear:zookeeper-solon-plugin zookeeper 适配插件(支持Solon cloud 配置服务、注册与发现服务)
    org.noear:water-solon-plugin water 适配插件(支持Solon cloud 配置服务、注册与发现服务、事件总线服务、日志服务、跟踪服务、监控、分布式任务、锁服务)
    org.noear:rabbitmq-solon-plugin rabbitmq 适配插件(支持Solon cloud 事件总线服务)
    org.noear:rocketmq-solon-plugin rocketmq 适配插件(支持Solon cloud 事件总线服务)
    org.noear:mqtt-solon-plugin mqtt 适配插件(支持Solon cloud 事件总线服务)
    org.noear:kafka-solon-plugin kafka 适配插件(支持Solon cloud 事件总线服务)
    org.noear:guava-solon-plugin guava 适配插件(支持Solon cloud 融断服务)
    org.noear:sentinel-solon-plugin sentinel 适配插件(支持Solon cloud 融断服务)
    org.noear:semaphore-solon-plugin semaphore 适配插件(支持Solon cloud 融断服务)
    org.noear:aliyun-oss-solon-plugin aliyun-oss 适配插件(支持Solon cloud 分布式文件服务)
    org.noear:aws-s3-solon-plugin aws-s3 适配插件(支持Solon cloud 分布式文件服务)
    org.noear:snowflake-id-solon-plugin snowflake 算法适配插件(支持Solon cloud 分布式ID服务)
    org.noear:xxl-job-solon-plugin xxl-job 适配插件(支持Solon cloud 分布式任务服务)

    (3)通用客户端

    通用客户端,提供了所有不同框架的统一使用界面,同时提供了自由手动操控的机制。

    //手动获取配置(不管背后是哪个配置框架,都是如此)
     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"));
     
     //等...
    

    二、快速概览

    (1)hello world

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

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

    (2)使用配置服务(目前适配有:water, consul, nacos, zookeeper)

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

    solon.cloud.water:
      server: water  
      config:
        load: "test.properties" #默认加载一个配置
    

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

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

    (3)使用注册与发现服务实现RPC调用(目前适配有:water, consul, nacos, zookeeper)

    服务端

    //
    // 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;
        }
    }
    

    客户端

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

    (4)使用Slf4j日志接口,转发到分布式日志记录器(目前适配有:water)

    Solon Cloud Log 强调语义标签(或固化的元信息)。通过语议标签,对日志进行固定索引,进而实现更快的查询效果。

    @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;
        }
    }
    

    注:也可以改用 logbacklog4j 做日志服务,只需要排除掉 solon.logging.impl 框架却可

    (5)使用分布式事件进行业务水平扩展(目前适配有:water, rabbitmq, rocketmq, mqtt, kafka)

    Solon Cloud Event 的两个特性说明:

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

    例,发布事件

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

    订阅与消费事件

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

    (6)使用分布式名单做IP限制(目前适配有:water)

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

    (7)使用融断器进行限流控制(目前适配有:sentinel, guava, semaphore)

    添加配置(此配置可通过配置服务,动态更新)

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

    通过注解,添加埋点

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

    (8)使用跟踪服务获取并传播TraceId(目前适配有:water)

    通过MDC传递给 slf4j MDC

    String traceId = CloudClient.trace().getTraceId();
    
    MDC.put(CloudClient.trace().HEADER_TRACE_ID_NAME(), traceId);
    

    通过Http Header 传给后Http节点

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

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

    (9)使用简单监控服务(目前适配有:water)

    //监控服务的路径请求性能(后端实现的时候,可以进一步记录超5秒、超1秒的次数;以及典线图)
    CloudClient.metric().addMeter("path", path, milliseconds);
    
    //监控服务的路径请求出错次数
    CloudClient.metric().addCount("path_err", path, 1);
    
    //监控服务的运行时状态
    CloudClient.metric().addGauge("service", "runtime", RuntimeStatus.now());
    

    (10)使用分布式任务(目前适配有:water, xxl-job)

    //注解模式 - Hander 风格(也可以用:Bean method 风格)
    @CloudJob("JobHandlerDemo1")
    public class JobHandlerDemo1 implements Handler {
        @Override
        public void handle(Context ctx) throws Throwable {
            //任务处理
        }
    }
    
    //手动模式
    CloudClient.job().register("JobHandlerDemo3","",c->{
        //任务处理 
    });
    

    (11)使用分布式ID,生成有序不重复ID(目前适配有:snowflake)

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

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

    (12)使用分布式锁,对流量或资源进行控制(目前适配有:water, redis)

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

    (13)使用分布式文件服务(目前适配有:aws-s3, aliyun-oss)

    //使用分布式文件,存储用户扩展信息
    CloudClient.file().putText("solon/user_"+user_id, "{name:noear}")
    

    (14)使用网关,为同一套接口提供不同的输出(Solon 自带)

    网关的技术本质,是一个定制了的 Solon Handler。如此理解,新切感会好些:)

    //网关1
    @Mapping("/api/rest/**")
    @Component
    public class Gateway1 extends Gateway {
        @Override
        protected void register() {
            //设定默认render
            before(c -> c.attrSet("@render", "@json"));
    
            //添加服务
            add("user", UserServiceImpl.class, true);
    
        }
    }
    
    //网关2
    @Mapping("/api/rpc/**")
    @Component
    public class Gateway3 extends Gateway {
        @Override
        protected void register() {
            //设定默认render
            before(c -> c.attrSet("@render", "@type_json"));
    
            //添加服务(不带mapping的函数;需要 remoting = true,才会加载出来)
            add("user", UserServiceImpl.class, true);
        }
    }
    
    //网关3(这个比较复杂,和实战性)
    @Mapping("/api/v2/app/**")
    @Component
    public class Gateway3 extends UapiGateway {
        @Override
        protected void register() {
        
            filter(new BreakerFilter()); //融断过滤器
    
            before(new StartHandler()); //开始计时
            before(new ParamsParseHandler()); //参数解析
            before(new ParamsSignCheckHandler(new Md5Encoder())); //参数签名较验
            before(new ParamsRebuildHandler(new AesDecoder())); //参数重构
    
            after(new OutputBuildHandler(new AesEncoder())); //输出构建
            after(new OutputSignHandler(new Md5Encoder())); //输出签名
            after(new OutputHandler()); //输出
            after(new EndBeforeLogHandler()); //日志
            after(new EndHandler("v2.api.app")); //结束计时
    
            addBeans(bw -> "api".equals(bw.tag()));
        }
    }
    

    三、附:完整的配置

    application.yml

    solon.app:
      group: demo       #配置服务使用的默认组
      name: helloapp    #发现服务使用的应用名
    
    solon.cloud.water:
      server: water   #water服务地址
      config:
        load: "test.properties" #默认加载一个配置
      discovery:
        enable: true  #设为 false 时,solon.cloud.local.discovery 会生效(一般用于本地调试)
    
    solon.cloud.local:
      discovery:
        service:
          hellorpc:
            - "http://localhost:7112"  #本地服务配置
      breaker:
        main: 100
    
    

    pom.xml (以下配置打包只有4.7m)

    <parent>
        <groupId>org.noear</groupId>
        <artifactId>solon-parent</artifactId>
        <version>1.5.5</version>
    </parent>
    
    <dependencies>
        <!-- RPC 框架 -->
        <dependency>
            <groupId>org.noear</groupId>
            <artifactId>solon-rpc</artifactId>
        </dependency>
    
        <!-- 配置服务、注册与发现服务、日志服务、锁服务、名单服务、跟踪服务... (含 okhttp,redis,memcaced,HikariCP 等...) -->
        <dependency>
            <groupId>org.noear</groupId>
            <artifactId>water-solon-plugin</artifactId>
        </dependency>
    
        <!-- 融断服务 -->
        <dependency>
            <groupId>org.noear</groupId>
            <artifactId>sentinel-solon-plugin</artifactId>
        </dependency>
    
        <!-- 文件服务 -->
        <dependency>
            <groupId>org.noear</groupId>
            <artifactId>aliyun-oss-solon-plugin</artifactId>
        </dependency>
    
        <!-- ID服务 -->
        <dependency>
            <groupId>org.noear</groupId>
            <artifactId>snowflake-id-solon-plugin</artifactId>
        </dependency>
    
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
    
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    
    <build>
        <finalName>${project.artifactId}</finalName>
    
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <compilerArgument>-parameters</compilerArgument>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
    
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <finalName>${project.artifactId}</finalName>
                    <appendAssemblyId>false</appendAssemblyId>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>demo.DemoApp</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    
    </build>
    
  • 相关阅读:
    Unique Binary Search Trees——LeetCode
    Binary Tree Inorder Traversal ——LeetCode
    Maximum Product Subarray——LeetCode
    Remove Linked List Elements——LeetCode
    Maximum Subarray——LeetCode
    Validate Binary Search Tree——LeetCode
    Swap Nodes in Pairs——LeetCode
    Find Minimum in Rotated Sorted Array——LeetCode
    Linked List Cycle——LeetCode
    VR AR MR
  • 原文地址:https://www.cnblogs.com/noear/p/14734649.html
Copyright © 2011-2022 走看看