zoukankan      html  css  js  c++  java
  • bloom 单实例多接口proxy+api 控制cache 测试

    bloom 是支持多proxy 配置的(基于shared)但是对于多proxy 的处理有一个bug (处理map 一直获取的是第一个)参考https://github.com/valeriansaliou/bloom/issues/16,以前有写过简单的介绍
    以下是一个多api 接口cache 的测试以及对于api cache 控制的试用

    环境准备

     
    fn map_shards() -> [Option<Uri>; MAX_SHARDS as usize] {
        // Notice: this array cannot be initialized using the short format, as hyper::Uri doesnt 
        //   implement the Copy trait, hence the ugly hardcoded initialization vector w/ Nones.
        let mut shards = [
            None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
            None,
        ];
        for shard in &APP_CONF.proxy.shard {
            // Shard number overflows?
            if shard.shard >= MAX_SHARDS {
                panic!("shard number overflows maximum of {} shards", MAX_SHARDS);
            }
            // Store this shard
            shards[shard.shard as usize] = Some(
                format!(
                    "http://{}:{}",
                   // 此处有bug
                    APP_CONF.proxy.shard[0].host, APP_CONF.proxy.shard[0].port
                )
                .parse()
                .expect("could not build shard uri"),
            );
        }
        shards
    }

    为:

    fn map_shards() -> [Option<Uri>; MAX_SHARDS as usize] {
        // Notice: this array cannot be initialized using the short format, as hyper::Uri doesnt 
        //   implement the Copy trait, hence the ugly hardcoded initialization vector w/ Nones.
        let mut shards = [
            None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
            None,
        ];
        for shard in &APP_CONF.proxy.shard {
            // Shard number overflows?
            if shard.shard >= MAX_SHARDS {
                panic!("shard number overflows maximum of {} shards", MAX_SHARDS);
            }
            // Store this shard
            shards[shard.shard as usize] = Some(
                format!(
                    "http://{}:{}",
                    shard.host, shard.port
                )
                .parse()
                .expect("could not build shard uri"),
            );
        }
        shards
    }
     

    相关修复的docker 镜像 dalongrong/bloom:v1.28.1

    • docker-compose 文件
    version: "3"
    services: 
      lb: 
        image: openresty/openresty:alpine
        volumes:
        - "./nginx-lb.conf:/usr/local/openresty/nginx/conf/nginx.conf"
        - "./access_test.log:/usr/local/openresty/nginx/logs/access_test.log"
        - "./access_test2.log:/usr/local/openresty/nginx/logs/access_test2.log"
        ports:
        - "80:80"
        - "8080:8080"
        - "8081:8081"
      bloom: 
        image: dalongrong/bloom:v1.28.1
        volumes: 
        - "./bloom.cfg:/etc/bloom.cfg"
        ports: 
        - "8811:8811"
        - "9001:8080"
      redis:
        image: redis
        ports:
        - "6379:6379"
    • bloom 配置
    [server]
    log_level = "debug"
    inet = "0.0.0.0:8080"
    [control]
    inet = "0.0.0.0:8811"
    tcp_timeout = 900
    [proxy]
    [[proxy.shard]]
    shard = 1
    host = "lb"
    port = 8080
    [[proxy.shard]]
    shard = 2
    host = "lb"
    port = 8081
    [cache]
    ttl_default = 3600
    executor_pool = 64
    disable_read = false
    disable_write = false
    compress_body = false
    [redis]
    host = "redis"
    port = 6379
    database = 0
    pool_size = 80
    max_lifetime_seconds = 60
    idle_timeout_seconds = 600
    connection_timeout_seconds = 1
    max_key_size = 256000
    max_key_expiration = 2592000
    • openresty 配置以及基于openresty 的api
      为了方便测试同时基于openresty 的content_by_lua 以及header_filter_by_lua 处理api 以及添加api 控制需要的
      Bloom-Response-Buckets http header
     
    worker_processes  1;
    user root;  
    events {
        worker_connections  1024;
    }
    http {
        include       mime.types;
        default_type  application/octet-stream;
        lua_need_request_body on;
        #gzip  on; // should not use gzip 
        resolver 127.0.0.11 ipv6=off;     
        log_format graylog2_json escape=json '{ "timestamp": "$time_iso8601", '
                         '"remote_addr": "$remote_addr", '
                         '"body_bytes_sent": $body_bytes_sent, '
                         '"request_time": $request_time, '
                         '"response_status": $status, '
                         '"request": "$request", '
                         '"request_method": "$request_method", '
                         '"host": "$host",'
                         '"request_body":"$request_body",'
                         '"upstream_cache_status": "$upstream_cache_status",'
                         '"upstream_addr": "$upstream_addr",'
                         '"http_x_forwarded_for": "$http_x_forwarded_for",'
                         '"http_referrer": "$http_referer", '
                         '"http_user_agent": "$http_user_agent" }';
        log_format graylog2_json2 escape=json '{ "timestamp": "$time_iso8601", '
                         '"remote_addr": "$remote_addr", '
                         '"body_bytes_sent": $body_bytes_sent, '
                         '"request_time": $request_time, '
                         '"response_status": $status, '
                         '"request": "$request", '
                         '"request_method": "$request_method", '
                         '"host": "$host",'
                         '"request_body":"$request_body",'
                         '"upstream_cache_status": "$upstream_cache_status",'
                         '"upstream_addr": "$upstream_addr",'
                         '"http_x_forwarded_for": "$http_x_forwarded_for",'
                         '"http_referrer": "$http_referer", '
                         '"http_user_agent": "$http_user_agent" }';     
        real_ip_header     X-Forwarded-For;
        real_ip_recursive on;
        server {
            listen       80;
            charset utf-8;
            default_type text/html;
            location /userdemo {
                proxy_pass http://bloom:8080;
                proxy_set_header Bloom-Request-Shard 1;
                proxy_set_header Host $host;
                proxy_read_timeout 10000;
                proxy_send_timeout 10000;
                proxy_buffer_size 1M; 
                proxy_buffers 8 1M; 
                proxy_busy_buffers_size 1M; 
                proxy_temp_file_write_size 1M;
                proxy_set_header  X-Real-IP $remote_addr;
                proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header  X-Forwarded-Host $host;
            }
            location ^~ /appdemo {
                proxy_pass http://bloom:8080;
                proxy_set_header Bloom-Request-Shard 2;
                proxy_set_header Host $host;
                proxy_read_timeout 10000;
                proxy_send_timeout 10000;
                proxy_buffer_size 1M; 
                proxy_buffers 8 1M; 
                proxy_busy_buffers_size 1M; 
                proxy_temp_file_write_size 1M;
                proxy_set_header  X-Real-IP $remote_addr;
                proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header  X-Forwarded-Host $host;
            }
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
        }
        server {
            listen       8080;
            charset utf-8;
            default_type text/html;
            location /userdemo {
               access_log  /usr/local/openresty/nginx/logs/access_test.log  graylog2_json;
               content_by_lua_block {
                   ngx.say("this is a demo")
               }
               header_filter_by_lua_block {
                  ngx.header["Bloom-Response-Buckets"] = "user_id:10012"
               } 
            }
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
        }
        server {
            listen       8081;
            charset utf-8;
            default_type text/html;
            location /appdemo {
               access_log  /usr/local/openresty/nginx/logs/access_test2.log  graylog2_json2;
               content_by_lua_block {
                   ngx.say("appdemo")
               }
               header_filter_by_lua_block {
                  ngx.header["Bloom-Response-Buckets"] = "login:10012"
               } 
            }
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
        }
    } 
    • api 接口控制
      基于nodejs
      package.json
     
    {
      "name": "api",
      "version": "1.0.0",
      "main": "index.js",
      "license": "MIT",
      "dependencies": {
        "bloom-control": "^1.2.1"
      },
      "scripts":{
        "start":"node app.js"
      }
    }

    app.js

    var BloomControl = require("bloom-control").BloomControl;
    var bloomControl = new BloomControl({
      host  : "127.0.0.1",  // Or '127.0.0.1' if you are still using IPv4
      port  : 8811,   // Default port is '8811'
      shard : 1       // Specify the Bloom shard to use, as 
                      //   a Bloom instance can host multiple cache shards, eg. for different API workers
    }).connect({
      connected : function() {
        // Connected handler
        console.info("Bloom Control succeeded to connect to host.");
      },
      disconnected : function() {
        // Disconnected handler
        console.error("Bloom Control is now disconnected.");
      },
      timeout : function() {
        // Timeout handler
        console.error("Bloom Control connection timed out.");
      },
      retrying : function() {
        // Retry handler
        console.error("Trying to reconnect to Bloom Control...");
      },
      error : function(error) {
        // Failure handler
        console.error("Bloom Control failed to connect to host.", error);
      }
    });
    bloomControl.purgeBucket(`user_id:10012`, function(error) {
        // Handle purge errors here
        if (error) {
            console.log("some wrong")
        }
        else{
          console.log("ok")
        }
    });

    测试

    • 启动服务
    docker-compose up -d
    • cache 测试


    清理cache

     
    cd api && yarn && yarn start

    效果

    说明

    基于bloom高效,方便的cache 能力,我们可以方便的开发基于cache 的应用,提高应用的稳定性以及可控制性,以上是一个试用
    大家可以自己扩展下,实现更加灵活的cache应用

    参考代码

    https://github.com/valeriansaliou/bloom
    https://github.com/rongfengliang/bloom-api-test

  • 相关阅读:
    1. Java 基础概念
    IDEA 插件
    IDEA 初始化配置
    二叉查找树
    阿里云安装Redis教程与相关问题
    H2知识小结
    重装VisualSVN Server报错
    linux(centos6.10)下去掉mysql的强密码验证
    TP-LINK路由器端口映射全套教程(亲测有效)
    idea2018.3.6,离线使用maven的方法
  • 原文地址:https://www.cnblogs.com/rongfengliang/p/13181139.html
Copyright © 2011-2022 走看看