应用场景JVM-Sandbox,SwiftNIO 还提供了一些 Channel

摘要北京时间 3 月 21 日,Oracle 官方宣布 Java 10 正式发布。这是 Java
大版本周期变化后的第一个正式发布版本,非常值得关注。引言北京时间 3 月 21
日,Oracle 官方宣布 Java 10 正式发布。这是 Java
大版本周期变化后的第一个正式发布版本(详见这里),非常值得关注。你可以点击以下地址即刻下载:
9 月,Oracle 将 Java 大版本周期从原来的 2-3
年,调整成每半年发布一个大的版本。而版本号仍延续原来的序号,即 Java
8、Java 9、Java 10、Java
11…..但和之前不一样的是,同时还有一个版本号来表示发布的时间和是否为
LTS(长期支持版本),比如 Java 10 对应 18.3。如下示例:/jdk-10/bin$
./java -versionopenjdk version “10” 2018-03-20OpenJDK Runtime
Environment 18.3 (build 10+46)OpenJDK 64-Bit Server VM 18.3 (build
10+46, mixed mode)需要注意的是 Java 9 和 Java 10 都不是 LTS
版本。和过去的 Java
大版本升级不同,这两个只有半年左右的开发和维护期。而未来的 Java
11,也就是 18.9 LTS,才是 Java 8 之后第一个 LTS 版本(得到 Oracle
等商业公司的长期支持服务)。这种发布模式已经得到了广泛应用,一个成功的例子就是
Ubuntu Linux 操作系统,在偶数年 4 月的发行版本为
LTS,会有很长时间的支持。如 2014 年 4 月份发布的 14.04 LTS,Canonical
公司和社区支持到 2019 年。类似的,Node.js,Linux kernel,Firefox
也采用类似的发布方式。Java
未来的发布周期,将每半年发布一个大版本,每个季度发布一个中间特性版本。这样可以把一些关键特性尽早合并入
JDK 之中,快速得到开发者反馈,可以在一定程度上避免 Java 9
两次被迫推迟发布日期的尴尬。下图为 2017 年 JavaOne 大会时,Oracle
公开的未来 Java 版本发布和支持周期图。Java 10 新特性这次发布的 Java
10,新带来的特性并不多。根据官网公开资料,共有 12 个 JEP(JDK Enhancement
Proposal 特性加强提议),带来以下加强功能:JEP286,var
局部变量类型推断。JEP296,将原来用 Mercurial 管理的众多 JDK
仓库代码,合并到一个仓库中,简化开发和管理过程。JEP304,统一的垃圾回收接口。JEP307,G1
垃圾回收器的并行完整垃圾回收,实现并行性来改善最坏情况下的延迟。JEP310,应用程序类数据
(AppCDS)
共享,通过跨进程共享通用类元数据来减少内存占用空间,和减少启动时间。JEP312,ThreadLocal
握手交互。在不进入到全局 JVM 安全点 (Safepoint)
的情况下,对线程执行回调。优化可以只停止单个线程,而不是停全部线程或一个都不停。JEP313,移除
JDK 中附带的 javah 工具。可以使用 javac -h 代替。JEP314,使用附加的
Unicode
语言标记扩展。JEP317,能将堆内存占用分配给用户指定的备用内存设备。JEP317,使用
Graal 基于 Java 的编译器,可以预先把 Java
代码编译成本地代码来提升效能。JEP318,在 OpenJDK
中提供一组默认的根证书颁发机构证书。开源目前 Oracle 提供的的 Java SE
的根证书,这样 OpenJDK
对开发人员使用起来更方便。JEP322,基于时间定义的发布版本,即上述提到的发布周期。版本号为$FEATURE.$INTERIM.$UPDATE.$PATCH,分别是大版本,中间版本,升级包和补丁版本。部分特性说明1.
var 类型推断。这个语言功能在其他一些语言 (C#、JavaScript) 和基于 JRE
的一些语言 (Scala 和 Kotlin) 中,早已被加入。在 Java
语言很早就在考虑,早在 2016 年正式提交了 JEP286
提议。后来举行了一次公开的开发者调查,获得最多建议的是采用类似 Scala
的方案,“同时使用 val 和 var”,约占一半;第二多的是“只使用
var”,约占四分之一。后来 Oracle 公司经过慎重考虑,采用了只使用 var
关键字的方案。有了这个功能,开发者在写这样的代码时:ArrayList myList =
new ArrayList()可以省去前面的类型声明,而只需要var list = new
ArrayList()编译器会自动推断出 list
变量的类型。对于链式表达式来说,也会很方便:var stream =
blocks.stream(); … int maxWeight = stream.filter(b -> b.getColor()
== BLUE) .mapToInt(Block::getWeight) .max();开发者无须声明并且 import
引入 Stream 类型,只用 stream 作为中间变量,用 var
关键字使得开发效率提升。不过 var
的使用有众多限制,包括不能用于推断方法参数类型,只能用于局部变量,如方法块中,而不能用于类变量的声明,等等。另外,我个人认为,对于开发者而言,变量类型明显的声明会提供更加全面的程序语言信息,对于理解并维护代码有很大的帮助。一旦
var 被广泛运用,开发者阅读三方代码而没有 IDE
的支持下,会对程序的流程执行理解造成一定的障碍。所以我建议尽量写清楚变量类型,程序的易读维护性有时更重要一些。2.
统一的 GC 接口在 JDK10 的代码中,路径为
openjdk/src/hotspot/share/gc/,各个 GC 实现共享依赖 shared 代码,GC
包括目前默认的 G1,也有经典的 Serial、Parallel、CMS 等 GC 实现。3.
应用程序类数据(AppCDS)共享CDS 特性在原来的 bootstrap
类基础之上,扩展加入了应用类的 CDS(Application Class-Data Sharing)
支持。其原理为:在启动时记录加载类的过程,写入到文本文件中,再次启动时直接读取此启动文本并加载。设想如果应用环境没有大的变化,启动速度就会得到提升。我们可以想像为类似于操作系统的休眠过程,合上电脑时把当前应用环境写入磁盘,再次使用时就可以快速恢复环境。

摘要近日,苹果开源了一款基于事件驱动的高性能跨平台网络应用程序开发框架
SwfitNIO,它有点类似 Netty,但开发语言使用的是
Swift。1、SwiftNIO是什么SwfitNIO
实际上是一个底层工具,用于开发高性能的网络应用程序,作为“每连接一个线程”的替代方案。为了提升性能,SwfitNIO
使用了非阻塞 IO,这从它的名字就可以看出来。非阻塞 IO 与阻塞式 IO
非常不一样,因为不管是往网络上发送数据还是从网络上接收数据,应用程序都无需等待,系统内核会在有可操作的
IO 时通知 SwfitNIO。SwfitNIO 并不会提供类似 Web
框架那样的解决方案,而是致力于为上层框架提供底层的构建块。在开发 Web
应用程序时,大部分开发者不会直接使用 SwfitNIO,他们会从 Swift
生态系统众多的 Web 框架中选择一个。不过,这些框架中的大部分都使用了
SwfitNIO。2、受支持的平台SwfitNIO 的目标是支持所有可以运行 Swift
的平台。目前,SwfitNIO 可以在 macOS 和 Linux 上运行,包括:Ubuntu
14.04+macOS 10.12+3、基本架构SwfitNIO 包含了几种基本构建块,所有的
SwfitNIO
应用程序都是由这几种组件组成的。EventLoopGroupEventLoopChannelChannelHandlerBootstrapByteBuffer▶
EventLoopPromise 和 EventLoopFutureEventLoop 是 SwfitNIO 最基本的 IO
原语,它等待事件的发生,在发生事件时触发某种回调操作。在大部分 SwfitNIO
应用程序中,EventLoop 对象的数量并不多,通常每个 CPU 核数对应一到两个
EventLoop 对象。一般来说,EventLoop
会在应用程序的整个生命周期中存在,进行无限的事件分发。EventLoop
可以组合成 EventLoopGroup,EventLoopGroup 提供了一种机制用于在各个
EventLoop 间分发工作负载。例如,服务器在监听外部连接时,用于监听连接的
socket 会被注册到一个 EventLoop 上。但我们不希望这个 EventLoop
承担所有的连接负载,那么就可以通过 EventLoopGroup 在多个 EventLoop
间分摊连接负载。目前,SwiftNIO 提供了一个 EventLoopGroup
实现(MultiThreadedEventLoopGroup)和两个 EventLoop
实现(SelectableEventLoop 和
EmbeddedEventLoop)。MultiThreadedEventLoopGroup 会创建多个线程(使用
POSIX 的 pthreads 库),并为每个线程分配一个 SelectableEventLoop
对象。SelectableEventLoop 使用选择器(基于 kqueue 或
epoll)来管理来自文件和网络 IO 事件。EmbeddedEventLoop 是一个空的
EventLoop,什么事也不做,主要用于测试。▶
Channels、ChannelHandler、ChannelPipeline 和 ChannelHandlerContext尽管
EventLoop
非常重要,但大部分开发者并不会与它有太多的交互,最多就是用它创建
EventLoopPromise 和调度作业。开发者经常用到的是 Channel 和
ChannelHandler。每个文件描述符对应一个 Channel,Channel
负责管理文件描述符的生命周期,并处理发生在文件描述符上的事件:每当
EventLoop 检测到一个与相应的文件描述符相关的事件,就会通知
Channel。ChannelPipeline 由一系列 ChannelHandler 组成,ChannelHandler
负责按顺序处理 Channel 中的事件。ChannelPipeline
就像数据处理管道一样,所以才有了这个名字。ChannelHandler 要么是
Inbound,要么是 Outbound,要么两者兼有。Inbound 的 ChannelHandler
负责处理“inbound”事件,例如从 socket 读取数据、关闭 socket
或者其他由远程发起的事件。Outbound 的 ChannelHandler
负责处理“outbound”事件,例如写数据、发起连接以及关闭本地
socket。ChannelHandler
按照一定顺序处理事件,例如,读取事件从管道的前面传到后面,而写入事件则从管道的后面传到前面。每个
ChannelHandler 都会在处理完一个事件后生成一个新的事件给下一个
ChannelHandler。ChannelHandler
是高度可重用的组件,所以尽可能设计得轻量级,每个 ChannelHandler
只处理一种数据转换,这样就可以灵活组合各种
ChannelHandler,提升代码的可重用性和封装性。我们可以通过
ChannelHandlerContext 来跟踪 ChannelHandler 在 ChannelPipeline
中的位置。ChannelHandlerContext 包含了当前 ChannelHandler
到上一个和下一个 ChannelHandler 的引用,因此,在任何时候,只要
ChannelHandler 还在管道当中,就能触发新事件。SwiftNIO 内置了多种
ChannelHandler,包括 HTTP 解析器。另外,SwiftNIO 还提供了一些 Channel
实现,比如 ServerSocketChannel(用于接收连接)、SocketChannel(用于 TCP
连接)、DatagramChannel(用于 UDP socket)和
EmbeddedChannel(用于测试)。▶ BootstrapSwiftNIO 提供了一些 Bootstrap
对象,用于简化 Channel 的创建。有些 Bootstrap
对象还提供了其他的一些功能,比如支持 Happy Eyeballs。目前 SwiftNIO
提供了三种 Bootstrap:ServerBootstrap(用于监听
Channel),ClientBootstrap(用于 TCP Channel)和 DatagramBootstrap(用于
UDP Channel)。▶ ByteBufferSwiftNIO 提供了 ByteBuffer,一种快速的
Copy-On-Write 字节缓冲器,是大部分 SwiftNIO
应用程序的关键构建块。ByteBuffer
提供了很多有用的特性以及一些“钩子”,通过这些钩子,我们可以在“unsafe”的模式下使用
ByteBuffer。这种方式可以获得更好的性能,代价是应用程序有可能出现内存问题。在一般情况下,还是建议在安全模式下使用
ByteBuffer。▶ EventLoopPromise 和
EventLoopFuture并发代码和同步代码之间最主要的区别在于并非所有的动作都能够立即完成。例如,在向一个
Channel 写入数据时,EventLoop
有可能不会立即将数据冲刷到网络上。为此,SwiftNIO 提供了
EventLoopPromise和
EventLoopFuture,用于管理异步操作。EventLoopFuture实际上是一个容器,用于存放函数在未来某个时刻的返回值。每个
EventLoopFuture对象都有一个对应的
EventLoopPromise,用于存放实际的结果。只要 EventLoopPromise
执行成功,EventLoopFuture 也就完成了。通过轮询的方式检查 EventLoopFuture
是否完成是一种非常低效的方式,所以 EventLoopFuture
被设计成可以接收回调函数。也就是说,在有结果的时候回调函数会被执行。EventLoopFuture负责处理调度工作,确保回调函数是在最初创建
EventLoopPromise 的那个 EventLoop
上执行,所以就没有必要再针对回调函数做任何同步操作。4、SwiftNIO
的设计哲学SwiftNIO
的目标是要成为强大的网络应用程序开发框架,但并不想为所有的层次抽象提供完美的解决方案。SwiftNIO
主要专注在基本的 IO
原语和底层的协议实现上,将其他层次的抽象留给广大的社区去构建。SwiftNIO
将成为服务器端应用程序的构建块,但不一定就是应用程序直接拿来使用的框架。对性能有很高要求的应用程序可能会直接使用
SwiftNIO,减少上层抽象所带来的开销。SwiftNIO
可以帮助这些应用程序在提升性能的同时降低维护成本。SwiftNIO
还为某些场景提供了有用的抽象,高性能的网络服务器可以直接使用这些抽象。SwiftNIO
的核心仓库提供了一些非常重要的协议实现,比如
HTTP。不过,我们认为,大部分协议的实现应该要与底层的网络栈分开,因为它们的发布节奏是很不一样的。为此,我们鼓励社区自己去实现和维护他们的协议实现。实际上,SwiftNIO
提供的一些协议实现最初就是由社区开发的,比如 TLS 和
HTTP/2。5、相关资源源码托管:
文档:
SwiftNIO:聊天客户端:
客户端:
服务器端:
服务器:

摘要阿里巴巴于近期正式开源了其自研的动态非侵入AOP解决方案:JVM-Sandbox。JVM-Sandbox即JVM沙箱容器,一种JVM的非侵入式运行期AOP解决方案。写在前面随着软件部署规模的扩大,系统的功能的细化,系统间耦合度和链路复杂度不断加强。若要继续保持现规模系统的稳定性,需要实现并完善监控体系、故障定位分析、流量录制回放、强弱依赖检测、故障演练等支撑工具平台。出于对服务器规模和业务稳定性的考量,这些配套工具平台要具备对目标应用具有无侵入、实时生效、动态可插拔的特点。要实现这些,多少都会触及到一块底层技术——动态字节码增强。如果每个工具都自己实现一套字节码增强逻辑,前期实现的门槛与后期维护成本高,且不同工具间相互影响造成不可预知的风险。如何屏蔽字节码增强技术的高门槛,降低研发运维成本,同时又能支持上层多个工具平台功能的快速实现和动态管理,成为阿里集团的目标。从去年开始潜心修行,创新的研发了一套实时无侵入的字节码增强框架。于是
JVM-Sandbox
诞生了!诞生历程2014年GREYS第一版正式发布,一路看着他从无到有,并不断优化强大,感慨羡慕之余,也在想GREYS是不是只能做问题定位。2015年开始根据GREYS的底层代码完成了人生的第一个字节码增强工具——动态日志。之后又萌生了将其拆解成录制回放、故障模拟等工具的想法。扪心自问,我是想以一人一个团队的力量建立大而全的工具平台,还是做一个底层中台,让每一位技术人员都可以在它的基础上快速的实现业务功能。我选择了后者。应用场景JVM-Sandbox
的目标群体Btrace
好强大,也曾技痒想做一个更便捷、更适合自己的问题定位工具,既可支持线上链路监控排查,也可支持单机版问题定位。有时候突然一个问题反馈上来,需要入参才能完成定位,但恰恰没有任何日志,甚至出现在别人的代码里,好想开发一个工具可以根据需要动态添加日志,最好还能按照业务
ID
进行过滤。系统间的异常模拟可以使用的工具很多,可是系统内的异常模拟怎么办,加开关或是用
AOP
在开发系统中实现,好想开发一个更优雅的异常模拟工具,既能模拟系统间的异常,又能模拟系统内的异常。好想获取行调用链路数据,可以用它识别场景、覆盖率统计等等,覆盖率统计工具不能原生支持,统计链路数据不准确。想自己开发一个工具获取行链路数据。我想开发录制回放、故障模拟、动态日志、行链路获取等等工具,就算我开发完成了,这些工具底层实现原理相同,同时使用,要怎么消除这些工具之间的影响,怎么保证这些工具动态加载,怎么保证动态加载
/
卸载之后不会影响其他工具,怎么保证在工具有问题的时候,快速消除影响,代码还原。如果你有以上诉求,那么你就是
JVM-Sandbox 的潜在客户。JVM-Sandbox
提供动态增强类你所指定的类,获取你想要的参数和行信息;提供动态可插拔容器,管理基于
JVM-Sandbox 的模块。JVM-Sandbox 能做什么?在
JVM-Sandbox(以下简称沙箱)的世界观中,任何一个 Java
方法的调用都可以分解为BEFORE、RETURN和THROWS三个环节,由此在三个环节上引申出对应环节的事件探测和流程控制机制。不仅如此还有LINE事件,可以完成代码行的记录。//
BEFORE-EVENTtry { /* * do something… */ //LINE-EVENT a(); //
RETURN-EVENT return;} catch (Throwable cause) { //
THROWS-EVENT}基于BEFORE、RETURN和THROWS三个环节事件以及LINE事件,可以完成很多类
AOP
的操作。可以感知和改变方法调用的入参可以感知和改变方法调用返回值和抛出的异常可以感知一个请求按顺序执行了哪些行可以改变方法执行的流程在方法体执行之前直接返回自定义结果对象,原有方法代码将不会被执行在方法体返回之前重新构造新的结果对象,甚至可以改变为抛出异常在方法体抛出异常之后重新抛出新的异常,甚至可以改变为正常返回JVM-Sandbox
都有哪些可能的应用场景线上故障定位线上系统流控线上故障模拟方法请求录制和结果回放动态日志打印安全信息监测和脱敏行链路计算和覆盖率统计JVM
沙箱还能帮助你做很多很多,取决于你的脑洞有多大了。JVM-Sandbox
在阿里集团的应用线上故障演练17 年故障演练平台在 JVM-Sandbox 基础上仅耗时
1
周即完成故障注入部分的系统重构。重构后的系统在挂载效率和挂载成功率方面有了明显的提升,极大的缩短的故障演练的时间,演练效率提升了数十倍。基于
JVM-Sandbox 改造后的故障演练平台,通用性强,所有基于 JVM
启动的系统均支持,极大的拓展了故障演练的范围,故障演练已达到集团级部署。与
16 年故障演练数据对比,17 年的故障演练平台,覆盖 BU 提升了 1.6
倍,覆盖应用提升了 5 倍,覆盖场景提升了 37 倍。依赖检测17
年强弱依赖自动化检测平台诞生。它提供了依赖检测、强弱分析、依赖扫描、故障注入等多种能力,底层能力基于
JVM-Sandbox 在 1
周内完成功能开发。利用其模块容器的特性,将前人开发的模块与新增模块一起挂载共同工作,完成平台功能。强弱依赖梳理方面,承载了淘宝的系统强弱依赖梳理工作,260+
个应用一键接入系统,并实现了 0
人工成本的自动化、智能化梳理。服务端录制隔离回放机制在 JVM-Sandbox
基础上开发了一个 SS 模块,相当于一个录音机 + 回放机,
在调用中间件的时候, 顺序录制下了我们的中间件请求,
并且存储这份‘磁带’到服务器上。当我们需要隔离回放的时候,
将这份‘磁带’找到, 并且在需要的时候直接从‘磁带’读取,
并不需要真实地请求我们的中间件,
这样就保证了我们的读、写接口也能做到可重复使用,从而实现服务端的隔离回放。线上录制隔离回放不仅极大的缩短的业务回归的耗时,把业务测试同学从繁琐的数据准备和接口自动化脚本的编写过程中解放出来,而且极大的拓展了覆盖范围,使回归的范围更贴近用户,且场景更丰富。精准回归服务端录制隔离回放机制诞生之后,虽然有效的提升了覆盖范围,降低了自动化脚本的人工投入,但是也带来了新的问题。线上录制的场景是海量的,单个系统都可以达到万级、十万级甚至百万级别的录制,这些录制的场景中,存在大量的重复场景,如何识别重复场景,实现有效、精准的回放,成为新的待解决问题。17
年在 JVM-Sandbox 的基础上,利用 LineEvnet
实现了行链路识别和标记,有效的提升了回放的精准度和效率。JVM-Sandbox
在阿里集团已经实现全网部署,在其上加载不同的模块实现了不同的功能,每个功能根据
BU
和应用的需要进行加载:强弱依赖检测功能:覆盖淘宝、天猫、业务平台、菜鸟、飞猪、ICBU、CBU
等 7 个 BU,240+
个应用;线上故障演练功能:覆盖集团客户体验事业群、淘宝网、云零售事业部、天猫、业务平台、飞猪、菜鸟、钉钉、阿里健康、CBU、集团安全、支付宝等
16 个 BU,391 个应用;服务端录制回放:覆盖淘宝网、钉钉 2 个
BU;精准回归:覆盖淘宝网、业务平台、钉钉 3 个
BU。通过上边的事例,想必大家对 JVM-Sandbox
是什么,核心功能是什么,还能做哪些事情,以及是否可以为阿里以外的同学提供服务等问题更感兴趣了,下面我们着重介绍这部分内容。开源和共建1、已开源,寻求更多的同学一起完善
JVM-Sandbox 的功能。Github
地址:
JVM-Sandbox
的功能;3、希望更多的同学想到跟多的应用场景,并能开源出来供大家使用。综上,JVM-Sandbox
是一个纯 java 编写的 AOP
解决方案。它为研发人员提供了一个快速实现字节码增强工具的平台。他的模块管理功能可以最大限度的复用模块、协同合作,减少重复投入。随着
JVM-Sandbox
的开源,我们期待更多的人加入到功能扩张和优化上,使其适配更多的开源中间件和
JVM。希望有更多的同学,发挥其聪明才智,开发更多、更好的上层模块,提供给自己和其他人的人使用。也希望能够利用好已有的模块,组装出新的工具平台和应用场景。JVM-Sandbox
建设和应用期待大家共同建设。