精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Netty是如何解析Redis的RESP協議—響應篇

數據庫 其他數據庫
經過上面的層層處理,foobar 這個 FullBulkStringRedisMessage 消息是怎么存到 EmbeddedChannel 中呢?可以看到這里繼承了 DefaultChannelPipeline,并重寫了 onUnhandledInboundMessage 方法。

這篇是響應篇,一起來看看  RedisDecoderTest 中,是怎么模擬 client-cli 接受處理 server 響應的??

RedisDecoderTest

public class RedisDecoderTest {
    public static void main(String[] args) {
         EmbeddedChannel channel = newChannel(false);


        System.out.println(channel.writeInbound(byteBufOf("$6\r\nfoobar\r")));
        System.out.println(channel.writeInbound(byteBufOf("\n")));


        RedisMessage msg = channel.readInbound();
        System.out.println(msg instanceof FullBulkStringRedisMessage);

        String bytes = stringOf(((FullBulkStringRedisMessage) msg).content());
        System.out.println(bytes);


        ReferenceCountUtil.release(msg);

        channel.finish();
    }
    private static EmbeddedChannel newChannel(boolean decodeInlineCommands) {
        return new EmbeddedChannel(
                new RedisDecoder(decodeInlineCommands),
                new RedisBulkStringAggregator(),
                new RedisArrayAggregator());
    }
}

圖解

這里的重點就是這 3 個 ChannelInboundHandler 了。

圖片圖片

具備 decode 能力 ??

圖片圖片

下面進入源碼解讀:

何時調用到 decode 方法

當進行 channelRead  時進行 decode,比如  MessageToMessageDecoder  ??

圖片圖片

RedisDecoder

里面定義了 5 種 State

圖片圖片

比如上面例子中,傳輸的  $6\r\nfoobar\r\n  ,就屬于 RESP 協議中的 Bulk strings  大字符串,需要解析出 length 和 content,格式如下 :

$<length>\r\n<data>\r\n
比如
$5\r\nhello\r\n
$0\r\n\r\n

關鍵步驟

圖片圖片

decode 時,由于默認的 state 都是  DECODE_TYPE ,所以會先調用 decodeType 方法。

圖片圖片

decodeType

看看是不是 inline 的,默認是 false,我們也是設置了 false。

圖片圖片

decodeLength

圖片圖片

這里可以看到官網 Fast to parse 的影子。

圖片圖片

圖片圖片

decodeBulkString

創建 BulkStringHeaderRedisMessage,再把 state 切換到 DECODE_BULK_STRING_CONTENT ,最后調用 decodeBulkStringContent 。

圖片圖片

decodeBulkStringContent

創建 DefaultBulkStringRedisContent,并添加到 out 這個 list 中(2個)

圖片圖片

接著,就來到第二個 handler 了 ,RedisBulkStringAggregator

RedisBulkStringAggregator

起到一個聚合的作用,將消息包裝成 FullBulkStringRedisMessage。

圖片圖片

這個 decode 方法超過 100 行了,就粗略講一下。

在上面的方法中,我們往 out 中添加了 BulkStringHeaderRedisMessage 和 DefaultBulkStringRedisContent 這兩個。

圖片圖片

消息頭處理

先處理 BulkStringHeaderRedisMessage ,

圖片圖片

包裝成 FullBulkStringRedisMessage 。

圖片圖片

消息體處理

圖片圖片

appendPartialContent,把這個 ByteBuf 整合到 CompositeByteBuf 中。

圖片圖片

aggregate,擴展方法,目前是空實現。

最后,判斷是不是消息尾

圖片圖片

到了這里,handler 就處理完了,因為這個消息不是數組類型的,用不到 RedisArrayAggregator 。

第二次 writeInbound

上面代碼中共調用了兩次 writeInbound

System.out.println(channel.writeInbound(byteBufOf("$6\r\nfoobar\r")));
 System.out.println(channel.writeInbound(byteBufOf("\n")));

第二次時,會把之前的 bytebuf 拿出來計算下。

圖片圖片

可以看到,oldBytes 是 \r ,newBytes 則是 \n ,重新組合成新的 ByteBuf。

圖片圖片

這樣才能去創建這個 DefaultLastBulkStringRedisContent

圖片圖片

進而完成  RedisBulkStringAggregator 中的 last 條件分支。

圖片圖片

最后消息被包裝成 FullBulkStringRedisMessage。

尾節點  TailContext

經過上面的層層處理,foobar 這個 FullBulkStringRedisMessage 消息是怎么存到 EmbeddedChannel 中呢?

可以看到這里繼承了 DefaultChannelPipeline,并重寫了 onUnhandledInboundMessage 方法。

