分类:Linux/架构,部署     文章(16) 篇

Nginx性能优化总结 (2019-03-28)

 目录

1.Gzip 压缩

2.Expires缓存时间

3.事件处理模型优化use epoll

4.高效文件传输模式sendfile on

5.优化服务器域名的散列表大小

6.优化worker服务进程数

7.FastCGI参数调优

8.Log日志优化

9.资源防盗链

10.限制HTTP的请求方法

11.控制客户端请求速率

12.HTTPS配置优化

13.优化配置及详细注释事例

 


 

Gzip压缩:

#修改配置为 gzip on; #开启gzip压缩功能 gzip_min_length 10k; #设置允许压缩的页面最小字节数; 这里表示如果文件小于10个字节,就不用压缩,因为没有意义,本来就很小. gzip_buffers 4 16k; #设置压缩缓冲区大小,此处设置为4个16K内存作为压缩结果流缓存 gzip_http_version 1.1; #压缩版本 gzip_comp_level 2; #设置压缩比率,最小为1,处理速度快,传输速度慢;9为最大压缩比,处理速度慢,传输速度快; 这里表示压缩级别,可以是0到9中的任一个,级别越高,压缩就越小,节省了带宽资源,但同时也消耗CPU资源,所以一般折中为6 gzip types text/css text/xml application/javascript; #制定压缩的类型,线上配置时尽可能配置多的压缩类型! gzip_disable "MSIE [1-6]\."; #配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持) gzip vary on; #选择支持vary header;改选项可以让前端的缓存服务器缓存经过gzip压缩的页面; 这个可以不写,表示在传送数据时,给客户端说明我使用了gzip压缩

 

Nginx设置expires设定页面缓存时间

配置expires起到控制页面缓存的作用,合理的配置expires可以减少很多服务器的请求要配置expires,
官方文档:http://nginx.org/en/docs/http/ngx_http_headers_module.html
可以在http段中或者server段中或者location段中加入

location ~ \.(gif|jpg|jpeg|png|bmp|ico)$ {    root /var/www/img/;    expires 30d; # 30m:30 分钟,2h:2 小时,30d:30 天 }

控制图片等过期时间为30天,当然这个时间可以设置的更长。具体视情况而定

 

事件处理模型优化use epoll

epoll用在linux上, kqueue用在bsd上, 不能物理上共存。如果你的服务器cpu较好,linux内核新,可考虑用epoll.

events {     #单个进程允许的客户端最大连接数     worker_connections  20480;     #收到一个新连接通知后接受尽可能多的连接。     multi_accept on;      #使用epoll模型     use epoll; }

 

高效文件传输模式sendfile on

参数sendfile on 用于开启文件高效传输模式,同时将tcp_nopush on 和tcp_nodelay on 两个指令设置为on,可防止网络及磁盘I/O阻塞,提升Nginx工作效率

#开启高效文件传输模式 sendfile on; #减少网络报文段数量 tcp_nopush on; #提高I/O性能 tcp_nodelay on;

 

优化服务器域名的散列表大小

如果在 server_name 中配置了一个很长的域名,那么重载 Nginx 时会报错,因此需要使用 server_names_hash_max_size 来解决域名过长的问题

#域名散列表大小  server_names_hash_bucket_size 64; server_names_hash_max_size 2048;

 

优化worker服务进程数

worker进程数最开始的设置可以等于CPU的核数,高流量高并发场合也可以考虑将进程数提高至CPU核数*2, 设置太多没有意义。

#查看CPU总颗数: [root@nginx conf]# grep 'physical id' /proc/cpuinfo|sort|uniq|wc -l 1 #查看CPU总核数: [root@nginx conf]# grep processor /proc/cpuinfo |wc -l 4
#CPU的总核数4 worker_processes  4; 

 

FastCGI参数调优

如果是动态请求(如 PHP),那么 Nginx 就会把它通过 FastCGI 接口发送给 PHP 引擎服务, (即 php-fpm)进行解析.

fastcgi_connect_timeout 240; # Nginx服务器和后端FastCGI服务器连接的超时时间  fastcgi_send_timeout 240; # Nginx允许FastCGI服务器返回数据的超时时间,即在规定时间内后端服务器必须传完所有的数据,否则Nginx将断开这个连接  fastcgi_read_timeout 240; # Nginx从FastCGI服务器读取响应信息的超时时间,表示连接建立成功后,Nginx等待后端服务器的响应时间  fastcgi_buffer_size 64k; # Nginx FastCGI 的缓冲区大小,用来读取从FastCGI服务器端收到的第一部分响应信息的缓冲区大小  fastcgi_buffers 4 64k; # 设定用来读取从FastCGI服务器端收到的响应信息的缓冲区大小和缓冲区数量  fastcgi_busy_buffers_size 128k; # 用于设置系统很忙时可以使用的 proxy_buffers 大小  fastcgi_temp_file_write_size 128k; # FastCGI 临时文件的大小  # fastcti_temp_path /data/ngx_fcgi_tmp; # FastCGI 临时文件的存放路径  fastcgi_cache_path /data/ngx_fcgi_cache levels=2:2 keys_zone=ngx_fcgi_cache:512m inactive=1d max_size=40g; # 缓存目录

 

fastcgi_cache ngx_fcgi_cache; # 缓存FastCGI生成的内容,比如PHP生成的动态内容  fastcgi_cache_valid 200 302 1h; # 指定http状态码的缓存时间,这里表示将200和302缓存1小时  fastcgi_cache_valid 301 1d; # 指定http状态码的缓存时间,这里表示将301缓存1天  fastcgi_cache_valid any 1m; # 指定http状态码的缓存时间,这里表示将其他状态码缓存1分钟  fastcgi_cache_min_uses 1; # 设置请求几次之后响应被缓存,1表示一次即被缓存  fastcgi_cache_use_stale error timeout invalid_header http_500; # 定义在哪些情况下使用过期缓存  fastcgi_cache_key http://$host$request_uri; # 定义 fastcgi_cache 的 key

 

Log日志优化

1. 排除不需要的日志。

location ~ .*\.(js|jpg|JPG|jpeg|JPEG|css|bmp|gif|GIF)$ {     access_log off; }

2. 日志切割:nginx日志默认不做处理,都会存放到access.log,error.log, 导致越积越多。 可写个定时脚本按天存储,每天凌晨00:00执行

#!/bin/bash YESTERDAY=$(date -d "yesterday" +"%Y-%m-%d")   LOGPATH=/usr/local/openresty/nginx/logs/   PID=${LOGPATH}nginx.pid   mv ${LOGPATH}access.log ${LOGPATH}access-${YESTERDAY}.log   mv ${LOGPATH}error.log ${LOGPATH}error-${YESTERDAY}.log     kill -USR1 `cat ${PID}`

 

资源防盗链

大量的盗链对于服务器也是很大的消耗, 防盗链主要两种方法:

1. 根据 HTTP referer 实现防盗链

#第一种,匹配后缀 location ~ .*\.(gif|jpg|jpeg|png|bm|swf|flv|rar|zip|gz|bz2)$ {    # 指定需要使用防盗链的媒体资源     access_log  off;                                              # 不记录防盗链的日志     expires  15d;                                                 # 设置缓存时间     valid_referers  none  blocked  *.test.com  *.abc.com;         # 表示这些地址可以访问上面的媒体资源     if ($invalid_referer) {                                       # 如果地址不如上面指定的地址就返回403         return 403     } }

 2. 根据 cookie 实现防盗链:cookie 是服务器贴在客户端身上的 "标签" ,服务器用它来识别客户端

#第二种,绑定目录 location /images {       root /web/www/img;     vaild_referers nono blocked *.spdir.com *.spdir.top;     if ($invalid_referer) {         return 403;     } }

 

限制HTTP的请求方法

HTTP1.1定义了八种主要的方法,其中OPTIONS、DELETE等方法在生产环境可以被认为是不安全的,因此需要配置Nginx实现限制指定某些HTTP请求的方法来达到提升服务器安全的目的。

if ($request_method !~ ^(GET|HEAD|POST)$ ) {     return 501; }

 通过限制上传服务器的Web服务(可以具体到文件)使用GET方法,防止用户通过上传服务器访问存储内容

if ($request_method !~ ^(GET)$ ) {     return 501; }

 

控制客户端请求速率

# 以请求的客户端IP作为key值,内存区域命名为one,分配10m内存空间,访问速率限制为1秒1次请求 limit_req_zone $binary_remove_addr zone=one:10m rate=1r/s; # 使用前面定义的为one的内存空间,队列值为5,即可以有5个请求排队等候 limit_req  zone=one burst=5; 

 

HTTPS配置优化

NGINX配置HTTPS性能优化方案一则:

1) HSTS的合理使用
2) 会话恢复的合理使用
3) Ocsp stapling的合理使用
4) TLS协议的合理配置
5) False Start的合理使用
6) SNI功能的合理使用,
7) HTTP 2.0的合理使用(Nginx在1.9.x版本就开始支持http2协议)
8) SSL硬件加速卡合理使用

