L0服务,类似像我们账号,之前是一套大集群,一旦故障影响返回巨大,所以我们从几个角度考虑多集群的必要性:
- 从单一集群考虑,多个节点保证可用性,我们通常使用N+2的方式来冗余节点。
- 从单一集群故障带来的影响面角度考虑冗余多套集群。
- 单个机房内的机房故障导致的问题。
多集群:
我们利用PaaS 平台,给某个 appid 服务建立多套集群(物理上相当于两套资源, 逻辑上维护 cluster 的概念),对于不同集群服务启动后,从环境变量里可以获取当下服务的 cluster,在服务发现注册的时候,带入这些元信息。当然,不同集群可以隔离使用不同的缓存资源等。
业务隔离集群带来的问题是 cache hit ratio 下碎,不同业务形态数据正交,我们退而求其次整个集群全部连接。
统一为一套逻辑集群(物理上多套资源池),即 gRPC 客户端默认忽略服务发现中的 cluster 信息,按照全部节点,全部连接。能不能找到一种算法从全集群中选取一批节点(子集),利用划分子集限制连接池大小
- 长连接导致的内存和CPU开销, HealthCheck 可以高达30%。
- 短连接极大的资源成本和延迟。
合适的子集大小和选择算法:
- 通常20-100个后端,部分场景需要大子集, 比如大批量读写操作。
- 后端平均分给客户端。
- 客户端童后,保持重新均衡,同时对后端重后保持透明,同时连接的变动最小。
多租户
在一个微服务架构中允许多系统共存是利用微服务稳定性以及模块化最有效的方式之一 ,这种方式一般被称为多租户(multitenancy)。租户可以是测试,金丝雀发布, 影子系统(shadow systems),甚至服务层或者产品线,使用租户能够保证代码的隔离性并且能够基于流量租户做路由决策。
灰度测试成本代价很大,影响1/N 的用户。其中N为节点数量。
对于传輸中的数据(data-in-flight)(例如,消息队列中的请求或者消息)以及靜态数据(data-at-rest) (例如,存储或者持久化缓存),租户部能够保证隔离性和公平性,以及基于租户的路由机会。
如果我们对服务B做出改变,我们需要确保它仍然能够和服务A,C,D正常交互。在微服务架构中,我们需要做这些集成测试场景,也就是测试和该系统中其他服务的交互。通常来说,微服务架构有两种基本的集成测试方式:并行测试和生产环竟测试。
并行测试需要一个和生产环境一样的过渡(staging)环境,并且只是用来处理测试流量。在并行测试中,工程师团队首先完成生产服务的一次变动,然后将变动的代码部署到测试栈。这种方法可以在不影响生产环境的情况下让开发者稳定的测试服务,同时能够在发布前更容易的识别和控制 bug。尽管并行测试是一种非常有效的集成测试方法,但是它也带来了一些可能影响微服务架构成功的挑战:
- 混用环导致的不可靠测试。
- 多套环境带来的硬件成本。
- 难以做负载测试,仿真线上真实流量情况。
使用这种方法(内部叫染色发布),我们可以把待测试的服务B在一个隔离的沙盒环境中启动,并且在沙盒环境下可以访问集成环境(UAT)C和D。我们把测试流量路由到服务 B,同时保持生产流量正常流入到集成服务。服务B仅仅处理测试流量而不处理生产流量。另外要确保集成流量不要被测试流量影响。生产中的测试提出了两个基本要求,它们也构成了多租户体系结构的基础:
- 流量路由:能够基于流入栈中的流量类型做路由。
- 隔离性:能够可靠的隔离测试和生产中的资源,这样可以保证对于关键业务微服务没有副作用。
给入站请求绑定上下文(如:HTTP Header),in-process 使用 context 传递,跨服务使用 metadata 传递(如:opentracing baggage item),在这个架构中每一个基础组件都能够理解租户信息,并且能够基于租户路由隔离流量,同时在我们的平台中允许对运行不同的微服务有更多的控制,比如指标和日志。在微服务架构中典型的基础组件是日志,指标,存储 ,消息队列,缓存以及配置。基于租户信息隔离数据需要分别处理基础组件。
多租户架构本质上描述为:
跨服务传递清求携带上下文(context),数据隔离的流量路由方案。
利用服务发现注册租户信息,注册成特定的租户。