一、问题描述

在大访问量的Web服务中,MC集群作为缓解后端数据源访问压力的中间层已经成为了不可缺少的一部分,机器数量越来越大,维护成本也变得越来越高了,其中的问题有:

  • 故障机器自动剔除。后端某台MC机器宕机时,需要及时发现并将该机器从集群中移除。
  • 透明运维。需要能够在不用业务方做任何修改的情况下,快速的增加或迁移机器。
  • 跨机房同步。MC夸多个机房,并且每个机房的数据独立时,就需要考虑MC数据的一致性问题。

面临以上问题,传统的直接将MC服务器IP写在配置文件中无法满足及时响应的需求。为了解决这些问题,huati.weibo.com曾使用了一个基于Zookeeper的中间件来自动同步配置,但或多或少存在一些问题,于是我们决定尝试WCCS.

二、WCCS介绍

WCCS是由 @laruence 带领的微博主站架构研发部发起,由 @猫爷宋Qi 同学主导开发的一个MC中间件服务,它参考Twemproxy实现了自动检查MC的存活情况并自动剔除故障节点的功能,它支持根据key的前缀做正则匹配后在集群中定制分发策略,还可对hot key进行多机复制以达到分散压力的效果等。

除此之外WCCS还根据微博的业务特点,提供了多个集群间数据同步的功能,这样就可以将机房A的数据自动同步机房B,显著的提高了可用性。在进程模型方面,WCSS采用了和apache类似的多进程模型,通过worker进程接受和分发MC请求,配置为长连接方式并启动后,每个worker进程与后端的每个MC维持固定个数的连接。并支持对同一个pool中的不同MC端口设定不同的权重,以达到一定程度上的SLA。

下面用一个配置文件来展示WCCS的功能:

server: {

host = "0.0.0.0";  //监听的IP

port = 2888; //监听的端口

daemon = true; //是否以daemon方式运行

workers_num = 10; //启动多少个子进程

pid = "/usr/local/sinasrv2/var/run/wccs.pid";

};

pool:       //WCCS使用pool的方式对MC进行分组管理

(

{

name = "PoolDefault";    //pool的名字

timeout = 1000;    //与MC连接的超时时间

preconnect = true;    //是否使用持久连接

auto_eject_hosts = true;    //是否开启自动剔除故障MC实例

backend_connections = 20;    //每个worker与每个MC实例的连接数

backend_failure_limit = 500;  //触发自动剔除的最大失败次数

backend_retry_timeout = 30000; //自动重连被剔除机器的时间间隔,单位为毫秒

backend:     //pool对应的MC实例

(

{ ip = "10.73.19.37"; port = 7943; weight = 1 }, //weight指定MC实例权重

//....

);

},

);

keymap:

(

{

prefix = "*"; //路由前缀, WCCS支持将指定前缀的key分发到指定的pool中

pool = "PoolDefault"; //pool的名字

distribution = "ketama"; //分布策略采用一致性Hash,支持多种分发算法

hash = "md5";  //使用md5作为hash策略,支持多种hash算法

hash_tag = "{}";

need_sync = false; //是否开启跨机房同步

},

);

###以下为跨机房同步相关配置
                sync: {    //WCCS同步相关配置

dir = “/var/wccsdata”,  //开启跨机房同步时,用于记录MC的更新操作日志

backend :    //需要同步的WCCS端口

(

{ip = “127.0.0.1”; port = 2888},    // 位于机房B的WCCS集群

{ip = “127.0.0.1”; port = 2810}    // 位于机房C的WCCS集群

//....

)

            }

三、 对WCCS的一些测试

为了了解WCCS的特性,我对它进行了一些测试,重点测试了以下几点:

  1. keymap机制是如何工作的?
  2. 是否能及时自动剔除故障机器?
  3. 性能如何?
  4. 参数如何配配置才能够达到最大性能?

压测工具采用mcperf. 支持高并发访问,并可以输出清晰的测试报告。同时使用memcache-top观察后端MC的使用状况。

测试环境准备

  • 机器配置:
  • 网卡:1000M/s
  • CPU: 2.4GHz   12(逻辑)核心
  • IP : 10.13.2.143
  • 内存:48G