#以下是一个nginx优化https的配置模板: server {     # 把ssl on;这行去掉,ssl写在443端口后面。这样http和https的链接都可以用     listen 443 ssl http2 default_server;     server_name  site.xxx.com;       # HSTS的合理使用,max-age表明HSTS在浏览器中的缓存时间,includeSubdomainscam参数指定应该在所有子域上启用HSTS,preload参数表示预加载,通过Strict-Transport-Security: max-age=0将缓存设置为0可以撤销HSTS     add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";       ssl_certificate /usr/local/nginx/cert/server.pem;      ssl_certificate_key /usr/local/nginx/cert/server.key;        # 分配10MB的共享内存缓存,不同工作进程共享TLS会话信息     ssl_session_cache shared:SSL:10m;     # 设置会话缓存过期时间24h     ssl_session_timeout 1440m;       # TLS协议的合理配置     # 指定TLS协议的版本,不安全的SSL2和SSL3要废弃掉     ssl_protocols TLSv1 TLSv1.1 TLSv1.2;     # 启用ssl_prefer_server_ciphers,用来告诉Nginx在TLS握手时启用服务器算法优先,由服务器选择适配算法而不是客户端     ssl_prefer_server_ciphers on;     # 优先选择支持前向加密的算法,且按照性能的优先顺序排列     ssl_ciphers ssl_ciphers "ECDHE-ECDSA-CHACHA20-POLY1305 ECDHE-RSA-CHACHA20-POLY1305 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-SHA256 ECDHE-RSA-AES128-SHA256 ECDHE-ECDSA-AES128-SHA ECDHE-RSA-AES256-SHA384 ECDHE-RSA-AES128-SHA ECDHE-ECDSA-AES256-SHA384 ECDHE-ECDSA-AES256-SHA ECDHE-RSA-AES256-SHA DHE-RSA-AES128-SHA256 DHE-RSA-AES128-SHA DHE-RSA-AES256-SHA256 DHE-RSA-AES256-SHA ECDHE-ECDSA-DES-CBC3-SHA ECDHE-RSA-DES-CBC3-SHA EDH-RSA-DES-CBC3-SHA AES128-GCM-SHA256 AES256-GCM-SHA384 AES128-SHA256 AES256-SHA256 AES128-SHA AES256-SHA DES-CBC3-SHA !DSS";       # 会话恢复的合理使用     # 配置会话票证,减少了TLS握手的开销     ssl_session_tickets on;     # 生产key的命令通过openssl生成:openssl rand –out session_ticket.key 48     ssl_session_ticket_key /usr/local/nginx/ssl_cert/session_ticket.key;       #设置TLS日志格式     log_format ssl "$time_local $server_name $remote_addr $connection $connnection_requests $ssl_protocol $ssl_cipher $ssl_session_id $ssl_session_reused";     access_log /usr/local/nginx/logs/access.log ssl;       # Ocsp stapling的合理使用     # 启用OCSP stapling,指定更新文件内容,无需从服务商拉取     ssl_stapling on;     ssl_stapling_file /usr/local/nginx/oscp/stapling_file.ocsp;     # 或者不指定更新文件内容,在线获取,valid表示缓存5分钟,resolver_timeout表示网络超时时间     #resolver 8.8.8.8 8.8.4.4 223.5.5.5 valid=300s;     #resolver_timeout 5s;      # 启用OCSP响应验证,OCSP信息响应适用的证书                ssl_stapling_verify on;      ssl_trusted_certificate /usr/local/nginx/ssl_cert/trustchain.crt;            root   html;     index  index.html index.htm;       location / {         ...     }       error_page 403 /403.html;     location = /403.html {         root /usr/local/nginx/waf/403/default;     }     error_page 500 502 503 504 /502.html;     location = /502.html {         root /usr/local/nginx/waf/403/default;     } }

  

