2011/06/17

HTTP server over libevent - sample code (1)

使用libevent HTTP API寫一個簡易的server。

#include 
#include 
#include 

#define SVR_IP                         "127.0.0.1"
#define SVR_PORT                       8080

void specific_cb (struct evhttp_request *req, void *arg) {
    struct evbuffer *evbuf;
    
    if ((evbuf = evbuffer_new()) == NULL) {
        printf("evbuffer_new() failed");
        evhttp_send_reply(req, HTTP_INTERNAL, "Internal error", NULL);
        return;
    }

    /* Body */
    evbuffer_add_printf(evbuf, "It's work!");
    
    /* Response */
    evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
    
    /* Free resource */
    evbuffer_free(evbuf);
}

void generic_cb (struct evhttp_request *req, void *arg) {

    /* Response */
    evhttp_send_reply(req, HTTP_NOTFOUND, "Not found", NULL);
}

int main (int argc, char **argv) {
    struct event_base *evbase;
    struct evhttp     *evhttp;

    /* Init event base */
    if ((evbase = event_base_new()) == NULL) {
        printf("event_base_new() failed\n");
        return -1;
    }

    /* Init evhttp */
    if ((evhttp = evhttp_new(evbase)) == NULL) {
        printf("evhttp_new() failed\n");
        return -1;
    }

    /* Set server IP, port */
    if (evhttp_bind_socket(evhttp, SVR_IP, SVR_PORT) == -1) {
        printf("evhttp_bind_socket() failed\n");
        return -1;
    } else {
        printf("Listening on [%s:%d]\n", SVR_IP, SVR_PORT);
    }
    
    /* Set a callback for specific path */
    if (evhttp_set_cb(evhttp, "/test", specific_cb, NULL) < 0) {
        printf("evhttp_set_cb() failed\n");
        return -1;
    }
    
    /* Set a callback for default path */
    evhttp_set_gencb(evhttp, generic_cb, NULL);

    /* Enter event loop */
    event_base_dispatch(evbase);

    /* Free resource */
    evhttp_free(evhttp);
    event_base_free(evbase);
    
    return 0;
}
Compile and run
$ gcc -g -Wall -o httpd httpd.c -levent -I/opt/libevent-2.0.12-stable/include/ -L/opt/libevent-2.0.12-stable/lib/
$ LD_LIBRARY_PATH=/opt/libevent-2.0.12-stable/lib ./httpd
Listening on [127.0.0.1:8080]
try to send a request to server...
$ wget -q -O - http://127.0.0.1:8080/test
$ wget -S -O - http://127.0.0.1:8080/xxx
不知道為什麼我用2.0.10-stable版本跑會有下列warning,用2.0.12-stable就沒問題了。
[warn] evhttp_connection_base_new: bufferevent_new failed: No such file or directory
[warn] evhttp_get_request: cannot get connection on 9: No such file or directory



實際測試
測試工具: Apache benchmark
# ab -n 100000 -c 1000 http://127.0.0.1:8080/test
Platform Amazon EC2 large instance: 7541.13 [Req/Sec]
Server Software:
Server Hostname:        127.0.0.1
Server Port:            8080

Document Path:          /test
Document Length:        10 bytes

Concurrency Level:      1000
Time taken for tests:   13.260620 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Total transferred:      7408510 bytes
HTML transferred:       1001150 bytes
Requests per second:    7541.13 [#/sec] (mean)
Time per request:       132.606 [ms] (mean)
Time per request:       0.133 [ms] (mean, across all concurrent requests)
Transfer rate:          545.53 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   90 496.5      3    3113
Processing:     3   31  28.5     21     290
Waiting:        0   15  19.9      9     273
Total:          7  122 501.7     26    3255

Percentage of the requests served within a certain time (ms)
  50%     26
  66%     35
  75%     47
  80%     62
  90%     97
  95%    133
  98%   3040
  99%   3075
 100%   3255 (longest request)

Platform Amazon EC2 Extra Large Instance: 8464.56 [Req/Sec]
Server Software:
Server Hostname:        127.0.0.1
Server Port:            8080

Document Path:          /test
Document Length:        10 bytes

Concurrency Level:      1000
Time taken for tests:   11.813961 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Total transferred:      7400740 bytes
HTML transferred:       1000100 bytes
Requests per second:    8464.56 [#/sec] (mean)
Time per request:       118.140 [ms] (mean)
Time per request:       0.118 [ms] (mean, across all concurrent requests)
Transfer rate:          611.73 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   62 391.2      7    3068
Processing:     8   54  37.4     39     317
Waiting:        1   25  25.0     18     286
Total:          8  116 393.5     50    3322

Percentage of the requests served within a certain time (ms)
  50%     50
  66%     68
  75%     91
  80%    106
  90%    130
  95%    158
  98%    233
  99%   3046
 100%   3322 (longest request)

其實在Amazon server上 CPU 和 Network 都是很不穩定的,畢竟是虛擬機器,所以測試結果正負1000 request都是有可能的。


沒有留言:

張貼留言