部署方式:

在10.13.2.143上同时部署MC和WCCS,MC端口为11211,11212,各分配1G的最大使用内

存,WCCS端口为2888,WCCS上仅配置一个默认池

下面是我的测试步骤

1. keymap机制是如何工作的

给WCCS配置两个pool, DefaultPool和UserPool,其中DefaultPool

pool:       
(
    {
        name = "DefaultPool"; 
        backend: 
        (
             { ip = "10.2.13.143"; port = 21111; weight = 1 }, //仅一个实例,端口21111
        );
        //...
    },
      {
        name = "UserPool"; 
        backend: 
        (
             { ip = "10.2.13.143"; port = 21112; weight = 1 }, //仅一个实例,端口21112
        );
        //...
    },
);
keymap: (
    {
        prefix = "*";
        pool = "DefaultPool";
        distribution = "ketama";
        hash = "md5";
        hash_tag = "{}";
    },
    {
        prefix = "user";
        pool = "UserPool";
        distribution = "ketama";
        need_sync = true;
        hash = "md5";
        hash_tag = "{}";
    }
);

尝试写入user前缀和非user前缀的key,并查看key被写入到了哪个Pool中

小结:通过上面的截图可以看到,WCCS按照预期完成了key的分发。配置keymap时,必须包含一个prefix="*"的默认规则。这里需要注意的是,key前缀的匹配是贪婪的,即如果一个key可以匹配keymap中的多个前缀,key最终会被发送到前缀匹配最长的pool中。利用WCCS的keymap机制让key在集群分发机制也对业务变的透明了,是不是很cool?

2. 自动处理故障端口功能测试

首先修改配置

backend_failure_limit = 5; //连续失败五次后触发自动剔除

backend_retry_timeout =30000; //30秒

a) set key1 为frank,发现key1落在端口11212上,get key1,成功;直接连接11211端口,并执行 将key1设置为hello

b) kill掉11212端口

c) get key1 提示SERVER_ERROR unknown, 连续5次get,仍然提示错误,等待30s后, get key1返回hello, 说明key1已经读取到了11211端口上的数据,auto_reject已经完成

d) 启动11211端口,等待30s

e) 在WCCS端口上执行get key1得到结果为空,说明已经自动重连到已经恢复服务的11212端口.

小结:auto_reject开启后,自动剔除功能工作正常,在连续访问失败backend_failure_limit次后,经过 backend_retry_timeout 秒,WCCS会自动重连。重启MC后,无需重启WCCS。

3. 性能测试

写入数据1k-2k之间的数据

mcperf -s 10.13.2.143 -p 2888 --linger=0 --timeout=2--conn-rate=6000 --call-rate=1000 --num-calls=20  --num-conns=6000 --method=set--sizes=u1024,2048

参考线上MC压力峰值,并发数选择6000

mcperf -s 10.13.2.143 -p 11211 --linger=0 --timeout=0.2--conn-rate=6000 --call-rate=1000 --num-calls=15  --num-conns=6000 --method=get

原生MC


WCCS


小结:从上面可以看出WCCS的可以充分发挥后端的MC性能,在数据的平均大小为1.5k时,get的峰值可以达到71000/s。

值得注意的是,MC中value的大小直接影响了MC的性能,我将数据的平均大小调整到了0.65k, 又进行了一次测试:

重启MC, 注入1byte-1.3k之间的数据:

mcperf -s 10.13.2.143 -p2888 --linger=0 --timeout=2 --conn-rate=1000 --call-rate=100--num-calls=2000  --num-conns=1000--method=set --sizes=u1, 1331

MC的资源占用情况:

测试WCCS性能:

mcperf -s 10.13.2.143 -p 2888 --linger=0 --timeout=0.2--conn-rate=6000 --call-rate=1000 --num-calls=29  --num-conns=6000 --method=get

从上面的数据可以看出,当平均数据大小在0.65k左右时,WCCS的get操作的TPS可以达到16w/s,这个结果已经非常理想了。