优化配置及详细注释事例

#普通配置 #==性能配置   #运行用户 user nobody; #pid文件 pid logs/nginx.pid;  #Nginx基于事件的非阻塞多路复用模型(epoll或kquene) #一个进程在短时间内可以响应大量请求,工作进程设置与cpu数相同,避免cpu在多个进程间切换增加开销 #==worker进程数,通常设置<=CPU数量,auto为自动检测,一般设置最大8个即可,再大性能提升较小或不稳定 worker_processes auto;  #==将每个进程绑定到特定cpu上,避免进程在cpu间切换的开销 worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;  #==worker进程打开最大文件数,可CPU*10000设置,或设置系统最大数量655350 worker_rlimit_nofile 102400; #全局错误日志 error_log  logs/error.log;   #events模块中包含nginx中所有处理连接的设置,并发响应能力的关键配置 events {     #==每个进程同时打开的最大连接数(最大并发数)     worker_connections 102400;          #==告诉nginx收到一个新链接通知后接受尽可能多的链接     #multi_accept on;          #一般http 1.1协议下,浏览器默认使用两个并发链接     #如果是反向代理,nginx需要和客户端保持连接,还需要和后端服务器保持连接     #Http服务器时,设置max_client=worker_processes*worker_connections/2     #反向代理时,设置max_client=worker_processes*worker_connections/4         #==最大可用客户端数     #max_client           #==使用非阻塞模型,设置复用客户端线程的轮训方法     use epoll; }   #http模块控制着nginx http处理的所有核心特性 http {     #打开或关闭错误页面中的nginx版本号等信息     server_tokens on;     #!server_tag on;     #!server_info on;     #==优化磁盘IO设置,指定nginx是否调用sendfile函数来输出文件,普通应用设为on,下载等磁盘IO高的应用,可设为off     sendfile on;          #缓存发送请求,启用如下两个配置,会在数据包达到一定大小后再发送数据     #这样会减少网络通信次数,降低阻塞概率,但也会影响响应的及时性     #比较适合于文件下载这类的大数据包通信场景     #tcp_nopush on;     #tcp_nodelay on;      #==设置nginx是否存储访问日志,关闭这个可以让读取磁盘IO操作更快     access_log on;     #设置nginx只记录严重错误,可减少IO压力     #error_log logs/error.log crit;      #Http1.1支持长连接     #降低每个链接的alive时间可在一定程度上提高响应连接数量     #==给客户端分配keep-alive链接超时时间     keepalive_timeout 30;      #设置用户保存各种key的共享内存的参数,5m指的是5兆     limit_conn_zone $binary_remote_addr zone=addr:5m;     #为给定的key设置最大的连接数,这里的key是addr,设定的值是100,就是说允许每一个IP地址最多同时打开100个连接     limit_conn addr 100;      #include指在当前文件中包含另一个文件内容     include mime.types;     #设置文件使用默认的mine-type     default_type text/html;     #设置默认字符集     charset UTF-8;      #==设置nginx采用gzip压缩的形式发送数据,减少发送数据量,但会增加请求处理时间及CPU处理时间,需要权衡     gzip on;     #==加vary给代理服务器使用,针对有的浏览器支持压缩,有个不支持,根据客户端的HTTP头来判断是否需要压缩     gzip_vary on;     #nginx在压缩资源之前,先查找是否有预先gzip处理过的资源     #!gzip_static on;     #为指定的客户端禁用gzip功能     gzip_disable "MSIE[1-6]\.";     #允许或禁止压缩基于请求和相应的响应流,any代表压缩所有请求     gzip_proxied any;     #==启用压缩的最少字节数,如果请求小于1024字节则不压缩,压缩过程会消耗系统资源     gzip_min_length 1024;     #==数据压缩等级,1-9之间,9最慢压缩比最大,压缩比越大对系统性能要求越高     gzip_comp_level 2;     #需要压缩的数据格式     gzip_types text/plain text/css text/xml text/javascript  application/json application/x-javascript application/xml application/xml+rss;       #静态文件缓存     #==开启缓存的同时也指定了缓存文件的最大数量,20s如果文件没有被请求则删除缓存     open_file_cache max=100000 inactive=20s;     #==多长时间检查一次缓存的有效期     open_file_cache_valid 30s;     #==有效期内缓存文件最小的访问次数,只有访问超过2次的才会被缓存     open_file_cache_min_uses 2;     #当搜索一个文件时是否缓存错误信息     open_file_cache_errors on;      #==允许客户端请求的最大单文件字节数     client_max_body_size 4m;     #==客户端请求头缓冲区大小     client_header_buffer_size 4k;      #是否启用对发送给客户端的URL进行修改     proxy_redirect off;     #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP     proxy_set_header Host $host;     proxy_set_header X-Real-IP $remote_addr;     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;     #==nginx跟后端服务器连接超时时间(代理连接超时)     proxy_connect_timeout 60;     #==连接成功后,后端服务器响应时间(代理接收超时)     proxy_read_timeout 120;     #==后端服务器数据回传时间(代理发送超时)     proxy_send_timeout 20;     #==设置代理服务器(nginx)保存用户头信息的缓冲区大小     proxy_buffer_size 32k;     #==proxy_buffers缓冲区,网页平均在32k以下的设置     proxy_buffers 4 128k;     #==高负荷下缓冲大小(proxy_buffers*2)     proxy_busy_buffers_size 256k;     #==设定缓存文件夹大小,大于这个值,将从upstream服务器传     proxy_temp_file_write_size 256k;     #==1G内存缓冲空间,3天不用删除,最大磁盘缓冲空间2G     proxy_cache_path /home/cache levels=1:2 keys_zone=cache_one:1024m inactive=3d max_size=2g;       #设定负载均衡服务器列表     upstream nginx.test.com{         #后端服务器访问规则         #ip_hash;         #weight参数表示权重值,权值越高被分配到的几率越大         #server 10.11.12.116:80 weight=5;         #PC_Local         server 10.11.12.116:80;         #PC_Server         server 10.11.12.112:80;         #Notebook         #server 10.11.12.106:80;     }      #server代表虚拟主机,可以理解为站点(挂载多个站点,只需要配置多个server及upstream节点即可)     server {         #监听80端口         listen 80;         #识别的域名,定义使用nginx.test.com访问         server_name nginx.test.com;         #设定本虚拟主机的访问日志         access_log logs/nginx.test.com.access.log;                  #一个域名下匹配多个URI的访问,使用location进行区分,后面紧跟着的/代表匹配规则         #如动态资源访问和静态资源访问会分别指向不同的位置的应用场景         #         # 基本语法规则:location [=|~|~*|^~] /uri/ {...}          # = 开头表示精确匹配         # ^~ 开头表示uri以某个常规字符串开头,匹配成功后不再进行正则匹配         # ~ 开头表示区分大小写的正则匹配         # ~* 开头表示不区分大小写的正则匹配         # !~ 开头表示区分大小写的不匹配的正则         # !~* 开头表示不区分大小写的不匹配的正则         # / 通用匹配,任何请求都会被匹配到         #         # 理解如下:         # 有两种匹配模式:普通字符串匹配,正则匹配         # 无开头引导字符或以=开头表示普通字符串匹配         # 以~或~*开头表示正则匹配,~*表示不区分大小写         # 【多个location时,先匹配普通字符串location,再匹配正则location】         # 只识别URI部分,例如请求为“/test/1/abc.do?arg=xxx”         # (1)先查找是否有=开头的精确匹配,即“location=/test/1/abc.do {...}”         # (2)再查找普通匹配,以“最大前缀”为规则,如有以下两个location         #    location /test/ {...}         #    location /test/1/ {...}         #    则匹配后一项         # (3)匹配到一个普通location后,搜索并未结束,而是暂存当前结果,并继续进行正则搜索         # (4)在所有正则location中找到第一个匹配项后,以此匹配项为最终结果         # 【所以正则匹配项,匹配规则受定义前后顺序影响,但普通匹配不会】         # (5)如果未找到正则匹配项,则以(3)中缓存的结果为最终结果         # (6)如果一个匹配都没有,则返回404         # location =/ {...}与location / {...}的差别         # 前一个是精确匹配,只响应“/”的请求,所有“/xxx”形式的请求不会以“前缀匹配形式”匹配到它         # 后一个正相反,所有请求必然都是以“/”开头,所以没有其他匹配结果时一定会执行到它         # location ^~ / {...} ^~的意思是禁止正则匹配,表示匹配到此项后不再进行后续的正则搜索         # 相当于普通匹配模式匹配成功后就以此结果为最终结果,停止进行后续的正则匹配         location / {             #定义服务器的默认网站根目录位置,可以写相对路径,也可以写绝对路径             root html;             #定义首页索引文件的名称             index index.html index.htm;             #定义转发后端负载服务器组             proxy_pass http://nginx.test.com;         }          #定义错误提示页面         error_page 500 502 503 504 /50x.html;         location = /50x.html {             root html;         }         #静态文件,nginx自己处理         location ~ ^/(images|javascript|js|css|flash|media|static)/{             root /var/www/virtual/htdocs;             #过期时间1天             expires 1d;             #关闭媒体文件日志             access_log off;             log_not_found off;         }         #设定查看Nginx状态的地址         location /NginxStatus {             #!stub_status on; #无此关键字             access_log off;             auth_basic "NginxStatus";             auth_basic_user_file conf/htpasswd;         }         #禁止访问的文件.htxxx         location ~ /\.ht {             #deny all;禁止访问,返回403             deny all;             #allow all;允许访问         }     }     #网站较多的情况下ngxin又不会请求瓶颈可以考虑挂多个站点,并把虚拟主机配置单独放在一个文件内,引入进来     #include website.conf; }

 

 

 

