微服務(wù)分布式協(xié)作框架tridenter使用介紹

tridenter是一款基于SpringBoot框架開發(fā)的微服務(wù)分布式協(xié)作框架,它可以使多個獨立的SpringBoot應(yīng)用輕松快捷地組成一個集群,而不依賴外部的注冊中心(比如SpringCloud Eureka等)。
tridenter框架首先提供了豐富的分布式應(yīng)用集群管理API和工具,同時也提供了一套完整的微服務(wù)治理功能

tridenter的特性:

  1. 采用去中心化的思想管理集群
  2. 支持集群間的消息多播和單播
  3. 支持各種負載均衡策略
  4. 支持多種Leader選舉算法
  5. 提供進程池/調(diào)度進程池的實現(xiàn)
  6. 內(nèi)置微服務(wù)注冊中心
  7. 內(nèi)置多種微服務(wù)間調(diào)用的限流降級策略
  8. 內(nèi)置微服務(wù)Rest客戶端
  9. 內(nèi)置HTTP服務(wù)網(wǎng)關(guān)
  10. 集群狀態(tài)監(jiān)控和告警
  11. 分布式事務(wù)管理

集群中的消息多播是tridenter非常重要的功能,tridenter底層是通過Redis(PubSub)實現(xiàn)多播功能從而實現(xiàn)應(yīng)用的相互發(fā)現(xiàn)的,進而組成應(yīng)用集群的。集群中的每個成員都支持消息多播和單播的能力。
利用tridenter支持消息單播的能力,tridenter提供了Leader選舉算法接口,內(nèi)置了兩種Leader選舉算法,快速Leader選舉算法(基于Redis隊列)和一致性選舉算法(基于Paxos算法)
同時,利用tridenter支持消息單播的能力,tridenter提供了進程池,實現(xiàn)了跨進程的方法調(diào)用和方法分片的能力
另一方面,tridenter本身也提供了微服務(wù)治理的基本功能:
tridenter自帶注冊中心,而利用消息多播的原理,應(yīng)用是相互發(fā)現(xiàn),相互注冊的,所以集群中的每個成員都有一份全量的成員列表,即每個應(yīng)用都是注冊中心,體現(xiàn)了去中心化的設(shè)計思想。每個成員通過命名服務(wù),實現(xiàn)了應(yīng)用之間HTTP接口互相調(diào)用的能力,并提供了相關(guān)各種注解和Restful配置將服務(wù)發(fā)布方和消費方解耦
tridenter自帶網(wǎng)關(guān)功能,可以將應(yīng)用獨立發(fā)布成網(wǎng)關(guān)服務(wù),可代理分發(fā)HTTP請求和下載任務(wù)(暫不支持上傳)
tridenter還內(nèi)置了多種負載均衡算法和限流降級策略,用戶也可以自定義負載均衡算法或降級策略
tridenter實現(xiàn)了spring actuator的健康檢查接口,除了監(jiān)控集群狀態(tài),還自帶接口的統(tǒng)計分析等功能,初步實現(xiàn)了接口的統(tǒng)一管理和監(jiān)控
所以,基于tridenter框架,我們也可以搭建一套類似于Spring Cloud的微服務(wù)體系

tridenter采用了去中心化的設(shè)計思想,即開發(fā)人員不需要知道當前哪個是主節(jié)點,哪些節(jié)點是從節(jié)點,更不應(yīng)該顯式地定義某個應(yīng)用為主節(jié)點,這是由tridenter采用的Leader選舉算法決定的,默認的選舉算法是快速選舉算法。根據(jù)選舉算法,集群內(nèi)的任意一個應(yīng)用節(jié)點都有可能成為主節(jié)點,默認第一個啟動的應(yīng)用就是主節(jié)點,但是如果采用的是一致性選舉算法,可能就會不一樣。根據(jù)作者描述,一致性選舉算法目前不穩(wěn)定,推薦在應(yīng)用中使用快速選舉算法。

Maven:

        <dependency>
            <groupId>com.github.paganini2008.atlantis</groupId>
            <artifactId>tridenter-spring-boot-starter</artifactId>
            <version>1.0-RC3</version>
        </dependency>

tridenter的基本功能就是讓不同的Spring Boot應(yīng)用變成集群模式,所以配置的時候,我們要在application.properties 定義兩個系統(tǒng)變量,否則會報錯

spring.application.name=chaconne-management  # 服務(wù)名稱
spring.application.cluster.name=chaconne-management-cluster  #集群名稱

啟動之后,如果在Console看到以下信息則表示集群配置生效

