且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何实现日志的集中化存储以及使用loganalyzer做日志分析

更新时间:2021-07-15 11:33:40

日志记录的是,我们操作系统或某个服务或某个软件在运行过程当中所产生事件信息的,这对于我们后续分析系统比较有价值。

比如,某个服务在运行过程中出现故障了,就可以查看该服务的日志信息,分析日志找出服务出现故障的原因所在。

如:我们使用【yum】工具安装软件,系统都会把程序yum做的操作记录到日志里。

如果,我们管理的不是一台主机,每台主机的日志信息都是单独存放的,如果要分析报告当前所有主机的的所有服务的过去某一时间段运行状态,我们则要逐一查看每一台主机的日志文件了。这很不方便。不利于使用一些日志分析工具来分析日志。所以我们要做日志的集中化存储。意思是说:把所有主机产生日志信息发往日志服务器,由日志服务器帮助众多需要存储日志数据的主机存储日志数据。

存储日志数据有两种方式:

1
2
1、使用文件存储日志数据
2、把日志信息存储到数据库里

分析

   如果,我们多台主机同时有很多日志信息,都要日志服务器存储的话,使用文件存储日志数据的方式就无能为力了。因为:文件锁是文件级别的,不能解决“并发”的问题,效率是很底的。而数据库的锁是行级别的,可以实现“并发操作”。还有数据库提供:二进制日志、事务日志实现了故障恢复。还有把日志存储到数据库里,很方便使用一些日志分析工具来分析日志数据,如:loganalyzer

数据库能实现并发和故障恢复,使用数据库来存储日志数据无疑是***的选择。CentOS 5 以上的版本提供的记录日志数据的服务:rsyslog

它是多线程的,提供存储日志的方式有多种:

1
2
3
4
5
6
1、可以使用本地文件的方式存在日志。
   如:mail.*                   -/var/log/maillog
2、把日志数据发往另一台主机由它代为储存日志
   如:mail.*                  @192.168.60.40
3、使用数据库的方式记录日志信息。
   如:mail.*                 :ommysql:192.168.60.40,Syslog,syslog,syslog

    这里,我们选择使用MySQL关系型数据库集中化存储多台主机的日志数据信息。那Rsyslog日志记录服务程序是如何与数据库交互把数据存在到数据库中的呢?如下图的示:

如何实现日志的集中化存储以及使用loganalyzer做日志分析

一、安装MySQL数据库

选择使用编译好的二进制格式的MySQL程序包

1
mysql-5.5.22-linux2.6-i686.tar.gz

1创建MySQL的数据存放位置

为了备份日志方便把数据放在LVM卷中。还可以利用LVM的扩容功能,当我们的空间不够使用时。

查看,已经存在的卷组是否还有剩余空间,来创建LV

1
2
3
[root@mysql local]# vgdisplay  | grep -i"PE[[:space:]]*/[[:space:]]*Size"
 Alloc PE / Size       6656 / 52.00GiB
  Free  PE / Size       1023 / 7.99 GiB

说明:还有7.99GB,空间可以创建LV

注意:

如果存在的文件很大的话,见议我们在创建逻辑卷时***把PE的大小设置大点。

 

创建LV

1
2
3
4
root@mysql local]# lvcreate  -L 4G -n loglv vg0
 Logical volume "loglv" created
[root@mysql local]# lvscan  | grep "loglv"
 ACTIVE            '/dev/vg0/loglv'[4.00 GiB] inherit

格式化逻辑卷loglv

1
2
3
[root@mysql local]# mke2fs  -t ext4 -L LOGDATA /dev/vg0/loglv
[root@mysql local]# echo $?
0

挂载逻辑卷

设置开机自动挂载.编辑/etc/fstab文件增加下面一行。

1
/dev/mapper/vg0-loglv   /logdata                ext4    defaults        0 0

自动挂载测试

1
2
3
root@mysql local]# mount -a
[root@mysql local]# mount | grep"loglv"
/dev/mapper/vg0-loglv on /logdata type ext4(rw)

2、准备好安装MySQL数据库的必需条件

