奇虎360 和 Go

英文原文:Qihoo 360 and Go
翻译 by 开源中国奇虎360 和 go

在中国,奇虎 360 是一个互联网和手机安全产品及服务的主要供应商,截止到 2014 年 6 月,奇虎拥有 5 亿的 PC 活跃用户以及超过 6.4 亿移动用户。奇虎还运营着中国最受欢迎的网络浏览器和 PC 搜索引擎(原文如此)。

我的团队,推送服务团队(Push Service Team),为超过 50 个公司的产品提供服务(PC 和移动),包括成千上万放在我们的开放平台的应用程序。

我们对Go的青睐要从2012年第一次尝试为奇虎的一个产品提供推送功能开始。最初的nginx + lua + redis方案因为负载过大没能满足我们对实时性能的需求。在这种情况下,最新发布的1.0.3版Go引起了我们的注意,借助它提供的goroutine和channel特性,我们在几周之内开发完成了一个原型。我们的系统最初运行在20台服务器上,能够处理2000万实时连接,每天发送200万信息。现在这套系统在超过400台服务器运行,支持2亿实时连接,每天发送超过100亿条信息。

阅读全文

七种WebSocket框架的性能比较

前一篇文章使用四种框架分别实现百万websocket常连接的服务器介绍了四种websocket框架的测试方法和基本数据。 最近我又使用几个框架实现了websocket push服务器的原型,并专门对这七种实现做了测试。 本文记录了测试结果和一些对结果的分析。
这七种框架是:

最近用Golang实现了第八种,Go表现还不错。

阅读全文

使用四种框架分别实现百万websocket常连接的服务器

事实上,最近我又增加了几个框架,现在包括 Netty, Undertow, Jetty, Spray, Vert.x, Grizzly 和 Node.js七种框架。
测试数据可以看下一篇文章: 七种WebSocket框架的性能比较

著名的 C10K 问题提出的时候, 正是 2001 年。这篇文章可以说是高性能服务器开发的一个标志性文档,它讨论的就是单机为1万个连接提供服务这个问题,当时因为硬件和软件的限制,单机1万还是一个非常值得挑战的目标。但是时光荏苒,随着硬件和软件的飞速发展,单机1万的目标已经变成了最简单不过的事情。现在用任何一种主流语言都能提供单机1万的并发处理的能力。所以现在目标早已提高了100倍,变成C1000k,也就是一台服务器为100万连接提供服务。在2010年,2011年已经看到一些实现C1000K的文章了,所以在2015年,实现C1000K应该不是一件困难的事情。

本文是我在实践过程中的记录,我的目标是使用spran-websocket,netty, undertow和node.js四种框架分别实现C1000K的服务器,看看这几个框架实现的难以程度,性能如何。开发语言为Scala和Javascript。

当然,谈起性能,我们还必须谈到每秒每个连接有多少个请求,也就是RPS数,还要考虑每条消息的大小。
一般来说,我们会选取一个百分比,比如每秒20%的连接会收发消息。我的需求是服务器只是push,客户端不会主动发送消息。 一般每一分钟会为这一百万群发一条消息。
所以实现的测试工具每个client建立60000个websocket连接,一共二十个client。实际不可能使用20台机器,我使用了两台AWS C3.2xlarge(8核16G)服务器作为客户端机。每台机器10个客户端。
服务器每1分钟群发一条消息。消息内容很简单,只是服务器的当天时间。

最近看到360用Go实现的消息推送系统,下面是他们的数据:

目前360消息推送系统服务于50+内部产品,万款开发平台App,实时长连接数亿量级,日独数十亿量级,1分钟内可以实现亿量级广播,日下发峰值百亿量级,400台物理机,3000多个实例分布在9个独立集群中,每个集群跨国内外近10个IDC。

四个服务器的代码和Client测试工具代码可以在github上下载。 (其实不止四种框架了,现在包括Netty, Undertow, Jetty, Spray-websocket, Vert.x, Grizzly 和 Node.js 七种框架的实现)

测试下来可以看到每种服务器都能轻松达到同时120万的websocket活动连接,只是资源占用和事务处理时间有差别。120万只是保守数据,在这么多连接情况下服务器依然很轻松,下一步我会进行C2000K的测试。

阅读全文

为什么Disruptor会那么快?

Disruptor是一个高性能的线程间消息传递的框架。

LMAX 目标是成为当世最快的商务平台。 为了实现这个目标,LMAX需要做一些特殊的工作在Java平台上取得低延迟和高吞吐率的目标。 性能测试表明使用队列(queue)传递数据会带来延迟, 所以LAMX对这一块做了非常好的优化。

Disruptor就是他们的研究成果。 研究发现CPU级别的cache miss和 需要内核仲裁的锁非常的耗费性能, 所以他们创建了一个Disruptor, 这是一个锁无关的实现。

它不是一个为特别任务实现的方案,不仅仅应用于金融领域。Disruptor可以用来解决并发编程中的一个普遍的问题: 消息队列的处理(producer和consumer)。

它使用了一个和传统不一样方式来实现。 所以你可能不能用文本替换的方式使用ring buffer替换你代码中的Queue等。官方网站上提供了一些例子, 本文的参考文档上也列出了一些。 官方的技术白皮书介绍了一些你想知道的细节。 官方文档还提供了非常多的性能测试的代码,也是学习disruptor好材料。

Disruptor究竟有多块, 看官方的和ArrayBlockingQueue测试结果:

注意y轴的刻度是指数级别的, 如果按照均匀递增的刻度,一张图无法显示。
这张图可以这样解读。 x轴越靠近零的比例越多, 性能越好。
Disrutor延迟时间大部分小于1ns, 而ArrayBlockingQueue平均32ns左右了。

阅读全文

Linux Performance Analysis and Tools

Brendan Gregg曾是SUN公司(现已被Oracle收购)的kernal和性能工程师。2010年10月离开Oracle加入Joyent, 2014年成为Netflix公司的高级性能架构师。 Dtrace项目的专家之一, DTraceToolkit的创建者。 现在经常在他的博客上发表一些关于Linux性能的文章。
他专门开了一个页面介绍Linux 性能监控工具, 下图就是他的一副描述Linux监控工具的巨图:
Linux observability tools

阅读全文

Linux TCP/IP 协议栈调优

最近忙于系统性能的DEBUG和调优。 有些性能瓶颈和Linux的TCP/IP的协议栈的设置有关,所以特别google了一下Linux TCP/IP的协议栈的参数意义和配置,记录一下。
如果想永久的保存参数的设置, 可以将参数加入到/etc/sysctl.conf中。如果想临时的更改参数的配置, 可以修改/proc/sys/net/ipv4/下的参数, 机器重启后更改失效。

阅读全文

三步创建Disruptor应用

Disruptor是一个高性能的用于线程间消息处理的开源框架。它的目标就是.
我们知道,java.util.concurrent.ArrayBlockingQueue 是一个非常优秀的有界队列实现。Disruptor与之相比,性能更加的优秀。
性能比较
完整的性能报告在这里.

Disruptor内部使用了RingBuffer,它是Disruptor的核心的数据结构。和其它的RingBuffer实现不同,Disruptor没有尾指针。这样实现是经过深思熟虑的,你可以看这篇文档了解其细节。
更多的参考资料请参照官方文档以及并发编程网上翻译的一些文章

本文主要参考Disruptor入门这篇文章。

本文的代码已全部放在github上。

阅读全文