点击查看原文阅读(400) | 评论(2) | 分类:Node.js

Consul 使用手册 (2017-09-06)

 

介绍

Consul包含多个组件,但是作为一个整体,为你的基础设施提供服务发现和服务配置的工具.他提供以下关键特性:

  • 服务发现 Consul的客户端可用提供一个服务,比如 api 或者mysql ,另外一些客户端可用使用Consul去发现一个指定服务的提供者.通过DNS或者HTTP应用程序可用很容易的找到他所依赖的服务.
  • 健康检查 Consul客户端可用提供任意数量的健康检查,指定一个服务(比如:webserver是否返回了200 OK 状态码)或者使用本地节点(比如:内存使用是否大于90%). 这个信息可由operator用来监视集群的健康.被服务发现组件用来避免将流量发送到不健康的主机.
  • Key/Value存储 应用程序可用根据自己的需要使用Consul的层级的Key/Value存储.比如动态配置,功能标记,协调,领袖选举等等,简单的HTTP API让他更易于使用.
  • 多数据中心: Consul支持开箱即用的多数据中心.这意味着用户不需要担心需要建立额外的抽象层让业务扩展到多个区域.

Consul面向DevOps和应用开发者友好.是他适合现代的弹性的基础设施.

consul-cluster

基础架构

Consul是一个分布式高可用的系统. 这节将包含一些基础,我们忽略掉一些细节这样你可以快速了解Consul是如何工作的.如果要了解更多细节,请参考深入的架构描述.

每个提供服务给Consul的阶段都运行了一个Consul agent . 发现服务或者设置和获取 key/value存储的数据不是必须运行agent.这个agent是负责对节点自身和节点上的服务进行健康检查的.

Agent与一个和多个Consul Server 进行交互.Consul Server 用于存放和复制数据.server自行选举一个领袖.虽然Consul可以运行在一台server , 但是建议使用3到5台来避免失败情况下数据的丢失.每个数据中心建议配置一个server集群.

