微服务开发实战Think Coding

微服务之负载均衡

2018-11-11  本文已影响7人  老瓦在霸都

微服务都是分布式系统, 多个服务工作在一起齐心协力完成所需的工作, 事情不能交给一个人做, 所工作分担到多个微服务上是为负载均衡.

负载均衡策略

负载均衡 Load Balance 是最基本的分流策略, 将负载尽量均匀地分布到下游节点上, 但是如何分派, 是有讲究的.

大致有以下四种基本策略:

上述四种负载均衡策略一般都会加上健康检查功能, 定时查询下游节点的健康状态, 如果没有响应或者响应错误则在分派候选名单剔除这个节点, 直到节点恢复健康

负载均衡方法

DNS

DNS 会将域名映射为 IP 地址, 假设你有三台 server, 域名(Domain Name)为 www.mysite.com, DNS(Domain Name System) 会根据你的注册信息按照轮转的方式返回这三台 server 列表, 例如

www.mysite.com
解析为:
192.168.1.1
192.168.1.2
192.168.1.3

这个列表可以是变化的, 每次请求把上次列表的第一个放到最后

www.mysite.com
解析为:
192.168.1.2
192.168.1.3
192.168.1.1

可以用 nslookup 或 dig 命令查询域名和它实际映射的服务地址

nslookup baidu.com
Server:     64.104.123.245
Address:    64.104.123.245#53

Non-authoritative answer:
Name:   baidu.com
Address: 123.125.115.110
Name:   baidu.com
Address: 220.181.57.216

dig 命令显示的内容更多一些, 还可以加上 +trace 选项来显示DNS所查询用到服务器路径

$ dig cisco.com

; <<>> DiG 9.8.3-P1 <<>> cisco.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3992
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 6

;; QUESTION SECTION:
;cisco.com.         IN  A

;; ANSWER SECTION:
cisco.com.      5   IN  A   72.163.4.161

;; AUTHORITY SECTION:
cisco.com.      1800    IN  NS  ns1.cisco.com.
cisco.com.      1800    IN  NS  ns3.cisco.com.
cisco.com.      1800    IN  NS  ns2.cisco.com.

;; ADDITIONAL SECTION:
ns1.cisco.com.      600 IN  A   72.163.5.201
ns2.cisco.com.      1800    IN  A   64.102.255.44
ns3.cisco.com.      1800    IN  A   173.37.146.41
ns1.cisco.com.      1800    IN  AAAA    2001:420:1101:6::a
ns2.cisco.com.      1800    IN  AAAA    2001:420:2041:5000::a
ns3.cisco.com.      1800    IN  AAAA    2001:420:1201:7::a

;; Query time: 169 msec
;; SERVER: 64.104.123.245#53(64.104.123.245)
;; WHEN: Sat Nov 10 18:24:42 2018
;; MSG SIZE  rcvd: 229

DNS 作为负载均衡固然简单,可是 DNS 缺点也不少

  1. DNS 是一个分级系统, 本地域名服务器若查不到相应记录, 会向上级域名服务器查询,查到结果后在本地缓存至 TTL 时间过期

  2. DNS 也会在本地缓存, 客户端解析域名为IP 之后可能一直使用很长时间, 对于客户端的行为你无法控制
    DNS 解析速度并不快, 你要是把 TTL 设置得太小,缓存很快过期, 性能问题就会凸显

  3. DNS 在实时检测分流, 为域名实时添加和删除服务器方面很不方便,即使你能很快地搞定你的内部 DNS 系统,你依然需要等待在下级域名服务器和客户端的缓存过期

所以 DNS 通常就作为第一级负载均衡方案, 采用简单的 Round Robbin 策略,映射到几个 VIP 上

DNS SRV

服务记录(SRV记录)是域名系统中的数据规范,其定义用于指定服务的服务器的位置,即主机名和端口号。 它在RFC 2782中定义,其类型代码为33. 某些Internet协议(如会话初始协议(SIP)和可扩展消息传递和在线协议(XMPP))通常需要网络元素支持SRV。

一个 SRV 的记录格式如下:

_service._proto.name. TTL class SRV priority weight port target.

例如以下的 sip 服务的 DNS SRV

_sip._tcp.example.com. 86400 IN SRV 0 5 5060 sipserver.example.com.

常用命令

可以用 dig 和 nslookup 来查看 DNS SRV 的具体信息

$ dig _sip._tcp.example.com SRV

$ host -t SRV _sip._tcp.example.com

$ nslookup -querytype=srv _sip._tcp.example.com

$ nslookup
> set querytype=srv
> _sip._tcp.example.com

服务器端负载负载

局部与全局负载均衡

SLB(Server load balancing)是对集群内物理主机的负载均衡,而GSLB是对物理集群的负载均衡。
这里的负载均衡可能不只是简单的流量均匀分配,而是会根据策略的不同实现不同场景的应用交付。

GSLB(Global server load balancing) 是依赖于用户和实际部署环境的互联网资源分发技术,不同的目的对应着一系列不同的技术实现 - 基于DNS实现、基于重定向实现、基于路由协议实现。

