NFS网络文件共享存储服务

时间:2021-12-31 05:53:25

1.1 配置使用xinetd服务管理rsync实现开机自启动

1.1.1 检查xinetd服务是否安装

[root@backup ~]# rpm -qa xinetd

[root@backup ~]# rpm -ql xinetd

package xinetd is not installed

1.1.2 安装xinetd服务

[root@backup ~]# yum install xinetd -y

[root@backup ~]# rpm -qa xinetd

xinetd-2.3.14-40.el6.x86_64

1.1.3 修改/etc/xinetd/rsync文件

NFS网络文件共享存储服务

 

yes 改为no 即可被xinetd管理

更改完成后重启服务

/etc/init.d/xinetd restart

NFS网络文件共享存储服务

 

1.1.1 重启系统发现873端口交由xinetd管理

[root@backup ~]# netstat -lntup |grep 873

tcp 0 0 :::873 :::* LISTEN 1229/xinetd

1.2 NFS简介

NFS是Network File System的缩写,中文意思是网络文件系统,

NFS的主要功能是通过网络(一般是局域网)让不同的主机系统之间可以彼此共享文件或目录,

NFS网络文件系统适用于处理量级较小的业务,

如果大型网站,那么有可能还会用到更复杂的分布式文件系统,例如:Moosefs(mfs)、GlusterFS、FastDFS。

NFS是一个服务,与rsync服务类似,NFS服务也既有服务端、又有客户端

1.3 NFS网络文件系统的意义

1.实现数据信息统一一致;

2.节省局域网数据同步传输的带宽;

3.节省网站架构中服务器硬盘资源。

NFS网络文件共享存储服务

 

1.1 NFS系统存储原理

 

1.服务端提供可以被挂载的磁盘空间(共享目录);

2.客户端准备好本地挂载目录(挂载点);

3.客户端使用mount命令,将服务端的共享目录挂载到客户端的挂载点上。

 

1.2 两句话解释NFS服务端共享目录

 

以把NFS想象成一个移动硬盘或者U盘,服务端的共享目录,对于客户端来说,就是一块等待被使用的磁盘。

NFS服务端的共享目录可以被多个客户端挂载,就像一个多接口的移动电源,只要插上电源线,就可以同时给多部手机充电了。

 

1.3 RPC介绍

 

RPC协议的默认端口为111。

NFS的RPC服务最主要的功能就是记录每个NFS功能所对应的端口号,

并且在NFS客户端请求时将该端口和功能对应的信息传递给请求数据的NFS客户端,

从而确保客户端可以连接到正确的NFS端口上去,达到实现数据传输和交互数据的目的。

形象的说,这个RPC服务就像是连接NFS服务端和NFS客户端的一个中介,架起它们互相连接的桥梁。

拿房屋中介打个比喻:

租客要找房子,这里的租客就相当于NFS客户端;

中介负责介绍房子,这里的中介就相当于RPC服务;

房子所有者房东要将房子出租出去,这里的房东就相当于NFS服务;

租客找房子,就要找中介,中介要预先存有房子主人的信息,才能将房源信息告诉租客。

 

 

 

1.4 NFS工作流程

 

1.先启动RPC服务

2.启动NFS服务

3.客户请求NFS服务

4.返回端口到客户

5.拿着地址端口请求传输数据

 

1.5 NFS服务必需的软件

 

要部署NFS服务,必须安装两个软件包:nfs-utils和rpcbind。

nfs-utils:NFS主程序。包括rpc.nfsd、rpc.mountd两个daemons和相关文档说明及执行命令文件等;

rpcbind:RPC主程序。NFS可以被视为一个RPC程序,在启动任何一个RPC程序之前都需要做好端口和功能的对应映射工作,

这个映射工作就是由rpcbind完成的。因此,在提供NFS服务之前必须先启动rpnbind服务。

 

1.6 NFS服务端部署流程

 

服务端需要安装nfs-untils和rpcbind。

另外,由于NFS及其辅助程序都基于RPC协议(使用的端口为111),所以需要特殊注意,首先要确保系统中运行了rpcbind服务,即必须先启动rpcbind服务,然后再启动nfs服务

 

1.6.1 服务器环境检查

 

rpm -qa |egrep “rpcbind|nfs-utils”

 