你基础设施中需要发现其他服务的组件可以查询任何一个Consul 的server或者 agent.Agent会自动转发请求到server .

每个数据中运行了一个Consul server集群.当一个跨数据中心的服务发现和配置请求创建时.本地Consul Server转发请求到远程的数据中心并返回结果.

更多介绍查看官网点击前往

安装Consul

安装Consul,找到适合你系统的包下载他.Consul打包为一个’Zip’文件.前往下载

下载后解开压缩包.拷贝Consul到你的PATH路径中,在Unix系统中~/bin/usr/local/bin是通常的安装目录.根据你是想为单个用户安装还是给整个系统安装来选择.在Windows系统中有可以安装到%PATH%的路径中.

验证安装

完成安装后,通过打开一个新终端窗口检查consul安装是否成功.通过执行 consul你应该看到类似下面的输出

  1. [root@dhcp-10-201-102-248 ~]# consul
  2. usage: consul [--version] [--help] <command> [<args>]
  3.  
  4. Available commands are:
  5. agent Runs a Consul agent
  6. configtest Validate config file
  7. event Fire a new event
  8. exec Executes a command on Consul nodes
  9. force-leave Forces a member of the cluster to enter the "left" state
  10. info Provides debugging information for operators
  11. join Tell Consul agent to join cluster
  12. keygen Generates a new encryption key
  13. keyring Manages gossip layer encryption keys
  14. kv Interact with the key-value store
  15. leave Gracefully leaves the Consul cluster and shuts down
  16. lock Execute a command holding a lock
  17. maint Controls node or service maintenance mode
  18. members Lists the members of a Consul cluster
  19. monitor Stream logs from a Consul agent
  20. operator Provides cluster-level tools for Consul operators
  21. reload Triggers the agent to reload configuration files
  22. rtt Estimates network round trip time between nodes
  23. snapshot Saves, restores and inspects snapshots of Consul server state
  24. version Prints the Consul version
  25. watch Watch for changes in Consul

如果你得到一个consul not be found的错误,你的PATH可能没有正确设置.请返回检查你的consul的安装路径是否包含在PATH中.

运行Agent

完成Consul的安装后,必须运行agent. agent可以运行为serverclient模式.每个数据中心至少必须拥有一台server . 建议在一个集群中有3或者5个server.部署单一的server,在出现失败时会不可避免的造成数据丢失.

其他的agent运行为client模式.一个client是一个非常轻量级的进程.用于注册服务,运行健康检查和转发对server的查询.agent必须在集群中的每个主机上运行.

查看启动数据中心的细节请查看这里.

启动 Consul Server

  1. consul agent -server -bootstrap-expect 3 -data-dir /tmp/consul -node=s1 -bind=10.201.102.198 -ui-dir ./consul_ui/ -rejoin -config-dir=/etc/consul.d/ -client 0.0.0.0

运行cosnul agent以server模式,

  • -server : 定义agent运行在server模式
  • -bootstrap-expect :在一个datacenter中期望提供的server节点数目,当该值提供的时候,consul一直等到达到指定sever数目的时候才会引导整个集群,该标记不能和bootstrap共用
  • -bind:该地址用来在集群内部的通讯,集群内的所有节点到地址都必须是可达的,默认是0.0.0.0
  • -node:节点在集群中的名称,在一个集群中必须是唯一的,默认是该节点的主机名
  • -ui-dir: 提供存放web ui资源的路径,该目录必须是可读的
  • -rejoin:使consul忽略先前的离开,在再次启动后仍旧尝试加入集群中。
  • -config-dir::配置文件目录,里面所有以.json结尾的文件都会被加载
  • -client:consul服务侦听地址,这个地址提供HTTP、DNS、RPC等服务,默认是127.0.0.1所以不对外提供服务,如果你要对外提供服务改成0.0.0.0
  1. [root@dhcp-10-201-102-198 consul]# consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -node=s1 -bind=10.201.102.198 -ui-dir ./consul_ui/ -rejoin -config-dir=/etc/consul.d/ -client 0.0.0.0
  2. ==> WARNING: Expect Mode enabled, expecting 3 servers
  3. ==> Starting Consul agent...
  4. ==> Starting Consul agent RPC...
  5. ==> Consul agent running!
  6. Version: 'v0.7.4'
  7. Node ID: '422ec677-74ef-8f29-2f22-01effeed6334'
  8. Node name: 's1'
  9. Datacenter: 'dc1'
  10. Server: true (bootstrap: false)
  11. Client Addr: 0.0.0.0 (HTTP: 8500, HTTPS: -1, DNS: 8600, RPC: 8400)
  12. Cluster Addr: 10.201.102.198 (LAN: 8301, WAN: 8302)
  13. Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false
  14. Atlas: <disabled>
  15.  
  16. ==> Log data will now stream in as it occurs:
  17.  
  18. 2017/03/17 18:03:08 [INFO] raft: Restored from snapshot 139-352267-1489707086023
  19. 2017/03/17 18:03:08 [INFO] raft: Initial configuration (index=6982): [{Suffrage:Voter ID:10.201.102.199:8300 Address:10.201.102.199:8300} {Suffrage:Voter ID:10.201.102.200:8300 Address:10.201.102.200:8300} {Suffrage:Voter ID:10.201.102.198:8300 Address:10.201.102.198:8300}]
  20. 2017/03/17 18:03:08 [INFO] raft: Node at 10.201.102.198:8300 [Follower] entering Follower state (Leader: "")
  21. 2017/03/17 18:03:08 [INFO] serf: EventMemberJoin: s1 10.201.102.198
  22. 2017/03/17 18:03:08 [INFO] serf: Attempting re-join to previously known node: s2: 10.201.102.199:8301
  23. 2017/03/17 18:03:08 [INFO] consul: Adding LAN server s1 (Addr: tcp/10.201.102.198:8300) (DC: dc1)
  24. 2017/03/17 18:03:08 [INFO] consul: Raft data found, disabling bootstrap mode
  25. 2017/03/17 18:03:08 [INFO] serf: EventMemberJoin: s2 10.201.102.199
  26. 2017/03/17 18:03:08 [INFO] serf: EventMemberJoin: s3 10.201.102.200
  27. 2017/03/17 18:03:08 [INFO] serf: Re-joined to previously known node: s2: 10.201.102.199:8301
  28. 2017/03/17 18:03:08 [INFO] consul: Adding LAN server s2 (Addr: tcp/10.201.102.199:8300) (DC: dc1)
  29. 2017/03/17 18:03:08 [INFO] consul: Adding LAN server s3 (Addr: tcp/10.201.102.200:8300) (DC: dc1)
  30. 2017/03/17 18:03:08 [INFO] serf: EventMemberJoin: s1.dc1 10.201.102.198
  31. 2017/03/17 18:03:08 [INFO] consul: Adding WAN server s1.dc1 (Addr: tcp/10.201.102.198:8300) (DC: dc1)
  32. 2017/03/17 18:03:08 [WARN] serf: Failed to re-join any previously known node
  33. 2017/03/17 18:03:14 [INFO] agent: Synced service 'consul'
  34. 2017/03/17 18:03:14 [INFO] agent: Deregistered service 'consul01'
  35. 2017/03/17 18:03:14 [INFO] agent: Deregistered service 'consul02'
  36. 2017/03/17 18:03:14 [INFO] agent: Deregistered service 'consul03'
  • 查看集群成员