(1)创建用户mysql,用来被始化数据库使用的。

说明:***mysql是系统用户,这样就算mysql用户被人劫持,也无法登陆系统的。

1
2
3
[root@mysql local]# useradd  -r mysql
[root@mysql local]# id mysql
uid=399(mysql) gid=399(mysql)groups=399(mysql)

(2)、设置MySQL数据库的数据存放位置:在/logdata中创建data,且属主属组为mysql

1
2
3
4
[root@mysql logdata]# mkdir  data
[root@mysql logdata]# chown mysql:mysql./data/
[root@mysql logdata]# ll -d data
drwxr-xr-x 2 mysql mysql 4096 Aug 20 15:40data

3、安装MySQL数据库

(1)把程序包解压到”/uer/local”目录,为了后续维护方便并创建一个软链接。

1
2
3
4
5
6
[root@mysql user]# tar -xfmysql-5.5.22-linux2.6-i686.tar.gz  -C/usr/local/
[root@mysql user]# cd /usr/local/
[root@mysql local]# ln -svmysql-5.5.22-linux2.6-i686 mysql
`mysql' -> `mysql-5.5.22-linux2.6-i686'
[root@mysql local]# ll  | grep mysql
lrwxrwxrwx  1 root root   26 Aug 20 15:03mysql -> mysql-5.5.22-linux2.6-i686

(2)、我们要以:mysql用户的身份来初始化数据库,要有权限操作一些文件所以要修改解压后Mysql程序的属主属组为mysql

1
[root@mysql mysql]# chown -R mysql:mysql./*

说明:安装完数据后,把属主改为:root

(3)、初始化数据库

1
2
3
4
5
[root@node1 mysql]#./scripts/mysql_install_db --datadir=/logdata/data --user=mysql
Installing MySQL system tables...
OK
Filling help tables...
OK

说明:

1
2
--datadir            指定数据库的数据目录的位置(不使用默认的位置)
--user              指定初始化数据库的用户名(使用二进制格式MySQL程序包一定要使用mysql)

(4)、根据物理机的硬件情况与实际需要选择MySQL的配置文件

1
2
3
4
5
6
[root@node1 mysql]# ll support-files/*.cnf
-rw-r--r-- 1 mysql mysql  4691 Mar  3  2012 support-files/my-huge.cnf
-rw-r--r-- 1 mysql mysql 19759 Mar  3  2012 support-files/my-innodb-heavy-4G.cnf
-rw-r--r-- 1 mysql mysql  4665 Mar  3  2012 support-files/my-large.cnf
-rw-r--r-- 1 mysql mysql  4676 Mar  3  2012 support-files/my-medium.cnf
-rw-r--r-- 1 mysql mysql  2840 Mar  3  2012 support-files/my-small.cnf

说明

    不同的配置文件,要求的内存都不一样。


复制配置文件到/etc/mysql 目录下,并命名为:my.cnf

1
[root@node1 mysql]# cp support-files/my-large.cnf /etc/mysql/my.cnf


4、启动MySQL数据库服务器之前要做的一些设置

(1)、修改MySQL的配置文件

1
2
3
[root@node1 mysql]# vim /etc/mysql/my.cnf
thread_concurrency = 4          设置线程数  
datadir = /logdata/data        告诉MySQL服务器数据目录的位置

说明

     由于这些配置是作用于MySQL服务器的。要把它写在:[mysqld]段中。

(2)、复制启动MySQL数据库服务器的启动脚本,并命名为:mysqld

1
[root@node1 mysql]# cp support-files/mysql.server /etc/init.d/mysqld

检查是否执行权限

1
2
[root@node1 mysql]# ll /etc/init.d/mysqld
-rwxr-xr-x 1 root root 10650 Aug 20 15:55 /etc/init.d/mysqld

(3)、把mysqld服务启动脚本添加到chkconf的控制列表里,能够使用【server】命令控制服务的行为。 可以实现开机自动启动。

1
2
3
[root@node1 mysql]# chkconfig --add mysqld
[root@node1 mysql]# chkconfig  --list mysqld
mysqld          0:off   1:off   2:on    3:on    4:on    5:on    6:off