圖片圖片

DefaultChannelPipeline 中有尾節點 TailContext,它會去調用這個 onUnhandledInboundMessage 。

圖片圖片

進而將消息存到隊列中。

圖片圖片

最后,readInbound 就是從里面 poll 出來這個消息,再進行打印等操作即可。

圖片圖片

官方例子

我從 Netty 的 example 里 CV 了一份,大家可以快速上手。

使用時,主要還是注意這個 inbound ,outbound 的順序問題(如圖)。

圖片圖片

/**
 * Simple Redis client that demonstrates Redis commands against a Redis server.
 */
public class RedisClient {
    private static final String HOST = System.getProperty("host", "192.168.200.128");
    private static final int PORT = Integer.parseInt(System.getProperty("port", "6379"));

    public static void main(String[] args) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(NioSocketChannel.class)
             .handler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 protected void initChannel(SocketChannel ch) throws Exception {
                     ChannelPipeline p = ch.pipeline();
                     p.addLast(new RedisDecoder());
                     p.addLast(new RedisBulkStringAggregator());
                     p.addLast(new RedisArrayAggregator());
                     p.addLast(new RedisEncoder());
                     p.addLast(new RedisClientHandler());
                 }
             });

            // Start the connection attempt.
            Channel ch = b.connect(HOST, PORT).sync().channel();

            // Read commands from the stdin.
            System.out.println("Enter Redis commands (quit to end)");
            ChannelFuture lastWriteFuture = null;
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            for (;;) {
                final String input = in.readLine();
                final String line = input != null ? input.trim() : null;
                if (line == null || "quit".equalsIgnoreCase(line)) { // EOF or "quit"
                    ch.close().sync();
                    break;
                } else if (line.isEmpty()) { // skip `enter` or `enter` with spaces.
                    continue;
                }
                // Sends the received line to the server.
                lastWriteFuture = ch.writeAndFlush(line);
                lastWriteFuture.addListener(new GenericFutureListener<ChannelFuture>() {
                    @Override
                    public void operationComplete(ChannelFuture future) throws Exception {
                        if (!future.isSuccess()) {
                            System.err.print("write failed: ");
                            future.cause().printStackTrace(System.err);
                        }
                    }
                });
            }

            // Wait until all messages are flushed before closing the channel.
            if (lastWriteFuture != null) {
                lastWriteFuture.sync();
            }
        } finally {
            group.shutdownGracefully();
        }
    }
}


/**
 * An example Redis client handler. This handler read input from STDIN and write output to STDOUT.
 */
public class RedisClientHandler extends ChannelDuplexHandler {

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
        String[] commands = ((String) msg).split("\\s+");
        List<RedisMessage> children = new ArrayList<RedisMessage>(commands.length);
        for (String cmdString : commands) {
            children.add(new FullBulkStringRedisMessage(ByteBufUtil.writeUtf8(ctx.alloc(), cmdString)));
        }
        RedisMessage request = new ArrayRedisMessage(children);
        ctx.write(request, promise);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        RedisMessage redisMessage = (RedisMessage) msg;
        printAggregatedRedisResponse(redisMessage);
        ReferenceCountUtil.release(redisMessage);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        System.err.print("exceptionCaught: ");
        cause.printStackTrace(System.err);
        ctx.close();
    }

    private static void printAggregatedRedisResponse(RedisMessage msg) {
        if (msg instanceof SimpleStringRedisMessage) {
            System.out.println(((SimpleStringRedisMessage) msg).content());
        } else if (msg instanceof ErrorRedisMessage) {
            System.out.println(((ErrorRedisMessage) msg).content());
        } else if (msg instanceof IntegerRedisMessage) {
            System.out.println(((IntegerRedisMessage) msg).value());
        } else if (msg instanceof FullBulkStringRedisMessage) {
            System.out.println(getString((FullBulkStringRedisMessage) msg));
        } else if (msg instanceof ArrayRedisMessage) {
            for (RedisMessage child : ((ArrayRedisMessage) msg).children()) {
                printAggregatedRedisResponse(child);
            }
        } else {
            throw new CodecException("unknown message type: " + msg);
        }
    }

    private static String getString(FullBulkStringRedisMessage msg) {
        if (msg.isNull()) {
            return "(null)";
        }
        return msg.content().toString(CharsetUtil.UTF_8);
    }
}

結尾

這篇比請求篇稍微復雜些,還有 TailContext 這個隱藏的細節。

責任編輯:武曉燕 來源: Java4ye
相關推薦

2024-05-20 08:45:46

2021-07-15 10:35:16

NettyTCPJava

