一个会画图的工程师
发布日期:2021-06-30 19:33:06 浏览次数:2 分类:技术文章

本文共 2886 字,大约阅读时间需要 9 分钟。

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

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 后,发送数据前,发送数据后等。

 

 Broker端,消息的处理和落地

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

写消息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

作者jjenkov最后写了一个nio demo . 过了一遍源码,工作过程大致如图:

下面是Tomcat的整体架构

 

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

 

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

 

 

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

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

以StandardServer为例:

如下面的时序图所示:

Tomcat的三大ClassLoader

为什么 Tomcat 里要自定义 ClassLoader 呢,先来考虑一个问题:一个Tomcat 部署两个应用,App1 和 App2, App1 里定义了一个 com.fdx.AAA 类,App2 也定义了一个 com.fdx.AAA 类,但是里面的实现是不一样的,如果不自定义 ClassLoader,

而都用 AppClassLoader 来加载的话,你让它加载哪一个呢,一个 ClassLoader 是不能加载两个一样的类的。所以,ClassLoader 最重要的一个功能就是 类隔离。

 

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包发生了变化,会通知其他机器自动重新部署。这个功能,在有点规模的互联网公司应该也不会用它,肯定用自研的运维系统, 可以支持更灵活的应用部署,方便和公司的运维体系打通。

 

 

图片来源 

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

 

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

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

关于这么多框架如何搭配使用,这篇文章总结的不错,

 

 

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

转载地址:https://linuxstyle.blog.csdn.net/article/details/88852624 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Go语言源码分析CAS的实现和Java如出一辙
下一篇:协程和Java实现

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月11日 22时20分34秒