• 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>
    
  • 相关阅读:
    清除页面广告?身为前端,自己做一款简易的Chrome扩展吧
    Nginx 引入线程池,提升 9 倍性能
    调试时屏蔽JavaScript库代码 –Chrome DevTools Blackbox功能介绍
    收集的React.JS资料
    谈谈 React.js 的核心入门知识
    同时包含字母和数字的正则表达式
    Word2010撤销按钮失效,Ctrl+Z失效解决办法
    大数据于产业金融领域的运用究竟如何很好的实现
    HTTP 错误 500.19
    WindowsServer2012桌面图标设置
  • 原文地址:https://www.cnblogs.com/noear/p/14734649.html
Copyright © 2020-2023  润新知