1.6.2 安装NFSrpcbind

 

yum install -y rpcbind nfs-utils

 

1.6.3 编写NFS服务配置文件

 

NFS服务默认的配置文件为/etc/exports,并且里面初始没有内容,是个空文件,需要用户自行配置。

可以使用vim命令来编辑此文件,在其内添加如下内容:

/data/ 172.16.1.0/24(rw,sync)

也可以使用echo或cat命令来实现:

echo ‘/data/ 172.16.1.0/24(rw,sync)’ /etc/exports

cat > /etc/exports << EOF

##########config NFS server start by oldboy 2018-05-21##########

/data/ 172.16.1.0/24(rw,sync)

##########config NFS server end by oldboy 2018-05-21##########

EOF

NFS配置文件内容介绍:

a./data/为要共享的NFS服务端的目录,注意,被共享的目录一定要使用绝对路径;

b.172.16.1.0/24表示允许NFS客户端访问共享目录的网段范围,24表示255.255.255.0;

c. (rw,sync)中的rw表示允许读写,sync表示数据同步写入到NFS服务端的硬盘中;

d.配置文件里的“24”和“(”之间不能有空格,这一点一定要注意;

e.也可以使用通配符*替换IP地址,表示允许所有主机,即写成172.16.1.*的形式。

编辑完毕后,记得检查一下。

cat /etc/exports

 

1.6.4 创建服务端共享目录

 

mkdir -p /data/

 

1.6.5 设置服务端共享目录的属主和属组

 

NFS服务默认使用的用户和用户组是nfsnobody,所以需要将本地同步目录属主和属组为相应的用户。

命令:chown -R nfsnobody.nfsnobody /data/

 

1.6.6 启动及检查rpcbind服务

 

因为NFS及其辅助程序都是基于RPC协议的(端口为111),所以首先要确保系统中运行了rpcbind服务。

命令:/etc/init.d/rpcbind start

检查端口:lsof -i:111

检查rpcbind服务状态:/etc/init.d/rpcbind status

 

1.6.7 启动及检查nfs服务

 

注意,一定要确保rpcbind服务已经启动正常,再启动nfs服务。

命令:/etc/init.d/nfs start

检查nfs服务状态:/etc/init.d/nfs status

查看nfs服务向rpc服务注册的端口信息的命令:

rpcinfo -p localhost

或rpcinfo -p 127.0.0.1

 

1.6.8 重启nfs服务

 

 

 

如果修改了nfs的配置文件/etc/exports的话,需要重启服务才能使修改生效。

为了提供比较友好的用户体验,建议使用nfs服务平滑重启的参数reload,而不是直接使用restart参数。

命令:/etc/init.d/nfs reload

 

1.6.9 检查NFS服务端共享目录信息

 

可以使用showmount命令检查NFS服务端共享目录的信息。

命令:showmount -e localhost

或    showmount -e 127.0.0.1

或    showmount -e 172.16.1.31

 

1.6.10 服务端设置开机自启动rpcbindnfs

 

想要让rpcbind和nfs服务开机自启动,可以使用chkconfig命令来实现。

命令:chkconfig rpcbind on

chkconfig nfs on

检查:chkconfig --list | egrep -i “rpcbind|nfs”

 

1.6.11 服务端查看NFS默认自带的参数

 

配置并启动好NFS服务后,通过cat /var/lib/nfs/etab命令可以看到NFS配置的参数及默认自带的参数。

命令:cat /var/lib/nfs/etab

 

1.7 NFS客户端配置流程

 

1.7.1 服务器环境检查

 

无论做什么操作,都应该养成一个好的习惯,那就是先进行检查,再上手操作。

所以第一步应该先检查服务器上是否已经安装了rpcbind和nfs-utils软件。

命令:rpm -qa rpcbind nfs-utils

或    rpm -qa |egrep “rpcbind|nfs-utils”

 

1.7.2 安装NFSrpcbind

 

yum install -y rpcbind nfs-utils

 

1.7.3 启动及检查rpcbind服务

 

因为NFS及其辅助程序都是基于RPC协议的(端口为111),所以首先要确保系统中运行了rpcbind服务。

命令:/etc/init.d/rpcbind start

检查端口:lsof -i:111

检查rpcbind服务状态:/etc/init.d/rpcbind status

 

1.7.4 客户端设置开机自启动rpcbind

 

chkconfig rpcbind on

检查:chkconfig --list | egrep -i rpcbind

 

1.7.5 创建客户端本地挂载目录

 

想要挂载NFS服务端的共享目录,在客户端必须要有一个用于挂载的目录。

命令:mkdir -p /nfs_dir

 

1.7.6 客户端挂载NFS服务端共享目录

 

以上步骤全部操作完毕后,就可以在客户端挂载NFS服务端的共享目录了。

挂载命令:

mount -t nfs 172.16.1.31:/data/ /nfs_dir/

可以使用df或mount命令结合grep来检查是否挂载成功。

命令:df -h | grep '172.16.1.31'

或    mount | grep '172.16.1.31'

 

1.7.7 客户端设置开机自动挂载NFS服务端的共享目录

 

如果需要让客户端开机自动挂载NFS服务端的共享目录,有两种方法。

方法一:将挂载命令放在/etc/rc.local文件里。

缺点:可能会出现偶尔开机挂载不上的情况,工作中如果使用这种方法,除了开启自启动的配置以外,还有对是否挂载成功做监控。

配置/etc/rc.local文件的命令:

echo ‘# mount NFS server by oldboy 2018-05-21 #’ >> /etc/rc.local

echo ‘mount -t nfs 172.16.1.31:/data/ /nfs_dir/’ >> /etc/rc.local

方法二:将挂载信息放在/etc/fstab文件里。

这种方法有一个需要特殊注意的地方:fstab会优于网络被linux系统加载

网络没启动时执行fstab里配置的远程挂载会导致连接不上NFS服务端,无法实现开机正常挂载NFS远程共享目录。

但是,这个问题是可以被解决的,解决方法就是,在客户端启动netfs服务,并且让这个服务开机自启动

:/etc/init.d/netfs start;chkconfig netfs on

配置/etc/fstab文件的命令:

echo ’172.16.1.31:/data/  /nfs_dir   nfs    default    0 0’ >> /etc/fstab

 

1.7.8 客户端查看mount挂载NFS的参数

 

NFS客户端挂载好服务端的共享目录后,通过grep '172.16.1.31' /proc/mounts命令可以看到mount的详细参数。

命令:grep '172.16.11' /proc/mounts

 

1.8 /etc/exports配置文件格式

 

NFS服务默认的配置文件为/etc/exports,并且默认内容为空,需要使用者自行配置。

/etc/exports文件配置格式为:

NFS共享的目录 NFS客户端地址1(参数1,参数2,…) 客户端地址2(参数1,参数2,…)

NFS共享的目录 NFS客户端地址(参数1,参数2,…)

其中各个列的参数含义如下:

a.NFS共享的目录:为NFS服务端要共享的实际目录,要使用绝对路径。需要注意共享目录的本地权限,如果需要读写共享,一定要让本地目录可以被NFS客户端的用户(nfsnobody)读写;

b.NFS客户端地址:为NFS服务端授权的可访问共享目录的NFS客户端地址。可以为单独的IP地址或主机名、域名等,也可以为整个网段地址,还可以用“*”来匹配所有客户端服务器。这里所谓的客户端一般来说是前端的业务服务器;

c.权限参数集:对授权的NFS客户端所能拥有的访问权限的设置。

 

                1.  

 

案例1: /data 10.0.0.0/24(rw,rsync)  允许客户端读写,并且数据写入到服务端磁盘中。

案例2:/data 10.0.0.0/24(rw,rsync,all_squash,anonuid=2000,anongid=2000)

        允许客户端读写,并且数据同步写入到服务器端的磁盘中,并且指定客户端的用户GID和UID

案例3: /home/oldboy  10.0.0.0/24(ro) 只读  允许客户访问10.0.0.0段,但是只有可读权限。他会应用到测试环境中,线上环境不允许修改,所以设置了ro 可读。不给开发rw权限。

 

1.1 /etc/exports配置文件说明

1.1.1 /etc/exports文件说明

NFS共享目录:

NFS服务器端要共享的实际目录,要用绝对路径,如/data )。注意共享目录的本地权限,如果需要读写共享,一定要让本地目录可以被 NFS客户端的用户nfsnobody)读写