5、启动MySQL数据库并修改设置用户

启动MySQL数据库服务器

1
2
[root@node1 mysql]# service mysqld start
Starting MySQL..                                           [  OK  ]

查看监听端口

1
2
[root@node1 mysql]# netstat -anptl | grep mysqld
tcp        0      0 0.0.0.0:3306                0.0.0.0:*                   LISTEN      3041/mysqld

注意:

    安装MySQL数据库服务器默认添加了很多用户,这些用户都没有密码且权限是数据库的管理权限,极其不安全。且没有远程登陆数据库的用户,不方便数据库的管理维护。所以给MySQL数据库服务器设置密码,清理不需要的用户。增加可以远程登陆数据库的用户,且权限是管理员。

(1)、安装数据库时默认创建的用户如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> select user,host,password from mysql.user;
 
+------+------------------+----------+--------------+
| user | host             | password |
+------+------------------+----------+--------------+
| root | localhost        |         |
| root | node1.9527du.com |         |
| root | 127.0.0.1        |          |
| root | ::1              |          |
|    | localhost          |          |
|    | node1.9527du.com   |          |
+------+------------------+----------+---------------+
6 rows in set (0.01 sec)

(2)、删除用户

1
2
3
4
mysql> drop user 'root'@'node1.9527du.com';
mysql> drop user 'root'@'::1';
mysql> drop user ''@'localhost';
mysql> drop user ''@'node1.9527du.com';

(3)、添加管理MySQL数据库的用户,并给保留的用户设置密码。

1
2
mysql> set password for 'root'@'localhost' = password('root');
mysql> set password for 'root'@'127.0.0.1' = password('root');

(4)、添加管理MySQL数据库的用户

1
2
mysql> grant all on *.* to 'admin'@'%.%.%.%' identified by 'admin';
mysql> flush privileges;

(5)、修改后的用户列表

1
2
3
4
5
6
7
8
9
mysql> select user,host,password from mysql.user;
+-------+-----------+-------------------------------------------+----------------------
| user  | host      | password                                  |
+-------+-----------+-------------------------------------------+----------------------
| root  | localhost | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| root  | 127.0.0.1 | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| admin | %.%.%.%   | *4ACFE3202A5FF5CF467898FC58AAB1D615029441 |
+-------+-----------+-------------------------------------------+----------------------
3 rows in set (0.00 sec)


二、在192.168.60.99主机,设置rsyslog与MySQL数据库交互(把日志数据记录到数据库里):

1、安装rsyslog与MySQL数据库交互的驱动

1
[root@stu13 ~]# yum install rsyslog-mysql

查看安装了那些

1
2
3
4
[root@stu13 ~]# rpm -ql rsyslog-mysql
/lib/rsyslog/ommysql.so          rsyslog 连接MySQL数据库服务器的驱动
/usr/share/doc/rsyslog-mysql-5.8.10
/usr/share/doc/rsyslog-mysql-5.8.10/createDB.sql     创建表的SQL脚本

2、生成记录日志的数据库

说明:

    由于数据库服务器,在另外一台主机,所以,要创建能够远程连接数据库的用户如果,数据库没有设置远程连接的用户要先创建。

1
2
3
[root@stu13 ~]# mysql -uadmin -h192.168.60.40 -p < /usr/share/doc/rsyslog-mysql-5.8.10/createDB.sql
Enter password:
ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.60.40' (110)

说明:连接数据库服务器失败。

查看,原来是防火墙阻止了连接MySQL数据库服务器

1
2
3
4
5
6
7
8
9
10
11
[root@stu13 ~]# iptables -L -n
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  --  0.0.0.0/0            192.168.60.99       state ESTABLISHED
http_in    tcp  --  0.0.0.0/0            192.168.60.99       tcp dpt:80
https_in   tcp  --  0.0.0.0/0            192.168.60.99       tcp dpt:443
ssh_in     tcp  --  0.0.0.0/0            192.168.60.99       tcp dpt:22
vsftp_in   tcp  --  0.0.0.0/0            192.168.60.99       tcp dpt:21
ACCEPT     all  --  0.0.0.0/0            192.168.60.99       state RELATED
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0
......

