日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

SpringBoot + Disruptor 實(shí)現(xiàn)特快高并發(fā)處理,贊!

來源: 責(zé)編: 時(shí)間:2023-10-23 17:03:45 304觀看
導(dǎo)讀1.背景工作中遇到項(xiàng)目使用Disruptor做消息隊(duì)列,對(duì)你沒看錯(cuò),不是Kafka也不是rabbitmq。Disruptor有個(gè)最大的優(yōu)點(diǎn)就是快,還有一點(diǎn)它是開源的哦,下面做個(gè)簡(jiǎn)單的記錄。2.Disruptor介紹Disruptor 是英國外匯交易公司LMAX開發(fā)的

1.背景

工作中遇到項(xiàng)目使用Disruptor做消息隊(duì)列,對(duì)你沒看錯(cuò),不是Kafka也不是rabbitmq。Disruptor有個(gè)最大的優(yōu)點(diǎn)就是快,還有一點(diǎn)它是開源的哦,下面做個(gè)簡(jiǎn)單的記錄。GBo28資訊網(wǎng)——每日最新資訊28at.com

GBo28資訊網(wǎng)——每日最新資訊28at.com

2.Disruptor介紹

Disruptor 是英國外匯交易公司LMAX開發(fā)的一個(gè)高性能隊(duì)列,研發(fā)的初衷是解決內(nèi)存隊(duì)列的延遲問題(在性能測(cè)試中發(fā)現(xiàn)竟然與I/O操作處于同樣的數(shù)量級(jí))。GBo28資訊網(wǎng)——每日最新資訊28at.com

基于 Disruptor 開發(fā)的系統(tǒng)單線程能支撐每秒 600 萬訂單,2010 年在 QCon 演講后,獲得了業(yè)界關(guān)注。GBo28資訊網(wǎng)——每日最新資訊28at.com

GBo28資訊網(wǎng)——每日最新資訊28at.com

Disruptor是一個(gè)開源的Java框架,它被設(shè)計(jì)用于在生產(chǎn)者—消費(fèi)者(producer-consumer problem,簡(jiǎn)稱PCP)問題上獲得盡量高的吞吐量(TPS)和盡量低的延遲。GBo28資訊網(wǎng)——每日最新資訊28at.com

從功能上來看,Disruptor 是實(shí)現(xiàn)了“隊(duì)列”的功能,而且是一個(gè)有界隊(duì)列。那么它的應(yīng)用場(chǎng)景自然就是“生產(chǎn)者-消費(fèi)者”模型的應(yīng)用場(chǎng)合了。GBo28資訊網(wǎng)——每日最新資訊28at.com

Disruptor是LMAX在線交易平臺(tái)的關(guān)鍵組成部分,LMAX平臺(tái)使用該框架對(duì)訂單處理速度能達(dá)到600萬TPS,除金融領(lǐng)域之外,其他一般的應(yīng)用中都可以用到Disruptor,它可以帶來顯著的性能提升。GBo28資訊網(wǎng)——每日最新資訊28at.com

其實(shí)Disruptor與其說是一個(gè)框架,不如說是一種設(shè)計(jì)思路,這個(gè)設(shè)計(jì)思路對(duì)于存在“并發(fā)、緩沖區(qū)、生產(chǎn)者—消費(fèi)者模型、事務(wù)處理”這些元素的程序來說,Disruptor提出了一種大幅提升性能(TPS)的方案。GBo28資訊網(wǎng)——每日最新資訊28at.com

Disruptor的github主頁:https://github.com/LMAX-Exchange/disruptorGBo28資訊網(wǎng)——每日最新資訊28at.com

3.Disruptor 的核心概念

先從了解 Disruptor 的核心概念開始,來了解它是如何運(yùn)作的。下面介紹的概念模型,既是領(lǐng)域?qū)ο螅彩怯成涞酱a實(shí)現(xiàn)上的核心對(duì)象。GBo28資訊網(wǎng)——每日最新資訊28at.com

(1) Ring BufferGBo28資訊網(wǎng)——每日最新資訊28at.com

