电商日志分析项目 – 02 日志的生成和采集(Flume)

Hadoop安装与配置

Hadoop3.1.4的单机安装参考

Flume的安装与配置

Flume的安装与配置参考

Apache httpd 安装

安装httpd的原因主要是使用它提供的ab压测工具.

  1. 安装httpd
yum install -y httpd
  1. 配置httpd,为了避免和ngixn端口冲突修改端口号为81,配置如下:
vi /etc/httpd/conf/httpd.conf

修改内容如下:

#Listen 80
Listen 81
  1. 启动服务
systemctl enable httpd # 开机自启动
systemctl start httpd # 启动httpd
  1. 查看启动状态
systemctl status httpd

注意:

  • 其实使用httpd只是为了使用ab工具,无需启动httpd服务

AB压测生成日志

访问http://hadoop100/university/ 登陆进入后台界面

后台UI界面生成商品链接

点击获取商品链接,页面打印生成的JSON格式数据
file

同时在服务器生成文件/tmp/project-urls.txt,里面保存着所有商品链接:

http://hadoop100/shop/detail.html?id=4028f00176e118120176e17d0e0f0000
http://hadoop100/shop/detail.html?id=4028f00176e1aa620176e2319b730000
http://hadoop100/shop/detail.html?id=4028f00176e1aa620176e6a991e60001
http://hadoop100/shop/detail.html?id=4028f00176e1aa620176e6ab478d0002
http://hadoop100/shop/detail.html?id=4028f00176e1aa620176e6aca6890003
http://hadoop100/shop/detail.html?id=4028f08176e0e2af0176e0e2bd600007

后台UI界面AB压测生成日志

编写压测脚本ab_test.sh,内容可自行修改,如下:

$ vi /opt/bin/project/ab-test.sh

#!/bin/bash
n=$(cat /tmp/project-urls.txt | wc -l)

for ((i=1;i<=$n;i++))
do
    echo "No.$i"
    url=$(shuf -n1 /tmp/project-urls.txt)
    r=$(shuf -i 6-100 -n 1)
    c=$(shuf -i 1-5 -n 1)

    echo "access url  -> $url"
    echo "requests    -> $r"
    echo "concurrency -> $c"

    ab -n $r -c $c $url >> /tmp/project-abtest-results.log &
done

说明:

  • 给与执行权限方便执行
  • shuf在指定范围生成随机数
  • ab apache benchmark工具,常用于压力测试
    • -n 请求数
    • -c 并发数
  • 压测结果可在/tmp/project-abtest-resuilts.log中找到

压测结果说明
file

点击AB压测生成日志
file

产生的日志在/var/log/nginx/access.log中。

使用FLume收集滚动日志上传到HDFS上

修改nginx生成的日志文件所有者

nginx默认生成的日志文件access.log的用户组和用户分别是adm和nginx,如下所示:

[hadoop@hadoop100 nginx]$ ll
-rw-r-----  1 nginx  adm    135470 Apr 21 01:22 access.log

而现在需要让另一用户读取该文件,做日志的分析监控. 应该修改日志文件的所属用户组和用户,避免出现权限问题。

修改Nginx运行时进程的用户与组

Nginx运行时进程需要有用户与组的支持,用以实现对网站文件读取时进行访问控制。主进程由 root创建,子进程由指定的用户与组创建, 一般默认为 nginx admnobody nobody

由于我们项目中使用的操作账户为hadoop,而这个用户对nginx用户生成的日志没有操作权限,因此使用Flume收集时会出现权限问题导致收集失败。

当然也可以简单粗暴的临时使用下面的命令解决问题

$ sudo chown hadoop:hadoop -R /var/log/nginx/

但是这样并不能从根本解决问题,因为下次滚动生成的日志所有者还会变成原来配置的。

修改 nginx 用户与组有两种办法。如果是编译安装,可以在编译前指定用户和组;也可以修改配置文件指定用户与组,然后重启服务器即可。

编译 nginx 时指定用户与组

即修改 ./configure 后面指定用户与组的参数

./configure \
--prefix=/usr/local/nginx \
--user=nginx \        //指定用户名是 nginx
--group=nginx \       //指定组名是 nginx
--with-http_stub_status_module

修改 nginx 配置文件指定用户与组

打开文件/etc/nginx/nginx.conf,我这里默认是

user nginx;   //修改用户为nginx,组为nginx

现在我们改成

user hadoop hadoop; // //修改用户为 hadoop,组为 hadoop

sudo service nginx restart重启服务后,查看进程情况,主进程由root创建,子进程则由nginx创建。

file

修改 Nginx 日志滚动策略

可以通过修改这个文件修改 Nginx 的日志滚动策略(如有需要)

$ sudo vi /etc/logrotate.d/nginx

