基于nginx 模块 ngx_http_stub_status_module 实现,在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module,否则配置完成之后监测会是提示语法错误注意: 状态页显示的是整个服务器的状态,而非虚拟主机的状态。
状态页用于输出 nginx 的基本状态信息:
为了安全考虑,可以搭配验证模块一起使用
server {
listen 80;
server_name www.lucky.com;
root /data/html;
location /status {
stub_status;
auth_basic "welcome future";
auth_basic_user_file /mnt/.nginxuser;
}
}
只允许自己,拒绝所有
server {
listen 80;
server_name www.lucky.com;
root /data/html;
location /status {
stub_status;
auth_basic "welcome future";
auth_basic_user_file /mnt/.nginxuser;
allow 192.168.91.3;
deny all;
}
}
更改子配置文件:
编译之前,先关闭 nginx,导入压缩包,并解压
[root@localhost opt]# unzip echo-nginx-module-master.zip
[root@localhost opt]# cd nginx-1.18.0/
[root@localhost nginx-1.18.0]# systemctl stop nginx
[root@localhost nginx-1.18.0]# ./configure --help | grep add
--with-http_addition_module enable ngx_http_addition_module
--add-module=PATH enable external module
[root@localhost nginx-1.18.0]# ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/opt/echo-nginx-module-master
[root@localhost nginx-1.18.0]# make && make install
[root@localhost nginx-1.18.0]# systemctl start nginx
官方文档 http://nginx.org/en/docs/varindex.html
$remote_addr | 存放了客户端的地址,注意是客户端的公网IP |
$args | 变量中存放了URL中的参数 |
$document_uri | 保存了当前请求中不包含参数的URI,注意是不包含请求的指令 |
$host | 存放了请求的host名称服务端的地址 |
$request_filename | 当前请求的资源文件的磁盘路径,由root或alias指令与URI请求生成的文件绝对路径 |
$scheme | 请求的协议,例如:http,https,ftp |
$http_user_agent | 客户端浏览器的详细信息 |
$http_cookie | 客户端的cookie信息 |
$document_root | 保存了针对当前资源的请求的系统根目录 |
假如需要自定义变量名称和值,使用指令 set $variable value;
访问日志是记录客户端即用户的具体请求内容信息,而在全局配置模块中的 error log 是记录 nginx服务器运行时的日志保存路径和记录日志的 level,因此两者是不同的,而且Nginx的错误日志一般只有一个,但是访问日志可以在不同 server 中定义多个,定义一个日志需要使用 access_log 指定日志的保存路径,使用 log_format 指定日志的格式,格式中定义要保存的具体日志内容。
访问日志由 ngx_http_log_module 模块实现
Syntax: access_log path [format [buffer=size] [gzip[=level]] (flush=time] [if=condition]];access_log off;
Defau1t:
access_log 1ogs/access.1og combined;
Context: http,server, location,if in location,limit_except
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'
'$server_name:$server_port';
log_format test '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'
'$server_name:$server_port';
格式可以定义多个
###注意如果开启 include 注意定义自配置文件与 日志格式的上下关系 , 日志格式一定要在 include 之前 否则会不生效。
查看
可以配置它以输出自定义的JSON格式日志。这种格式对于日志记录和后续分析非常有用,因为JSON格式易于解析并且适合于许多日志分析工具,如方便ELK收集日志。
修改主配置文件:
[root@localhost ~]# vim /apps/nginx/conf/nginx.conf
30 log_format access_json '{"@timestamp":"$time_iso8601",'
31 '"host":"$server_addr",'
32 '"clientip":"$remote_addr",'
33 '"size":$body_bytes_sent,'
34 '"responsetime":$request_time,'
35 '"upstreamtime":"$upstream_response_time",'
36 '"upstreamhost":"$upstream_addr",'
37 '"http_host":"$host",'
38 '"uri":"$uri",'
39 '"xff":"$http_x_forwarded_for",'
40 '"referer":"$http_referer",'
41 '"tcp_xff":"$proxy_protocol_addr",'
42 '"http_user_agent":"$http_user_agent",'
43 '"status":"$status"}';
44 access_log logs/access.log access_json;
查看json格式日志:
{"@timestamp":"2024-02-25T21:54:30+08:00", '"host":"192.168.190.102",' '"clientip":"192.168.190.100",' '"size":612,' '"responsetime":0.000,' '"upstreamtime":"-",' '"upstreamhost":"-",' '"http_host":"192.168.190.102",' '"uri":"/index.html",' '"xff":"-",' '"referer":"-",' '"tcp_xff":"-",' '"http_user_agent":"curl/7.29.0",' '"status":"200"}'
支持对指定类型的文件进行压缩然后再传输给客户端,而且压缩还可以设置压缩比例,压缩后的文件大小将比源文件显著变小,这样有助于降低出口带宽的利用率,降低企业的IT支出,不过会占用相应的CPU资源。Nginx对文件的压缩功能是依赖于模块 ngx_http_gzip_module
#启用或禁用gzip压缩,默认关闭
gzip on | off;
#压缩比由低到高从1到9,默认为1
gzip_comp_level level;
#禁用IE6 gzip功能
gzip_disable "MSIE [1-6]\.";
#gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
#启用压缩功能时,协议的最小版本,默认HTTP/1.1
gzip_http_version 1.0 | 1.1;
#指定Nginx服务需要向服务器申请的缓存空间的个数和大小,平台不同,默认:32 4k或者16 8k;
gzip_buffers number size;
#指明仅对哪些类型的资源执行压缩操作;默认为gzip_types text/html,不用显示指定,否则出错
gzip_types mime-type ...;
#如果启用压缩,是否在响应报文首部插入“Vary: Accept-Encoding”,一般建议打开
gzip_vary on | off;
#预压缩,先压缩好,不用临时压缩,消耗cpu
gzip_static on | off;‘
太小的文件没必要压缩,压缩说不定变大了
测试
如果不是 200,按ctrl强制刷新:
gzip_static on | off 预压缩,先压缩好,不用临时压缩,消耗cpu
更改配置文件:
更改子配置文件:
压缩文件:
[root@localhost data]# gzip index.html
[root@localhost data]# ls
index.html.gz
[root@localhost data]# mv index.html.gz m.html.gz
测试
Web网站的登录页面都是使用https加密传输的,加密数据以保障数据的安全,HTTPS能够加密信息,以免敏感信息被第三方获取,所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议,HTTPS其实是有两部分组成:HTTP + SSL / TLS,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。
过程:
1.客户端发起HTTPS请求
用户在浏览器里输入一个 https 网址,然后连接到服务器的 443 端口
2.服务端的配置
采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请,区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面。这套证书其实就是一对公钥和私钥
3.传送服务器的证书给客户端
证书里其实就是公钥,并且还包含了很多信息,如证书的颁发机构,过期时间等等
4.客户端解析验证服务器证书
这部分工作是由客户端的TLS来完成的,首先会验证公钥是否有效,比如:颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框提示证书存在问题。如果证书没有问题,那么就生成一个随机值,然后用证书中公钥对该随机值进行非对称加密
5.客户端将加密信息传送服务器
这部分传送的是用证书加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加感解密了
6. 服务端解密信息
服务端将客户端发送过来的加密信息用服务器私钥解密后,得到了客户端传过来的随机值
7.服务器加密信息并发送信息
服务器将数据利用随机值进行对称加密,再发送给客户端
8.客户端接收并解密信息
客户端用之前生成的随机值解密服务段传过来的数据,于是获取了解密后的内容
nginx 的 https 功能基于模块 ngx_http_ssl_module 实现,因此如果是编译安装的nginx要使用参数 ngx_http_ssl_module 开启 ssl 功能,但是作为 nginx 的核心功能,yum安装的 nginx 默认就是开启的,编译安装的nginx需要指定编译参数 --with-http_ssl_module 开启
ssl on | off;
#为指定的虚拟主机配置是否启用ssl功能,此功能在1.15.0废弃,使用listen [ssl]替代
listen 443 ssl;
ssl_certificate /path/to/file;
#指向包含当前虚拟主机和CA的两个证书信息的文件,一般是crt文件
ssl_certificate_key /path/to/file;
#当前虚拟主机使用的私钥文件,一般是key文件
ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];
#支持ssl协议版本,早期为ssl现在是TLS,默认为后三个
ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
#配置ssl缓存
off: #关闭缓存
none: #通知客户端支持ssl session cache,但实际不支持
builtin[:size]:#使用OpenSSL内建缓存,为每worker进程私有
[shared:name:size]:#在各worker之间使用一个共享的缓存,需要定义一个缓存名称和缓存空间大小,一兆可以存储4000个会话信息,多个虚拟主机可以使用相同的缓存名称
ssl_session_timeout time;
#客户端连接可以复用ssl session cache中缓存的有效时长,默认5m
编译安装的nginx需要指定编译参数 --with-http_ssl_module 开启
#所有的证书需要放在一起不能移开
bash certificate.sh
cat kgc.com.crt ca.crt > www.kgc.com.crt
#kgc.com.crt(购买者)
#ca.crt(颁发者)
mv kgc.com.key www.kgc.com.key
#www.kgc.com.key(验证钥匙)
[root@localhost ~]# cd /data
[root@localhost data]# ls
[root@localhost data]# mkdir ssl
[root@localhost data]# cd ssl/
[root@localhost ssl]# rz -E
rz waiting to receive.
[root@localhost ssl]# ls
certificate.sh
[root@localhost ssl]# bash certificate.sh
[root@localhost ssl]# ls
ca.crt ca.key certificate.sh kgc.com.crt kgc.com.csr kgc.com.key
[root@localhost ssl]# cat kgc.com.crt ca.crt > www.kgc.com.crt
[root@localhost ssl]# mv kgc.com.key www.kgc.com.key
[root@localhost ssl]# ll www*
-rw-r--r--. 1 root root 2201 2月 26 10:25 www.kgc.com.crt
-rw-------. 1 root root 1704 2月 26 10:23 www.kgc.com.key
生成私钥工具:
更改子配置文件:
测试
Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求,此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE库,rewrite是nginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用的功能,比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为自动访问,另外还可以在一定程度上提高网站的安全性。
用于条件匹配判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进行配置,Nginx的if语法仅能使用if做单次判断,不支持使用if else或者if elif这样的多重判断,用法如下:
格式
if (条件匹配) {
action
}
使用正则表达式对变量进行匹配,匹配成功时if指令认为条件为true,否则认为false,变量与表达式之间使用以下符号链接:
location /main {
index index.html;
default_type text/html;
if ( $scheme = http ){
echo "if-----> $scheme";
}
if ( $scheme = https ){
echo "if ----> $scheme";
}
#if (-f $request_filename) {
# echo "$request_filename is exist";
#}
if (!-e $request_filename) {
echo "$request_filename is not exist";
#return ;
}
}
示例
return用于完成对请求的处理,并直接向客户端返回响应状态码,比如:可以指定重定向URL(对于特殊重定向状态码,301/302等) 或者是指定提示文本内容(对于特殊状态码403/500等),处于此指令后的所有配置都将不被执行,return可以在server、if 和 location块进行配置
语法格式:
location /main {
index index.html;
default_type text/html;
if ( $scheme = http ){
return 666 "if-----> $scheme"; #如果是http的 打印http
}
if (!-e $request_filename){
return 302 /index.html; #如果用户不存在,返回302,直接跳转到主页面
}
任意跳转:
location / {
root /data;
if (!-e $request_filename){
return 302 http://www.baidu.com;
}
}
如果访问不存在就跳转到百度
测试
301 和 302区别:
301 永久重定向 读取过一次,就会将此条配置缓存在我们的客户端,即使 nginx 宕机,在缓存时间内,还是可以跳转。
302 临时重定向 不会有缓存在客户端,每次跳转需要 nginx 服务器解析,一旦服务器宕机就无法跳转
自定义内容:
指定key并给其定义一个变量,变量可以调用Nginx内置变量赋值给key,另外set定义格式为set $key value,value可以是text, variables和两者的组合。
location /main {
root /data/nginx/html/pc;
index index.html;
default_type text/html;
set $name kgc;
echo $name;
set $my_port $server_port(nginx 自带的变量 服务端口 一般80);
echo $my_port;
}
实例
用于中断当前相同作用域(location)中的其他Nginx配置,与该指令处于同一作用域的Nginx配置中,位于它前面的配置生效,位于后面的 ngx_http_rewrite_module 模块中指令就不再执行,Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置,该指令可以在server块和locationif块中使用。
注意: 如果break指令在location块中后续指令还会继续执行,只是不执行 ngx_http_rewrite_module 模块的指令,其它指令还会执行
location /main {
root /data/nginx/html/pc;
index index.html;
default_type text/html;
set $name kgc;
echo $name;
break; #location块中break后面指令还会执行
set $my_port $server_port;
echo $my_port;
}
示例
注意: 如果break指令在location块中后续指令还会继续执行,只是不执行 ngx_http_rewrite_module 模块的指令,其它指令还会执行。
通过正则表达式的匹配来改变URI,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配,rewrite主要是针对用户请求的URL或者是URI做具体处理.
语法格式:
rewrite可以配置在 server、location、if
语法格式 :
rewrite regex replacement(www.baidu.com) [flag];
正则匹配原始访问url 替代你想让客户访问的 标志 ()premanent301
redirect302 break last
rewrite 将用户请求的URI基于regex所描述的模式进行检查,匹配到时将其替换为表达式指定的新的URI
正则表达式格式:
. #匹配除换行符以外的任意字符
\w #匹配字母或数字或下划线或汉字
\s #匹配任意的空白符
\d #匹配数字 [0-9] 。。
\b #匹配单词的开始或结束
^ #匹配字付串的开始
$ #匹配字符串的结束
* #匹配重复零次或更多次
+ #匹配重复一次或更多次
? #匹配重复零次或一次
{n} #匹配重复n次
{n,} #匹配重复n次或更多次
{n,m} #匹配重复n到m次
*? #匹配重复任意次,但尽可能少重复
+? #匹配重复1次或更多次,但尽可能少重复
?? #匹配重复0次或1次,但尽可能少重复
{n,m}? #匹配重复n到m次,但尽可能少重复
{n,}? #匹配重复n次以上,但尽可能少重复
\W #匹配任意不是字母,数字,下划线,汉字的字符
\S #匹配任意不是空白符的字符
\D #匹配任意非数字的字符
\B #匹配不是单词开头或结束的位置
[^g] #匹配除了g以外的任意字符
[^gg] #匹配除了gg 这几个字母以外的任意字符
rewrite flag 使用介绍
利用nginx的rewrite的指令,可以实现url的重新跳转,rewrtie有四种不同的flag,分别是 redirect(临时重定向302)、permanent(永久重定向301)、break和last。其中前两种是跳转型的flag,后两种是代理型。
代理型是在web服务器内部实现跳转
redirect;302
#临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302
permanent;301
#重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求,状态码:301
break;
#重写完成后,停止对当前URL在当前location中后续的其它重写操作,而后直接跳转至重写规则配置块之后的其它配置;结束循环,建议在location中使用
#适用于一个URL一次重写
#一次匹配
last;
#重写完成后,停止对当前URI在当前location中后续的其它重写操作,而后对新的URL启动新一轮重写检查,不建议在location中使用
#适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户301
#多次匹配
实例:
更改子配置文件:
创建所需文件夹:
案例:http 转https :
针对全站跳转:
location / { #针对全站跳转
if ( $scheme = http ) { #如果不加条件判断,会导致死循环
rewrite /(.*) https://$host/$1 permanent;
}
}
last 与 break:
location /break { #访问break
rewrite .* /test break; #重写到test
}
location /last { #访问break
rewrite .* /test last; #重写到test
}
location /test {
rewrite 403; #last返回403,因为last会多次匹配
}
说明:
redirect;302:临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302
permanent;301:重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求,状态码:301
break:重写完成后,停止对当前URL在当前location中后续的其它重写操作,而后直接跳转至重写规则配置块之后的其它配置;结束循环,建议在location中使用,适用于一个URL一次重写
last:重写完成后,停止对当前URI在当前location中后续的其它重写操作,而后对新的URL启动新一轮重写检查,不建议在location中使用。适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户301。
要求:
/20200106/static->/static?id=20200106
/20200123/image ->/image?id=20200123
方法:
rewrite ^/(\d+)/(.+)/ /$2?id=$1 break;
\d+:一个以上数字;.+:一个以上的字符
要求:
www.lucky.com/images/20200106/1.jpg => www.lucky.com/index.do?name=images&dir=20200106=&fi1e=1.jpg
规则配置:
if($host ~* (.*)\.lucky\.com) {
rewrite ^/(.*)/(\d+)/(.*)$ /index.do?name=$1&dir=$2&file=$3 last;}
示例
防盗链基于客户端携带的 referer 实现,referer 是记录打开一个页面之前记录是从哪个页面跳转过来的标记信息,如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗链,referer 就是之前的那个网站域名,正常的 referer 信息有以下几种:
none: #请求报文首部没有 referer 首部,
比如用户直接在浏览器输入域名访问web网站,就没有referer信息。
blocked: #请求报文有 referer 首部,但无有效值,
比如为空。
server_names: #referer首部中包含本主机名及即nginx 监听的server_name。
arbitrary_string: #自定义指定字符串,但可使用*作通配符。
示例: *.kgc.org www.kgc.*
regular expression:#被指定的正则表达式模式匹配到的字符串,要使用~开头
示例: ~.*\.kgc\.com
.被盗端添加文件a.jpg:
[root@localhost data]# ls
a.jpg beijing favicon.ico index.html ssl
2. 盗取端开启httpd服务,添加web前端配置:
第二台
[root@localhost ~]# cd /var/www/html/
<html>
<body>
<h1>ni hao </h1>
<img src="http://192.168.91.3/a.jpg"/> #这里如果写域名,需要修改hosts配置添加域名解析
</body>
</html>
实验
第一台
清空子配置文件:
添加图片:
第二台机器:
添加httpd子配置文件:
测试
实现防盗链 :
server{
listen 80;
server_name www.lucky.com;
root /data/html;
location ~* \.(jpg|gif|swf)$ {
root /data/html;
valid_referers none blocked *.lucky.com lucky.com;
if ( $invalid_referer ) {
rewrite ^/ http://www.lucky.com/error.png;
}
}
}
实验:
更改配置文件:
自定义返回图片:
更改配置文件:
正向代理:代理的是客户端去访问服务端
反向代理:代理的是服务端
反向代理:reverse proxy,指的是代理外网用户的请求到内部的指定的服务器,并将数据返回给用户的一种方式,这是用的比较多的一种方式。
Nginx 除了可以在企业提供高性能的web服务之外,另外还可以将 nginx 本身不具备的请求通过某种预定义的协议转发至其它服务器处理,不同的协议就是Nginx服务器与其他服务器进行通信的一种规范,主要在不同的场景使用以下模块实现不同的功能。
ngx_http_proxy_module: #将客户端的请求以http协议转发至指定服务器进行处理
ngx_http_upstream_module #用于定义为proxy_pass,fastcgi_pass,uwsgi_pass等指令引用的后端服务器分组 负载均衡
ngx_stream_proxy_module:#将客户端的请求以tcp协议转发至指定服务器处理 四层代理
ngx_http_fastcgi_module:#将客户端对php的请求以fastcgi协议转发至指定服务器助理
ngx_http_uwsgi_module: #将客户端对Python的请求以uwsgi协议转发至指定服务器处理
同构协议:代理服务器两边请求一样
异构协议:代理服务器两边请求不一样
主配置里面,PHP语言的程序模板已经写好:
客户端:192.168.91.5,服务器:192.168.91.4;代理服务器:192.168.91.3
代理服务器配置文件:
客户端开启httpd服务:
客户端访问代理服务器:
Nginx 可以将客户端的请求转发至单台后端服务器,但是无法转发至特定的一组的服务器,而且不能对后端服务器提供相应的服务器状态监测,Nginx 可以基于 ngx_http_upstream_module 模块提供服务器分组转发、权重分配、状态监测、调度算法等高级功能。
配置方式
server address [parameters];
#配置一个后端web服务器,配置在 upstream 内,至少要有一个 server 服务器配置。
#server 支持的 parameters 如下:
weight=number #设置权重,默认为1,实现类似于LVS中的WRR,WLC等
max_conns=number #给当前后端server设置最大活动链接数,默认为0表示没有限制
max_fails=number #后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进行检测多少次,如果都失败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探测后端服务器健康性检查,而非周期性的探测
fail_timeout=time #后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复可用,如果发现可用,则将后端服务器参与调度,默认为10秒
backup #设置为备份服务器,当所有后端服务器不可用时,才会启用此备用服务器 sorry server 自己不能转自己
down #标记为 down 状态
resolve #当 server 定义的是主机名的时候,当A记录发生变化会自动应用新IP而不用重启Nginx
配置格式:
http {
upstream web {
server 192.168.91.3 weight=5;
server 192.168.91.4;
server 192.168.91.5;
least_conn;
ip_hash;
keepalive 32;
fair;
}
}
server {
listen 80;
server_name www.lucky.com;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
root /data/html;
location / {
proxy_pass http://web/
}
}
上面的配置中,upstream块定义了后端服务器的列表和负载均衡算法。server块定义了反向代理服务器的监听端口和域名,以及请求转发的配置。具体说明如下:
1. 轮询 一人一次
2. 加权轮询
3. ip hash
4. url hash
5. cookie hash
6.最少连接数
7.fair 根据响应时间
用的四层,只能控制tcp、udp(实现反向代理功能,包括TCP协议代理)
配置文件: vim /etc/redis.conf
4层是指传输层的 TCP/UDP 协议
7层是指应用层的 HTTP 协议
代理原理:
因篇幅问题不能全部显示,请点此查看更多更全内容