如其名,環(huán)形的緩沖區(qū)。曾經(jīng) RingBuffer 是 Disruptor 中的最主要的對(duì)象,但從3.0版本開始,其職責(zé)被簡(jiǎn)化為僅僅負(fù)責(zé)對(duì)通過 Disruptor 進(jìn)行交換的數(shù)據(jù)(事件)進(jìn)行存儲(chǔ)和更新。在一些更高級(jí)的應(yīng)用場(chǎng)景中,Ring Buffer 可以由用戶的自定義實(shí)現(xiàn)來完全替代。GBo28資訊網(wǎng)——每日最新資訊28at.com

(2) Sequence DisruptorGBo28資訊網(wǎng)——每日最新資訊28at.com

通過順序遞增的序號(hào)來編號(hào)管理通過其進(jìn)行交換的數(shù)據(jù)(事件),對(duì)數(shù)據(jù)(事件)的處理過程總是沿著序號(hào)逐個(gè)遞增處理。一個(gè) Sequence 用于跟蹤標(biāo)識(shí)某個(gè)特定的事件處理者( RingBuffer/Consumer )的處理進(jìn)度。GBo28資訊網(wǎng)——每日最新資訊28at.com

雖然一個(gè) AtomicLong 也可以用于標(biāo)識(shí)進(jìn)度,但定義 Sequence 來負(fù)責(zé)該問題還有另一個(gè)目的,那就是防止不同的 Sequence 之間的CPU緩存?zhèn)喂蚕?Flase Sharing)問題。GBo28資訊網(wǎng)——每日最新資訊28at.com

注:這是 Disruptor 實(shí)現(xiàn)高性能的關(guān)鍵點(diǎn)之一,網(wǎng)上關(guān)于偽共享問題的介紹已經(jīng)汗牛充棟,在此不再贅述。GBo28資訊網(wǎng)——每日最新資訊28at.com

GBo28資訊網(wǎng)——每日最新資訊28at.com

(3) SequencerGBo28資訊網(wǎng)——每日最新資訊28at.com

Sequencer 是 Disruptor 的真正核心。此接口有兩個(gè)實(shí)現(xiàn)類 SingleProducerSequencer、MultiProducerSequencer ,它們定義在生產(chǎn)者和消費(fèi)者之間快速、正確地傳遞數(shù)據(jù)的并發(fā)算法。GBo28資訊網(wǎng)——每日最新資訊28at.com

(4) Sequence BarrierGBo28資訊網(wǎng)——每日最新資訊28at.com

用于保持對(duì)RingBuffer的 main published Sequence 和Consumer依賴的其它Consumer的 Sequence 的引用。 Sequence Barrier 還定義了決定 Consumer 是否還有可處理的事件的邏輯。GBo28資訊網(wǎng)——每日最新資訊28at.com

(5) Wait StrategyGBo28資訊網(wǎng)——每日最新資訊28at.com

定義 Consumer 如何進(jìn)行等待下一個(gè)事件的策略。 (注:Disruptor 定義了多種不同的策略,針對(duì)不同的場(chǎng)景,提供了不一樣的性能表現(xiàn))GBo28資訊網(wǎng)——每日最新資訊28at.com

(6) EventGBo28資訊網(wǎng)——每日最新資訊28at.com

在 Disruptor 的語義中,生產(chǎn)者和消費(fèi)者之間進(jìn)行交換的數(shù)據(jù)被稱為事件(Event)。它不是一個(gè)被 Disruptor 定義的特定類型,而是由 Disruptor 的使用者定義并指定。GBo28資訊網(wǎng)——每日最新資訊28at.com

(7) EventProcessorGBo28資訊網(wǎng)——每日最新資訊28at.com

EventProcessor 持有特定消費(fèi)者(Consumer)的 Sequence,并提供用于調(diào)用事件處理實(shí)現(xiàn)的事件循環(huán)(Event Loop)。GBo28資訊網(wǎng)——每日最新資訊28at.com

(8) EventHandlerGBo28資訊網(wǎng)——每日最新資訊28at.com

Disruptor 定義的事件處理接口,由用戶實(shí)現(xiàn),用于處理事件,是 Consumer 的真正實(shí)現(xiàn)。GBo28資訊網(wǎng)——每日最新資訊28at.com

