Motan 中使用异步 RPC 接口

这周六参加了一个美团点评的技术沙龙,其中一位老师在介绍他们自研的 RPC 框架时提到一点:RPC 请求分为 sync,future,callback,oneway,并且需要遵循一个原则:能够异步的地方就不要使用同步。正好最近在优化一个业务场景:在一次页面展示中,需要调用 5 个 RPC 接口,导致页面响应很慢。正好启发了我。

为什么慢?

大多数开源的 RPC 框架实现远程调用的方式都是同步的,假设 [接口 1,…,接口 5] 的每一次调用耗时为 200ms (其中接口 2 依赖接口 1,接口 5 依赖接口 3,接口 4),那么总耗时为 1s,这整个是一个串行的过程。

多线程加速


深入理解 RPC 之传输篇

RPC 被称为“远程过程调用”,表明了一个方法调用会跨越网络,跨越进程,所以传输层是不可或缺的。一说到网络传输,一堆名词就蹦了出来:TCP、UDP、HTTP,同步 or 异步,阻塞 or 非阻塞,长连接 or 短连接…

本文介绍两种传输层的实现:使用 Socket 和使用 Netty。前者实现的是阻塞式的通信,是一个较为简单的传输层实现方式,借此可以了解传输层的工作原理及工作内容;后者是非阻塞式的,在一般的 RPC 场景下,性能会表现的很好,所以被很多开源 RPC 框架作为传输层的实现方式。

RpcRequest 和 RpcResponse

传输层传输的主要对象其实就是这两个类,它们封装了请求 id,方法名,方法参数,返回值,异常等 RPC 调用中需要的一系列信息。

1
2
3
4
5
6
7
8
9
10
public class RpcRequest implements Serializable {
private String interfaceName;
private String methodName;
private String parametersDesc;
private Object[] arguments;
private Map<String, String> attachments;
private int retries = 0;
private long requestId;
private byte rpcProtocolVersion;
}

深入理解 RPC 之动态代理篇

提到 JAVA 中的动态代理,大多数人都不会对 JDK 动态代理感到陌生,Proxy,InvocationHandler 等类都是 J2SE 中的基础概念。动态代理发生在服务调用方 / 客户端,RPC 框架需要解决的一个问题是:像调用本地接口一样调用远程的接口。于是如何组装数据报文,经过网络传输发送至服务提供方,屏蔽远程接口调用的细节,便是动态代理需要做的工作了。RPC 框架中的代理层往往是单独的一层,以方便替换代理方式(如 motan 代理层位于 com.weibo.api.motan.proxy ,dubbo 代理层位于 com.alibaba.dubbo.common.bytecode )。

实现动态代理的方案有下列几种:

  • jdk 动态代理
  • cglib 动态代理
  • javassist 动态代理
  • ASM 字节码
  • javassist 字节码

深入理解 RPC 之序列化篇 -- 总结篇

上一篇 《深入理解 RPC 之序列化篇 –Kryo》, 介绍了序列化的基础概念,并且详细介绍了 Kryo 的一系列特性,在这一篇中,简略的介绍其他常用的序列化器,并对它们进行一些比较。序列化篇仅仅由 Kryo 篇和总结篇构成可能有点突兀,等待后续有时间会补充详细的探讨。

定义抽象接口

1
2
3
4
5
6
public interface Serialization {

byte[] serialize(Object obj) throws IOException;

<T> T deserialize(byte[] bytes, Class<T> clz) throws IOException;
}

RPC 框架中的序列化实现自然是种类多样,但它们必须遵循统一的规范,于是我们使用 Serialization 作为序列化的统一接口,无论何种方案都需要实现该接口。


南京 IAS 架构师峰会观后感

上周六,周日在南京举办了 IAS 架构师峰会,这么多人的技术分享会还是头一次参加,大佬云集,涨了不少姿势。特此一篇记录下印象深刻的几场分享。由于全凭记忆叙述,故只能以流水账的形式还原出现场的收获。

大型支付交易平台的演进过程

大型支付交易平台的演进过程

陈斌,《架构即未来》译者,易宝支付 CTO。

交易系统具备以下特点,交易量大,并发度高,业务敏感度高,响应速度容忍度低… 从而使得支付交易平台需要有以下的特点:

  • 高可用:7X24*365 随时可用
  • 高安全:需满足 PCI-DSS 要求
  • 高效率:每笔交易的成本要低
  • 高扩展:随业务的快速发展扩张

从以上几点话题引申出了系统扩展的三个阶段

**X 轴扩展 – 扩展机器 **

也就是通俗意义中集群方案,横向扩展,通过添加多台机器负载均衡,从而扩展计算能力,这是最简单粗暴,也是最直接易用的方案。

**Y 轴扩展 – 拆分服务 **

当水平扩展遇到瓶颈后,可以进行服务的拆分,将系统按照业务模块进行拆分,从而可以选择性定制化地扩展特定的模块。如电商系统中拆分出订单模块,商品模块,会员模块,地址模块… 由于各个模块的职责不同,如订单模块在双 11 时压力很大,可以多部署一些订单模块,而其他压力不大的模块,则进行少量地部署。

**Z 轴扩展 – 拆分数据 **

服务拆分之后仍然无法解决与日俱增的数据量问题,于是引发了第三层扩展,数据的分片,我理解的 sharding,不仅仅存在于数据库,还包含了 redis,文件等。

另外陈斌老师还聊了一个有意思的话题,系统可用性下降的原因根源是什么?最终他给出的答案是:人。系统升级后引发的事故 80% 是由于人的误操作或者触发了 bug 等人为因素导致的,是人就会手抖。借此引出了单元测试,持续集成,持续交付的重要性。健全这三者是保障系统可用性的最大利器。

