Glider
           中间层
          开发优化实践

@孤独的登山人
Agenda

   Glider架构
   基本策略
   优化历程
   优化总结
   思维&规范
Glider 位置

数
据     主站备库                    RAC               主站日志
源
                    DataX / TimeTunnel

计
算               Hadoop集群                        实时流数据
层

存
储           MyFOX                        Prom
层 查
  询                    数据中间层 / glider
  层

产       数据魔方                   淘宝指数         开放API
品
Glider 架构
基本策略
Http : keep-alive

Node V0.5.3 +

var agent = new http.Agent({
    maxSockets : 100
});

var options = {
  agent : agent
  …
}

http.get(options. Function(res){
 …
});
基本策略
Config : auto-reload


var self = this;
…
fs.watchFile(fpath ,function(curr, prev){
 if(self.load_timer) return;

 if(curr.ctime.toString() != prev.ctime.toString()){
    self.load_timer = setTimeout(function(){
       self.loadCfg(fpath);
     },LOAD_DELAY);
  }
});
基本策略
Socket Pool – Generic Pool

var poolModule = require('generic-pool');

var pool = poolModule.Pool({
 name : 'mysql',
 create : function(callback){
    var Client = require('mysql').Client;
    var c = new Client();
       …
 },
 destroy : function(client){
     client.end();
 },
 max : Cfg.maxSockets,
 idleTimeoutMillis : Cfg.timeout
});
基本策略
Cluster
   Multi-Worker-Listen

    Master.send(listenfd)

    Worker.listen(…)

    Master.close(listenfd);



   Master-Listen (we use this for fully control)

    Master.listen()
    Master.send(sockfd)

    Worker.receive(sockfd)
    CreateReqRes(sockfd)
优化历程
First Time
Siege
Keep-alive
Singel core ‘hello,world’ : 8000qps
(5 cpu core) 4 workers




              260 QPS !!!
               WHY ??
优化历程
Thinking…
优化历程
Thinking…
              Calculate Each-step Overhead
  Http Requset(skip other steps:)




 Unit/Benchmark Test

            var TEST_NUMBER = 100*1000;
            var start = new Date();
            for(var i=0; i< TEST_NUMBER; i++){
              step1();
            }
            var end = new Date();
            console.log(‘time : ’ + (end – start));
优化历程
Step-overhead …

 I. URL -> SQL conversion           : 0.8ms


 II. Main control                   : 0.5ms


 III.Table LeftJoin (2000 X 2000)   : 13ms




 Equation:
 1S / (13 + 0.8 + 0.5)ms * 4 == 280
优化历程
Optimization

 URL -> SQL conversion

 • Pre-parsing / Template

 • keywords replacement

   var obj = {
     …
     id : ‘#id’,
     thedate : ‘#date’
   }



 Result:
  0.8ms  0.05 ms
优化历程
Optimization
 Table LeftJoin (2000 X 2000)

 Language Skills

     避免重复计算
     Array / Object 遍历效率斟酌
     Array.push / array[i] 比较
     引入临时量,避免对象多次查找
     String ‘+’ 与 array.join(‘’) 比较
     使用V8 提供的函数
    …

    https://github.com/windyrobin/iFrame/blob/master/pp.md

 Result:
  13ms  5.6 ms
优化历程
Optimization
 Table LeftJoin (2000 X 2000)

 Change Data Structure

                                             {
 [                                               columns : ["id", "pid", "first"],
     {id : 1, tid : 2, first : ‘hello’},         data :[
     {id : 2, tid : 3, first: ‘tom’},              *1, 2, ‘hello’+,
     {id : 3, tid : 3, first: ‘jim’},              *2, 3, ‘tom’+,
      …                                            *3, 3, ‘jim’+,
 ]                                                 …
                                                 ]
                                             }
 Result:
  Speed : 5.6 ms  2.6 ms                  (For computing)
  Store size  50%                         (For memcache)
  Transfer size  50%                      (For JSON response)
优化历程
Now (no cache)

       Step   Main Control   Inner Join   Content Deliver    QPS
Size
2000 x 2000   0.5ms          1.7ms        1ms(22KB)          1200



500 x 500     0.5ms          0.5ms        0.25ms(5KB)        3100



100 x 100     0.5ms          0.1ms        0.1ms(1KB)         5100




Table 2000 X 2000 : LeftJoin : 2.6ms , InnerJoin : 1.7ms

Content Deliver == JSON  String  Buffer  Socket Write …
优化总结
Thinking…
Thinking…


NodeJS

For Frontend Engineer ?!!!


 Node Platform = JS + System P+ Network P
Stardard

    JS has many pitfalls
    Async mode is tricky
    For fluent team cooperation
    We are designing a server on our own
    The server is a long-time running programe
    We need helps from community
 …




 Stardard is a               MUST             !!!
Stardard


   We need             YOUR contribution!
      减少外部依赖,谨慎选择开源模块
      面向接口编程,不管内部实现如何,接口定义要简洁、清晰、固定
      对于复杂的逻辑运算,不仅要有Unit Test,还要有相应的Benchmark Test
      对于外部的网络请求,一定也要有相应的benchmark test,摸清其 qps,
      response time, CPU 耗费
     对于异步回调函数,一定要检查其是否错误,即第一个回调参数,并做相应处理
     谨慎使用 fs 同步操作函数组---除非你清楚知道其不会造成严重后果
    …


   https://github.com/windyrobin/iFrame/blob/master/style.md
   https://github.com/windyrobin/iFrame/blob/master/pp.md
   https://github.com/windyrobin/iFrame/blob/master/mng.md