(9) ProducerGBo28資訊網(wǎng)——每日最新資訊28at.com

即生產(chǎn)者,只是泛指調(diào)用 Disruptor 發(fā)布事件的用戶代碼,Disruptor 沒有定義特定接口或類型。GBo28資訊網(wǎng)——每日最新資訊28at.com

GBo28資訊網(wǎng)——每日最新資訊28at.com

4.案例-demo

通過下面8個(gè)步驟,你就能將Disruptor Get回家啦:GBo28資訊網(wǎng)——每日最新資訊28at.com

(1) 添加pom.xml依賴GBo28資訊網(wǎng)——每日最新資訊28at.com

<dependency>    <groupId>com.lmax</groupId>    <artifactId>disruptor</artifactId>    <version>3.4.4</version></dependency>

(2) 消息體ModelGBo28資訊網(wǎng)——每日最新資訊28at.com

/** * 消息體 */@Datapublic class MessageModel {    private String message;}

(3) 構(gòu)造EventFactoryGBo28資訊網(wǎng)——每日最新資訊28at.com

public class HelloEventFactory implements EventFactory<MessageModel> {    @Override    public MessageModel newInstance() {        return new MessageModel();    }}

(4) 構(gòu)造EventHandler-消費(fèi)者GBo28資訊網(wǎng)——每日最新資訊28at.com

