Programming/node.js2015. 3. 25. 20:14

restful api 만들려고 하는 데 페이지(URI)별 따로 모듈로 빼서 작업할 때 


routes module.exports 할때 매번 해당 모듈페이지에서 DB커넥션 작업 해야되나 고민하는데...


app.js에서 최초 한번 커넥션풀 유지해서 하는 방법에 대해서 어떻게 하나 예시 찾던 중 해결책 발견


참고사이트 : http://cwbuecheler.com/web/tutorials/2014/restful-web-app-node-express-mongodb/



var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
// Database
var mongo = require('mongoskin');
var db = mongo.db("mongodb://localhost:27017/nodetest2", {native_parser:true});
/ Make our db accessible to our router
app.use(function(req,res,next){
    req.db = db;
    next();
});
app.use('/', routes);
app.use('/users', users);

routes 위에다가 requset 정보에 db 커넥션풀 정보를 포함하게 정의하고 next 실행
그리고 각각의 routes 모듈에 보낼 수 있다
DB 커넥션풀 정보 필요없는 routes는 알아서 제외하면될 듯 



Posted by 시니^^
Programming/node.js2015. 3. 19. 15:18

node.js에서 간략하게 IP기반으로 사용자 (위치) 지역 정보 데이터 분석용으로 GeoIP 라이브러리 있나 찾아봤음


역시 라이브러리 geoip-lite 라고 있음!!


Github : https://github.com/bluesmoon/node-geoip


1. 설치방법

$ npm install geoip-lite


2. 코드작성 및 사용법

$ vi geoip.js
=====================================
var geoip = require('geoip-lite');
var ip = "207.97.227.239";
var geo = geoip.lookup(ip);
console.log(geo);
====================================
$ node geoip.js 
{ range: [ 3479297920, 3479301339 ],
  country: 'US',
  region: 'TX',
  city: 'San Antonio',
  ll: [ 29.4889, -98.3987 ],
  metro: 641 }

※ ll 배열값에서 ll: [<latitude(위도)>, <longitude(경도)>] 순서임!!


3. GeoIP 정보 업데이트방법

※ github보면 geoip.startWatchingDataUpdate(); 함수로도 가능한데 아래 script로 하는게 더 낫은듯함

$ cd /usr/lib/node_modules/geoip-lite
$ npm run-script updatedb

> geoip-lite@1.1.5 updatedb /usr/lib/node_modules/geoip-lite
> node scripts/updatedb.js
Retrieving GeoIPCountryCSV.zip ... DONE
Extracting GeoIPCountryCSV.zip ... DONE
Processing Data (may take a moment) ...
Still working (96813) ... DONE
Retrieving GeoIPv6.csv ... DONE
Processing Data (may take a moment) ... DONE
Retrieving GeoLiteCity-latest.zip ... DONE
Extracting GeoLiteCity-latest.zip ... DONE
Processing Data (may take a moment) ...
Still working (122762) ...
Still working (246870) ...
Still working (368626) ...
Still working (490380) ...
Still working (612413) ...
Still working (734688) ...
Still working (855126) ...
Still working (977268) ...
Still working (1096307) ...
Still working (1217573) ...
Still working (1339167) ...
Still working (1459608) ...
Still working (1580033) ...
Still working (1700173) ...
Still working (1822030) ...
Still working (1943449) ... DONE
Retrieving GeoLiteCityv6.csv ... DONE
Processing Data (may take a moment) ... DONE
Successfully Updated Databases from MaxMind.


※ https://github.com/PaddeK/node-maxmind-db 추가 라이브러리(동일하게 MaxMind DB 기반이긴함) 

Posted by 시니^^

elasticsearch Bulk insert(put) 대량 데이터 입력하기

공식 가이드 API : http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-bulk.html


1) 데이터 파일 생성

$ vi put_data
{ "index":{ "_index" : "logstash-2015.03.06", "_type" : "access_log", "_id" : "1" } }
{ "host":"web01","http_host": "192.168.1.123"}
{ "index":{ "_index" : "logstash-2015.03.06", "_type" : "access_log", "_id" : "2" } }
{ "host":"web01","http_host": "192.168.1.124"}


2) Curl Post 로 전송

