[转]Spring 5 新功能:函数式 Web 框架

英文原文:New in Spring 5: Functional Web Framework by
中文翻译: Spring 5 新功能:函数式 Web 框架 by 开源中国

就像在昨天Juergen发布的博客的一样,Spring 5.0框架第二个里程碑版本中介绍了一个新的函数式web框架。在这篇文章中,我将更详细的介绍这个框架。

紧记该函数式web框架是在Spring5.0第一个里程碑版本基础上构建的。并且我们依旧提供基于注解的请求处理(例如@Controller,@RequestMapping),关于基于注解的请求处理部分的相关信息请查阅关于Spring5.0第一个里程碑版本的博客。

阅读全文

继续了解Java的纤程库 - Quasar

前一篇文章Java中的纤程库 - Quasar中我做了简单的介绍,现在进一步介绍这个纤程库。

Quasar还没有得到广泛的应用,搜寻整个github也就pinterest/quasar-thrift这么一个像样的使用Quasar的库,。并且官方的文档也很简陋,很多地方并没有详细的介绍,和Maven的集成也不是很好。这些都限制了Quasar的进一步发展。

但是,作为目前最好用的Java coroutine的实现,它在某些情况下的性能还是表现相当出色的,希望这个项目能够得到更大的支持和快速发展。

因为Quasar文档的缺乏,所以使用起来需要不断的摸索和在论坛上搜索答案,本文将一些记录了我在Quasar使用过程中的一些探索。

阅读全文

[转]列出所有的Maven依赖

转发一个脚本,以列表形式显示maven中的依赖。
原文: List all your Maven dependencies

1
2
3
4
5
6
7
8
9
10
# first grab all dependencies
mvn dependency:resolve

# then list them with -o to keep noise low,
# remove extra information and duplicates
mvn -o dependency:list \
| grep ":.*:.*:.*" \
| cut -d] -f2- \
| sed 's/:[a-z]*$//g' \
| sort -u

输出结果如下所示:

1
2
3
4
5
6
7
asm:asm:jar:1.5.3
asm:asm:jar:3.1
biz.aQute:bnd:jar:0.0.169
cglib:cglib:jar:2.1_3
classworlds:classworlds:jar:1.1
classworlds:classworlds:jar:1.1-alpha-2
...

理解RxJava的线程模型

ReactiveX是Reactive Extensions的缩写,一般简写为Rx,最初是LINQ的一个扩展,由微软的架构师Erik Meijer领导的团队开发,在2012年11月开源,Rx是一个编程模型,目标是提供一致的编程接口,帮助开发者更方便的处理异步数据流,Rx库支持.NET、JavaScript和C++,Rx近几年越来越流行了,现在已经支持几乎全部的流行编程语言了,Rx的大部分语言库由ReactiveX这个组织负责维护,比较流行的有RxJava/RxJS/Rx.NET,社区网站是 reactivex.io

Netflix参考微软的Reactive Extensions创建了Java的实现RxJava,主要是为了简化服务器端的并发。2013年二月份,Ben Christensen 和 Jafar Husain发在Netflix技术博客的一篇文章第一次向世界展示了RxJava。

RxJava也在Android开发中得到广泛的应用。

ReactiveX
An API for asynchronous programming with observable streams.
A combination of the best ideas from the Observer pattern, the Iterator pattern, and functional programming.

虽然RxJava是为异步编程实现的库,但是如果不清楚它的使用,或者错误地使用了它的线程调度,反而不能很好的利用它的异步编程提到系统的处理速度。本文通过实例演示错误的RxJava的使用,解释RxJava的线程调度模型,主要介绍SchedulerobserveOnsubscribeOn的使用。

阅读全文

Java中的纤程库 - Quasar

最近遇到的一个问题大概是微服务架构中经常会遇到的一个问题:

服务 A 是我们开发的系统,它的业务需要调用 BCD 等多个服务,这些服务是通过http的访问提供的。 问题是 BCD 这些服务都是第三方提供的,不能保证它们的响应时间,快的话十几毫秒,慢的话甚至1秒多,所以这些服务的Latency比较长。幸运地是这些服务都是集群部署的,容错率和并发支持都比较高,所以不担心它们的并发性能,唯一不爽的就是就是它们的Latency太高了。

简化的微服务架构

系统A会从Client接收Request, 每个Request的处理都需要多次调用B、C、D的服务,所以完成一个Request可能需要1到2秒的时间。为了让A能更好地支持并发数,系统中使用线程池处理这些Request。当然这是一个非常简化的模型,实际的业务处理比较复杂。

可以预见,因为系统B、C、D的延迟,导致整个业务处理都很慢,即使使用线程池,但是每个线程还是会阻塞在B、C、D的调用上,导致I/O阻塞了这些线程, CPU利用率相对来说不是那么高。

当然在测试的时候使用的是B、C、D的模拟器,没有预想到它们的响应是那么慢,因此测试数据的结果还不错,吞吐率还可以,但是在实际环境中问题就暴露出来了。

阅读全文

[转]Java 8:StampedLock,ReadWriteLock以及synchronized的比较

原文出处:Tal Weiss, 译文出处: 有孚