使用默认策略允许连接数据库服务器

1
2
[root@stu13 ~]# iptables -P INPUT ACCEPT
[root@stu13 ~]# iptables -P OUTPUT ACCEPT

再次导入sql脚本生成数据库和表

1
2
[root@stu13 ~]# mysql -uadmin -h192.168.60.40 -p < /usr/share/doc/rsyslog-mysql-5.8.10/createDB.sql
Enter password:

3、查看是否创建成功

1
2
3
4
5
6
7
8
mysql> show tables from Syslog;
+------------------------+---------
| Tables_in_Syslog       |
+------------------------+---------
| SystemEvents           |
| SystemEventsProperties |
+------------------------+---------
2 rows in set (0.00 sec)

SQL脚本(/usr/share/doc/rsyslog-mysql-5.8.10/createDB.sql)创建的表

1
2
3
[root@stu13 ~]# grep -i "CREATE[[:space:]]*TABLE" /usr/share/doc/rsyslog-mysql-5.8.10/createDB.sql
CREATE TABLE SystemEvents
CREATE TABLE SystemEventsProperties

说明:

   通过中show tables from Syslog查看与sql脚本中定义的表相同证明执行SQL脚本已经成功。


4、基于安全考虑:添加一个管理Syslog数据库的用户。且该用户没有操作其它数据库的任何权限。在192.168.60.0/24内使用

(1)、创建并授权

1
2
mysql> grant all on Syslog.* to 'syslog'@'192.168.60.%' identified by 'syslog';
Query OK, 0 rows affected (0.01 sec)

(2)、刷新授权表

1
2
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

(3)、测试是否可以远程登陆数据库服务器

1
2
3
4
5
[root@stu13 ~]# mysql -usyslog -h192.168.60.40 -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
......
mysql>

5、设置rsyslog的配置文件让它加载ommmysql.so 模块

在rsyslog日志系统的配置文件中,使用【$ModLoad】指令装载连接MySQL的驱动:ommysql.so

指定把日志数据送往的数据库服务器(日志服务器)

1
2
3
[root@stu13 ~]# vim /etc/rsyslog.conf
$ModLoad ommysql            加载模块
.info;mail.none;authpriv.none;cron.none    :ommysql:192.168.60.40,Syslog,syslog,syslog                                            设置连接数据库需要的一些信息,及使用存储日志                                            数据的数据库为:Syslog

重启rsyslog

1
2
3
[root@stu13 ~]# service rsyslog restart
Shutting down system logger:                               [  OK  ]
Starting system logger:                                    [  OK  ]


三、测试:rsyslog + ommmysql + MySQL 集中存储日志是否正常工作

1、在192.168.60.99主机使用yum程序安装软件

1
2
3
[root@stu13 ~]# yum install tree
[root@stu13 ~]# date
Wed Aug 20 22:50:43 CST 2014

2、通过远程连接数据库查看日志服务器是否记录了yum命令安装tree程序的日志

1
2
3
4
5
6
7
8
mysql> select DeviceReportedTime,FromHost,Message from Syslog.SystemEvents;
+---------------------+----------+-----------------------------------------------------
| DeviceReportedTime  | FromHost | Message                                                                                                             |
+---------------------+----------+-----------------------------------------------------
| 2014-08-20 22:49:56 | stu13    |  [origin software="rsyslogd" swVersion="5.8.10" x-pid="2995" x-info="http://www.rsyslog.com"] start                 |
| 2014-08-20 22:50:39 | stu13    |  Installed: tree-1.5.3-2.el6.i686                                                                                   |
+---------------------+----------+---------------------------------------------------------------------------------------------------------------------+
20 rows in set (0.00 sec)

说明:

从select检索的数据中可以看出,日志服务器已经正常工作。


四、在192.168.60.40主机部署loganalyzer -3.6.5.tar.gz日志分析系统

说明

    其实loganalyzer是php网页文件,它从日志服务器中检索数据并以很直观的方式,动态显示出来。所以,日志分析系统工作要依赖于LAMP平台。在部署loganalyzer之前要安装好LAMP平台。