小结:测试环境下,并发6000/s,平均数据大小1.5k(1k-2k之间)时,get可以达到的TPS为7w/s,当平均数据大小为0.65k时(0-1.3k之间)时,get可以达到的TPS为16w/s。这说明WCCS的性能是足够高的。另外通过综合测试,还发现WCCS挂载两个MC端口时,综合性能无法达到2台MC的处理性能, 跟单个MC端口性能相近。

4.  调整配置文件中的参数值,比较不同的配置对性能的影响

调整workers_num, backend_connections的值,并测试性能变化。具体过程略。

调整workers_num和backend_connections的值后发现影响WCCS的性能的主要因素是WCCS于后端MC维持的长连接数量,这个数值等于

workers_num*backend_connections*pool中MC端口数

线上配置时需要注意总连接数不要超过MC设置的最大值。测试后发现当这个值维持在300左右时,就可以足以达到上面16w/s的TPS了。

backend_failure_limit是所有的worker共享的,考虑到push情况下MC失败也会比较多,启用auto_reject时,为了防止误判,可以将这个值设置的稍微大一些(如500)。

5.同步功能测试

启动两个WCCS端口2888和2889,并将2888 need_sync设置为true,    2888端口上的相关配置如下:

sync: {    //WCCS同步相关配置

dir = “/var/wccsdata”,  //开启跨机房同步时,用于记录MC的更新操作日志

backend :    //需要同步的WCCS端口

(

{ip = “127.0.0.1”; port = 2888}

{ip = “127.0.0.1”; port = 2889}

)

}

keymap:

(

{

prefix = "*"; //路由前缀, WCCS支持将指定前缀的key分发到指定的pool中

pool = "PoolDefault";

distribution = "ketama"; //分布策略采用一致性Hash

hash = "md5";  //使用md5作为hash策略

hash_tag = "{}";

need_sync = true; //开启同步

},

);

在2888端口上写入数据,并尝试从2889端口上读取。通过终端操作时,发现数据可以被正确同步。

提示:MC数据同步功能开启后,数据可以立即被同步,但是使用PHP客户端测试时发现,同步到2889端口上的数据丢失flag了字段,使用PHP MC客户端写入一个数组后,读取出的类型为字符串,没有对象进行自动解析,这一点使用的时候需要注意。

6. 其他注意问题:

a. WCSS会维持比较多的连接,需要通过ulimit放宽系统支持的文件描述符的数量

b. /O是影响WCCS性能的主要因素,需要通过Irqbalance打开中断优化,防止所有的I/O都阻塞在同一个CPU上。

c. WCCS在实例之间自动同步数据的功能实现方式为,首先记录接受到的MC数据更新命令到发送到本地的日志文件中,WCCS使用单独的进程对日志进行扫描,并发将幂等命令直接发送到需要被同步的机房中,非幂等的add、incr、decr、cas操作都会被转换为delete操作。

7. WCCS一些可以改进的方面

目前WCCS没有提供使用情况监控功能,使用中间件后,将无法通过监控后端MC的连接数评估连接的情况,只能通过netstat查看socket的连接数。

WCCS没有提供通过一个key获取key所在的机器的功能,不过如果知道MC的 IP列表,可以自行遍历个个实例获得。