如图所示

  1. 用户的客户端 Client 向 DNS server 查询 mysite.com 的地址

  2. DNS server 返回域名所对应的服务器地址
    2.1 用户向本级配置的本地DNS服务器发出查询请求,如果本地DNS服务器有该域名的缓存记录,则返回给用户,否则进行下一步;
    2.2 本地DNS服务器进行递归查询,最终会查询到域名注册商处的授权DNS服务器
    2.3 授权DNS服务器返回一条NS记录给本地DNS服务器。这条NS记录可能是指向随机一个GSLB设备的接口地址或者是所有GSLB设备的接口地址;
    2.4 本地DNS服务器向其中一个GSLB地址发出域名查询请求,如果请求超时会向其它地址发出查询;
    2.5 GSLB设备选出最优解析结果,返回一条A记录给本地DNS服务器。根据全局负载均衡策略设定的不同可能返回一个或多个VIP地址;
    2.6 本地服务器将查询结果通过一条A记录返回给用户,并将缓存这条记录。

此例中由于client 和 数据中心 DC1 在一个区域, 响应更快, GSLB 选出 DC 1 的 Float VIP

  1. 用户连接 Float VIP, 它是一个飘移的虚拟地址, 当主集群健康时时候就分派请求到主集群 Primary LB 的负载均衡器地址, 否则就连到备份集群 Backup LB

  2. 数据中心1的主集群被选中, 请求分派到主集群 Primary LB 负载均衡器地址

  3. 主集群负载均衡器 Primary LB 将请求分派到一个选中的应用程序服务器 AppServer

负载均衡设备及软件

硬件一般选用的比较多的有 Citrix Netscalar, Cisco ACE, F5 等等, 性能强劲, 功能强大, 从传输层到应用层完美支持, 就是价格不菲.
软件方面就我所知, 开源的 HAProxy 和 Nginx 都很常见, 现在基于云端的负载均衡也渐渐多了起来

下面重点讲讲如下两个软件版本的负载均衡软件, 先用 Python Flask 写一个最简单的应用

from flask import Flask, Response
import optparse

app = Flask(__name__)
counter = 0

@app.route("/")
def hello():
    global counter
    counter = counter + 1
    return Response("Hits: %d" % counter)


if __name__ == "__main__":

    parser = optparse.OptionParser()

    parser.add_option('-p', '--port',
        action="store", dest="port",
        help="listen port", default="5000")

    options, args = parser.parse_args()

    print('listen port:', options.port)

    app.run("0.0.0.0", port=options.port, debug=True)


Flask>=0.12.2

以 ubuntu 系统为例, 运行如下命令在 5001 和 5002 两个端口分别启动这个小服务

virtualenv -p python3 venv
pip install -r requirements.txt
python app.py 5001 &
python app.py 5002 &

下面我们在 ubuntu 系统上分别用 nginx 和 haproxy 来做负载均衡

Nginx

它是著名的 web server , 由于性能卓越, 也常用来做 HTTP 层的反向代理和负载均衡

vi /etc/nginx/nginx.conf

# Nginx configuration

upstream wiki_app_server {
    server 127.0.0.1:5001 weight=1 max_fails=2 fail_timeout=30s;
    server 127.0.0.1:5002 weight=1 max_fails=2 fail_timeout=30s;
}

server {

    listen 80 default_server;
    listen [::]:80 default_server;

    server_name localhost;
    index index.html;

    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /workspace/walter/wfnote/site;

    
    location /wiki/
    {
        proxy_pass [http://wiki_app_server;](http://wiki_app_server)
        proxy_set_header Host $host:$server_port;
        proxy_set_header X-Forwarded-For $remote_addr;
    }
}

第一次请求, 显示 Hits: 1
第二次请求, 显示 Hits: 1
第三次请求, 显示 Hits: 2
第四次请求, 显示 Hits: 2

HAProxy

HAProxy 可以说是最流行的负载均衡软件, 它不同于 nginx , 专注于代理和流量分派, 在传输层和应用层都有比较好的支持

vi /etc/haproxy/haproxy.cfg

global
    log 127.0.0.1 local0 notice
    maxconn 2000
    user haproxy
    group haproxy

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    retries 3
    option redispatch
    timeout connect  5000
    timeout client  10000
    timeout server  10000

listen appname 0.0.0.0:80
    mode http
    stats enable
    balance roundrobin
    option httpclose
    option forwardfor
    server lamp1 127.0.0.1:5001 check
    server lamp2 127.0.0.1:5002 check

第一次请求, 显示 Hits: 1
第二次请求, 显示 Hits: 1
第三次请求, 显示 Hits: 2
第四次请求, 显示 Hits: 2

客户端负载均衡

在客户端使用配置的若干个接入点, 在客户端使用轮询的策略进行访问, 比如Cassandra 或 Kafka 在启动时只需配置两三个接入点的地址, 之后会从服务器端拿到整个集群的地址, 在客户端根据预设的负载均衡策略来访问相应的节点.

Spring Cloud Ribbon 是 Netflix 开源的一个基于Http和TCP的客户端负载均衡工具,可与服务注册中心 Eureka 集成, 拿到注册的服务器地址列表后, 根据设定的规则进行客户端的负载均衡.

参考资料

上一篇下一篇

猜你喜欢

热点阅读