$ curl -s -XPOST localhost:9200/_bulk --data-binary @put_data
{"took":317,"errors":false,"items":[{"index":{"_index":"logstash-2015.03.06","_type":"access_log","_id":"1","_version":1,"status":201}},{"index":{"_index":"logstash-2015.03.06","_type":"access_log","_id":"2","_version":1,"status":201}}]}


3) 데이터 확인

$ curl -XGET localhost:9200/logstash-2015.03.06/access_log/1
{"_index":"logstash-2015.03.06","_type":"access_log","_id":"1","_version":1,"found":true,"_source":{ "host":"web01","http_host": "192.168.1.123"}}

$ curl -XGET localhost:9200/logstash-2015.03.06/access_log/2
{"_index":"logstash-2015.03.06","_type":"access_log","_id":"2","_version":1,"found":true,"_source":{ "host":"web01","http_host": "192.168.1.124"}}


4) index와 type이 동일하다면 url쓰고 제외해도됨

$ vi put_data 
{ "index":{ "_id" : "1" } }
{ "host":"web01","http_host": "192.168.1.123"}
{ "index":{ "_id" : "2" } }
{ "host":"web01","http_host": "192.168.1.124"}

$ curl -s -XPOST localhost:9200/logstash-2015.03.06/access_log/_bulk --data-binary @put_data
{"took":321,"errors":false,"items":[{"index":{"_index":"logstash-2015.03.06","_type":"access_log","_id":"1","_version":1,"status":201}},{"index":{"_index":"logstash-2015.03.06","_type":"access_log","_id":"2","_version":1,"status":201}}]}


※ UDP 방식도 있는 듯한데 2.0에서 삭제될 예정이라고함

Bulk UDP has been deprecated and will be removed in Elasticsearch 2.0. You should use the standard bulk API instead.


Curl 참조해서 다른 스크립트 언어에서도 POST 로 방식으로 짜면될듯함

node.js의 경우 라이브러리 활용하면 될 듯 : https://github.com/phillro/node-elasticsearch-client

//Bulk index example
var commands = []
commands.push({ "index" : { "_index" :'my_index_name', "_type" : "my_type_name"} })
commands.push({field1:'value',field2:'value'})


    elasticSearchClient.bulk(commands, {})
            .on('data', function(data) {})
            .on('done', function(done){})
            .on('error', function(error){})
            .exec();


Posted by 시니^^

elasticsearch index templates 만들기

가이드 : http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html


1. GET을 이용한 저장된 전체 인덱스 템플릿가져오기

$ curl -XGET localhost:9200/_template/
{"logstash":{"order":0,"template":"logstash-*","settings":{"index.refresh_interval":"5s"},"mappings":{"_default_":{"dynamic_templates":[{"string_fields":{"mapping":{"index":"analyzed","omit_norms":true,"type":"string","fields":{"raw":{"index":"not_analyzed","ignore_above":256,"type":"string"}}},"match_mapping_type":"string","match":"*"}}],"properties":{"geoip":{"dynamic":true,"path":"full","properties":{"location":{"type":"geo_point"}},"type":"object"},"@version":{"index":"not_analyzed","type":"string"}},"_all":{"enabled":true}}},"aliases":{}},"nginx_log":{"order":0,"template":"nginx_log-*","settings":{"index.refresh_interval":"5s"},"mappings":{"_default_":{"dynamic_templates":[{"string_fields":{"mapping":{"index":"analyzed","omit_norms":true,"type":"string","fields":{"raw":{"index":"not_analyzed","ignore_above":256,"type":"string"}}},"match":"*","match_mapping_type":"string"}}],"properties":{"geoip":{"dynamic":true,"path":"full","properties":{"location":{"type":"geo_point"}},"type":"object"},"@version":{"index":"not_analyzed","type":"string"}},"_all":{"enabled":true}}},"aliases":{}}}

※ 2개 logstash / nginx_log  두개 인덱스 템플릿 등록된게 보인다


2. GET을 이용해서 하나만 지정해서 보기

