RPC调用与GC垃圾回收

退步的程序员 2018-09-21 15:53:25 ⋅ 611 阅读

来自:https://www.toutiao.com/i6602500222134256135

作者:Java高级架构师

RPC调用

  • 多个服务协同完成一次业务时,由于业务约束(如红包不符合使用条件、账户余额不足等)、系统故障(如网络或系统超时或中断、数据库约束不满足等),都可能造成服务处理过程在任何一步无法继续,使数据处于不一致的状态。传统的基于数据库本地事务的解决方案只能保障单个服务的一次处理具备原子性、隔离性、一致性与持久性,但无法保障多个分布服务间处理的一致性


  • 分析源代码,基本原理如下:

  • client 一个线程调用远程接口,生成一个唯一的 ID (比如一段随机字符串,UUID 等) , Dubbo 是使用 AtomicLong 从 0 开始累计数字的

  • 将打包的方法调用信息(如调用的接口名称,方法名称,参数值列表等),和处理结果的回调对象 call back ,全都封装在一起,组成一个对象 0bject

  • 向专门存放调用信息的全局 ConcurrentHashMap 里面 put ( ID , object )

  • 将 ID 和打包的方法调用信息封装成一对象 connRequest ,使用 Iosession.write ( connRequest )异步发送出去

  • 当前线程再使用call back 的get()方法试图获取远程返回的结果,在 get()内部,则使用 Synchronized 获取回调对象 caIlback 的锁,再先检测是否已经获取到结果,如果没有,然后调用 callbaCk 的 wait()方法,释放 callback 上的锁,让当前线程处于等待状态

  • 服务端接收到请求并处理后,将结果(此结果中包含了前面的 ID ,即回传)发送给客户端,客户端 socket连接上专门监听消息的线程收到消息,分析结果,取到 ID ,再从前面的ConcurrentHashMap里面 get(ID) ,从而找到 callback ,将方法调用结果设置到 callback 对象里

  • 监听线程接着使用 synchronized 获取回调对象 callback 的锁(因为前面调用过 wait ( ) ,那个线程已释放 callback 的锁了),再 notlfyAll ( ) ,唤醒前面处于等待状态的线程继续执行( call back 的 get ( )方法继续执行就能拿到调用结果了),至此,整个过程结束

  • 当前线程怎么让它暂停,等结果回来后,再向后执行?

  • 先生成一个对象obj ,在一个全局 map 里 put ( 1D obj )存放起来,再用synchronized获取obj锁,再调用obj.wait()让当前线程处于等待状态,然后另一消息监听线程等到服务端结果来了后,再 map.get (ID )找到 obj ,再用 synchronized获取obj 锁,再调用obj.notifyAll唤配前面处于等待状态的线程

  • Socket 通信是一个全双工的方式,如果有多个线程同时进行远程方法调用,这时建立在client server之间的socket连接上会有很多双方发送的消息有传递,前后顺序也可能是乱七八嘈的,server处理完结果后,将结果消息发送给 client, client收到很多消息,怎么知道消息结果是原先哪个线程调用的? 使用一个ID ,让其唯一,然后传递给服务端,再服务端又回传回来,这样就知道结果是原先哪个线程的了

GC垃圾回收

大多数刚创建的对象会被分配在Eden区,当Eden区满的时候,执行Minor GC,将消亡的对象清理掉,并将剩余的对象复制到一个存活区Survivor0,当Survivor0也满的时候,将其中仍然活着的对象直接复制到Survivor1,以后Eden区执行Minor GC后,就将剩余的对象添加Survivor1,当两个存活区切换了几次(HotSpot虚拟机默认15次,用-XX:MaxTenuringThreshold控制,大于该值进入老年代)之后,仍然存活的对象将被复制到老年代

年轻代收集器

  • Serial收集器:“停止-复制”算法,单线程,进行垃圾收集时必须暂停其他线程的所有工作

  • ParNew收集器:Serial收集器的多线程版本,“停止-复制”算法,多线程

  • Parallel Scavenge收集器:”停止-复制“算法,并行的多线程收集器,可控制的吞吐量

老年代收集器

  • Serial Old:Serial收集器的老年代版本,同样是一个单线程收集器,使用“标记-整理”算法

  • Parallel Old收集器:Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法

  • CMS收集器:CMS(Conrrurent Mark Sweep)收集器是以获取最短回收停顿时间为目标的收集器,使用"标记-清除"算法

