********************* 배포 프로세스 **************************
A : 현장 설명
대량의 온라인 서비스를보고 또는 Nginx에 서비스를 로그인 할 필요를 들어, 매일은 매우 가치있는 로그의 큰 숫자를 생성합니다. 백작은, 사용자 행동 분석, 인터페이스 요구 사항의 품질, 성능 모니터링을보고하는 데 사용 할 수있다. 그러나 전통적인 방식의 nginx 로그 데이터는 자신의 nginx, 트래픽 로그에 흩어져 대형 디스크 자체가 충격의 일종이다됩니다.
우리는 함께 찍은 균일 수집의 nginx 로그의이 부분을 필요로 수집 프로세스의 결과 다음과 같은 요구 사항을 충족 할 필요가 :
교통 모니터링, 데이터 분석, 통계 작업과 같은 데이터를 얻기 위해 다양한 서비스를 지원하는이 사업을 권장합니다.
데이터 실시간
고성능 보장
2 : 기술 프로그램
감사합니다 openresty 고성능 카프카, 우리는 매우 가볍고 될 수 있으며, 다음과 같이 현재의 수요 구조의 효율적인 구현은 다음과 같습니다
프로그램 설명 :
1 : nginx를 한 후, 사용 루아 전체 로그 통합을 재생하는 온라인 요청 : 통합 로그 형식으로 무효 필터 리퀘스트 패킷 등을 포함한다.
2 : 다른 주제로 나누어 서로 다른 사업에 따라 nginx를 기록.
3 : 루아는 카프카 클러스터에 비동기 전송 producter을 얻을 수 있습니다.
4 : 로그에 관심이 다른 비즈니스 그룹에 대한 로그 데이터를 획득의 실시간 소비.
세 : 관련 기술의
openresty : http://openresty.org
카프카가 살았던 : http://kafka.apache.org
루아 - Resty - 카프카가 살았 : https://github.com/doujiang24/lua-resty-kafka
四:安装配置
为了简单直接,我们采用单机形式配置部署,集群情况类似。
1)准备openresty依赖:
Java代码 收藏代码
apt-get install libreadline-dev libncurses5-dev libpcre3-dev libssl-dev perl make build-essential
# 或者
yum install readline-devel pcre-devel openssl-devel gcc
2)安装编译openresty:
Java代码 收藏代码
#1:安装openresty:
cd /opt/nginx/ # 安装文件所在目录
wget https://openresty.org/download/openresty-1.9.7.4.tar.gz
tar -xzf openresty-1.9.7.4.tar.gz /opt/nginx/
#配置:
# 指定目录为/opt/openresty,默认在/usr/local。
./configure –prefix=/opt/openresty \
–with-luajit \
–without-http_redis2_module \
–with-http_iconv_module
make
make install
3)安装lua-resty-kafka
Java代码 收藏代码
#下载lua-resty-kafka:
wget https://github.com/doujiang24/lua-resty-kafka/archive/master.zip
unzip lua-resty-kafka-master.zip -d /opt/nginx/
#拷贝lua-resty-kafka到openresty
mkdir /opt/openresty/lualib/kafka
cp -rf /opt/nginx/lua-resty-kafka-master/lib/resty /opt/openresty/lualib/kafka/
4):安装单机kafka
Java代码 收藏代码
cd /opt/nginx/
wget http://apache.fayea.com/kafka/0.9.0.1/kafka_2.10-0.9.0.1.tgz
tar xvf kafka_2.10-0.9.0.1.tgz
# 开启单机zookeeper
nohup sh bin/zookeeper-server-start.sh config/zookeeper.properties > ./zk.log 2>&1 &
**# 绑定broker ip,必须绑定
**#在config/servier.properties下修改host.name
host.name={your_server_ip}
# 启动kafka服务
nohup sh bin/kafka-server-start.sh config/server.properties > ./server.log 2>&1 &
# 创建测试topic
sh bin/kafka-topics.sh –zookeeper localhost:2181 –create –topic test1 –partitions 1 –replication-factor 1
五:配置运行
开发编辑/opt/openresty/nginx/conf/nginx.conf 实现kafka记录nginx日志功能,源码如下:
Java代码 收藏代码
worker_processes 12;
events {
use epoll;
worker_connections 65535;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 0;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 8k;
gzip_http_version 1.1;
gzip_types text/plain application/x-javascript text/css application/xml application/X-JSON;
charset UTF-8;
# 配置后端代理服务
upstream rc{
server 10.10.*.15:8080 weight=5 max_fails=3;
server 10.10.*.16:8080 weight=5 max_fails=3;
server 10.16.*.54:8080 weight=5 max_fails=3;
server 10.16.*.55:8080 weight=5 max_fails=3;
server 10.10.*.113:8080 weight=5 max_fails=3;
server 10.10.*.137:8080 weight=6 max_fails=3;
server 10.10.*.138:8080 weight=6 max_fails=3;
server 10.10.*.33:8080 weight=4 max_fails=3;
# 最大长连数
keepalive 32;
}
# 配置lua依赖库地址
lua_package_path “/opt/openresty/lualib/kafka/?.lua;;”;
server {
listen 80;
server_name localhost;
location /favicon.ico {
root html;
index index.html index.htm;
}
location / {
proxy_connect_timeout 8;
proxy_send_timeout 8;
proxy_read_timeout 8;
proxy_buffer_size 4k;
proxy_buffers 512 8k;
proxy_busy_buffers_size 8k;
proxy_temp_file_write_size 64k;
proxy_next_upstream http_500 http_502 http_503 http_504 error timeout invalid_header;
root html;
index index.html index.htm;
proxy_pass http://rc;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 使用log_by_lua 包含lua代码,因为log_by_lua指令运行在请求最后且不影响proxy_pass机制
log_by_lua '
-- 引入lua所有api
local cjson = require "cjson"
local producer = require "resty.kafka.producer"
-- 定义kafka broker地址,ip需要和kafka的host.name配置一致
local broker_list = {
{ host = "10.10.78.52", port = 9092 },
}
-- 定义json便于日志数据整理收集
local log_json = {}
log_json["uri"]=ngx.var.uri
log_json["args"]=ngx.var.args
log_json["host"]=ngx.var.host
log_json["request_body"]=ngx.var.request_body
log_json["remote_addr"] = ngx.var.remote_addr
log_json["remote_user"] = ngx.var.remote_user
log_json["time_local"] = ngx.var.time_local
log_json["status"] = ngx.var.status
log_json["body_bytes_sent"] = ngx.var.body_bytes_sent
log_json["http_referer"] = ngx.var.http_referer
log_json["http_user_agent"] = ngx.var.http_user_agent
log_json["http_x_forwarded_for"] = ngx.var.http_x_forwarded_for
log_json["upstream_response_time"] = ngx.var.upstream_response_time
log_json["request_time"] = ngx.var.request_time
-- 转换json为字符串
local message = cjson.encode(log_json);
-- 定义kafka异步生产者
local bp = producer:new(broker_list, { producer_type = "async" })
-- 发送日志消息,send第二个参数key,用于kafka路由控制:
-- key为nill(空)时,一段时间向同一partition写入数据
-- 指定key,按照key的hash写入到对应的partition
local ok, err = bp:send("test1", nil, message)
if not ok then
ngx.log(ngx.ERR, "kafka send err:", err)
return
end
';
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
六:检测&运行
Java代码 收藏代码
检测配置,只检测nginx配置是否正确,lua错误日志在nginx的error.log文件中
./nginx -t /opt/openresty/nginx/conf/nginx.conf
# 启动
./nginx -c /opt/openresty/nginx/conf/nginx.conf
# 重启
./nginx -s reload
七:测试
1:使用任意http请求发送给当前nginx,如:
引用
2:查看upstream代理是否工作正常
3:查看kafka 日志对应的topic是否产生消息日志,如下:
引用
# 从头消费topic数据命令
sh kafka-console-consumer.sh –zookeeper 10.10.78.52:2181 –topic test1 –from-beginning
效果监测:
4:ab压力测试
引用
#单nginx+upstream测试:
ab -n 10000 -c 100 -k http://10.10.34.15/m/personal/AC8E3BC7-6130-447B-A9D6-DF11CB74C3EF/rc/[email protected]&page=2&size=10
#结果
Server Software: nginx
Server Hostname: 10.10.34.15
Server Port: 80
Document Path: /m/personal/AC8E3BC7-6130-447B-A9D6-DF11CB74C3EF/rc/[email protected]
Document Length: 13810 bytes
Concurrency Level: 100
Time taken for tests: 2.148996 seconds
Complete requests: 10000
Failed requests: 9982
(Connect: 0, Length: 9982, Exceptions: 0)
Write errors: 0
Keep-Alive requests: 0
Total transferred: 227090611 bytes
HTML transferred: 225500642 bytes
Requests per second: 4653.34 [#/sec] (mean)
Time per request: 21.490 [ms] (mean)
Time per request: 0.215 [ms] (mean, across all concurrent requests)
Transfer rate: 103196.10 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 2
Processing: 5 20 23.6 16 701
Waiting: 4 17 20.8 13 686
Total: 5 20 23.6 16 701
Percentage of the requests served within a certain time (ms)
50% 16
66% 20
75% 22
80% 25
90% 33
95% 41
98% 48
99% 69
100% 701 (longest request)
引用
#单nginx+upstream+log_lua_kafka接入测试:
ab -n 10000 -c 100 -k http://10.10.78.52/m/personal/AC8E3BC7-6130-447B-A9D6-DF11CB74C3EF/rc/[email protected]&page=2&size=10
#结果
Server Software: openresty/1.9.7.4
Server Hostname: 10.10.78.52
Server Port: 80
Document Path: /m/personal/AC8E3BC7-6130-447B-A9D6-DF11CB74C3EF/rc/[email protected]
Document Length: 34396 bytes
Concurrency Level: 100
Time taken for tests: 2.234785 seconds
Complete requests: 10000
Failed requests: 9981
(Connect: 0, Length: 9981, Exceptions: 0)
Write errors: 0
Keep-Alive requests: 0
Total transferred: 229781343 bytes
HTML transferred: 228071374 bytes
Requests per second: 4474.70 [#/sec] (mean)
Time per request: 22.348 [ms] (mean)
Time per request: 0.223 [ms] (mean, across all concurrent requests)
Transfer rate: 100410.10 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.2 0 3
Processing: 6 20 27.6 17 1504
Waiting: 5 15 12.0 14 237
Total: 6 20 27.6 17 1504
Percentage of the requests served within a certain time (ms)
50% 17
66% 19
75% 21
80% 23
90% 28
95% 34
98% 46
99% 67
100% 1004 (longest request)
********************* 最重要的模块 **************************
nginx配置文件配置如下:
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
upstream myServer {
server 192.168.0.109:8080 weight=1;
}
lua_package_path "/opt/openresty/lualib/kafka/?.lua;;";
lua_need_request_body on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location /test1 {
# 请求转向自定义的服务器列表
proxy_pass http://myServer;
}
location /test2 {
# 使用log_by_lua 包含lua代码,因为log_by_lua指令运行在请求最后且不影响proxy_pass机制
log_by_lua '
-- 引入lua所有api
local topic = "test"
local cjson = require "cjson"
local producer = require "resty.kafka.producer"
-- 定义kafka broker地址,ip需要和kafka的host.name配置一致
local broker_list = {
{ host = "192.168.0.109", port = 9092 },
{ host = "192.168.0.110", port = 9092 },
{ host = "192.168.0.101", port = 9092 }
}
-- 定义json便于日志数据整理收集
local log_json = {}
log_json["uri"]=ngx.var.uri
log_json["args"]=ngx.req.get_uri_args()
log_json["host"]=ngx.var.host
log_json["request_body"]=ngx.var.request_body
log_json["remote_addr"] = ngx.var.remote_addr
log_json["remote_user"] = ngx.var.remote_user
log_json["time_local"] = ngx.var.time_local
log_json["status"] = ngx.var.status
log_json["body_bytes_sent"] = ngx.var.body_bytes_sent
log_json["http_referer"] = ngx.var.http_referer
log_json["http_user_agent"] = ngx.var.http_user_agent
log_json["http_x_forwarded_for"] = ngx.var.http_x_forwarded_for
log_json["upstream_response_time"] = ngx.var.upstream_response_time
log_json["request_time"] = ngx.var.request_time
-- 转换json为字符串
local message = cjson.encode(ngx.req.get_uri_args());
-- 定义kafka异步生产者
local bp = producer:new(broker_list, { producer_type = "async" })
-- 发送日志消息,send第二个参数key,用于kafka路由控制:
-- key为nill(空)时,一段时间向同一partition写入数据
-- 指定key,按照key的hash写入到对应的partition
local ok, err = bp:send(topic, nil, message)
if not ok then
ngx.log(ngx.ERR, "kafka send err:", err)
return
end
';
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
********************* 遇到的坑 **************************
问题概述:
利用server1服务器上的openresty nginx的lua脚本往server5中kafka写数据,发现报错 无法解析主机(no resolver defined to resolve "xxxxx"),xxxxx是某台机器的域名,再后来,经过一天的摸索,发现了问题。
问题原因:
最终发现,原来是openResty不会去解析 host 映射,因为kafka客户端用IP连接后会请求broker,然后去到zookeeper拿到broker集群信息(地址记录是 kafka236:1111),这时候lua消费者拿到的是 kafka236 的IP,
但是又不会通过 host去解析,就会报错无法解析主机的问题。
솔루션
라우터 DNS 확인 서비스가있는 경우에 직접 DNS 서버에 도메인 이름 DNS의 해상도, 다음의 nginx 구성 지점을 구성 (자신의 DNS 서비스를 구축 할 필요가없는 경우)
nginx.conf 구성 :
DNS 구성 :
비고 :
카프카 서버가 기본 카프카 카프카 클라이언트 서버의 IP 또는 도메인 이름을 구성한 경우 1, 로컬 호스트와 연결되지 않은 (서버는 로컬 호스트를 사용하지 않는)
2, 서버 카프카가 구성 들으면 IP, 다음 IP 주소가 기록 사육사
카프카는 서버의 도메인 이름을 구성 들어요 경우 도메인 이름은 사육사에 기록
카프카 서버가 advertised.listeners 도메인 이름을 갖도록 구성된 경우, 사육사가 들어 무엇 구성에 상관없이 도메인 이름으로 기록되지 않습니다
나중에 발견
도메인 이름이나 IP 구성 openresty-1.7.10.2, 카프카의 낮은 버전에 액세스 할 수 있습니다
openresty-1.13.6.2의 높은 버전은 해결이 작동하지 않는 구성, 도메인 이름에 액세스 할 카프카, 유일한 IP를 구성합니다.