从RocketMQ的common模块分析RocketMQ

前言

从之前的几节介绍了消息中间件,以及之间的使用区别,这节将会从RocketMQ的common模块出发,分析设计了思路以及可以借鉴的代码逻辑,代码技巧等,毕竟目前好的架构师一半是来自阿里,学习阿里的这套代码规范以及设计思路,帮助读者在项目中更好的,更高层面思考模块的设计,后续将会陆续的从其他模块调选精辟的设计思路来分析。

从UtilAll.java类设计工具类

阅读源码的步骤第一步并不是直接看源码,而是先看官网文档,官方文档拥有太多可以学习的地方,比如,使用的demo,出现历史背景,支持者,贡献者论坛等,如果项目里发现有存在bug可以在论坛中提出,让ASF提供帮助。看完了官方文档之后就进入源码的学习,第一先从test包开始debug查看使用到的类,以及调用链。
这里是UtilAll.java的线程栈跟踪的代码

public static String currentStackTrace() {
        StringBuilder sb = new StringBuilder();
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        for (StackTraceElement ste : stackTrace) {
            sb.append("\n\t");
            sb.append(ste.toString());
        }

        return sb.toString();
    }

分析stack的方法,这里设计的Map是当前线程对应着线程栈的信息。从这里看出设计工具类的时候,声明为顶层的接口,实现多态设计。

public static String jstack(Map map) {
        StringBuilder result = new StringBuilder();
        try {
            Iterator> ite = map.entrySet().iterator();
            while (ite.hasNext()) {
                Map.Entry entry = ite.next();
                StackTraceElement[] elements = entry.getValue();
                Thread thread = entry.getKey();
                if (elements != null && elements.length > 0) {
                    String threadName = entry.getKey().getName();
                    result.append(String.format("%-40sTID: %d STATE: %s%n", threadName, thread.getId(), thread.getState()));
                    for (StackTraceElement el : elements) {
                        result.append(String.format("%-40s%s%n", threadName, el.toString()));
                    }
                    result.append("\n");
                }
            }
        } catch (Throwable e) {
            result.append(RemotingHelper.exceptionSimpleDesc(e));
        }

        return result.toString();
    }

并发场景使用concurrent包

高能并发场景下的解码以及编码,使用了Bifunction,BiConsumer等关于这两个的使用详细说明这里连接一篇文章,而有关concurrentHashMap使用了reentranlock实现细粒度的锁的文章。从Rmq的使用JDK的源码都使用到了lamada表达式函数编程思想。

public void test_encode_decode() throws IOException {
        RegisterBrokerBody registerBrokerBody = new RegisterBrokerBody();
        TopicConfigSerializeWrapper topicConfigSerializeWrapper = new TopicConfigSerializeWrapper();
        registerBrokerBody.setTopicConfigSerializeWrapper(topicConfigSerializeWrapper);
        
        ConcurrentMap topicConfigTable = new ConcurrentHashMap();
        for (int i = 0; i < 10000; i++) {
            topicConfigTable.put(String.valueOf(i), new TopicConfig(String.valueOf(i)));
        }

        topicConfigSerializeWrapper.setTopicConfigTable(topicConfigTable);

        byte[] compareEncode = registerBrokerBody.encode(true);
        byte[] encode2 = registerBrokerBody.encode(false);
        System.out.println(compareEncode.length);
        System.out.println(encode2.length);
        RegisterBrokerBody decodeRegisterBrokerBody = RegisterBrokerBody.decode(compareEncode, true);

        assertEquals(registerBrokerBody.getTopicConfigSerializeWrapper().getTopicConfigTable().size(), decodeRegisterBrokerBody.getTopicConfigSerializeWrapper().getTopicConfigTable().size());

    }

从原子类思考Unsafe类

Atomic开头的基本数据类型里面,使用了内存屏障的voilatile的属性,以及Unsafe类的对native方法的操作,从硬件的层面对数据的原子性进行了处理,这里一篇文章写得比较详细,包括了对voilatile的详细解说以及对并发的锁的控制。

你可能感兴趣的:(rabbitMQ,分布式事务,人工智能,中间件)