$ curl -XGET localhost:9200/_template/nginx_log
{"nginx_log":{"order":0,"template":"nginx_log-*","settings":{"index.refresh_interval":"5s"},"mappings":{"_default_":{"dynamic_templates":[{"string_fields":{"mapping":{"index":"analyzed","omit_norms":true,"type":"string","fields":{"raw":{"index":"not_analyzed","ignore_above":256,"type":"string"}}},"match":"*","match_mapping_type":"string"}}],"properties":{"geoip":{"dynamic":true,"path":"full","properties":{"location":{"type":"geo_point"}},"type":"object"},"@version":{"index":"not_analyzed","type":"string"}},"_all":{"enabled":true}}},"aliases":{}}}


3. PUT 신규 템플릿 신규 등록

$ curl -XPUT localhost:9200/_template/nginx_log2 -d ' > { > "order":0, > "template":"nginx_log2-*", > "settings":{ > "index.refresh_interval":"5s" > }, > "mappings":{ > "_default_":{ > "dynamic_templates":[{ > "string_fields":{ > "mapping":{ > "index":"analyzed", > "omit_norms":true, > "type":"string", > "fields":{ > "raw":{ > "index":"not_analyzed", > "ignore_above":256, > "type":"string" > } > } > }, > "match_mapping_type":"string", > "match":"*" > } > } > ], > "properties":{ > "geoip":{ > "dynamic":true, > "path":"full", > "properties":{ > "location":{ > "type":"geo_point" > } > }, > "type":"object" > }, > "@version":{ > "index":"not_analyzed", > "type":"string" > } > }, > "_all":{ > "enabled":true > } > } > }, > "aliases":{ > } > }' {"acknowledged":true}


4. DELETE 템플릿 삭제

$ curl -XDELETE localhost:9200/_template/nginx_log2
{"acknowledged":true}


이것 외에도 GET할때 여러개 템플릿 같이 보기등 가이드사이트 가면 몇가지 예시 더 있음 참고할것!~

Posted by 시니^^

Elasticsearch  node.js를 이용해서 데이터 입력(PUT) 하기


logstash이 잘되어있어서 패턴 잘구성해서 logstash을 이용해도 되지만 logstash패턴 사용하는 법을 좀 봐야되고...

잘 사용법도 모르는 환경에서 계속 서비스 RDBMS에 커넥션 유지하는 것도 부담스러워서 따로 node.js로 짜기로함 


기본적으로 콘솔에서 curl 날리는 예시는 아래와 같음

$ curl -XPUT 'http://localhost:9200/logstash-2015.03.06/access_log/1' -d '{ > "host": "web01", > "http_host": "192.168.1.123", > "clientip": "192.2.3.55", > "timestamp": "Fri Feb 06 2015 14:04:22 GMT+0900 (KST)", > "verb": "GET", > "request": "/css/comm.css", > "httpversion": "1.1", > "response": "304", > "bytes": "0", > "referrer": "http://192.168.1.124/", > "agent": "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17", > "request_time": 0 > }'


등록 결과  아래와 같이 나온걸 볼 수 있다

{"_index":"logstash-2015.03.06","_type":"access_log","_id":"1","_version":1,"created":true}


브라우져에서 head 들어가보면 확인 가능하다.

http://localhost:9200/_plugin/head/


이걸 node.js http라이브러리이용하면 간단하다.