NFS客户端地址:

为NFS服务器端授权的可访问共享目录的NFS客户端地址,可以为单独的IP地址或主机名、域名等,也可以为整个网段地址。还可以用来匹配所有客户端服务器,这里所谓的客户端一般来说是前端的业务的业务服务器,例如:web服务。

权限参数集

对授权的NFS客户端的访问权限设置。

nfs权限(共享目录\借给你手机)nfs配置的/ etc/exports /data 172.16.1.0/24(rw)

本地文件系统权限(\手机密码不告诉你)挂载目录的权限rwxr- xr-x root root/data

1.2 NFS服务端设置rpcbind nfs开机自启动

[root@nfs01 ~]#  chkconfig rpcbind on

[root@nfs01 ~]#  chkconfig nfs  on

[root@nfs01 ~]#  chkconfig |egrep "rpcbinf|nfs"

nfs             0:off  1:off  2:on   3:on   4:on   5:on   6:off

nfslock         0:off  1:off  2:off  3:on   4:on   5:on   6:off

1.3 nfs配置参数说明

注意:nfs服务默认没有认证机制,安全性不如分布式文件系统

只能通过控制配置文件中网络地址信息,实现安全性

基本配置语法:

共享的目录              共享的主机      参数选项

/data                   172.16.1.0/24       rw,sync

                1. 企业两类案例:

