系列文章
- .Net微服务实战之技术选型篇
- .Net微服务实战之技术架构分层篇
- .Net微服务实战之DevOps篇
- .Net微服务实战之负载均衡(上)
- .Net微服务实战之CI/CD
- .Net微服务实战之Kubernetes的搭建与使用
相关源码:https://github.com/SkyChenSky/Sikiro
前言
2020.1.10,陪我老婆到她所属的千亿企业的科技部值班,顺便参观了一下他们IT部门,舒适的环境让我灵感大发,终于把这篇拖了半年的博文完成了。
上一篇文章《.Net微服务实战之负载均衡(上)》从DNS、LVS和Nginx讲解如何在实战中结合使用,那么以上三种负载方式离开发人员相对来说比较远,平常也不容易接触到,更多是由团队的运维或者技术Leader关注的比较多。
该篇主要讲解在微服务架构中,如何使用我们耳熟能详的API网关+服务注册中心进行负载均衡的请求。让大家在实际工作中知道,如何将拆分后的微服务应用衔接起来,如何在微服务应用之间跨主机的访问容器进行请求。
下文的中间件的部署与使用,我将以下面的网络拓扑图的形式大家进行演示。在实际开发项目中,是以Docker Overlay的网络方式部署的,有些中间件为了开放给开发人员使用并且在文章中很好的展示给各位读者,我是把容器端口映射到了宿主,大家可以根据自生的实际情况进行定义。该文虽然是说.Net的微服务,但是实际上这几个中间件可以使用到其他各种平台,也是比较开源界相对热门、稳定的。
其次我也把在日常和同行沟通的时候,讨论得最多的问题给整理了出来,也方便入门微服务的读者能解答心中的疑惑,只有基础、理论理解清楚了,才能很好的进行实施。
我被问得多的那些问题
服务之间的调用关系容易混乱,该怎么划分?
下图的架构分层图是我当时实施后的应用分层,在这张图有几个关键点我给大家列一下
- 自顶向下的分为UI层、聚合API层、公共API层,
- 每一层只会依赖于下一层,不会跨层依赖,也不会同一层之间存在调用依赖
- 聚合API层与公共API层都是属于内网环境,无法被外网直接访问,聚合API层如果要被UI层调用或者外网访问则由API网关暴露出去,公共API层需要被聚合API层访问则由RPC、Consul与Fabio进行衔接请求。
- 纵向维度的从物理视角出发,分层目的是为了职责分离,避免调用关系乱套,循环依赖的问题
- 水平维度的从业务视角出发,分解目的是为了解耦与复用
在微服务架构里前后端分离后不知道如何调用API接口?
该问题其实跟微服务无关,也就是前后端分离的基本问题。提出的人应该是属于做单体系统多了,然后去了解微服务的时候发现概念多中间件多,什么API网关、服务注册中心、RPC的直接把他们搞晕了。
对于该问题的回答就是,客户端与API之间是使用HTTP协议进行交互的,甚至是微服务内的服务与服务之间都是以HTTP协议进行交互,因为马丁福勒在他的博客里说了个重要的单词【轻量】,该词就是指轻量级的通信协议也就是HTTP。
那么对于该问题的一个衍生问题就是,我怎么知道该接口怎么调用呢?答案就是Swagger,Swagger担任的服务描述的重任,他描述了,接口路径、协议类型、参数结构,只要有了以上3者是不是就很好让前后端人员对接了。
清楚上面的问题后,再引入API网关,API网关其实就是把原本零散的API服务给整合起来,形成统一的流量入口,由API网关进行路由转发,如下图:
微服务里服务与服务之间是怎么通信的?
首先协议跟上面的问题一致是HTTP的,那么在.Net里HTTP API是不是可以通过HttpClient进行请求?但是HttpClient调用API时是需要关注很多参数的细节,那么RPC的优势就来了。
RPC主要工作是像调用内部方法一样做远程调用和隐藏请求细节。在.Net里WebApiClient和gRPC都是不错的RPC框架。
此外,RPC框架也是我认为做微服务第一个考虑选型并且慎重选型的组件。
从服务注册中心拿到的是服务地址列表,该怎么做负载均衡请求?
我们从服务注册中心拿到某个服务信息是一组ip+port的集合,那么需要对该集合的某一项进行请求。
有两种解决方式:
- 调用端RPC集成,从注册中心获取服务地址列表,然后使用负载均衡算法选择其中一个IP+Port让RPC进行请求
- 使用中间件,该中间件是与注册中心集成的,例如Consul+Fabio,调用端会通
过RPC框架请求Fabio,Fabio会从Consul获取健康的地址请求转发。
下面的使用我主要以中间件的方式来解决上述的问题,主要.Net多数RPC是没有集成注册中心,如果由开发人员整合起来,改动相对会花精力与时间。
PS:上面的提到的API网关、Fabio请求转发如果把大家绕晕了话,你们可以把他们两个当成类似Nginx功能(不完全一样)的中间件。
那么经过上面问题讲述后,那么就可以开始接下来的Kong、Consul、Fabio与.Net Core的集成使用。
Docker环境的准备
所有服务器关闭防火墙,不然下面使用Overlay2后,容器之间也无法ping通,如果原本已经启动了防火墙后再关闭的后需要重启docker。
#关闭防火墙
systemctl disable firewalld
#重启docker systemctl restart docker 在Server A初始化Docker Swarm docker swarm init --advertise-addr 192.168.88.138 然后在其他worker节点Server B和Server C执行上面反馈的指令加入Docker Swarm集群 docker swarm join --token SWMTKN-1-0odogegq3bwui4o76aq5v05doqqvuycb5jmuckjmvzy4bfmm59-ewht2cz6fo0r39ky44uv00aq5 192.168.88.138:2377 在Server A上可以查看Docker Swarm节点信息 docker node ls 在Server A创建Overlay2网络覆盖,方便后续创建的容器之间可以跨主机访问 docker network create -d overlay --attachable overlay
测试容器之间是否可以跨主机访问
#创建nginx集群 docker service create -d --network=overlay --replicas 3 --name=nginx nginx #查找出某个实例的Ip docker inspect 1af2984adda9 #进入另外容器实例尝试请求跨主机请求 docker exec -it 1af2984adda9 /bin/bash curl 10.0.1.8 有以下响应结果就是网络环境OK了。