/var/log/nginx/*.log {
        daily
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 640 nginx adm
        sharedscripts
        postrotate
                if [ -f /var/run/nginx.pid ]; then
                        kill -USR1 $(cat /var/run/nginx.pid)
                fi
        endscript
}

其中nginx adm就是滚动日志的权限拥有者及所在群组, 640表示滚动日志的权限。下面比如我们需要将滚动日志的用户组和用户改为hadoop:hadoop, 只需要修改此处:

#create 640 nginx adm
create 640 hadoop hadoop

滚动access.log日志文件

接着编写Linux Shell脚本实现/var/log/nginx/access.log日志滚动到flume-logs目录下。

/opt/bin/project目录下新建rolling-log.sh,并添加执行权限,内容如下:

#!/bin/bash
#定义日期格式
dataformat=$(date +%Y-%m-%d-%H-%M-%S)

#复制access.log并重命名,添加时间信息
cp /var/log/nginx/access.log /var/log/nginx/access_$dataformat.log

host=$(hostname)
sed -i 's/^/'${host}',&/g' /var/log/nginx/access_$dataformat.log
#统计日志文件行数
lines=$(wc -l < /var/log/nginx/access_$dataformat.log)

#将格式化的日志移动到flumeLogs目录下
mv /var/log/nginx/access_$dataformat.log /var/log/nginx/flume-logs

#清空access.log的内容
sed -i '1,'${lines}'d' /var/log/nginx/access.log

#重启nginx , 使access.log可以继续滚动
kill -USR1 $(cat /var/run/nginx.pid)

##返回给服务器信息
ls -al /var/log/nginx/flume-logs/

后台管理界面点击生成滚动日志

file

编写Flume Agent配置文件:

vi /opt/pkg/flume/conf/log2hdfs.conf`

# define the agent a1
a1.sources=r1
a1.channels=c1
a1.sinks=k1

# define the source
#上传目录类型
a1.sources.r1.type=spooldir
a1.sources.r1.spoolDir=/var/log/nginx/flume-logs
#定义自滚动日志完成后的后缀名
a1.sources.r1.fileSuffix=.FINISHED
#根据每行文本内容的大小自定义最大长度4096=4k
a1.sources.r1.deserializer.maxLineLength=4096

# define the sink
a1.sinks.k1.type = hdfs
#上传的文件保存在hdfs的/flume/logs目录下
a1.sinks.k1.hdfs.path = hdfs://hadoop100:8020/flume/logs/%y-%m-%d/
a1.sinks.k1.hdfs.filePrefix=access_log
a1.sinks.k1.hdfs.fileSufix=.log
a1.sinks.k1.hdfs.batchSize=1000
a1.sinks.k1.hdfs.fileType = DataStream
a1.sinks.k1.hdfs.writeFormat= Text
# roll 滚动规则:按照数据块128M大小来控制文件的写入,与滚动相关其他的都设置成0
#为了演示,这里设置成500k写入一次
a1.sinks.k1.hdfs.rollSize= 512000
a1.sinks.k1.hdfs.rollCount=0
a1.sinks.k1.hdfs.rollInteval=0
#控制生成目录的规则:一般是一天或者一周或者一个月一次,这里为了演示设置10秒
a1.sinks.k1.hdfs.round=true
a1.sinks.k1.hdfs.roundValue=10
a1.sinks.k1.hdfs.roundUnit= second
#是否使用本地时间
a1.sinks.k1.hdfs.useLocalTimeStamp=true

#define the channel
a1.channels.c1.type = memory
#自定义event的条数
a1.channels.c1.capacity = 500000
#flume事务控制所需要的缓存容量1000条event
a1.channels.c1.transactionCapacity = 1000

#source channel sink cooperation
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

创建脚本flume_start.sh,用于启动Flume Agent

#!/bin/bash
/opt/pkg/flume-1.9.0/bin/flume-ng agent --conf ./conf/ -f ./conf/log2hdfs.conf --name a1 -Dflume.root.logger=INFO,console

编写停止Flume脚本 flume_stop.sh,停止Flume

#!/bin/bash

JAR="flume"

#停止flume函数
echo "begin to stop flume process.."
num=$(ps -ef|grep java|grep $JAR|wc -l)
echo "当前已经启动的flume进程数:$num"
if [ "$num" != "0" ];then
   #正常停止flume
   ps -ef|grep java|grep $JAR|awk '{print $2;}'|xargs kill -9
   echo "进程已经关闭..."
else
   echo "服务未启动,无须停止..."
fi

编写重启Flume脚本 flume-log2hdfs.sh,综合了前两个脚本

#!/bin/bash

#先停止正在启动的flume
./flume_stop.sh

nohup ./flume_start.sh > nohup_output.log 2>&1 &
echo "启动flume成功……"

后台管理界面点击启动FLume采集
file

查看滚动日志是否成功上传到HDFS系统

file

异常: 日志收集失败,报错:

2021-03-09 22:38:50,834 (SinkRunner-PollingRunner-DefaultSinkProcessor) [ERROR - org.apache.flume.sink.hdfs.HDFSEventSink.process(HDFSEventSink.java:459)] process failed
java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V

原因: flume/lib/guava-xxx.jar 和 hadoop自带的jar包发生冲突

解决: 将flume/lib下的guava包删除或者改名, 只保留hadoop的版本即可

Views: 129

Index