var http = require('http'); function elasticsearchPut(index,type,id,put_data){ var option = { hostname: 'localhost', port: 9200, path: '/'+index+'/'+type+'/'+id, method: 'PUT' }; var req = http.request(option, function(res) { console.log('STATUS: ' + res.statusCode); console.log('HEADERS: ' + JSON.stringify(res.headers)); res.setEncoding('utf8'); res.on('data', function (chunk) { console.log(chunk); }); }); req.on('error', function(e) { console.log('problem with request: ' + e.message); }); // DATA PUT req.write(JSON.stringify(put_data)); req.end(); } var index = 'logstash-2015.03.06'; var type = 'access_log'; var id = 2; var data = { "host": "web01", "http_host": "192.168.1.123", "clientip": "192.2.3.55", "timestamp": "Fri Feb 06 2015 14:04:22 GMT+0900 (KST)", "verb": "GET", "request": "/css/comm.css", "httpversion": "1.1", "response": "304", "bytes": "0", "referrer": "http://192.168.1.124/", "agent": "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17", "request_time": 0 }; elasticsearchPut(index,type,id,data);


콘솔에서 실행하면 아래와 같이 결과 메세지를 동일하게 볼 수 있다.

$ node test.js 
STATUS: 201
HEADERS: {"content-type":"application/json; charset=UTF-8","content-length":"91"}
{"_index":"logstash-2015.03.06","_type":"access_log","_id":"2","_version":1,"created":true}


예시로 nginx access_log로 했는데 실제 사용하는데는 이벤트나 구매내역등 실제 서비스로그를 RDBMS에서 주기적으로 가져와서 분석하는 용도로 사용함


추가적 node.js 라이브러리 및 Bulk insert 참고

elasticsearch Bulk insert(put) 대량 데이터 입력하기


Posted by 시니^^

각 툴에 대한 설명

1) elasticsearch => JAVA Lucene기반의 검색엔진

   URL : http://www.elasticsearch.org/

   Github : https://github.com/elasticsearch/elasticsearch


2) logstash => 실시간으로 다양한 로그를 가져와서 elasticsearch 넣어주는 역할

   URL :  http://logstash.net/

   Github : https://github.com/elasticsearch/logstash

   ※ logstash 경우 꼭 elasticsearch와 연동하지 않더라도 다양한 어플리케이션 로그를 input으로 받아서 다른 저장소로 전달하는 ouput 작업을 하기 위해서 쓰기 좋은 듯하다.


3) Kibana => elasticsearch와 연동해서 시각적으로 볼 수 있게 해주는 툴 node.js기반임

   URL :  http://www.elasticsearch.org/overview/kibana/

   Github : https://github.com/elasticsearch/kibana


설치 및 실행가이드

1. JAVA설치 - elasticsearch 사용하기 위해서 필요

$ yum install java
==================================================
 Package                              Arch        
==================================================
Installing:
 java-1.7.0-openjdk                   x86_64      
Installing for dependencies:
 flac                                 x86_64      
 giflib                               x86_64      
 jpackage-utils                       noarch      
 libasyncns                           x86_64      
 libsndfile                           x86_64      
 pulseaudio-libs                      x86_64      
 ttmkfdir                             x86_64      
 tzdata-java                          noarch      
 xorg-x11-fonts-Type1                 noarch      
Transaction Summary
==================================================
Install      10 Package(s)


2. elasticsearch 설치 및 실행

$ wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.4.4.tar.gz
$ tar xvfz elasticsearch-1.4.4.tar.gz
$ cd elasticsearch-1.4.4/bin
$ ./elasticsearch -d
$ ps aux | grep elasticsearch 

※ 옵션 -d 데몬으로 백그라운드실행


※ ElasticSearch 모니터링 추가 Plugin 설치 

$ ./plugin -install mobz/elasticsearch-head

=> URL : http://localhost:9200/_plugin/head/


$ ./plugin -install lukas-vlcek/bigdesk 

=> URL :  http://localhost:9200/_plugin/bigdesk/


$ ./plugin -install lmenezes/elasticsearch-kopf

=> URL :  http://localhost:9200/_plugin/kopf/


3. Logstash 설치

$ wget https://download.elasticsearch.org/logstash/logstash/logstash-1.4.2.tar.gz
$ tar xvfz logstash-1.4.2.tar.gz


※ 테스트 Nginx Access Log 추가

  참고사이트 : http://www.bravo-kernel.com/2014/12/setting-up-logstash-1-4-2-to-forward-nginx-logs-to-elasticsearch/


1) nginx.conf 로그구조 수정 후 Nginx 재시작

http {
    log_format main '$http_host '
                    '$remote_addr [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    '$request_time '
                    '$upstream_response_time';
    access_log  /var/log/nginx/access.log  main;
}


2) nginx 패턴 추가

