如何用Netty写一个高性能的分布式服务框架
Posted 漫谈Java架构
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何用Netty写一个高性能的分布式服务框架相关的知识,希望对你有一定的参考价值。
提纲
什么是Netty? 能做什么?
贴近日常生活, 先设计一个服务框架
RPC的一些Features&好的实践
如何压榨性能
Why Netty? (延伸: Netty --> NIO --> Linux Epoll一些实现细节)
什么是Netty? 能做什么?
Netty是一个致力于创建高性能网络应用程序的成熟的IO框架
相比较与直接使用底层的Java IO API, 你不需要先成为网络专家就可以基于Netty去构建复杂的网络应用
业界常见的涉及到网络通信的相关中间件大部分基于Netty实现网络层
设计一个分布式服务框架
Architecture
远程调用的流程
以上流程对方法调用者是透明的, 一切看起来就像本地调用一样
重要概念: RPC三元组 <ID, Request, Response>
启动服务端(服务提供者)并发布服务到注册中心
启动客户端(服务消费者)并去注册中心订阅感兴趣的服务
服务端收到收到并反序列化请求信息, 根据<group, providerName, version>从本地服务字典里查找到对应providerObject, 再根据<methodName, args[]>通过反射调用指定方法, 并将方法返回值序列化为字节数组返回给客户端
客户端收到响应信息再反序列化为Java对象后由Proxy返回给方法调用者
远程调用客户端图解
若是netty4.x的线程模型, IO Thread(worker) —> Map<InvokeId, Future>代替全局Map能更好的避免线程竞争
远程调用服务端图解
重要概念: RPC三元组 <ID, Request, Response>
远程调用传输层图解
左图为客户端, 右图为服务端
设计传输层协议栈
协议头
协议体
metadata: <group, providerName, version>
methodName
parameterTypes[]
真的需要?
Java方法静态分派规则参考JLS <Java语言规范> $15.12.2.5 Choosing the Most Specific Method 章节
有什么问题?
能解决吗?
反序列化时ClassLoader.loadClass()潜在锁竞争
协议体码流大小
泛化调用多了参数类型
args[]
其他: traceId, appName…
一些Features&好的实践&压榨性能
创建客户端代理对象
注意拦截toString, equals, hashCode等方法避免远程调用
jdk proxy/javassist/cglib/asm/bytebuddy
集群容错 —> 负载均衡 —> 网络
Proxy做什么?
有哪些创建Proxy的方式?
要注意的:
推荐的(bytebuddy):
优雅的同步/异步调用
先往上翻再看看'远程调用客户端图解'
再往下翻翻看看Failover如何处理更好
思考下如何拿到future?
单播/组播
消息派发器
FutureGroup
泛化调用
Object $invoke(String methodName, Object... args)
parameterTypes[]
序列化/反序列化(协议header标记serializer type, 同时支持多种)
可扩展性
-java.util.ServiceLoader
-META-INF/services/com.xxx.Xxx
Java SPI
服务级别线程池隔离
要挂你先挂, 别拉着我
责任链模式的拦截器
太多扩展需要从这里起步
指标度量(Metrics)
链路追踪
OpenTracing
注册中心
略
流控(应用级别/服务级别)
要有能方便接入第三方流控中间件的扩展能力
Provider线程池满了怎么办?
软负载均衡
要有预热逻辑
加权随机 (二分法, 不要遍历)
加权轮训(最大公约数)
最小负载
一致性hash(有状态服务场景)
其他
集群容错
异步调用怎么处理?
Bad
以上是关于如何用Netty写一个高性能的分布式服务框架的主要内容,如果未能解决你的问题,请参考以下文章