同步区域有点像拜访你的公公婆婆。你当然是希望待的时间越短越好。说到锁的话情况也是一样的,你希望获取锁以及进入临界区域的时间越短越好,这样才不会造成瓶颈。

synchronized关键字是语言层面的加锁机制,它可以用于方法以及代码块。这个关键字是由HotSpot JVM来实现的。我们在代码中分配的每一个对象,比如String, Array或者一个JSON文档,在GC的层面的对象头部,都内建了一个加锁的机制。JIT编译器也是类似的,它在进行字节码的编译和反编译的时候,都取决于特定的某个锁的具体的状态和竞争级别。

同步块的一个问题在于——进入临界区域内的线程不能超过一个。这对生产者消费者场景是一个很大的打击,尽管这里有些线程会尝试进行独占式的数据编辑,而另外一些线程只是希望读取一下数据,这个是可以和别的线程同时进行的。

读写锁(ReadWriteLock)是一个理想的解决方案。你可以指定哪些线程会阻塞别的操作(写线程),哪些线程可以和别人共同进行内容的消费(读线程)。一个美满的结局?恐怕不是。

读写锁不像同步块,它并不是JVM中内建支持的,它只不过是段普通的代码。同样的,要想实现锁机制,它得引导CPU原子地或者按某个特定的顺序来执行某些特定的操作,以避免竞争条件。这通常都是通过JVM预留的一个后门来实现的——unsafe类。读写锁使用的是CAS操作来将值直接设置到内存中去,这是它们线程排队算法中的一部分。

尽管这样,读写锁也还不够快,有时候甚至会表现得非常慢,慢到你压根儿就不应该使用它。然而JDK的这帮家伙们没有放弃治疗,现在他们带来了一个全新的StampedLock。这个读写锁使用了一组新的算法以及Java 8 JDK中引入的内存屏障的特性,这使得这个锁更高效也更健壮。

它兑现了自己的诺言了吗?让我们拭目以待。

阅读全文

Java CompletableFuture 详解

Future是Java 5添加的类,用来描述一个异步计算的结果。你可以使用isDone方法检查计算是否完成,或者使用get阻塞住调用线程,直到计算完成返回结果,你也可以使用cancel方法停止任务的执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class BasicFuture {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(10);
Future<Integer> f = es.submit(() ->{
// 长时间的异步计算
// ……
// 然后返回结果
return 100;
});
// while(!f.isDone())
// ;
f.get();
}
}

虽然Future以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,只能通过阻塞或者轮询的方式得到任务的结果。阻塞的方式显然和我们的异步编程的初衷相违背,轮询的方式又会耗费无谓的CPU资源,而且也不能及时地得到计算结果,为什么不能用观察者设计模式当计算结果完成及时通知监听者呢?

很多语言,比如Node.js,采用回调的方式实现异步编程。Java的一些框架,比如Netty,自己扩展了Java的 Future接口,提供了addListener等多个扩展方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
future.addListener(new ChannelFutureListener()
{
@Override
public void operationComplete(ChannelFuture future) throws Exception
{
if (future.isSuccess()) {
// SUCCESS
}
else {
// FAILURE
}
}
});

Google guava也提供了通用的扩展Future:ListenableFutureSettableFuture 以及辅助类Futures等,方便异步编程。

1
2
3
4
5
6
7
8
9
10
11
final String name = ...;
inFlight.add(name);
ListenableFuture<Result> future = service.query(name);
future.addListener(new Runnable() {
public void run() {
processedCount.incrementAndGet();
inFlight.remove(name);
lastProcessed.set(name);
logger.info("Done with {0}", name);
}
}, executor);

Scala也提供了简单易用且功能强大的Future/Promise异步编程模式

作为正统的Java类库,是不是应该做点什么,加强一下自身库的功能呢?

在Java 8中, 新增加了一个包含50个方法左右的类: CompletableFuture,提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果,并且提供了转换和组合CompletableFuture的方法。

下面我们就看一看它的功能吧。

阅读全文

Spymemcached的一个坑

Spymemcached 是 Memcached 的一个流行的Java client库(另一个比较著名的是原淘宝的 伯岩/庄晓丹 开发的XMemcached, 他也开发另一个Taobao开源的项目 Metamorphosis),性能表现出色,广泛应用于Java + Memcached 项目中。
Spymemcached 最早由 Dustin Sallings 开发,Dustin 后来和别人一起创办了Couchbase (原NorthScale),职位为首席架构师。2014加入Google。

阅读全文

Netty 5.0 中的新变化和注意点

本文翻译自官方文档New and noteworthy in 5.0.
本文带你了解Netty 5.0 的值得注意的改变和新特性,帮助你将应用程序迁移到最新的版本.

不像 3.x 和 4.0 之间的改变那么大, 5.0 并没有很大的改变,尽管它在设计的简化性上做了一些突破. 我们尽可能平滑地使4.x转换到5.0,但是如果在迁移的过程中有问题请让我们知道.

其它版本之间的改变和新特性文档请看:
Netty 4.1中的新变化和注意点
Netty 4.0中的新变化和注意点

阅读全文