1、编译安装LAMP平台

说明:数据库使用,日志服务器的数据库。

(1)、准备编译httpd、php程序的环境

1
2
3
4
5
[root@node1 admin]# gcc --version
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

支持https 协议

1
2
[root@node1 admin]# rpm -qa | grep "openssl-devel"
openssl-devel-1.0.0-27.el6.i686

http 数据传输支持的压缩工具

1
2
[root@node1 admin]# rpm -qa | grep "zlib-devel"
zlib-devel-1.2.3-29.el6.i686

地址重写依赖的API

1
2
[root@node1 admin]# rpm -qa | grep "pcre-devel"
pcre-devel-7.8-6.el6.i686

httpd 2.4要求arp的版本要1.4以上,而系统上的版本不适用,要更新。

1
2
3
4
[root@node1 admin]# tar -xf apr-1.4.6.tar.bz2
[root@node1 admin]# cd apr-1.4.6
[root@node1 apr-1.4.6]# ./configure  --prefix=/usr/local/apr-1.4.6
[root@node1 apr-1.4.6]# make && make install
1
2
3
4
[root@node1 admin]# tar -xf apr-util-1.4.1.tar.bz2
[root@node1 admin]# cd apr-util-1.4.1
[root@node1 apr-util-1.4.1]# ./configure --prefix=/usr/local/apr-util-1.4 --with-apr=/usr/local/apr-1.4.6
[root@node1 apr-util-1.4.1]# make && make install

更新加密算库.

1
2
3
4
[root@node1 admin]# tar -xf libmcrypt-2.5.8.tar.bz2
[root@node1 admin]# cd libmcrypt-2.5.8
[root@node1 libmcrypt-2.5.8]# ./configure --prefix=/usr/local/libmcrypt
[root@node1 libmcrypt-2.5.8]# make && make install

(2)、编译httpd服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@node1 admin]# tar -xf httpd-2.4.1.tar.bz2
[root@node1 httpd-2.4.1]# ./configure \
--prefix=/usr/local/httpd-2.4 \
--sysconfdir=/etc/httpd-2.4  \          配置文件存放的位置
--enable-so \                           支持动态装卸载模块
--enable-mods-shared=all \              把所有共享模块都编译进来
--enable-ssl \                          支持使用https
--enable-mpms-shared=all \              支持mpm共享,把prefork、worker、event都编译进来
--enable-cgi \                          支持cgi
--enable-rewrite \                      支持地址重写功能
--with-apr=/usr/local/apr-1.4.6 \          指定apr的位置
--with-apr-util=/usr/local/apr-util-1.4 \   指定apr-util的位置
--with-pcre  \
--with-mpm=event \                   默认使用的mpm是event
--with-z


1
[root@node1 httpd-2.4.1]# make && make install


2、编译安装:PHP

1
2
root@node1 admin]# tar -xf php-5.4.26.tar.bz2
[root@node1 admin]# cd php-5.4.26

配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@node1 php-5.4.26]# ./configure \
--prefix=/usr/local/php-5.4 \
--with-apxs2=/usr/local/httpd-2.4/bin/apxs \
--enable-mod-charset  \
--enable-mbstring \
--with-config-file-path=/etc  \
--with-config-file-scan-dir=/etc/php.d \
--with-libxml-dir \
--with-openssl \
--with-zlib \             
--with-bz2 \
--with-pcre-dir \
--with-jpeg-dir \
--with-png-dir  \
--with-freetype-dir \
--with-gd \            支持gd库。
--enable-mbstring \     
--with-mcrypt=/usr/local/libmcrypt \    启用新的加密库
--with-mysql=/usr/local/mysql \         连接的数据库需要的驱动
--with-mysqli=/usr/local/mysql/bin/mysql_config


报错error:

1
2
3
4
checking for floorf... yes
checking for png_read_header in -ljpng... yes
If configure fails try --with-vpx-dir=<DIR>
configure: error: png.h not found.

说明:

     没有安装png的开发库

    查找yum源中是否有png提供的开发库