?

Glider

  • 1.
    Glider 中间层 开发优化实践 @孤独的登山人
  • 2.
    Agenda  Glider架构  基本策略  优化历程  优化总结  思维&规范
  • 3.
    Glider 位置 数 据 主站备库 RAC 主站日志 源 DataX / TimeTunnel 计 算 Hadoop集群 实时流数据 层 存 储 MyFOX Prom 层 查 询 数据中间层 / glider 层 产 数据魔方 淘宝指数 开放API 品
  • 4.
  • 5.
    基本策略 Http : keep-alive NodeV0.5.3 + var agent = new http.Agent({ maxSockets : 100 }); var options = { agent : agent … } http.get(options. Function(res){ … });
  • 6.
    基本策略 Config : auto-reload varself = this; … fs.watchFile(fpath ,function(curr, prev){ if(self.load_timer) return; if(curr.ctime.toString() != prev.ctime.toString()){ self.load_timer = setTimeout(function(){ self.loadCfg(fpath); },LOAD_DELAY); } });
  • 7.
    基本策略 Socket Pool –Generic Pool var poolModule = require('generic-pool'); var pool = poolModule.Pool({ name : 'mysql', create : function(callback){ var Client = require('mysql').Client; var c = new Client(); … }, destroy : function(client){ client.end(); }, max : Cfg.maxSockets, idleTimeoutMillis : Cfg.timeout });
  • 8.
    基本策略 Cluster  Multi-Worker-Listen Master.send(listenfd) Worker.listen(…) Master.close(listenfd);  Master-Listen (we use this for fully control) Master.listen() Master.send(sockfd) Worker.receive(sockfd) CreateReqRes(sockfd)
  • 9.
    优化历程 First Time Siege Keep-alive Singel core‘hello,world’ : 8000qps (5 cpu core) 4 workers 260 QPS !!! WHY ??
  • 10.
  • 11.
    优化历程 Thinking… Calculate Each-step Overhead  Http Requset(skip other steps:)  Unit/Benchmark Test var TEST_NUMBER = 100*1000; var start = new Date(); for(var i=0; i< TEST_NUMBER; i++){ step1(); } var end = new Date(); console.log(‘time : ’ + (end – start));
  • 12.
    优化历程 Step-overhead … I.URL -> SQL conversion : 0.8ms II. Main control : 0.5ms III.Table LeftJoin (2000 X 2000) : 13ms Equation: 1S / (13 + 0.8 + 0.5)ms * 4 == 280
  • 13.
    优化历程 Optimization URL ->SQL conversion • Pre-parsing / Template • keywords replacement var obj = { … id : ‘#id’, thedate : ‘#date’ } Result: 0.8ms  0.05 ms
  • 14.
    优化历程 Optimization Table LeftJoin(2000 X 2000) Language Skills  避免重复计算  Array / Object 遍历效率斟酌  Array.push / array[i] 比较  引入临时量,避免对象多次查找  String ‘+’ 与 array.join(‘’) 比较  使用V8 提供的函数 … https://github.com/windyrobin/iFrame/blob/master/pp.md Result: 13ms  5.6 ms
  • 15.
    优化历程 Optimization Table LeftJoin(2000 X 2000) Change Data Structure { [ columns : ["id", "pid", "first"], {id : 1, tid : 2, first : ‘hello’}, data :[ {id : 2, tid : 3, first: ‘tom’}, *1, 2, ‘hello’+, {id : 3, tid : 3, first: ‘jim’}, *2, 3, ‘tom’+, … *3, 3, ‘jim’+, ] … ] } Result: Speed : 5.6 ms  2.6 ms (For computing) Store size  50% (For memcache) Transfer size  50% (For JSON response)
  • 16.
    优化历程 Now (no cache) Step Main Control Inner Join Content Deliver QPS Size 2000 x 2000 0.5ms 1.7ms 1ms(22KB) 1200 500 x 500 0.5ms 0.5ms 0.25ms(5KB) 3100 100 x 100 0.5ms 0.1ms 0.1ms(1KB) 5100 Table 2000 X 2000 : LeftJoin : 2.6ms , InnerJoin : 1.7ms Content Deliver == JSON  String  Buffer  Socket Write …
  • 17.
  • 18.
  • 19.
    Thinking… NodeJS For Frontend Engineer?!!! Node Platform = JS + System P+ Network P
  • 20.
    Stardard  JS has many pitfalls  Async mode is tricky  For fluent team cooperation  We are designing a server on our own  The server is a long-time running programe  We need helps from community … Stardard is a MUST !!!
  • 21.
    Stardard We need YOUR contribution!  减少外部依赖,谨慎选择开源模块  面向接口编程,不管内部实现如何,接口定义要简洁、清晰、固定  对于复杂的逻辑运算,不仅要有Unit Test,还要有相应的Benchmark Test  对于外部的网络请求,一定也要有相应的benchmark test,摸清其 qps, response time, CPU 耗费  对于异步回调函数,一定要检查其是否错误,即第一个回调参数,并做相应处理  谨慎使用 fs 同步操作函数组---除非你清楚知道其不会造成严重后果 … https://github.com/windyrobin/iFrame/blob/master/style.md https://github.com/windyrobin/iFrame/blob/master/pp.md https://github.com/windyrobin/iFrame/blob/master/mng.md
  • 22.