• Feeds

  • Thrift, Protocol Buffers installation and Java code howto

    I. Thrift installation and Java code

    1. build and install thrift

    install boost
    cd <boost_root>/tools/jam
    ./build_dist.sh
    # linux* will depends the platform
    cp stage/bin.linux*/bjam <boost_root>
    # build boost, use bjam will faster
    cd <boost_root>
    ./configure –without-icu –prefix=/usr/local/boost
    ./bjam -toolset=gcc –build-type=release install –prefix=/usr/local/boost

    # build thrift
    ./bootstrap.sh
    ./configure –with-boost=/usr/local
    make
    make install

    2. Build Thrift java library

    install apache ant if necessary

    cd lib/java/
    ant

    get libthrift.jar

    3. Create .thrift file and gen Java code

    (See http://wiki.apache.org/thrift/Tutorial for more .thrift tutorial info)
    tim.thrift

    struct dns_record {
    1: string key,
    2: string value,
    3: string type = 'A',
    4: i32 ttl = 86400,
    5: string first,
    6: string last
    }
    
    service TestDns {
    dns_record test(1:string q);
    }

    <thrift_root>/bin/thrift –gen java tim.thrift
    code will be generated in gen-java/*.java

    4. Write java code

    // new object
    dns_record dr = new dns_record(key, value, type, ttl, first, last)
    // serialize
    TSerializer serializer = new TSerializer(new TBinaryProtocol.Factory());
    TDeserializer deserializer = new TDeserializer(new TBinaryProtocol.Factory());
    byte[] bytes = serializer.serialize(dr);

    see also: http://wiki.apache.org/thrift/ThriftUsageJava

    II. Protocol Buffers install and Java code

    1. Build and install Protocol buffers

    ./configure
    make
    make install

    2. Build protobuf Java library

    install maven if not necessary

    cd protobuf/java
    mvn test
    mvn package

    get jar from target/protobuf-java-x.x.x.jar

    3. Create .proto file and gen Java code

    tim.proto

    package dns;
    
    message DnsRecord {
    required string key = 1;
    required string value = 2;
    required string first = 3;
    required string last = 4;
    optional string type = 5 [default = "A"];
    optional int32  ttl = 6 [default = 86400];
    }
    
    message DnsResponse {
    repeated DnsRecord records = 1;
    }

    bin/protoc –java_out . tim.proto

    4. Write Java code

    // protocol buffer need a builder to create object
    Dns.DnsRecord.Builder b = Dns.DnsRecord.newBuilder();
    b.setKey("key");
    b.setValue("value...");
    ...
    b.builder();
    
    byte[] bytes = dr.toByteArray();
    Dns.DnsRecord dr2 = Dns.DnsRecord.parseFrom(bytes);

    III. Resources

    Thrift: http://incubator.apache.org/thrift/

    Protocol Buffers: http://code.google.com/apis/protocolbuffers/

    Tim’s Blog: https://timyang.net/

    BlackBerry黑莓8700优缺点

    用了BlackBerry 8700一两周了,感觉如下。

    1. 自带的浏览器很不错, 感觉比Opera mini好用,支持qwerty全键盘快捷键
    2. 输入速度很快,键盘设计很合理 尤其是英文, 可以很方便记录很多临时想法, 比如这篇文章刚才在地铁上就完成了
    3. 可以和电脑同步address, calender, task.
    4. 支持多任务及copy/paste
    5. 常用BlackBerry软件8700都支持
    6. 可以给手机设置密码, 手机丢了也无需担心数据安全
    7. 可以给PC做modem通过移动gprs/edge上网
    8. 价格便宜, 大白菜价,可能是公司最便宜的手机了, 目前价格400-600元。

    缺点
    1. 上网经常碰到请求超时(4.2ROM),刷机4.5后解决,但是4.5没有自带拼音输入法,第三方的输入法兼容性稍差。
    2. 待机时间不够长,每天上网1-2小时待机2-3天
    3. 外形稍宽,一只手操作比如切换到滚轮和回车键有点费力,长相一般,不过自己觉得还行。
    4. 没有相机和扩展存储卡

    另外8700引以为豪的是越狱中的专用手机

    blackberry 8700

    如何写nginx module

    对于一些访问量特别大,业务逻辑也相对简单的Web调用来说,通过一个nginx module来实现是一种比较好的优化方法。实现一个nginx module实际上比较简单。

    1. nginx 配置添加

    ./configure --add-module=/path/to/module1/source

    2. 添加 /path/to/module1/source/config 文件,内容

    ngx_addon_name=ngx_http_hello_module
    HTTP_MODULES="$HTTP_MODULES ngx_http_hello_module"
    NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_hello_module.c"
    CORE_LIBS="$CORE_LIBS -lfoo"

    最后一行如果没有使用其他library, 可以去掉

    3. 源代码 /path/to/module1/source/ngx_http_hello_module.c, 主要的业务逻辑在make_http_get_body 中完善。典型的hello world源代码如下

    #include <ngx_config.h>
    #include <ngx_core.h>
    #include <ngx_http.h>
    
    #define OUT_BUFSIZE 256
    
    static char *ngx_http_hello_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    static char *ngx_http_foo_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    
    static ngx_int_t ngx_http_hello_process_init(ngx_cycle_t *cycle);
    static void ngx_http_hello_process_exit(ngx_cycle_t *cycle);
    
    static ngx_int_t make_http_header(ngx_http_request_t *r);
    static ngx_int_t make_http_get_body(ngx_http_request_t *r, char *out_buf);
    
    static char g_foo_settings[64] = {0};
    
    /* Commands */
    static ngx_command_t  ngx_http_hello_commands[] = {
        { ngx_string("ngx_hello_module"),
          NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
          ngx_http_hello_set,
          NGX_HTTP_LOC_CONF_OFFSET,
          0,
          NULL },
    
        { ngx_string("hello"),
          NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
          ngx_http_foo_set,
          NGX_HTTP_LOC_CONF_OFFSET,
          0,
          NULL },  
    
          ngx_null_command
    };
    
    static ngx_http_module_t  ngx_http_hello_module_ctx = {
        NULL,                                  /* preconfiguration */
        NULL,                                     /* postconfiguration */
    
        NULL,                                  /* create main configuration */
        NULL,                                  /* init main configuration */
    
        NULL,                                  /* create server configuration */
        NULL,                                  /* merge server configuration */
    
        NULL,                                  /* create location configuration */
        NULL                                   /* merge location configuration */
    };
    
    /* hook */
    ngx_module_t  ngx_http_hello_module = {
        NGX_MODULE_V1,
        &ngx_http_hello_module_ctx,              /* module context */
        ngx_http_hello_commands,                 /* module directives */
        NGX_HTTP_MODULE,                       /* module type */
        NULL,                                  /* init master */
        NULL,                                  /* init module */
        ngx_http_hello_process_init,             /* init process */
        NULL,                                  /* init thread */
        NULL,                                  /* exit thread */
        ngx_http_hello_process_exit,             /* exit process */
        NULL,                                  /* exit master */
        NGX_MODULE_V1_PADDING
    };
    
    /* setting header for no-cache */
    static ngx_int_t make_http_header(ngx_http_request_t *r){
        ngx_uint_t        i;
        ngx_table_elt_t  *cc, **ccp;
    
        r->headers_out.content_type.len = sizeof("text/html") - 1;
        r->headers_out.content_type.data = (u_char *) "text/html";
        ccp = r->headers_out.cache_control.elts;
        if (ccp == NULL) {
    
            if (ngx_array_init(&r->headers_out.cache_control, r->pool,
                               1, sizeof(ngx_table_elt_t *))
                != NGX_OK)
            {
                return NGX_ERROR;
            }
    
            ccp = ngx_array_push(&r->headers_out.cache_control);
            if (ccp == NULL) {
                return NGX_ERROR;
            }
    
            cc = ngx_list_push(&r->headers_out.headers);
            if (cc == NULL) {
                return NGX_ERROR;
            }
    
            cc->hash = 1;
            cc->key.len = sizeof("Cache-Control") - 1;
            cc->key.data = (u_char *) "Cache-Control";
    
            *ccp = cc;
    
        } else {
            for (i = 1; i < r->headers_out.cache_control.nelts; i++) {
                ccp[i]->hash = 0;
            }
    
            cc = ccp[0];
        }
    
        cc->value.len = sizeof("no-cache") - 1;
        cc->value.data = (u_char *) "no-cache";
    
        return NGX_OK;
    }
    
    static ngx_int_t make_http_get_body(ngx_http_request_t *r, char *out_buf){
        char *qs_start = (char *)r->args_start;
        char *qs_end = (char *)r->uri_end;
        char uri[128] = {0};
        char *id;
    
        if (qs_start == NULL || qs_end == NULL){
            return NGX_HTTP_BAD_REQUEST;
        }
        if ((memcmp(qs_start, "id=", 3) == 0)){
            id = qs_start + 3;
            *qs_end = '\0';
        }else{
            return NGX_HTTP_BAD_REQUEST;
        }
        snprintf(uri, r->uri.len + 1, "%s", r->uri.data);
        sprintf(out_buf, "Author: https://timyang.net/\nconfig=%s\nid=%snuri=%s\nret=%lx\n", g_foo_settings, id, uri, ngx_random());
        return NGX_OK;
    }
    
    static ngx_int_t
    ngx_http_hello_handler(ngx_http_request_t *r)
    {
        ngx_int_t     rc;
        ngx_buf_t    *b;
        ngx_chain_t   out;
    
        /* Http Output Buffer */
        char out_buf[OUT_BUFSIZE] = {0};
    
        if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
            return NGX_HTTP_NOT_ALLOWED;
        }
    
        rc = ngx_http_discard_request_body(r);
    
        if (rc != NGX_OK && rc != NGX_AGAIN) {
            return rc;
        }
    
        /* make http header */
        rc = make_http_header(r);
        if (rc != NGX_OK) {
            return rc;
        }
    
        if (r->method == NGX_HTTP_HEAD) {
            r->headers_out.status = NGX_HTTP_OK;
            return ngx_http_send_header(r);
        } else if (r->method == NGX_HTTP_GET) {
            /* make http get body buffer */
            rc = make_http_get_body(r, out_buf);
            if (rc != NGX_OK) {
                return rc;
            }
        } else {
            return NGX_HTTP_NOT_ALLOWED;
        }
    
        b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
        if (b == NULL) {
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }
    
        out.buf = b;
        out.next = NULL;
    
        b->pos = (u_char *)out_buf;
        b->last = (u_char *)out_buf + strlen(out_buf);
        b->memory = 1;
        b->last_buf = 1;
        r->headers_out.status = NGX_HTTP_OK;
        r->headers_out.content_length_n = strlen(out_buf);
    
        rc = ngx_http_send_header(r);
    
        if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
            return rc;
        }
    
        return ngx_http_output_filter(r, &out);
    }
    
    static char *
    ngx_http_hello_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    {
        ngx_http_core_loc_conf_t *clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    
        /* register hanlder */
        clcf->handler = ngx_http_hello_handler;
    
        return NGX_CONF_OK;
    }
    
    static char *
    ngx_http_foo_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    {
        ngx_str_t *value = cf->args->elts;
        memcpy(g_foo_settings, value[1].data, value[1].len);
        g_foo_settings[value[1].len] = '�';
    
        return NGX_CONF_OK;
    }
    
    static ngx_int_t
    ngx_http_hello_process_init(ngx_cycle_t *cycle)
    {
        // do some init here
        return NGX_OK;
    }
    
    static void
    ngx_http_hello_process_exit(ngx_cycle_t *cycle)
    {
        return;
    }

    4. 配置文件 nginx.conf

            location /hello {
                ngx_hello_module;
                hello 1234;
            }

    5. 访问 http://localhost/hello?id=1

    也可参考更详细的英文说明:
    Emiller’s Guide To Nginx Module Development