一个会画图的工程师

发现小谢图画的很好,虽然有些也是他引用的,但是我觉得还是很好所以这里收集下。

 【RocketMQ源码学习】2-Namesrv

3-Remoting模块 

rocketmq-remoting 模块是 RocketMQ 中负责网络通信的模块,被其他所有需要网络通信的模块依赖。它是基于 Netty 实现的,避免了网络编程很多 tricky 的问题。

首先来看下 RocketMQ NettyServer 的 Reactor 线程模型,一个 Reactor 主线程负责监听 TCP 连接请求,建立好连接后丢给 Reactor 线程池,它负责将建立好连接的 socket 注册到 selector 上去(这里有两种方式,NIO和Epoll,可配置),然后监听真正的网络数据。拿到网络数据后,再丢给 Worker 线程池。
Worker 拿到网络数据后,就交给 Pipeline,从 Head 到 Tail 一个个 Handler 的走下去,这些 Handler 是在创建 Server 的时候指定的。NettyEncoder 和 NettyDecoder 负责网络数据和 RemotingCommand 之间的编解码。NettyServerHandler 拿到解码得到的 RemotingCommand 后,根据 RemotingCommand.type 来判断是 request 还是 response,如果是 request, 就根据 RomotingCommand 的 code(code用来标识不同类型的请求) 去 processorTable 找到对应的 processor,然后封装成 task 后,丢给对应的 processor 线程池, 如果是 response 就根据 RemotingCommand.opaque 去 responseTable 中拿到对应的 ResponseFuture,把结果 set 给它。

对于 Client,经过 Pipeline 的顺序是从 Tail 到 Head。不管是 Server 和 Client,并不是每次数据流转都得经过所有的 Handler,而是会根据 Context 中的一些信息去判断。

整个数据流转过程中还有很多hook, 比如处理 command 前,处理 command 后,发送数据前,发送数据后等。

 

【RocketMQ源码学习】4-消息发送 

 Broker端,消息的处理和落地

【RocketMQ源码学习】5-消息消费 

Pull 的过程比较简单(因为应用代码要去做比较多的事情),所以这里我主要来梳理一下 Push 方式的整个过程。

【RocketMQ源码学习】6-消息存储 

写消息MappedFile Append Message

MappedFile 和物理文件是一一对应的,append的过程,消息的具体构成如图所示,大部分字段都很好理解,这里重点关注下 queueOffset 和 physicaloffset. queueOffset 是指对应的 consumeQueue 中的 offset, physicaloffset 是指该消息的物理offset,即图中的 wroteOffset, 它等于 fileFromOffset(当前mappedFile的物理offset) 加上 mappedFile 对应的 buffer 的 position(一个逻辑的offset).

ReputMessageService 也是一个单独的线程,它负责构建 ConsumeQueue 和 Index。

ConsumeQueue的结构如图:

Index File

Java Nio

作者jjenkov最后写了一个nio demo https://github.com/fdx321/java-nio-server. 过了一遍源码,工作过程大致如图:

【Tomcat学习笔记】2-整体架构

下面是Tomcat的整体架构

 

这个类图是Tomcat最主要的一个结构:

 

Engine、Host、Context、Wrapper 四种 Container 都可以配置 Valve,即使不配置,每个 Container 代码里都有默认的Valve(StandardEngineValve, StandardHostValve …)是处理请求的时候必须经过的。关于 Pipeline 和 Valve,就是一个水管中间有多个阀门,每个数据流过来都在阀门的地方被处理一下。 四个容器的Pipeline串起来,可以用张图来描述一下:

 

【Tomcat学习笔记】3-组件声明周期 

LifecycleState 这个枚举类定义了生命周期的各个阶段,这个状态机是这样子滴:

【Tomcat学习笔记】4-启动流程分析

它们是如何一层一层完成初始化和启动的

以StandardServer为例:

如下面的时序图所示:

【Tomcat学习笔记】9-ClassLoader

Tomcat的三大ClassLoader

为什么 Tomcat 里要自定义 ClassLoader 呢,先来考虑一个问题:一个Tomcat 部署两个应用,App1 和 App2, App1 里定义了一个 com.fdx.AAA 类,App2 也定义了一个 com.fdx.AAA 类,但是里面的实现是不一样的,如果不自定义 ClassLoader,
而都用 AppClassLoader 来加载的话,你让它加载哪一个呢,一个 ClassLoader 是不能加载两个一样的类的。所以,ClassLoader 最重要的一个功能就是 类隔离。

 

【Tomcat学习笔记】14-Cluster 

Tomcat Cluster 这块代码较多,代码主要在 org.apache.catalina.ha 和 org.apache.catalina.tribes 两个package. ha这个package主要做了两件事,或者说Tomcat cluster 主要就做了这两件事:集群间 Session 同步 和 集群War部署。tribes 则是Tomcat 集群通讯模块。

Tomcat 做了个集群的功能,大部分功能主要是解决session在集群中的同步,然而在有点规模的互联网公司都不怎么用它。

  1. 对于无状态的应用,通过apache/ngnix 负载均衡到 各个 tomcat就可以了
  2. 对于有状态的(session)应用,往往都自研分布式Session应用。分布式系统下用 Tomcat 的 session 会有很多限制。

Tomcat还做了个功能,监控集群中应用的变更,如果有一台的War包发生了变化,会通知其他机器自动重新部署。这个功能,在有点规模的互联网公司应该也不会用它,肯定用自研的运维系统, 可以支持更灵活的应用部署,方便和公司的运维体系打通。

 

 

 Java Volatile 学习笔记

图片来源 http://mechanical-sympathy.blogspot.com

说明:他引用的这个作者在JVM方面有一定的研究,图画的不错

https://mechanical-sympathy.blogspot.com/

 

终于搞清楚Java的日志了 

Java的日志框架很多,JUL, Log4J, Lobback, JCL, SLF4J等

先来看下slf4j官方的一张图:

关于这么多框架如何搭配使用,这篇文章总结的不错,slf4j、jcl、jul、log4j1、log4j2、logback大总结

 

 

Spring事务管理

所谓声明式事务,就是通过配置的方式省去很多代码,从而让Spring来帮你管理事务。本质上就是配置一个Around方式的AOP,在执行方法之前,用TransactionInterceptor截取,然后调用PlatformTransactionManager的某个实现做一些事务开始前的事情,然后在方法执行后,调用PlatformTransactionManager的某个实现做commit或rollback. 如图: