浅谈微服务与负载均衡LBS

微服务这几年应该是我听过最多的,很多公司的架构现在都在往这个方面迁移,包括很多的互联网公司,以及其它行业的软件公司。至于原因吗,很多人都出自己的理解,从业务需求上讲,可以scale-out,满足业务增长的需求,另外从软件开发者的角度,服务化的架构确实是降低了各个软件模块的偶合,更方便软件的开发,部署,测试。

但这里为什么把微服务跟负载均衡服务器联系在一起呢?

首先看一下当软件的架构从传统的单体应用切换到微服务架构后对我们开发软件的工程师的影响。

微服务

在以前单体应用开发的时候,模块之间的关联都是通过简单的方法调用,比如,如果moduleA里面有个ClassA,它想要调用另外一个ModuleB里面的ClassB来完全某个功能,我们通常会这样写:

ClassA {

  public void methodA() {
    ...
    new ClassB().methodB()
    ...
  }
}

这样ClassA就跟ClassB产生了关联,偶合。

再来看一下用微服务架构后,我们会怎么来完成上面同样的功能。
ModuleB 里面的ClassB可能会提供一个Restful 的API来完成原来相同的功能:/moduleb/methodb, 这样改造之后,ClassA就需要这样子来调用原来的功能:

ClassA {

  public void methodA() {
    ...
    String methodBUrl="http://127.0.0.1:8080/moduleb/methodb";
    HttpClient client = new HttpClient(methodBUrl);
    Response rsp = client.post(data)
    ...
  }
}

这样ModuleA跟ModuleB就解耦了,但还有什么问题呢?
在ClassA.methodA()里面,我们把提供服务的机器的ip/port硬编码到http url里面了localhost:8080, 但在真实的软件部署环境中,会有很多的问题:

  1. 服务的提供者跟服务的使用者通过不会部署在同一台机器上
  2. 部署服务的机器可能是VM,或者更复杂的是,这是跑在云端的,这些环境通常不会分配固定的IP地址,而是一个变化的IP
  3. 相同的服务可能会被布置到多个机器上,一开始我们就说到微服务就可提供scale-out,服务的使用者如果只调用某台机器上提供的服务,就起不到Scale-out的作用
  4. 服务如果挂起了,就会单点失败的问题,需要将服务的请求redirect到其它的机器上

    问题好像起来越多了,怎么来解决这些问题呢?首先可能我们会想到用DNS来解决,用hostname来代替IP地址,确实可以解决一些问题,但一些复杂的问题,单单用DNS不能完美地解决,比如上面提到的第4个问题。

这里就要用到负载均衡服务器了。

负载均衡LBS

顾名思义,这个负载均衡服务器最基本的功能就是要保证所有提供服务的机器要大概一样忙,不能一台机器忙到爆,另外一台机器在叹空调。这样不公平,如果是这样,我们也没有必要花钱买这么多的机器了。所以LBS在决定将服务请求forward到某台机器前需要一些策略来保证大家相对一样忙。

所以前提就是需要将所有的服务请求发到负载均衡服务器,比如Haproxy,再由LBS转发到真正的服务的机器上,因些前面例子里,URL里面应该写成LBS服务器的hostname:http://lbs_hostname:port

浅谈微服务与负载均衡LBS_第1张图片

但这样是不是就解决所有问题呢?没有,上面提到的第4个问题还是没有解决。如果某个机器上的服务挂起了,就应当将服务的请求转发到其它机器上面。

在微服务的架构中,还有另外一个必要的模块,这个模块会提供服务的发现与注册,以及对服务的healthy check。这个模块通常会跟LBS部署在一起,业界常用到的有consul/etcd/zookeeper。

比如consul-template会根据consul里注册的服务的healthy check的结果,动态地为LBS生成配置,在配置里只会包含healthy的服务器的host信息,每当配置变化里会重启LBS来保证服务的请求只转发到健康的机器上。

你可能感兴趣的:(微服务)