2024-08-16 21:47:18

2018-07-06 15:58:34

SpringSchemaJava

2011-08-24 10:41:04

網絡協議DNSARP協議

2009-04-03 08:26:02

2022-05-16 08:22:37

零拷貝Netty

2020-12-15 08:03:57

Mybatis配置文件

2013-03-11 10:17:13

路由協議路由器設置網絡連接設置

2013-02-26 17:31:50

思科路由協議路由器設置

2024-06-12 13:36:24

2010-08-02 16:56:03

ICMP協議

2021-08-03 14:29:30

ARPANET互聯網協議TCP

2021-07-08 21:19:04

BashLinux

2023-11-09 23:31:02

C++函數調用

2017-11-09 10:42:11

Nginx負載均衡策略

2024-06-03 08:09:46

2021-01-30 19:35:44

HDFS單點Hadoop

2020-12-29 08:34:08

spring循環依賴開發

2018-11-05 08:10:30

Netty架構模型
點贊
收藏

51CTO技術棧公眾號

欧美一区二区黄片| 国产免费一区视频观看免费 | 国产大学生自拍| 日韩一区二区三区精品| 欧美视频免费在线| 日韩第一页在线观看| 天天干视频在线观看| 奇米精品一区二区三区四区| 欧美xxxx做受欧美.88| 30一40一50老女人毛片| 999久久久国产999久久久| 亚洲一区二区精品视频| 三区精品视频观看| 亚洲狼人综合网| 免费在线看成人av| 久久久这里只有精品视频| 卡一卡二卡三在线观看| 亚洲AV无码成人片在线观看| 黄色a级在线观看| 777777国产7777777| 久久97精品| 欧美放荡的少妇| 四虎永久在线精品无码视频| h网站久久久| 久久奇米777| 欧美日韩免费高清一区色橹橹| 色一情一乱一伦一区二区三区丨 | 日本资源在线| 欧美国产乱子伦| 国产一区二区黄色| 国产suv一区二区| 日本va欧美va欧美va精品| 97精品国产97久久久久久| 日本少妇高清视频| 四虎国产精品免费观看| 亚洲人精品午夜在线观看| 国产精品嫩草69影院| 婷婷精品久久久久久久久久不卡| 黄网站在线免费| 天堂网在线播放| 午夜亚洲伦理| 国内揄拍国内精品| 国产这里有精品| 色琪琪久久se色| 国产亚洲福利一区| 亚洲国产精品无码久久久久高潮| www.国产com| 欧美fxxxxxx另类| www亚洲欧美| 99re6热在线精品视频| 欧美一区二区麻豆红桃视频| 国产亚洲精品久久久久久777| 9.1成人看片| 另类图片第一页| 亚洲第一网站免费视频| 无码人妻精品一区二区三| 亚洲视频三区| 精品国内二区三区| 欧美性做爰毛片| 国产视频精品自拍| 日韩精品视频在线观看视频| av官网在线播放| 亚洲视频1区2区| 樱空桃在线播放| 五月花成人网| 午夜久久久久久久久久一区二区| 国内精品视频在线| 巨胸大乳www视频免费观看| 精品视频在线你懂得| 欧美精品一区二区久久久| 日韩少妇一区二区| 久久91精品| 中文字幕在线看视频国产欧美| 国产黄色录像视频| 香蕉国产精品| 欧美精品久久久久久久免费观看 | 午夜精品在线视频一区| 内射国产内射夫妻免费频道| 一根才成人网| 欧美日韩不卡在线| 国内精品免费视频| 亚洲妇女av| 色七七影院综合| 久久久久久久久久综合| 亚洲中午字幕| 成人免费自拍视频| 内射后入在线观看一区| 久久久久久夜精品精品免费| 日韩高清三级| 中文字幕在线观看播放| 精品久久久久久中文字幕大豆网| 亚洲男人天堂色| 2021年精品国产福利在线| 亚洲精选一区二区| 欧美国产日韩在线观看成人| 国产日韩免费| 日韩成人中文电影| 国产日韩欧美精品电影三级在线| 欧美性受xxxx黑人猛交| 中文字幕黄色av| 国产高清不卡一区| 欧美一区二区福利| 色帝国亚洲欧美在线| 疯狂做受xxxx高潮欧美日本| wwwwwxxxx日本| 伊人久久中文字幕| 性欧美videos另类喷潮| 国产女同一区二区| 熟妇人妻中文av无码| 国产精品美女久久久久久2018 | 好吊视频一区二区三区四区| 国产成人精品av| 丰满肉肉bbwwbbww| 国产精品美女一区二区三区| 大陆极品少妇内射aaaaa| 亚洲综合视频| 国产亚洲精品一区二区| 日韩免费在线视频观看| 国产一区二区三区四| 欧美三日本三级少妇三99| 黄页网站在线| 91麻豆精品国产91久久久资源速度 | 国产精欧美一区二区三区蓝颜男同| 91麻豆精品国产91久久久更新时间| 中文乱码人妻一区二区三区视频| 欧美在线播放| 成人精品久久一区二区三区| av中文字幕在线| 色综合久久中文字幕| 无码一区二区精品| 国产精品v亚洲精品v日韩精品 | 午夜精品国产精品大乳美女| 国产精品玖玖玖| 国产蜜臀97一区二区三区| 六月丁香婷婷激情| 日韩系列在线| 91福利视频网| 亚洲 欧美 激情 小说 另类| 亚洲免费大片在线观看| 做a视频在线观看| 日韩国产一区二区| 国产精品热视频| 最新国产在线观看| 欧美最新大片在线看| 在线观看国产精品一区| 久久婷婷一区| 日本中文不卡| 成人h在线观看| 91黄色免费网站| 91麻豆免费看片| 国产热re99久久6国产精品| 四虎精品一区二区三区| 亚洲一区二区视频在线| 免费在线观看日韩av| 亚洲国产不卡| 成人免费在线看片| av在线资源| 洋洋av久久久久久久一区| 国产精品视频第一区| 日韩精品福利视频| 韩国精品主播一区二区在线观看 | 天天色天天综合网| 91tv精品福利国产在线观看| 亚洲精品女av网站| 美女精品视频| 精品视频1区2区| 国产丝袜不卡| 超碰在线中文字幕| 日韩av在线免播放器| 国产三级精品三级在线观看| 国产视频一区二区三区在线观看| 天天干天天操天天玩| 中文av一区| 国产精品果冻传媒潘| 中文在线а√天堂| 中文字幕在线看视频国产欧美在线看完整| ,亚洲人成毛片在线播放| 亚洲精选视频在线| 国产乱了高清露脸对白| 日韩精品欧美精品| 影音先锋男人的网站| 国产无遮挡又黄又爽又色视频| 全国精品久久少妇| 椎名由奈jux491在线播放 | 538在线一区二区精品国产| 国产这里有精品| 久久综合国产精品| 91看片破解版| 国产日韩欧美一区在线| 一区高清视频| 欧美三级电影在线| 国产精品永久在线| а√在线中文网新版地址在线| 久久久久亚洲蜜桃| 日韩福利视频在线| 午夜精品999| 农村寡妇一区二区三区| 亚洲欧美在线综合| 欧美综合国产精品久久丁香| 欧美日本一道| 亚洲精品日韩欧美| 精品人妻一区二区三区蜜桃 | 涩涩视频在线观看| 亚洲制服丝袜在线| 欧美乱大交做爰xxxⅹ小说| 成人美女视频在线看| mm131亚洲精品| 亚洲一区日韩| 国产一区二区三区乱码| 欧美3p视频| 日本一区二区三区视频免费看| 日韩最新av| 国产欧美日韩丝袜精品一区| 午夜久久中文| 性色av一区二区三区红粉影视| 男人的天堂在线视频免费观看| 亚洲精品中文字幕女同| 亚洲老妇色熟女老太| 欧美日韩免费不卡视频一区二区三区 | 999久久久精品视频| 久久亚洲一区| 九色在线视频观看| 国自产拍偷拍福利精品免费一| 一本久道久久综合狠狠爱亚洲精品| 日韩最新在线| 国产欧美韩日| 中文字幕久久精品一区二区| 国产日韩精品电影| 97精品国产99久久久久久免费| 8090成年在线看片午夜| 日本h片在线| 九色精品免费永久在线| lutube成人福利在线观看| 欧美1区2区3| 岛国av午夜精品| 久久精品国产亚洲av高清色欲| 亚洲欧洲日韩女同| 一级特黄曰皮片视频| 久久人人爽人人爽| 成年人网站免费在线观看| 成人av网在线| 黄色免费看视频| 成人蜜臀av电影| 欧美大喷水吹潮合集在线观看| 国产成人久久精品77777最新版本| 91丨九色丨蝌蚪| 国内精品久久久久影院色| 亚洲视频一二三四| 老色鬼精品视频在线观看播放| 五月婷婷激情久久| 美国三级日本三级久久99| 久久久久久三级| 蜜桃免费网站一区二区三区| 日日躁夜夜躁aaaabbbb| 久久国产精品99精品国产| 中文字幕22页| 国产一区二区三区美女| 亚洲男人天堂2021| 国产不卡在线播放| www.美色吧.com| av在线播放不卡| www.中文字幕av| 欧美国产1区2区| 亚洲精品久久久久久国| 亚洲视频图片小说| 成熟的女同志hd| 亚洲成人免费在线观看| 久久久久在线视频| 欧美日韩国产另类不卡| 韩国三级丰满少妇高潮| 天堂国产一区二区三区| 欧美日韩一本到| 国产伦精品一区二区三区四区 | 亚洲欧美日韩国产成人精品影院 | 欧美日韩亚洲一区二区三区| 福利网址在线观看| 欧美日韩国产美| 亚洲h视频在线观看| 日韩精品亚洲视频| 91精品专区| 欧美国产精品日韩| 韩日精品一区二区| 成人久久精品视频| 精品久久ai| 婷婷五月色综合| 国产精品激情| 91国产精品视频在线观看| 国产福利一区在线| 免费看91的网站| 亚洲综合男人的天堂| 高清乱码免费看污| 欧美一卡二卡在线观看| 人人九九精品| 久久在线免费视频| 日本免费一区二区三区四区| 亚洲www永久成人夜色| 香蕉精品久久| 麻豆一区二区三区在线观看| 国产亚洲精品久久久久婷婷瑜伽| 久久99999| 91麻豆免费在线视频| 2欧美一区二区三区在线观看视频| 亚洲热在线视频| 久久午夜免费电影| 欧美又粗又大又长| 在线观看欧美精品| 丰满肉肉bbwwbbww| 色妞欧美日韩在线| 另类图片综合电影| 国产成人一区二区三区免费看| 成人高清电影网站| 国产成人无码a区在线观看视频| 精品一区二区成人精品| 野花社区视频在线观看| 亚洲一区二区三区爽爽爽爽爽| 中文字幕资源网| 亚洲欧美变态国产另类| 18aaaa精品欧美大片h| 91日韩在线视频| 日韩精品一区二区三区免费观影 | 日韩va欧美va亚洲va久久| caopor在线| 1024精品合集| 伊人网站在线观看| 亚洲日本中文字幕免费在线不卡| 91桃色在线| 国产精品二区在线| 一区二区三区四区在线观看国产日韩 | 天堂va蜜桃一区二区三区 | 91国产视频在线播放| 国色天香久久精品国产一区| 亚洲日本无吗高清不卡| 日本午夜精品视频在线观看 | 国产精品com| 午夜精品影视国产一区在线麻豆| 天天夜碰日日摸日日澡性色av| 国产69精品久久久久777| 农村妇女精品一区二区| 91精品国产综合久久久蜜臀粉嫩| 日本高清中文字幕在线| 国产精品美女视频网站| 经典一区二区| 久久综合久久色| 中文一区二区完整视频在线观看| 国产精品成人无码| 中文字幕在线成人| 日韩一区二区三免费高清在线观看| 日本不卡在线观看| 日本麻豆一区二区三区视频| 国产一级久久久久毛片精品| 欧美中文字幕一二三区视频| 都市激情在线视频| 国产精品第3页| 日本不卡二三区| 亚洲第一天堂久久| 一区二区三区高清在线| 男人天堂一区二区| 26uuu另类亚洲欧美日本一| 亚洲 国产 日韩 欧美| 国产亚洲一卡2卡3卡4卡新区| 孩xxxx性bbbb欧美| 精品视频在线一区| 一二三在线视频| 粉嫩av亚洲一区二区图片| 久久久香蕉视频| 亚洲精品电影网在线观看| 亚洲天堂av影院| 欧美另类视频在线| 蜜桃视频一区二区三区在线观看 | 在线观看一二三区| 日韩在线观看免费av| 亚洲91网站| 91av资源网| 国产精品国产自产拍高清av | 精品一区二区日韩| 久久久久无码精品国产| 日韩av中文字幕在线免费观看| 26uuu亚洲电影| 亚洲综合欧美日韩| 国产成人自拍高清视频在线免费播放| 日本a在线观看| 一区二区三区视频在线| 日韩一区二区三区精品| 日韩视频第二页| 中文字幕欧美一| 视频二区在线| 国产精品偷伦视频免费观看国产 | 天堂精品一区二区三区| 国产麻豆一区| 日韩美女爱爱视频| 国产日韩欧美一区二区三区乱码 | 国产婷婷色综合av蜜臀av| 在线黄色的网站 | 9色精品在线| 日本伦理一区二区三区| 国产精品视频九色porn| 快灬快灬一下爽蜜桃在线观看| 91精品国产综合久久久久久久 | 国语对白做受69| 久久一区二区三区喷水|