新开一个终端窗口运行consul members, 你可以看到Consul集群的成员.

  1. [root@dhcp-10-201-102-198 ~]# consul members
  2. Node Address Status Type Build Protocol DC
  3. s1 10.201.102.198:8301 alive server 0.7.4 2 dc1
  4. s2 10.201.102.199:8301 alive server 0.7.4 2 dc1
  5. s3 10.201.102.200:8301 alive server 0.7.4 2 dc1

启动 Consul Client

  1. consul agent -data-dir /tmp/consul -node=c1 -bind=10.201.102.248 -config-dir=/etc/consul.d/ -join 10.201.102.198

运行cosnul agent以client模式,-join 加入到已有的集群中去。

  1. [root@dhcp-10-201-102-248 ~]# consul agent -data-dir /tmp/consul -node=c1 -bind=10.201.102.248 -config-dir=/etc/consul.d/ -join 10.201.102.198
  2. ==> Starting Consul agent...
  3. ==> Starting Consul agent RPC...
  4. ==> Joining cluster...
  5. Join completed. Synced with 1 initial agents
  6. ==> Consul agent running!
  7. Version: 'v0.7.4'
  8. Node ID: '564dc0c7-7f4f-7402-a301-cebe7f024294'
  9. Node name: 'c1'
  10. Datacenter: 'dc1'
  11. Server: false (bootstrap: false)
  12. Client Addr: 127.0.0.1 (HTTP: 8500, HTTPS: -1, DNS: 8600, RPC: 8400)
  13. Cluster Addr: 10.201.102.248 (LAN: 8301, WAN: 8302)
  14. Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false
  15. Atlas: <disabled>
  16.  
  17. ==> Log data will now stream in as it occurs:
  18.  
  19. 2017/03/17 15:35:16 [INFO] serf: EventMemberJoin: c1 10.201.102.248
  20. 2017/03/17 15:35:16 [INFO] agent: (LAN) joining: [10.201.102.198]
  21. 2017/03/17 15:35:16 [INFO] serf: EventMemberJoin: s2 10.201.102.199
  22. 2017/03/17 15:35:16 [INFO] serf: EventMemberJoin: s3 10.201.102.200
  23. 2017/03/17 15:35:16 [INFO] serf: EventMemberJoin: s1 10.201.102.198
  24. 2017/03/17 15:35:16 [INFO] agent: (LAN) joined: 1 Err: <nil>
  25. 2017/03/17 15:35:16 [INFO] consul: adding server s2 (Addr: tcp/10.201.102.199:8300) (DC: dc1)
  26. 2017/03/17 15:35:16 [INFO] consul: adding server s3 (Addr: tcp/10.201.102.200:8300) (DC: dc1)
  27. 2017/03/17 15:35:16 [INFO] consul: adding server s1 (Addr: tcp/10.201.102.198:8300) (DC: dc1)
  28. 2017/03/17 15:35:16 [INFO] agent: Synced node info
  • 查看集群成员

新开一个终端窗口运行consul members, 你可以看到Consul集群的成员.

  1. [root@dhcp-10-201-102-248 ~]# consul members
  2. Node Address Status Type Build Protocol DC
  3. c1 10.201.102.248:8301 alive client 0.7.4 2 dc1
  4. s1 10.201.102.198:8301 alive server 0.7.4 2 dc1
  5. s2 10.201.102.199:8301 alive server 0.7.4 2 dc1
  6. s3 10.201.102.200:8301 alive server 0.7.4 2 dc1
  • 加入集群
  1. [root@dhcp-10-201-102-248 ~]# consul join 10.201.102.198
  2. Node Address Status Type Build Protocol DC
  3. c1 10.201.102.248:8301 alive client 0.7.4 2 dc1
  4. s1 10.201.102.198:8301 alive server 0.7.4 2 dc1
  5. s2 10.201.102.199:8301 alive server 0.7.4 2 dc1
  6. s3 10.201.102.200:8301 alive server 0.7.4 2 dc1

停止Agent

你可以使用Ctrl-C 优雅的关闭Agent. 中断Agent之后你可以看到他离开了集群并关闭.

在退出中,Consul提醒其他集群成员,这个节点离开了.如果你强行杀掉进程.集群的其他成员应该能检测到这个节点失效了.当一个成员离开,他的服务和检测也会从目录中移除.当一个成员失效了,他的健康状况被简单的标记为危险,但是不会从目录中移除.Consul会自动尝试对失效的节点进行重连.允许他从某些网络条件下恢复过来.离开的节点则不会再继续联系.

此外,如果一个agent作为一个服务器,一个优雅的离开是很重要的,可以避免引起潜在的可用性故障影响达成一致性协议.

查看这里了解添加和移除server.

更新服务