MC中间件WCCS的更多相关文章

  1. django的中间件

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA2EAAAGUCAIAAAAzrr3rAAAgAElEQVR4nOy9d5wcx3kmzAXl80m6zy

  2. 分布式数据库中间件–(3) Cobar对简单select命令的处理过程

    友情提示:非原文链接可能会影响您的阅读体验,欢迎查看原文.(http://blog.geekcome.com) 原文地址:http://blog.geekcome.com/archives/284 在 ...

  3. Python 之Memcache中间件

    一.引子 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载,它通过在内存中缓存数据和减少读取数据库的次数,从而提高动态数据库驱动网站的速度.Memcache ...

  4. [置顶] flume高并发优化——(15)中间件版本升级

    在系统平稳运行一年的基础上,为提供更好的服务,现针对java,kafka,flume,zk,统一进行版本升级,请各位小伙伴跟着走起来,不要掉队啊! 名称 老版本号 新版本号 jdk 1.7.0_25 ...

  5. ASP.NET Core如何使用压缩中间件提高Web应用程序性能

    前言 压缩可以大大的降低我们Web服务器的响应速度,压缩从而提高我们网页的加载速度,以及节省一定的带宽. 何时使用相应压缩中间件 在IIS,Apache,Nginx中使用基于服务端的响应压缩技术.中间 ...

  6. 亿级用户下的新浪微博平台架构 前端机(提供 API 接口服务),队列机(处理上行业务逻辑,主要是数据写入),存储(mc、mysql、mcq、redis 、HBase等)

    https://mp.weixin.qq.com/s/f319mm6QsetwxntvSXpKxg 亿级用户下的新浪微博平台架构 炼数成金前沿推荐 2014-12-04 序言 新浪微博在2014年3月 ...

  7. ASP.NET Core 中的那些认证中间件及一些重要知识点

    前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...

  8. ASP.NET Core应用的错误处理[3]:ExceptionHandlerMiddleware中间件如何呈现“定制化错误页面”

    DeveloperExceptionPageMiddleware中间件利用呈现出来的错误页面实现抛出异常和当前请求的详细信息以辅助开发人员更好地进行纠错诊断工作,而ExceptionHandlerMi ...

  9. ASP.NET Core应用的错误处理[2]:DeveloperExceptionPageMiddleware中间件如何呈现“开发者异常页面”

    在<ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式>中,我们通过几个简单的实例演示了如何呈现一个错误页面,这些错误页面的呈现分别由三个对应的中间件来完成,接下来我们将 ...

随机推荐

  1. AlphaDict 软件公布

    今天 Release 了 1.1. 主要是移植到了 window 平台, 无须安装,直接执行. 对 UI 又一次进行了设计,应该比之前好看多了. 加入了 生词本 功能,方便 学习外语. ------- ...

  2. [置顶] 基于视频采集卡驱动的错误修改CX26828

    基于视频采集卡驱动的错误修改CX26828 1. 设置root密码 command:sudo passwd root 2.查看系统状态 输入命令:lsmod root@ubuntu:/home/yu# ...

  3. 晨曦之光 linux Crontab 使用(转)

    cron用法说明 cron的用法老是记不住,索性写下来备忘.下文内容大部分是根据<Cron Help Guide>翻译而来,有些部分是自己加上的. 全文如下: cron来源于希腊单词chr ...

  4. JSP-标准动作标记

    JSP标准动作标记 在客户请求JSP页面时,JSP动作利用XML语法格式的标记来控制Servlet引擎的行为.利用JSP动作可以动态地插入文件.重用JavaBean组件.把用户重定向到另外的页面.为J ...

  5. 四种数据持久化方式(下) :SQLite3 和 Core Data

    在上文,我们介绍了iOS开发中的其中2种数据持久化方式:属性列表.归档解档. 本节将继续介绍另外2种iOS持久化数据的方法:数据库 SQLite3.Core Data 的运用: 在本节,将通过对4个文 ...

  6. 模拟dispatch_once

    dispatch_once   dispatch_once可以保证一段代码只被执行一次,因此出现之后使用最多的场景就是实现单例.本文来模拟实现dispatch_once的功能. 模拟dispatch_ ...

  7. JavaScript函数的四种存在形态

    函数的四种存在形态: 1.函数形态 2.方法形态 将函数赋值给某一个对象的成员,那么就称为方法 3.构造器形态 4.上下文形态   1.函数形态: var foo = function() { ale ...

  8. centos 6 搭建ftp服务器支持匿名读写

    转载请注明: 凌云物网智科嵌入式实验室: http://iot-yun.com/     郭文学<guowenxue@gmail.com> vsftpd在运行时一定要关闭SELinux,否 ...

  9. Java NIO 学习笔记

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/SJQ. http://www.cnblogs.com/shijiaqi1066/p/3344148.html ...

  10. (转)修改ECSHOP前后台的title中的ecshop

    前台部分: 1:去掉头部TITLE部分的ECSHOP演示站 Powered by ecshop 前者在后台商店设置 - 商店标题修改 后者打开includes/lib_main.php $page_t ...