$ vi ./logstash-1.4.2/patterns/nginx 
NGUSERNAME [a-zA-Z\.\@\-\+_%]+
NGUSER %{NGUSERNAME}
NGINXACCESS %{IPORHOST:http_host} %{IPORHOST:clientip} \[%{HTTPDATE:timestamp}\] \"(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})\" %{NUMBER:response} (?:%{NUMBER:bytes}|-) %{QS:referrer} %{QS:agent} %{NUMBER:request_time:float} %{NUMBER:upstream_time:float}
NGINXACCESS %{IPORHOST:http_host} %{IPORHOST:clientip} \[%{HTTPDATE:timestamp}\] \"(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})\" %{NUMBER:response} (?:%{NUMBER:bytes}|-) %{QS:referrer} %{QS:agent} %{NUMBER:request_time:float

3) Nginx logstash conf 생성

$ vi ./logstash-1.4.2/log_list/nginx.conf

====================================================== input { file { path => "/var/log/nginx/access.log" } } filter { mutate { replace => { "type" => "nginx_access" } } grok { match => { "message" => "%{NGINXACCESS}" } } date { match => [ "timestamp" , "dd/MMM/YYYY:HH:mm:ss Z" ] } geoip { source => "clientip" } } output { elasticsearch { host => localhost port => 9200 protocol => http } stdout { codec => rubydebug } }

※ 데이터 읽어와서 NGINXACCESS 매칭해서 elasticsearch로 보내는 설정정보이다

   elasticsearch 외에도 logstash의 경우 다양한 input output방식으로 데이터를 실시간 전달가능하다.

※ protocol 디폴트가 node이므로 버젼에 따라서 Kibana 사용할려면 http 설정해줘야될 경우도 있다

자세한 내용 참고 : http://logstash.net/docs/1.4.2/outputs/elasticsearch


4) conf TEST 옵션으로 확인
$ ../bin/logstash -f nginx.conf -t
Configuration OK


5) logstash 실행

$ ../bin/logstash -f nginx.conf
{
         "message" => "192.168.25.111 192.0.0.30 [02/Mar/2015:15:10:37 +0900] \"GET /favicon.ico HTTP/1.1\" 404 3652 \"-\" \"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17\" 0.000 -",
        "@version" => "1",
      "@timestamp" => "2015-03-02T06:10:37.000Z",
            "host" => "testServer01",
            "path" => "/var/log/nginx/access.log",
            "type" => "nginx_access",
       "http_host" => "192.168.25.111",
        "clientip" => "192.0.0.30",
       "timestamp" => "02/Mar/2015:15:10:37 +0900",
            "verb" => "GET",
         "request" => "/favicon.ico",
     "httpversion" => "1.1",
        "response" => "404",
           "bytes" => "3652",
        "referrer" => "\"-\"",
           "agent" => "\"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17\"",
    "request_time" => 0.0
}


※ elasticsearch-head 설치했다면 http://localhost:9200/_plugin/head/ 데이터 확인


4. Kibana 설치

$ wget https://download.elasticsearch.org/kibana/kibana/kibana-4.0.0-linux-x64.tar.gz
$ tar xvfz kibana-4.0.0-linux-x64.tar.gz 
$ cd kibana-4.0.0-linux-x64

1) config 수정 ( port 및 elasticsearch_url 등)

$ vi config/kibana.yml ====================================================== # Kibana is served by a back end server. This controls which port to use. port: 5601 # The Elasticsearch instance to use for all your queries. elasticsearch_url: "http://localhost:9200"

※ 설치법 찾아보면 kibana_index: "logstash-*" 인덱스 수정하라고 하는 듯한데 logstash-*로 인덱스 잡아주면 아래 에러 나면서 사이트 접속이 안됨.....

Fatal Error Courier Fetch Error: unhandled error Error: Request to Elasticsearch failed: {"_index":"logstash-*","_type":"config","_id":"4.0.0","error":"[logstash-*] missing"}

   그래서 kibana_index: ".kibana" 그대로 유지하였더니 잘됨... 보니까 kibana_index란 셋팅하는 대쉬보드 정보 저장하는 저장소의 정보인듯함... 검색 인덱스 셋팅은 kibana 접속후에 아래와같이 Configure an index pattern에서 index 추가하면됨

2) 최종적으로 웹브라우져 켜서 config 에 설정한 port 로 접속하면됨

 - http://server_ip:5601 


※ visualization 과 Dashboard 설정하는 부분은 나중에 시간있을때 추가하는걸로~!!




Posted by 시니^^