服务定义可以通过配置文件并发送SIGHUP给agent来进行更新.这样你可以让你在不关闭服务或者保持服务请求可用的情况下进行更新.

  1. consul reload

另外 HTTP API可以用来动态的添加,移除和修改服务.

注册服务

搭建好conusl集群后,用户或者程序就能到consul中去查询或者注册服务。可以通过提供服务定义文件或者调用HTTP API来注册一个服务.

首先,为Consul配置创建一个目录.Consul会载入配置文件夹里的所有配置文件.在Unix系统中通常类似 /etc/consul.d (.d 后缀意思是这个路径包含了一组配置文件).

  1. mkdir /etc/consul.d

然后,我们将编写服务定义配置文件.假设我们有一个名叫web的服务运行在 80端口.另外,我们将给他设置一个标签.这样我们可以使用他作为额外的查询方式:

  1. echo '{"service": {"name": "web", "tags": ["rails"], "port": 80}}' >/etc/consul.d/web.json

现在重启agent , 设置配置目录:

  1. $ consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -node=s1 -bind=10.201.102.198 -rejoin -config-dir=/etc/consul.d/ -client 0.0.0.0
  2.  
  3. ...
  4. [INFO] agent: Synced service 'web'
  5. ...
  • -data-dir:提供一个目录用来存放agent的状态,所有的agent允许都需要该目录,该目录必须是稳定的,系统重启后都继续存在

你可能注意到了输出了 “synced” 了 web这个服务.意思是这个agent从配置文件中载入了服务定义,并且成功注册到服务目录.

如果你想注册多个服务,你应该在Consul配置目录创建多个服务定义文件.

HTTP API注册服务,curl命令或者postman 以PUT方式请求consul HTTP API更多细节点击查看

  1. curl -X PUT -d '{"Datacenter": "dc1", "Node": "c2", "Address": "10.155.0.106", "Service": {"Service": "MAC", "tags": ["lianglian", "Mac"], "Port": 22}}' http://127.0.0.1:8500/v1/catalog/register

查询服务

一旦agent启动并且服务同步了.我们可以通过DNS或者HTTP的API来查询服务.

  • DNS API

让我们首先使用DNS API来查询.在DNS API中,服务的DNS名字是 NAME.service.consul. 虽然是可配置的,但默认的所有DNS名字会都在consul命名空间下.这个子域告诉Consul,我们在查询服务,NAME则是服务的名称.

对于我们上面注册的Web服务.它的域名是 web.service.consul :

  1. [root@dhcp-10-201-102-198 ~]# dig @127.0.0.1 -p 8600 web.service.consul
  2.  
  3. ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.17.rc1.el6 <<>> @127.0.0.1 -p 8600 web.service.consul
  4. ; (1 server found)
  5. ;; global options: +cmd
  6. ;; Got answer:
  7. ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39468
  8. ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
  9. ;; WARNING: recursion requested but not available
  10.  
  11. ;; QUESTION SECTION:
  12. ;web.service.consul. IN A
  13.  
  14. ;; ANSWER SECTION:
  15. web.service.consul. 0 IN A 10.201.102.198
  16.  
  17. ;; Query time: 0 msec
  18. ;; SERVER: 127.0.0.1#8600(127.0.0.1)
  19. ;; WHEN: Tue Mar 28 16:10:24 2017
  20. ;; MSG SIZE rcvd: 52
  21.  
  22. [root@dhcp-10-201-102-198 ~]#