2021-06-05 18:20:11 [INFO ] io.undertow - starting server: Undertow - 2.0.29.Final
2021-06-05 18:20:11 [INFO ] org.xnio - XNIO version 3.3.8.Final
2021-06-05 18:20:11 [INFO ] org.xnio.nio - XNIO NIO Implementation Version 3.3.8.Final
2021-06-05 18:20:11 [INFO ] i.a.f.t.m.ApplicationMulticastGroup - Registered candidate: {applicationContextPath: http://192.168.159.1:6543, applicationName: chaconne-management, clusterName: chaconne-management-cluster, id: fafdc9ada3a5d1de3836b1a0ba4ef174, leader: false, startTime: 1622888405582, weight: 1}, Proportion: 1/1
2021-06-05 18:20:11 [INFO ] i.a.f.t.m.ApplicationRegistryCenter - Register application: [{applicationContextPath: http://192.168.159.1:6543, applicationName: chaconne-management, clusterName: chaconne-management-cluster, id: fafdc9ada3a5d1de3836b1a0ba4ef174, leader: false, startTime: 1622888405582, weight: 1}] to ApplicationRegistryCenter
2021-06-05 18:20:11 [INFO ] i.a.f.c.SerialDependencyListener - SerialDependencyHandler initialize successfully.
2021-06-05 18:20:11 [INFO ] i.a.f.t.e.ApplicationLeaderElection - This is the leader of application cluster 'chaconne-management-cluster'. Current application event type is 'indi.atlantis.framework.tridenter.election.ApplicationClusterLeaderEvent'
2021-06-05 18:20:11 [INFO ] i.a.f.t.e.ApplicationLeaderElection - Current leader: {applicationContextPath: http://192.168.159.1:6543, applicationName: chaconne-management, clusterName: chaconne-management-cluster, id: fafdc9ada3a5d1de3836b1a0ba4ef174, leader: true, startTime: 1622888405582, weight: 1}
2021-06-05 18:20:11 [INFO ] o.s.b.w.e.u.UndertowServletWebServer - Undertow started on port(s) 6543 (http) with context path ''
2021-06-05 18:20:12 [INFO ] i.a.f.c.m.ChaconneManagementMain - Started ChaconneManagementMain in 12.134 seconds (JVM running for 12.829)

首先:

2021-06-05 18:20:11 [INFO ] i.a.f.t.m.ApplicationMulticastGroup - Registered candidate: {applicationContextPath: http://192.168.159.1:6543, applicationName: chaconne-management, clusterName: chaconne-management-cluster, id: fafdc9ada3a5d1de3836b1a0ba4ef174, leader: false, startTime: 1622888405582, weight: 1}, Proportion: 1/1
2021-06-05 18:20:11 [INFO ] i.a.f.t.m.ApplicationRegistryCenter - Register application: [{applicationContextPath: http://192.168.159.1:6543, applicationName: chaconne-management, clusterName: chaconne-management-cluster, id: fafdc9ada3a5d1de3836b1a0ba4ef174, leader: false, startTime: 1622888405582, weight: 1}] to ApplicationRegistryCenter

這兩行日志分別表示成功注冊消息多播組和應(yīng)用注冊中心

2021-06-05 18:20:11 [INFO ] i.a.f.t.e.ApplicationLeaderElection - This is the leader of application cluster 'chaconne-management-cluster'. Current application event type is 'indi.atlantis.framework.tridenter.election.ApplicationClusterLeaderEvent'
2021-06-05 18:20:11 [INFO ] i.a.f.t.e.ApplicationLeaderElection - Current leader: {applicationContextPath: http://192.168.159.1:6543, applicationName: chaconne-management, clusterName: chaconne-management-cluster, id: fafdc9ada3a5d1de3836b1a0ba4ef174, leader: true, startTime: 1622888405582, weight: 1}

這兩行日志分別表示利用ApplicationLeaderElection選舉算法選出當前的應(yīng)用是leader,(快速選舉算法默認將第一個啟動的應(yīng)用作為Leader, 有點類似Jgroups)

tridenter-spring-boot-starter是一個基礎(chǔ)型的框架,提供了各種分布式能力,下面介紹一下幾種能力:

進程池

多個同名應(yīng)用(${spring.application.name})可以組建成一個進程池,就像線程池分配不同的線程調(diào)用某個方法一樣,進程池可以進行跨應(yīng)用的方法調(diào)用,前提是這個方法是存在的

示例代碼:

    @MultiProcessing(value = "calc", defaultValue = "11")
    public int calc(int a, int b) {
        if (a % 3 == 0) {
            throw new IllegalArgumentException("a ==> " + a);
        }
        log.info("[" + counter.incrementAndGet() + "]Port: " + port + ", Execute at: " + new Date());
        return a * b * 20;
    }

    @OnSuccess("calc")
    public void onSuccess(Object result, MethodInvocation invocation) {
        log.info("Result: " + result + ", Take: " + (System.currentTimeMillis() - invocation.getTimestamp()));
    }

    @OnFailure("calc")
    public void onFailure(ThrowableProxy info, MethodInvocation invocation) {
        log.info("========================================");
        log.error("{}", info);
    }

說明:

  1. 注解 @MultiProcessing修飾方法calc, 表示這個方法是多進程調(diào)用的
  2. onSuccess和onFailure兩個方法都是異步的調(diào)用的

方法分片

方法分片又叫方法并行處理,其實就是將一組參數(shù)的每一個參數(shù)使用進程池分發(fā)到不同應(yīng)用上運行,然后再合并輸出,并需要實現(xiàn)分片規(guī)則接口,見源碼:

public interface Parallelization {

    Object[] slice(Object argument); // 切片

    Object merge(Object[] results);  // 合并

}

示例代碼:

    @ParallelizingCall(value = "loop-test", usingParallelization = TestCallParallelization.class)
    public long total(String arg) {// 0,1,2,3,4,5,6,7,8,9
        return 0L;
    }

    public static class TestCallParallelization implements Parallelization {

        @Override
        public Long[] slice(Object argument) {
            String[] args = ((String) argument).split(",");
            Long[] longArray = new Long[args.length];
            int i = 0;
            for (String arg : args) {
                longArray[i++] = Long.parseLong(arg);
            }
            return longArray;
        }

        @Override
        public Long merge(Object[] results) {
            long total = 0;
            for (Object o : results) {
                total += ((Long) o).longValue();
            }
            return total;
        }

    }

說明:

  1. 注解@ParallelizingCall修飾total方法,表示這個方法要做分片處理
  2. 參數(shù)arg, 比如說你可以傳 0,1,2,3,4,5,6,7,8,9,分片規(guī)則會調(diào)用slice方法將參數(shù)以“,”分割,變成數(shù)組,然后將每個值轉(zhuǎn)換成long型,再分發(fā)到各個應(yīng)用執(zhí)行,全部執(zhí)行完了,再執(zhí)行merge方法進行加和操作,有點MapReduce的味道
  3. total方法返回的0,是指當參數(shù)為空或方法異常返回的默認值

微服務(wù)能力

Rest客戶端

示例代碼:

@RestClient(provider = "test-service")
// @RestClient(provider = "http://192.168.159.1:5050")
public interface TestRestClient {

    @PostMapping("/metrics/sequence/{dataType}")
    Map<String, Object> sequence(@PathVariable("dataType") String dataType, @RequestBody SequenceRequest sequenceRequest);

}

說明:

  1. 注解@RestClient修飾的接口說明這是個Http客戶端
  2. 注解中,provider屬性表示服務(wù)提供方,可以是集群中的某個應(yīng)用名(${spring.application.name}),也可以是具體http地址
  3. 支持Spring注解(GetMapping, PostMapping, PutMapping, DeleteMapping), 此外,用注解@Api可提供更細粒度的參數(shù)設(shè)置

網(wǎng)關(guān)

@EnableGateway
@SpringBootApplication
@ComponentScan
public class GatewayMain {

    public static void main(String[] args) {
        final int port = 9000;
        System.setProperty("server.port", String.valueOf(port));
        SpringApplication.run(GatewayMain.class, args);
    }
}

引用注解@EnableGateway就行了,tridenter的網(wǎng)關(guān)底層是用Netty4實現(xiàn)的

配置路由:
@Primary
@Component
public class MyRouterCustomizer extends DefaultRouterCustomizer {

    @Override
    public void customize(RouterManager rm) {
        super.customize(rm);
        rm.route("/my/**").provider("tester5");
        rm.route("/test/baidu").url("https://www.baidu.com").resourceType(ResourceType.REDIRECT);
        rm.route("/test/stream").url("  https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png").resourceType(ResourceType.STREAM);
    }

}

說明:
ResourceType的4種類型:
DEFAULT, 轉(zhuǎn)發(fā)請求
REDIRECT, 跳轉(zhuǎn)
STREAM, 二進制流
FILE 保存文件

限流降級

限流是指在客戶端限流,而非服務(wù)端
限流會依賴3個指標:

  1. 響應(yīng)超時率
  2. 錯誤率
  3. 并發(fā)度
    默認情況,當這三個指標中有任一指標超過80%,即會觸發(fā)限流,調(diào)用降級服務(wù)
    限流指標統(tǒng)計類 : RequestStatisticIndicator
    降級服務(wù)接口:FallbackProvider
    相關(guān)源碼可自行研究

健康監(jiān)控

目前tridenter提供了3個HealthIndicator的子類

  1. ApplicationClusterHealthIndicator
    顯示集群的整體健康狀態(tài)
  2. TaskExecutorHealthIndicator
    顯示集群線程池的健康狀態(tài)
  3. RestClientHealthIndicator
    顯示Rest客戶端的健康狀態(tài)(響應(yīng)超時率,錯誤率,并發(fā)度)

最后,微服務(wù)分布式協(xié)作框架tridenter的源碼地址:https://github.com/paganini2008/tridenter-spring-boot-starter.git

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

  • 表情是什么,我認為表情就是表現(xiàn)出來的情緒。表情可以傳達很多信息。高興了當然就笑了,難過就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 129,447評論 2 7
  • 16宿命:用概率思維提高你的勝算 以前的我是風險厭惡者,不喜歡去冒險,但是人生放棄了冒險,也就放棄了無數(shù)的可能。 ...
    yichen大刀閱讀 7,576評論 0 4

友情鏈接更多精彩內(nèi)容