@Slf4jpublic class HelloEventHandler implements EventHandler<MessageModel> {    @Override    public void onEvent(MessageModel event, long sequence, boolean endOfBatch) {        try {            //這里停止1000ms是為了確定消費(fèi)消息是異步的            Thread.sleep(1000);            log.info("消費(fèi)者處理消息開始");            if (event != null) {                log.info("消費(fèi)者消費(fèi)的信息是:{}",event);            }        } catch (Exception e) {            log.info("消費(fèi)者處理消息失敗");        }        log.info("消費(fèi)者處理消息結(jié)束");    }}

(5) 構(gòu)造BeanManagerGBo28資訊網(wǎng)——每日最新資訊28at.com

/** * 獲取實(shí)例化對(duì)象 */@Componentpublic class BeanManager implements ApplicationContextAware {    private static ApplicationContext applicationContext = null;    @Override    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {        this.applicationContext = applicationContext;    }    public static ApplicationContext getApplicationContext() { return applicationContext; }    public static Object getBean(String name) {        return applicationContext.getBean(name);    }    public static <T> T getBean(Class<T> clazz) {        return applicationContext.getBean(clazz);    }}

(6) 構(gòu)造MQManagerGBo28資訊網(wǎng)——每日最新資訊28at.com

@Configurationpublic class MQManager {    @Bean("messageModel")    public RingBuffer<MessageModel> messageModelRingBuffer() {        //定義用于事件處理的線程池, Disruptor通過java.util.concurrent.ExecutorSerivce提供的線程來觸發(fā)consumer的事件處理        ExecutorService executor = Executors.newFixedThreadPool(2);        //指定事件工廠        HelloEventFactory factory = new HelloEventFactory();        //指定ringbuffer字節(jié)大小,必須為2的N次方(能將求模運(yùn)算轉(zhuǎn)為位運(yùn)算提高效率),否則將影響效率        int bufferSize = 1024 * 256;        //單線程模式,獲取額外的性能        Disruptor<MessageModel> disruptor = new Disruptor<>(factory, bufferSize, executor,                ProducerType.SINGLE, new BlockingWaitStrategy());        //設(shè)置事件業(yè)務(wù)處理器---消費(fèi)者        disruptor.handleEventsWith(new HelloEventHandler());        // 啟動(dòng)disruptor線程        disruptor.start();        //獲取ringbuffer環(huán),用于接取生產(chǎn)者生產(chǎn)的事件        RingBuffer<MessageModel> ringBuffer = disruptor.getRingBuffer();        return ringBuffer;    }}

(7) 構(gòu)造Mqservice和實(shí)現(xiàn)類-生產(chǎn)者GBo28資訊網(wǎng)——每日最新資訊28at.com

public interface DisruptorMqService {    /**     * 消息     * @param message     */    void sayHelloMq(String message);}@Slf4j@Component@Servicepublic class DisruptorMqServiceImpl implements DisruptorMqService {    @Autowired    private RingBuffer<MessageModel> messageModelRingBuffer;    @Override    public void sayHelloMq(String message) {        log.info("record the message: {}",message);        //獲取下一個(gè)Event槽的下標(biāo)        long sequence = messageModelRingBuffer.next();        try {            //給Event填充數(shù)據(jù)            MessageModel event = messageModelRingBuffer.get(sequence);            event.setMessage(message);            log.info("往消息隊(duì)列中添加消息:{}", event);        } catch (Exception e) {            log.error("failed to add event to messageModelRingBuffer for : e = {},{}",e,e.getMessage());        } finally {            //發(fā)布Event,激活觀察者去消費(fèi),將sequence傳遞給改消費(fèi)者            //注意最后的publish方法必須放在finally中以確保必須得到調(diào)用;如果某個(gè)請(qǐng)求的sequence未被提交將會(huì)堵塞后續(xù)的發(fā)布操作或者其他的producer            messageModelRingBuffer.publish(sequence);        }    }}

(8) 構(gòu)造測(cè)試類及方法GBo28資訊網(wǎng)——每日最新資訊28at.com

@Slf4j@RunWith(SpringRunner.class)@SpringBootTest(classes = DemoApplication.class)public class DemoApplicationTests {    @Autowired    private DisruptorMqService disruptorMqService;    /**     * 項(xiàng)目?jī)?nèi)部使用Disruptor做消息隊(duì)列     * @throws Exception     */    @Test    public void sayHelloMqTest() throws Exception{        disruptorMqService.sayHelloMq("消息到了,Hello world!");        log.info("消息隊(duì)列已發(fā)送完畢");        //這里停止2000ms是為了確定是處理消息是異步的        Thread.sleep(2000);    }}

測(cè)試運(yùn)行結(jié)果:GBo28資訊網(wǎng)——每日最新資訊28at.com

2020-04-05 14:31:18.543  INFO 7274 --- [           main] c.e.u.d.d.s.Impl.DisruptorMqServiceImpl  : record the message: 消息到了,Hello world!2020-04-05 14:31:18.545  INFO 7274 --- [           main] c.e.u.d.d.s.Impl.DisruptorMqServiceImpl  : 往消息隊(duì)列中添加消息:MessageModel(message=消息到了,Hello world!)2020-04-05 14:31:18.545  INFO 7274 --- [           main] c.e.utils.demo.DemoApplicationTests      : 消息隊(duì)列已發(fā)送完畢2020-04-05 14:31:19.547  INFO 7274 --- [pool-1-thread-1] c.e.u.d.disrupMq.mq.HelloEventHandler    : 消費(fèi)者處理消息開始2020-04-05 14:31:19.547  INFO 7274 --- [pool-1-thread-1] c.e.u.d.disrupMq.mq.HelloEventHandler    : 消費(fèi)者消費(fèi)的信息是:MessageModel(message=消息到了,Hello world!)2020-04-05 14:31:19.547  INFO 7274 --- [pool-1-thread-1] c.e.u.d.disrupMq.mq.HelloEventHandler    : 消費(fèi)者處理消息結(jié)束

5.總結(jié)

其實(shí) 生成者 -> 消費(fèi)者 模式是很常見的,通過一些消息隊(duì)列也可以輕松做到上述的效果。不同的地方在于,Disruptor 是在內(nèi)存中以隊(duì)列的方式去實(shí)現(xiàn)的,而且是無鎖的。這也是 Disruptor 為什么高效的原因。GBo28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-14545-0.htmlSpringBoot + Disruptor 實(shí)現(xiàn)特快高并發(fā)處理,贊!

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 深入探討 Golang 中的追加操作

下一篇: Golang數(shù)組:全面指南與實(shí)際示例

標(biāo)簽:
  • 熱門焦點(diǎn)
  • 5月安卓手機(jī)好評(píng)榜:魅族20 Pro奪冠

    性能榜和性價(jià)比榜之后,我們來看最后的安卓手機(jī)好評(píng)榜,數(shù)據(jù)來源安兔兔評(píng)測(cè),收集時(shí)間2023年5月1日至5月31日,僅限國內(nèi)市場(chǎng)。第一名:魅族20 Pro好評(píng)率:97.50%不得不感慨魅族老品牌還
  • K6:面向開發(fā)人員的現(xiàn)代負(fù)載測(cè)試工具

    K6 是一個(gè)開源負(fù)載測(cè)試工具,可以輕松編寫、運(yùn)行和分析性能測(cè)試。它建立在 Go 和 JavaScript 之上,它被設(shè)計(jì)為功能強(qiáng)大、可擴(kuò)展且易于使用。k6 可用于測(cè)試各種應(yīng)用程序,包括 Web
  • 摸魚心法第一章——和配置文件說拜拜

    為了能摸魚我們團(tuán)隊(duì)做了容器化,但是帶來的問題是服務(wù)配置文件很麻煩,然后大家在群里進(jìn)行了“親切友好”的溝通圖片圖片圖片圖片對(duì)比就對(duì)比,簡(jiǎn)單對(duì)比下獨(dú)立配置中心和k8s作為配
  • 一篇聊聊Go錯(cuò)誤封裝機(jī)制

    %w 是用于錯(cuò)誤包裝(Error Wrapping)的格式化動(dòng)詞。它是用于 fmt.Errorf 和 fmt.Sprintf 函數(shù)中的一個(gè)特殊格式化動(dòng)詞,用于將一個(gè)錯(cuò)誤(或其他可打印的值)包裝在一個(gè)新的錯(cuò)誤中。使
  • 谷歌KDD'23工作:如何提升推薦系統(tǒng)Ranking模型訓(xùn)練穩(wěn)定性

    谷歌在KDD 2023發(fā)表了一篇工作,探索了推薦系統(tǒng)ranking模型的訓(xùn)練穩(wěn)定性問題,分析了造成訓(xùn)練穩(wěn)定性存在問題的潛在原因,以及現(xiàn)有的一些提升模型穩(wěn)定性方法的不足,并提出了一種新
  • 品牌洞察丨服務(wù)本地,美團(tuán)直播成效幾何?

    來源:17PR7月11日,美團(tuán)App首頁推薦位出現(xiàn)&ldquo;美團(tuán)直播&rdquo;的固定入口。在直播聚合頁面,外賣&ldquo;神槍手&rdquo;直播間、美團(tuán)旅行直播間、美團(tuán)買菜直播間等均已上線,同時(shí)
  • 東方甄選單飛:有些鳥注定是關(guān)不住的

    作者:彭寬鴻來源:華爾街科技眼&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;東方甄選創(chuàng)始人俞敏洪帶隊(duì)的&ldquo;7天甘肅行&rdquo;直播活動(dòng)已在近日順利收官。成立后一
  • 微軟發(fā)布Windows 11新版 引入全新任務(wù)欄狀態(tài)

    近日,微軟發(fā)布了Windows 11新版,而Build 22563更新主要引入了幾周前曝光的平板模式任務(wù)欄等,系統(tǒng)更流暢了。更新中,Windows 11加入了專門針對(duì)平板優(yōu)化的任務(wù)欄
  • 2022爆款:ROG魔霸6 冰川散熱系統(tǒng)持續(xù)護(hù)航

    喜逢開學(xué)季,各大商家開始推出自己的新產(chǎn)品,進(jìn)行打折促銷活動(dòng)。對(duì)于忠實(shí)的端游愛好者來說,能夠擁有一款夢(mèng)寐以求的筆記本電腦是一件十分開心的事。但是現(xiàn)在的
Top 主站蜘蛛池模板: 平阳县| 姜堰市| 梨树县| 楚雄市| 红安县| 山阳县| 梧州市| 团风县| 九台市| 合江县| 京山县| 永清县| 佛坪县| 南乐县| 双辽市| 安福县| 堆龙德庆县| 凯里市| 汉沽区| 南乐县| 贺州市| 措美县| 启东市| 泰安市| 西和县| 新平| 新闻| 康平县| 辉南县| 涿鹿县| 化隆| 习水县| 夏邑县| 东平县| 灯塔市| 赫章县| 满城县| 衡南县| 宜春市| 博爱县| 广河县|