在技术晚宴,陈斌老师又分享了一些管理经验:** 如何打造一支优秀的技术团队 **。

分析了构成团队的四要素:

  • 人员:健全职级体系,区别考评,挖掘潜能,及时鼓励,扁平化管理
  • 组织:面向产出,利于创新,敏捷小团队
  • 过程:聚集问题的根源,适当地使⽤用 ITIL,不断优化过程,自动化取代人工
  • 文化:鼓励分享,打破 devops 的边界,鼓励创新,树⽴立正确的技术负债观

对于技术人员来说可能有点抽象,不过对于立志于要成为 CIO 的人肯定是大有裨益的,具体的理解可以参考《架构即未来》中的具体阐释。(ps:这里的架构并不是指技术架构,别问我为什么知道,问问我看了一半后在落灰的那本书,你什么都明白了)


深入理解 RPC 之序列化篇 --Kryo

一年前,笔者刚刚接触 RPC 框架,从单体式应用向分布式应用的变革无疑是让人兴奋的,同时也对 RPC 背后到底做了哪些工作产生了兴趣,但其底层的设计对新手而言并不是很友好,其涉及的一些常用技术点都有一定的门槛。如传输层常常使用的 netty,之前完全没听过,想要学习它,需要掌握前置知识点 nio;协议层,包括了很多自定义的协议,而每个 RPC 框架的实现都有差异;代理层的动态代理技术,如 jdk 动态代理,虽然实战经验不多,但至少还算会用,而 cglib 则又有一个盲区;序列化层倒还算是众多层次中相对简单的一环,但 RPC 为了追求可扩展性,性能等诸多因素,通常会支持多种序列化方式以供使用者插拔使用,一些常用的序列化方案 hessian,kryo,Protobuf 又得熟知…

这个系列打算就 RPC 框架涉及到的一些知识点进行探讨,本篇先从序列化层的一种选择 –kryo 开始进行介绍。

序列化概述

大白话介绍下 RPC 中序列化的概念,可以简单理解为对象 –> 字节的过程,同理,反序列化则是相反的过程。为什么需要序列化?因为网络传输只认字节。所以互信的过程依赖于序列化。有人会问,FastJson 转换成字符串算不算序列化?对象持久化到数据库算不算序列化?没必要较真,广义上理解即可。

JDK 序列化


给初中级 JAVA 准备的面试题

笔者作为一个今年刚毕业的初级 JAVA,根据群里水友的讨论,也结合自己刚毕业时的一些面经,加上近期一点点在公司面试别人的经验,总结了如下的常见面试问题,适用于初级和中级 JAVA。

JAVA

  1. HashMap 相关

HashMap 一直是经典的面试题,所有面试官都喜欢问他,因为它可以牵扯出非常多的知识点,而面试者到底能了解到何种程度,则一定程度反映其综合能力。

细节聊扩容因子 LoadFactor=0.75,初始大小 InitailCapacity=16


打开 orika 的正确方式

缘起

架构分层

开发分布式的项目时,DO 持久化对象和 DTO 传输对象的转换是不可避免的。集中式项目中,DO-DAO-SERVICE-WEB 的分层再寻常不过,但分布式架构(或微服务架构)需要拆分模块时,不得不思考一个问题:WEB 层能不能出现 DAO 或者 DO 对象?我给出的答案是否定的。

新的项目分层结构

这张图曾出现在我过去的文章中,其强调了一个分层的要素:服务层 (应用层) 和表现层应当解耦,后者不应当触碰到任何持久化对象,其所有的数据来源,均应当由前者提供。


JAVA 拾遗 -- 关于 SPI 机制

JDK 提供的 SPI(Service Provider Interface)机制,可能很多人不太熟悉,因为这个机制是针对厂商或者插件的,也可以在一些框架的扩展中看到。其核心类 java.util.ServiceLoader 可以在 jdk1.8 的文档中看到详细的介绍。虽然不太常见,但并不代表它不常用,恰恰相反,你无时无刻不在用它。玄乎了,莫急,思考一下你的项目中是否有用到第三方日志包,是否有用到数据库驱动?其实这些都和 SPI 有关。再来思考一下,现代的框架是如何加载日志依赖,加载数据库驱动的,你可能会对 class.forName(“com.mysql.jdbc.Driver”)这段代码不陌生,这是每个 java 初学者必定遇到过的,但如今的数据库驱动仍然是这样加载的吗?你还能找到这段代码吗?这一切的疑问,将在本篇文章结束后得到解答。

首先介绍 SPI 机制是个什么东西


使用 Spring Cloud Sleuth 实现链路监控

在服务比较少的年代,一个系统的接口响应缓慢通常能够迅速被发现,但如今的微服务模块,大多具有规模大,依赖关系复杂等特性,错综复杂的网状结构使得我们不容易定位到某一个执行缓慢的接口。分布式的服务跟踪组件就是为了解决这一个问题。其次,它解决了另一个难题,在没有它之前,我们客户会一直询问:你们的系统有监控吗?你们的系统有监控吗?你们的系统有监控吗?现在,谢天谢地,他们终于不问了。是有点玩笑的成分,但可以肯定的一点是,实现全链路监控是保证系统健壮性的关键因子。

介绍 Spring Cloud Sleuth 和 Zipkin 的文章在网上其实并不少,所以我打算就我目前的系统来探讨一下,如何实现链路监控。全链路监控这个词意味着只要是不同系统模块之间的调用都应当被监控,这就包括了如下几种常用的交互方式:

1 Http 协议,如 RestTemplate,Feign,Okhttp3,HttpClient…

2 Rpc 远程调用,如 Motan,Dubbo,GRPC…


Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×