13518219792

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

如何用Netty写一个高性能的分布式服务框架?

如何用Netty写一个高性能的分布式服务框架?

作者:阿里技术 2021-06-24 10:27:48

开发

前端

开发工具

分布式 Netty 是一个致力于创建高性能网络应用程序的成熟的 IO 框架。

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:申请域名、虚拟空间、营销软件、网站建设、崂山网站维护、网站推广。

 [[407122]] 

一  什么是 Netty? 能做什么?

二  设计一个分布式服务框架

1  Architecture

2  远程调用的流程

以上流程对方法调用者是透明的,一切看起来就像本地调用一样。

3  远程调用客户端图解

重要概念:RPC三元 组

PS: 若是 netty4.x 的线程模型,IO Thread(worker) —> Map 代替全局 Map 能更好的避免线程竞争。

4  远程调用服务端图解

5  远程调用传输层图解

6  设计传输层协议栈

协议头

协议体

1)metadata:

2)methodName

3)parameterTypes[] 真的需要吗?

(a)有什么问题?

( b)能解决吗?

( c)args[]

( d)其他:traceId,appName…

三  一些Features&好的实践&压榨性能

1  创建客户端代理对象

1)Proxy 做什么?

2)有哪些创建 Proxy 的方式?

3)要注意的:

4)推荐的(bytebuddy):

2  优雅的同步/异步调用

3  单播/组播

4  泛化调用

5  序列化/反序列化

协议 header 标记 serializer type,同时支持多种。

6  可扩展性

Java SPI:

7  服务级别线程池隔离

要挂你先挂,别拉着我。

8  责任链模式的拦截器

太多扩展需要从这里起步。

9  指标度量(Metrics)

10  链路追踪

OpenTracing

11  注册中心

12  流控(应用级别/服务级别)

要有能方便接入第三方流控中间件的扩展能力。

13  Provider线程池满了怎么办?

14  软负载均衡

1)加权随机 (二分法,不要遍历)

2)加权轮训(最大公约数)

3)最小负载

4)一致性 hash (有状态服务场景)

5)其他

注意:要有预热逻辑。

15  集群容错

1)Fail-fast

2)Failover

异步调用怎么处理?

3)Fail-safe

4)Fail-back

5)Forking

6)其他

16  如何压榨性能(Don’t trust it,Test it)

1)ASM 写个 FastMethodAccessor 来代替服务端那个反射调用

2)序列化/反序列化

在业务线程中序列化/反序列化,避免占用 IO 线程:

选择高效的序列化/反序列化框架:

选择只是第一步,它(序列化框架)做的不好的,去扩展和优化之:

3)IO 线程绑定 CPU

4)同步阻塞调用的客户端和容易成为瓶颈,客户端协程:

name description
kilim 编译期间字节 码增强
quasar agent 动 态字节码增强
ali_wisp ali_jvm 在底层直接实现

5)Netty Native Transport & PooledByteBufAllocator:

6)尽快释放 IO 线程去做他该做的事情,尽量减少线程上下文切换。

四  Why Netty?

1  BIO vs NIO

2  Java 原生 NIO API 从入门到放弃

复杂度高

稳定性差,坑多且深

NIO代码实现方面的一些缺点

1)Selector.selectedKeys() 产生太多垃圾

Netty 修改了 sun.nio.ch.SelectorImpl 的实现,使用双数组代替 HashSet 存储来 selectedKeys:

Nio 的代码到处是 synchronized (比如 allocate direct buffer 和 Selector.wakeup() ):

2)fdToKey 映射

3)Selector在linux 平台是 Epoll LT 实现

4)Direct Buffers 事实上还是由 GC 管理

五  Netty 的真实面目

1  Netty 中几个重要概念及其关系

EventLoop

Boss: mainReactor 角色,Worker: subReactor 角色

2  Netty4 Thread Model

3  ChannelPipeline

4  Pooling&reuse

PooledByteBufAllocator

Recycler

5  Netty Native Transport

相比 Nio 创建更少的对象,更小的 GC 压力。

针对 linux 平台优化,一些 specific features:

6  多路复用简介

select/poll

epoll

7  稍微深入了解一点 Epoll

LT vs ET

概念:

可读:

可写:

图解:

epoll 三个方法简介

1)主要代码:linux-2.6.11.12/fs/eventpoll.c

2)int epoll_create(int size)

创建 rb-tree(红黑树)和 ready-list (就绪链表):

3)int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event)

4)int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)

epoll 的数据结构

epoll_wait 工作流程概述 

对照代码:linux-2.6.11.12/fs/eventpoll.c:

1)epoll_wait 调用 ep_poll

2)文件描述符 fd 的 events 状态改变

3)ep_poll_callback 被触发

4)执行 ep_events_transfer 函数

5)执行 ep_send_events 函数

8  Netty 的最佳实践

1)业务线程池必要性

2)WriteBufferWaterMark

3)重写 MessageSizeEstimator 来反应真实的高低水位线

4)注意EventLoop#ioRatio的设置( 默认50)

5)空闲链路检测用谁调度?

6)使用ctx.writeAndFlush还是channel.writeAndFlush?

7)使用Bytebuf.forEachByte() 来代替循环 ByteBuf.readByte()的遍历操作,避免rangeCheck()

8)使用CompositeByteBuf来避免不必要的内存拷贝

9)如果要读一个int,用Bytebuf.readInt(),不要Bytebuf.readBytes(buf,0,4)

10)配置

UnpooledUnsafeNoCleanerDirectByteBuf来代替jdk的DirectByteBuf,让netty框架基于引用计数来释放堆外内存

io.netty.maxDirectMemory:

0:不使用cleaner,并且这个参数将直接限制netty的最大direct memory size,(jdk的direct memory size是独立的,不受此参数限制)。

11)最佳连接数

12)使用PooledBytebuf时要善于利用 -Dio.netty.leakDetection.level 参数

13)Channel.attr(),将自己的对象attach到channel上

9  从 Netty 源码中学到的代码技巧

1)海量对象场景中

AtomicIntegerFieldUpdater --> AtomicInteger

2)FastThreadLocal,相比jdk的实现更快

3)IntObjectHashMap / LongObjectHashMap …

4)RecyclableArrayList

5)JCTools

 

 


文章名称:如何用Netty写一个高性能的分布式服务框架?
网址分享:http://cdbrznjsb.com/article/cdesjhi.html

其他资讯

让你的专属顾问为你服务