CMS收集器

  • 初始标记:标记GCRoots能直接关联到的对象,时间很短

  • 并发标记:进行GCRoots Tracing(可达性分析)过程,时间很长

  • 重新标记:修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,时间较长

  • 并发清除:清除未标记(无关联引用)的对象,伴随着用户线程的执行,清除后会产生浮动垃圾

  • 优缺点:对CPU资源非常敏感,可能会导致应用程序变慢,吞吐率下降,无法处理浮动垃圾,采用的“标记-清除”算法,会产生大量的内存碎片

垃圾回收算法实现

  • 停止-复制算法:将内存分为两块,当其中一块内存用完了,将还存活着的对象复制到另一块中,再将使用过的内存一次性清理掉

  • 标记-清除算法:首先标记出所有需要回收的对象,标记完成后统一回收所有被标记的对象

  • 标记-整理算法:让所有存活对象都向一端移动,然后直接清理掉边界以外的内存


---------------END----------------

后续的内容同样精彩

长按关注“IT实战联盟”哦



全部评论: 0

    我有话说:

    阿里大牛谈垃圾回收算法是如何设计的?

    前言 如果大家关注 JDK,会发现在频繁发布的 JDK 版本中,和垃圾回收相关的 JEP (JDK Enhancement Proposals,Java 增强提案)越来越多了,垃圾回收

    微服务调用为啥都选择使用用RPC,http不更简单吗?

    最近在整理微服务技术架构体系,抛出一个问题大家讨论一下!  

    PowerJob —强大的分布式任务调度计算框架

    PowerJob让您轻松完成作业的调度繁杂任务的分布式计算。

    字节跳动 Go RPC 框架 KiteX 性能优化实践

    本文选自“字节跳动基础架构实践”系列文章。“字节跳动基础架构实践”系列文章是由字节跳动基础架构部门各技术团队及专家倾力打造的技术干货内容,和大家分享团队在基础架构发展和演进过程中的实践经验教训,

    「开源资讯」任务调度中间件PowerJob 3.3.0 发布

    PowerJob简介 PowerJob是全新一代分布式调度计算框架,能让您轻松完成作业的调度繁杂任务的分布式计算。 下载地址:https://gitee.com/KFCFans/PowerJob

    蚂蚁金服 Java RPC 开源框架—SOFARPC

    SOFARPC 是一个高可扩展性、高性能、生产级的 Java RPC 框架。

    PowerJob v3.3.2 已经发布,分布式任务调度中间件

    PowerJob v3.3.2 已经发布,PowerJob 是全新一代分布式调度计算框架,能让您轻松完成作业的调度繁杂任务的分布式计算。 此版本更新内容包括: Features 支持控制台查看

    Angular 11.0.0-rc.2 发布,Web 前端框架

    Angular 11.0.0-rc.2 现已发布,具体更新内容如下: Bug 修复 common:从r-> Y更改 week-numbering year 格式 compiler

    「开源资讯」.NET 5.0 RC 2 发布

    微软上周发布了 .NET 5.0 RC 2,此版本已接近最终发布,也是11月正式版发布前的最后一个 RC 版本。微软还表示这是一个“go live”版本,支持用于生产环境,当然这不是指稳定性方面具备

    搜索引擎技术选型调研:ElasticsearchSolr

    Elasticsearch是一个建立在全文搜索引擎 Apache Lucene™ 基础上的搜索引擎,可以说Lucene是当今最先进,最高效的全功能开源搜索引擎框架。

    Wine 6.0-RC5 发布,修复 21 个 bug

    Wine 6.0-RC5 已经发布。Wine(Wine Is Not an Emulator)是一个能够在多种兼容 POSIX 接口的操作系统(诸如 Linux、macOS  BSD 等

    Node实战篇:Express中间件request(四)

    Express 是一个路由和中间件 Web 框架,其自身只具有最低程度的功能:Express 应用程序基本上是一系列中间件函数调用

    字节跳动 | 微服务架构中如何优雅地重试?

    背景 在微服务架构中,一个大系统被拆分成多个小服务,小服务之间大量 RPC 调用,经常可能因为网络抖动等原因导致 RPC 调用失败,这时候使用重试机制可以提高请求的最终成功率,减少故障影响,让系统

    不要把Redis当垃圾桶了,T也有开发设计规范,避坑了吗?!

    Redis不是垃圾桶也不是 SUPER MAN,能力和资源都有限,不合理的使用会降低它的健康度,严重时甚至会

    MixGo V1.0 发布,混合型高性能 Go 框架

    Mix Go 是什么 Mix Go 是混合型高性能 Go 框架,该框架改造整合了 gin, logrus, gorm, go-redis, jwt

    Pulsar Go Client 0.4.0 发布

    Pulsar Client Go 是 Apache Pulsar 的 Go 语言客户端。近期,社区发布 Pulsar Client Go 0.4.0 版本。 新特性 支持在