/data 172.16.1.0/24(rw,sync)

多个客户端共享可读可写,默认的匿名用户65534

/backup  172.16.1.0/24(rw,sync,all_squash,anonuid=999,anongid=999)

改变匿名用户,指定匿名用户uid=999

参数

说明

rw

可读写的权限

ro 

只读的权限

no_root_squash

登入NFS主机,使用该共享目录时相当于该目录的拥有者,如果是root的话,

那么对于这个共享的目录来说,他就具有root的权限,这个参数『极不安全』,不建议使用

root_squash

登入NFS主机,使用该共享目录时相当于该目录的拥有者。但是如果是以root身份使用这个共享目录

的时候,那么这个使用者(root)的权限将被压缩成为匿名使用者,即通常他的UID与GID都会

变成nobody那个身份

all_squash

不论登入NFS的使用者身份为何,他的身份都会被压缩成为匿名使用者,

通常也就是nobody

anonuid

可以自行设定这个UID的值,这个UID必需要存在于你的/etc/passwd当中

anongid

同anonuid,但是变成groupID就是了

sync

资料同步写入到内存与硬盘当中

async

资料会先暂存于内存当中,而非直接写入硬盘

insecure

允许从这台机器过来的非授权访问

1.4 nfs配置参数实践

1.4.1 all_squash 参数实践

服务端修改配置

[root@nfs01 ~]# vim /etc/exports

#share 20171013 hzs

/data 172.16.1.0/24(rw,sync,all_squash)

[root@nfs01 ~]# /etc/init.d/nfs reload

         配置修改需要平滑重启nfs 服务

         reload    平滑重启

         用户的访问体验更好

nfs客户端进行测试

[root@backup mnt]# touch test.txt

[root@backup mnt]# ll

-rw-r--r-- 1 nfsnobody nfsnobody    8 Oct 13 11:28 test.txt

[root@backup ~]# su - clsn

[clsn@backup ~]$ cd /mnt/

[clsn@backup mnt]$ touch clsn1.txt

[clsn@backup mnt]$ ll

-rw-rw-r-- 1 nfsnobody nfsnobody    0 Oct 13 12:34 clsn1.txt

-rw-r--r-- 1 nfsnobody nfsnobody    8 Oct 13 11:28 test.txt

说明:

不论登入NFS的使用者身份为何,他的身份都会被压缩成为匿名使用者,通常也就是nobody

1.4.2 no_all_squash,root_squash 参数实践

服务端修改配置

[root@nfs01 ~]# vim /etc/exports

#share 20171013 hzs

/data 172.16.1.0/24(rw,sync,no_all_squash,root_squash)

[root@nfs01 ~]# /etc/init.d/nfs reload

客户端卸载重新挂载(服务器配置修改后客户端要重新挂载

[root@backup ~]# umount /mnt/

[root@backup ~]# mount -t nfs 172.16.1.31:/data /mnt

nfs客户端测试结果:

[root@backup mnt]# touch test1.txt

[root@backup mnt]# ll

-rw-r--r-- 1 nfsnobody nfsnobody    0 Oct 13 12:37 test1.txt

[root@backup mnt]# su - clsn

[clsn@backup ~]$ cd /mnt/

[clsn@backup mnt]$ touch clsn1.txt

touch: cannot touch `clsn1.txt': Permission denied

[clsn@backup mnt]$ touch clsn2.txt

touch: cannot touch `clsn2.txt': Permission denied

# 服务端验证:

[root@nfs01 ~]# ll /data/

-rw-rw-r-- 1 nfsnobody nfsnobody    0 Oct 13 12:34 clsn1.txt

-rw-r--r-- 1 nfsnobody nfsnobody    0 Oct 13 12:37 test1.txt

-rw-r--r-- 1 nfsnobody nfsnobody    8 Oct 13 11:28 test.txt

说明:no_all_squash,是所有用户都不进行压缩,所以clsn用户对nfs的目录没有写入的权限(与nfs服务器的共享目录权限有关)。root用户进行压缩所以可以写入。

1.4.3 no_root_squash 参数实践(root用户不进行压缩映射)

服务端修改配置

[root@nfs01 ~]# vim /etc/exports

#share 20171013 hzs

/data 172.16.1.0/24(rw,sync,no_root_squash)

[root@nfs01 ~]# /etc/init.d/nfs reload

客户端卸载重新挂载服务器配置修改后客户端要重新挂载

[root@backup ~]# umount /mnt/

[root@backup ~]# mount -t nfs 172.16.1.31:/data /mnt

nfs客户端测试结果:

[root@backup mnt]# touch root.txt

[root@backup mnt]# ll

total 16

-rw-rw-r-- 1 nfsnobody nfsnobody    0 Oct 13 12:34 clsn1.txt

-rw-r--r-- 1 root      root         0 Oct 13 12:45 root.txt

-rw-r--r-- 1 nfsnobody nfsnobody    0 Oct 13 12:37 test1.txt

-rw-r--r-- 1 nfsnobody nfsnobody    8 Oct 13 11:28 test.txt

删除测试

[root@backup mnt]# rm -rf ./*

[root@backup mnt]# ll

total 0

说明:由于对root用户没有进行压缩,所以到达nfs服务器后依旧是root身份,root用户默认对所有的文件都有权限,所以可以写入。(很危险)

1.5 NFS客户端访问服务原理

NFS网络文件共享存储服务

 

1.1.1 指定 NFS客户端地址的配置详细说明

客户端地址           

具体地址        

授权单一客户端访问NFS

10.0.0.30

一般情况,生产环境中此配置不多

授权整个网段可访问NFS

10.0.0.0/24

其中的24等同于255.255.255.0 ,指定网段为生产环境中最常见的配置

。配置简单,维护方便

授权整个网段可访问NFS

10.0.0.*

指定网段的另外写法(不推荐使用)

授权某个域名客户端访问

nfs.clsnedu.com

此方法生产环境中一般情况不常用

授权整个域名客户端访问

*.clsnedu.com

此方法生产环境中一般情况不常用

                1. 常见案例

常用格式说明

要共享的目录客户端IP地址或IP(1,2,)

配罝例一

/data10.0.0.0/24(ro,sync)

说明:允许客户端读写,并且数据同步写入到服务器揣的磁盘里

注意:24和"("之间不能有空格

配置例二

/data10.0.0.0/24(rw,sync/all_squash,anonuid=2000,anongid=2000)

说明:允许客户揣读写,并且数据同步写到服务器揣的磁盘里,并且指走客户端

的用户UID和GID,早期生产环境的一种配罝,适合多客户端共享一个NFS服务

单目录,如果所有服务器的nfsnobody账户UID都是65534,则本例没什么必

要了.早期centos5.5的系统默认情况下nfsnobody的UID不一定是65534,

此时如果这些服务器共享一个NFS目录,就会出现访问权限问题.

配置例三

/home/clsn10.0.0.0/24(ro)

说明:只读共享

用途:例如在生产环境中,开发人员有查看生产眼务器日志的需求,但又不希罜

给开发生产服务器的权限,那么就可以给开发提供从某个测试服务器NFS客户端

上查看某个生产服务器的日志目录(NFS共享)的权限,当然这不是唯一的方法,

例如可以把程序记录的日志发送到测试服务器供开发查看或者通过收集日志等其

1.2 客户端挂载及参数

1.2.1 挂载命令

mount -t   文件类型  IP:共享目录    挂载点

mount -o   挂载参数

1.2.2 挂载参数

   noatime                           atime

   noexec                            exec

   nodev                             dev

   nosuid                            suid

   nodiratime                        diratime

async sync remount rw ro

1.2.3 客户端开机自动挂载

把mount -t nfs IP:共享目录 挂载点 这个命令追加到 /etc/rc.local内

写入/etc/fstab的话,需要开启netfs服务,否则无法加载,因为在开机时先执行/etc/fstab脚本,

在执行/etc/sysconfig/network脚本,导致加载fstab时没有网络,连接不到服务端,无法挂载。

1.2.4 缺点

1、单点

2、数据没加密,没有用户认证(主机认证)

3、服务器宕机,客户端夯住。

4、并发访问能力小(2000PV访问量以内)

NFS服务端宕机,客户端会夯住,卡死。

查看客户端mount的参数文件 /proc/mounts

                1.  

[root@web01 ~]# tail -2 /proc/mounts

172.16.1.31:/data/ /video nfs4 rw,relatime,vers=4,rsize=65536,wsize=65536,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=172.16.1.7,minorversion=0,local_lock=none,addr=172.16.1.31 0 0

172.16.1.31:/backup/ /w nfs4 rw,relatime,vers=4,rsize=65536,wsize=65536,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=172.16.1.7,minorversion=0,local_lock=none,addr=172.16.1.31 0 0

1.2.5 客户端挂载性能优化:

mount -t nfs -o async,noatime,nodiratime,rsize=131072,wsize=131072  10.0.0.18:/data /mnt

如果对安全有要求就加nosuid,noexec,nodev

NFS官方内核优化可以修改,官方的建议:

[root@c58-nfs-server ~]# cat /proc/sys/net/core/rmem_default

8388608

[root@c58-nfs-server ~]# cat /proc/sys/net/core/rmem_max    

16777216

[root@c58-nfs-server ~]# echo 262144 > /proc/sys/net/core/rmem_default

[root@c58-nfs-server ~]# echo 262144 > /proc/sys/net/core/rmem_max

1.2.6 NFS生产场景内核优化

1)缺省设置:10240

/proc/sys/net/core/rmem_default

该文件指定了接收套接字缓冲区大小的缺省值(以字节为单位)。

2)缺省设置:110592

/proc/sys/net/core/rmem_max

该文件指定了接收套接字缓冲区大小的最大值(以字节为单位)。

3)缺省设置:131071

/proc/sys/net/core/wmem_default

该文件指定了发送套接字缓冲区大小的缺省值(以字节为单位)。 socket

4)缺省设置:110592

/proc/sys/net/core/wmem_max

该文件指定了发送套接字缓冲区大小的最大值(以字节为单位)。

cat >>/etc/sysctl.conf<<EOF

net.core.wmem_default = 8388608

net.core.rmem_default = 8388608

net.core.rmem_max = 16777216

net.core.wmem_max = 16777216

EOF

sysctl -p

命令行:

echo 8388608 > /proc/sys/net/core/rmem_default   

echo 16777216 > /proc/sys/net/core/rmem_max

 

1.2.7 从网站架构优化NFS

最高境界就是不访问NFS,前端使用CDN(分布式缓存)

200多万IP5000PV 还能用。 10000pv

1、使用CDN分布式外部缓存。挡住98%的访问,最低挡住90%1000 0台(一个月花5000钱)

2、内部用缓存(nginx,varnish,squid),一般用不到。 90% 100 1

3、读请求不访问NFS,而是把NFS数据推送到前端的服务器,访问本地。90% 10 1

4/backup根据目录拆分为不同的服务器。

4.1/backup/bss

4.2/backup/blog

4.3/backup/cms

bbs拆分为一台机器

blog拆分为一台机器

cms拆分为一台机器

----------------------------

4.1.1/backup/bss/a1拆分为一台机器

4.1.2/backup/bss/a2拆分为一台机器

4.1.3/backup/bss/a3拆分为一台机器