如你所见,一个A记录返回了一个可用的服务所在的节点的IP地址.`A记录只能设置为IP地址. 有也可用使用 DNS API 来接收包含 地址和端口的 SRV记录:

  1. [root@dhcp-10-201-102-198 ~]# dig @127.0.0.1 -p 8600 web.service.consul SRV
  2.  
  3. ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.17.rc1.el6 <<>> @127.0.0.1 -p 8600 web.service.consul SRV
  4. ; (1 server found)
  5. ;; global options: +cmd
  6. ;; Got answer:
  7. ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13331
  8. ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
  9. ;; WARNING: recursion requested but not available
  10.  
  11. ;; QUESTION SECTION:
  12. ;web.service.consul. IN SRV
  13.  
  14. ;; ANSWER SECTION:
  15. web.service.consul. 0 IN SRV 1 1 80 s1.node.dc1.consul.
  16.  
  17. ;; ADDITIONAL SECTION:
  18. s1.node.dc1.consul. 0 IN A 10.201.102.198
  19.  
  20. ;; Query time: 0 msec
  21. ;; SERVER: 127.0.0.1#8600(127.0.0.1)
  22. ;; WHEN: Tue Mar 28 16:10:56 2017
  23. ;; MSG SIZE rcvd: 84
  24.  
  25. [root@dhcp-10-201-102-198 ~]#

SRV记录告诉我们 web 这个服务运行于节点dhcp-10-201-102-198 的80端口. DNS额外返回了节点的A记录.

最后,我们也可以用 DNS API 通过标签来过滤服务.基于标签的服务查询格式为TAG.NAME.service.consul. 在下面的例子中,我们请求Consul返回有 rails标签的 web服务.我们成功获取了我们注册为这个标签的服务:

  1. [root@dhcp-10-201-102-198 ~]# dig @127.0.0.1 -p 8600 rails.web.service.consul SRV
  2.  
  3. ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.17.rc1.el6 <<>> @127.0.0.1 -p 8600 rails.web.service.consul SRV
  4. ; (1 server found)
  5. ;; global options: +cmd
  6. ;; Got answer:
  7. ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37307
  8. ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
  9. ;; WARNING: recursion requested but not available
  10.  
  11. ;; QUESTION SECTION:
  12. ;rails.web.service.consul. IN SRV
  13.  
  14. ;; ANSWER SECTION:
  15. rails.web.service.consul. 0 IN SRV 1 1 80 s1.node.dc1.consul.
  16.  
  17. ;; ADDITIONAL SECTION:
  18. s1.node.dc1.consul. 0 IN A 10.201.102.198
  19.  
  20. ;; Query time: 0 msec
  21. ;; SERVER: 127.0.0.1#8600(127.0.0.1)
  22. ;; WHEN: Tue Mar 28 16:11:45 2017
  23. ;; MSG SIZE rcvd: 90
  24.  
  25. [root@dhcp-10-201-102-198 ~]#
  • HTTP API

除了DNS API之外,HTTP API也可以用来进行服务查询:

  1. [root@dhcp-10-201-102-198 ~]# curl -s 127.0.0.1:8500/v1/catalog/service/web | python -m json.tool
  2. [
  3. {
  4. "Address": "10.201.102.198",
  5. "CreateIndex": 492843,
  6. "ID": "422ec677-74ef-8f29-2f22-01effeed6334",
  7. "ModifyIndex": 492843,
  8. "Node": "s1",
  9. "NodeMeta": {},
  10. "ServiceAddress": "",
  11. "ServiceEnableTagOverride": false,
  12. "ServiceID": "web",
  13. "ServiceName": "web",
  14. "ServicePort": 80,
  15. "ServiceTags": [
  16. "rails"
  17. ],
  18. "TaggedAddresses": {
  19. "lan": "10.201.102.198",
  20. "wan": "10.201.102.198"
  21. }
  22. }
  23. ]

目录API给出所有节点提供的服务.稍后我们会像通常的那样带上健康检查进行查询.就像DNS内部处理的那样.这是只查看健康的实例的查询方法:

  1. [root@dhcp-10-201-102-198 ~]# curl -s 127.0.0.1:8500/v1/catalog/service/web?passing | python -m json.tool
  2. [
  3. {
  4. "Address": "10.201.102.198",
  5. "CreateIndex": 492843,
  6. "ID": "422ec677-74ef-8f29-2f22-01effeed6334",
  7. "ModifyIndex": 492843,
  8. "Node": "s1",
  9. "NodeMeta": {},
  10. "ServiceAddress": "",
  11. "ServiceEnableTagOverride": false,
  12. "ServiceID": "web",
  13. "ServiceName": "web",
  14. "ServicePort": 80,
  15. "ServiceTags": [
  16. "rails"
  17. ],
  18. "TaggedAddresses": {
  19. "lan": "10.201.102.198",
  20. "wan": "10.201.102.198"
  21. }
  22. }
  23. ]

WEB管理界面

Consul同时提供了一个漂亮的功能齐全的WEB界面,开箱即用.界面可以用来查看所有的节点,可以查看健康检查和他们的当前状态.可以读取和设置K/V 存储的数据.UI自动支持多数据中心.点击前往下载

UI_Download

下载完后上传至服务器,建议所有server角色都使用WebUI,。

  1. consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -node=s1 -bind=10.201.102.198 -ui-dir ./consul_ui/ -rejoin -config-dir=/etc/consul.d/ -client 0.0.0.0
  • -ui-dir: 提供存放web ui资源的路径,指向该目录必须是可读的
  • -client:consul服务侦听地址,这个地址提供HTTP、DNS、RPC等服务,默认是127.0.0.1所以不对外提供服务,如果你要对外提供服务改成0.0.0.0

可通过http://10.201.102.198:8500访问WEB管理界面。

UI_Download

健康检查

我们现在看到Consul运行时如此简单.添加节点和服务,查询节点和服务.在这一节.我们将继续添加健康检查到节点和服务.健康检查是服务发现的关键组件.预防使用到不健康的服务.

这一步建立在前一节的Consul集群创建之上.目前你应该有一个包含多个节点的Consul集群.

  • 自定义检查

和服务注册类似,一个检查可以通过检查定义或HTTP API请求来注册.

我们将使用和检查定义来注册检查.和服务类似,因为这是建立检查最常用的方式.

在第二个节点的配置目录建立定义文件:

/etc/consul.d/web.json

  1. {"service": {
  2. "name": "Faceid",
  3. "tags": ["extract", "verify", "compare", "idcard"],
  4. "address": "10.201.102.198",
  5. "port": 9000,
  6. "check": {
  7. "name": "ping",
  8. "script": "curl -s localhost:9000",
  9. "interval": "3s"
  10. }
  11. }
  12. }

or

/etc/consul.d/web.json

  1. {"service": {
  2. "name": "Faceid",
  3. "tags": ["extract", "verify", "compare", "idcard"],
  4. "address": "10.201.102.199",
  5. "port": 9000,
  6. "check": {
  7. "id": "api",
  8. "name": "HTTP API on port 9000",
  9. "http": "http://localhost:9000",
  10. "interval": "10s",
  11. "timeout": "1s"
  12. }
  13. }
  14. }

more

检查健康状态

我们能适应HTTP API来检查他们.首先我们检查有哪些失败的检查.使用这个命令(注意:这个命令可以运行在任何节点)

  1. [root@dhcp-10-201-102-198 ~]# curl -s http://localhost:8500/v1/health/state/critical | python -m json.tool
  2. [
  3. {
  4. "CheckID": "service:Faceid",
  5. "CreateIndex": 493398,
  6. "ModifyIndex": 493846,
  7. "Name": "Service 'Faceid' check",
  8. "Node": "s1",
  9. "Notes": "",
  10. "Output": "",
  11. "ServiceID": "Faceid",
  12. "ServiceName": "Faceid",
  13. "Status": "critical"
  14. }
  15. ]

我们可以看到,只有一个检查我们的web服务在critical状态

另外,我们可以尝试用DNS查询web服务,Consul将不会返回结果.因为服务不健康.

  1. [root@dhcp-10-201-102-198 ~]# dig @127.0.0.1 -p 8600 Faceid.service.consul SRV
  2.  
  3. ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.17.rc1.el6 <<>> @127.0.0.1 -p 8600 Faceid.service.consul SRV
  4. ; (1 server found)
  5. ;; global options: +cmd
  6. ;; Got answer:
  7. ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40884
  8. ;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 3
  9. ;; WARNING: recursion requested but not available
  10.  
  11. ;; QUESTION SECTION:
  12. ;Faceid.service.consul. IN SRV
  13.  
  14. ;; ANSWER SECTION:
  15. Faceid.service.consul. 0 IN SRV 1 1 9000 s3.node.dc1.consul.
  16. Faceid.service.consul. 0 IN SRV 1 1 9000 s1.node.dc1.consul.
  17. Faceid