1
2
3
4
[root@node1 php-5.4.26]# yum list | grep -i png
jlibpng.i686                           2:1.2.49-1.el6_2                   @anaconda-RedHatEnterpriseLinux-201301301449.i386/6.4
dvipng.i686                            1.11-3.2.el6                       basic
libpng-devel.i686                      2:1.2.49-1.el6_2                    basic

安装开发库(png的API)

1
[root@node1 php-5.4.26]# yum instll libpng-devel

再次执行

1
2
[root@node1 php-5.4.26]# ./configure \
。。。。。。
1
[root@node1 php-5.4.26]#make && make install

说明:已经编译好php


提供php的配置文件

1
[root@node1 php-5.4.26]# cp php.ini-production  /etc/php.ini


2、测试:LAMP平台是否正常工作;

(1)、在httpd的配置文件中配置httpd使用php解析.php格式的网页

查看php模块是否安装到httpd中

1
2
[root@node1 php-5.4.26]# grep "LoadModule[[:space:]]*php" /etc/httpd-2.4/httpd.conf
LoadModule php5_module        modules/libphp5.so

设置主页

1
2
3
<IfModule dir_module>
    DirectoryIndex index.html index.php
</IfModule>

设置支持.php格式的网页文档

1
2
 AddType application/x-httpd-php .php
 AddType application/x-httpd-php-source .phps

(2)、测试是否能够连接MySQL数据库

1
2
3
4
5
6
7
8
9
[root@node1 httpd-2.4]#vim index.php
说明:index.php中的代码如下:
<?php
   $link = mysql_connect('192.168.60.40','admin','admin');
   if ($link)
      echo "Success...";
   else
      echo "Failure...";
?>

没启动数据库服务器之前:

1
2
[root@node1 httpd-2.4]# curl  http://192.168.60.40/index.php
Failure...

说明:连接数据库服务器失败

启动数据库服务器,并测试

1
2
3
4
[root@node1 httpd-2.4]# service mysqld start
Starting MySQL...                                          [  OK  ]
[root@node1 httpd-2.4]# curl  http://192.168.60.40/index.php
Success...

说明:

    已经连接到数据库服务器。证明:LAMP平台以经搭建成功。


3、部署loganalyzer -3.6.5.tar.gz日志分析系统

1
[root@node1 admin]# tar -xf loganalyzer-3.6.5.tar.gz

复制src目录下所以文件到httpd服务器的网页文件存放的目录下

1
[root@node1 loganalyzer-3.6.5]# cp -r ./src  /usr/local/httpd-2.4/htdocs/log

复制初始化使用的两个脚本并修改权限

1
2
3
[root@node1 loganalyzer-3.6.5]# cp contrib/*  /usr/local/httpd-2.4/htdocs/log/
[root@node1 loganalyzer-3.6.5]# cd /usr/local/httpd-2.4/htdocs/log/
[root@node1 log]# chmod u+x configure.sh secure.sh

执行脚本做初始化

1
2
[root@node1 log]# ./configure.sh
[root@node1 log]# ./secure.sh

修改配置文件的权限

1
[root@node1 log]# chmod 666 config.php

根据httpd服务器【User】和【Group】指令定义的用户名,也就是服务用户请求的进程(线程)的属主。修改loganalyzer提供的网页程序的属主属组。目录可以访问页面。

1
[root@node1 log]# chown -R daemon:daemon ./*


五、通过web接口配置日志分析系统loganalyzer

在浏览器输入:http://192.168.60.44/log

会打开下述窗口进行安装操作。

如何实现日志的集中化存储以及使用loganalyzer做日志分析

下一步:

如何实现日志的集中化存储以及使用loganalyzer做日志分析下一步:

如何实现日志的集中化存储以及使用loganalyzer做日志分析

点击“Finish!”会跳转到下述页面:

如何实现日志的集中化存储以及使用loganalyzer做日志分析

从上面可以看到:已经记录到两台主机(node1、stu13)的的日志数据信息了。








     本文转自成长的小虫 51CTO博客,原文链接:http://blog.51cto.com/9528du/1543758,如需转载请自行联系原作者