热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于微服务

原创不易,求分享、求一键三连微服务会让我们的应用变多,并且为了高可用一个服务会在线上部署多台,那么进行服务调用就存在节点之间的负载均衡和服务发现,负载均衡是为了让各个节点的负载尽量

原创不易,求分享、求一键三连


微服务会让我们的应用变多,并且为了高可用一个服务会在线上部署多台,那么进行服务调用就存在节点之间的负载均衡和服务发现,负载均衡是为了让各个节点的负载尽量平均,而服务发现是为了解耦服务中provider和consumer的发现和调用。

通常服务发现有两种常用的方式:一种是服务端服务发现,服务发现的和请求路由实现逻辑放在服务端;另外一种是客户端服务发现,因为这种发现和路由逻辑是由发送请求的客户端来实现的,像我们现在使用的kratos微服务框架就是用这种方式进行负载均衡的:


微服务进行服务发现和负载均衡中经常用到一个重要的组件就是注册中心,接下来我们先说一下我们用到的注册中心discovery(参考地址:https://github.com/bilibili/discovery/blob/master/doc/arch.md) 以下是discovery的架构图:


涉及三种角色:



  1. 提供服务的是service Provider;

  2. 服务订阅是Service Consumer ;

  3. 注册中心是Discovery Server;

接下来我们分别说一下注册中心是如何来进行服务注册、发现、注册中心节点之间的数据同步、以及遇到一些问题是如何避免的。


服务注册

当一个Provider启动的时候,首先需要判断服务是否启动成功,一般会定一个监控检测的接口,判断项目运行的依赖是否正常比如:mysql、redis或者mq等。

检测成功则会向discovery server发起register请求,请求成功之后,后续会以心跳的方式发送renew请求保证该服务能在注册中心续租成功,当服务下线会先将自己的健康检测的healthcheck设置下线状态,再发送Cancel到注册中心进行注销,将未处理的业务处理完成等待一段时候时间之后注销服务。


服务发现

discovry中consumer通过长轮询的方式获取使用的provider最新数据,有数据更新则进行本地数据变更,那么来看下什么是长轮询(HTTP Long-Polling)


长轮询通常被叫做“Hanging GET”,大致是这样的:

如果服务器没有数据可供客户端使用,则服务器不会发送空响应,而是保留请求并等待某些数据变为可用;一旦数据可用,将向客户端发送完整响应。

然后客户端立即从服务端重新请求信息,以便服务器几乎总是有一个可用的等待请求,它可以使用该请求来传递数据以响应事件。

使用HTTP长轮询的应用程序的基本生命周期如下:



  1. 客户端使用常规HTTP发出初始请求,然后等待响应

  2. 服务器会延迟其响应,知道更新可用数据或者发生超时。

  3. 当更新可用时,服务器会向客户端发送完整响应。

  4. 客户端通常会在收到响应后立即发送新的长轮询请求,或者在暂停后发送请求,以允许可接受的延迟期。

  5. 每个长轮询请求都有一个超时。由于超时,客户端必须在链接关闭后定期重新链接。


Discovery 节点的数据同步

当集群中的discovery接收到provider节点的请求之后,会讲请求转发到其他discovery进行数据同步,保持每个节点都能保持全部的最新数据,这种同步会有一些延迟,后面会说到这种延迟对服务发现的注册中心这种业务场景来说是影响不大的。


go-grpc内置的负载均衡


grpc在官网文档中提供了实现LoadBalance的方法,不同语言的grpc代码API中也提供了命名解析和负载均衡接口供扩展。默认提供的是DNS resolver的实现,接口规范实现简单,只需实现服务注册和服务监听和解析的逻辑就可以了,运行机制如下:

Resolver 解析器,用于从注册中心实时获取当前服务端的列表,同步发送给Balancer;

当grpc注册服务发现时,实际时注册的resolver.Builder, Builder会开启单独的groutine,进行watch逻辑,当调用UpdateState 向ClientConn发送服务地址表的更新;

resolver中的ClientConn结构提供了resolver通知ClientConn更新服务列表的回调方法。

Balancer 平衡器,接收从Resolver发送的服务端列表,建立维护长链接;client发起rpc调用时,按照一定的算法从连接池中选择一个连接进行rpc调用;

Register 注册,用于服务端初始化和在线时,将自己信息上报到注册中心,主要信息包含Ip+端口。


grpc HealthCheck

grpc提供了一个标准的健康检测协议,在grpc的所有语言实现中基本都提供了生成代码和用于设置运行状态的功能。

主动健康检查health check,可以在服务提供者服务不稳定时,被消费者感知,临时从负载节点中移除,减少错误请求。

有了上面说到的服务注册中心和负载均衡的支持,下面看如何实现平滑发布和平滑下线。


平滑发布

外置服务调用 Provider health check 接口,发现接口不通就不会注册,发现通就会注册,外挂有个旁者帮你去注册。

一般服务启动会进行一些数据初始化,环境初始化,等所有完成,然后将接口的 health check 接口状态改为可用,这时候docker 容器就可以放流量进来了,这就是常用的外挂方式。


平滑下线

如果我们这时候有个新功能需要上线,这时候需要先下线走 滚动更新。

k8s 发送 kill 进程id

go main 拦截 sigterm 信号,先告诉服务发现注册中心服务要注销,然后服务发现通知其他服务将自己本地的负载均衡连接池 close 掉,并且流量不要再发送过去了。但是服务发现通知其他 consumer 需要一定的同步时间,所以下一步我们将自己服务的 health check 接口标记为 下线状态。

最终我们一般要等到 2 个服务发现心跳周期,这是最差的情况,一般是实时的退出。

当然,不可避免依旧会遇到一些问题:


当注册中心挂了会怎样?

我们现在技术栈用的是B站开源的Kratos微服务框架,做的是客户端负载均衡,会把用到的数据缓存在客户端内存里,当注册中心挂掉了,就无法获取到注册中心的provider节点变更信息,这段时间不发版本,正常情况下就不会有大量的节点变更,注册中心做好监控告警,快速恢复注册中心。


当注册的节点未全局同步完成会怎样?

注册中心做了高可用会启动多个节点,节点之间的数据同步会遵循 CAP 定理 一致性(Consistency)(等同于所有节点访问同一份最新的数据副本);

可用性(Availability)(每次请求都能获取到非错的响应——但是不保证获取的数据为最新数据);

分区容错性(Partition tolerance)(以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择);

分布式系统智能满足三项中的两项不可能全部满足。Discovry是一个ap系统,数据同步会出现同步不成功、同步延迟等问题,对于未同步到的节点会延迟同步,只有部分节点可能会收到延迟,但是最终会都会同步成功。


当注销的节点未下线掉会怎样?

上面已经说到go-grpc支持健康检查的机制,如果节点未下线,但在provider下线前将健康检查接口置为不可用,则节点会从调用地址列表中移除,即使注册中心延迟下线,也不会有影响。

discovry中的provider是定期发送renew的方式进行续租,超过剔除心跳周期后,服务端会将对应的下线节点踢掉。


注册中心新节点上线,内存无数据会怎样?

新启动一个discovery节点到集群,这个时候新启动内存中没有其他节点的数据,discovery做了处理,在启动2-3个心跳周期才能提供consumer节点发现的服务,等待其他节点的数据全部同步之后才能提供服务。


discovery内部的自保护机制。

如果provider集群和discovery之间存在网络出现异常,但provider服务正常,只是心跳异常的情况,会启到保护的作用。

网络闪断和分区时自我保护模式

60s内丢失大量(小于Instance总数20.85)心跳数,“好”“坏”Instance信息都保留 所有node都会持续提供服务,单个node的注册和发现功能不受影响 最大保护时间,防止分区恢复后大量原先Instance真的已经不存在时,一直处于保护模式

参见(https://github.com/bilibili/discovery/blob/master/doc/arch.md)


染色环境(泳道环境)

为什么需要泳道环境?

我们同时存在几十个需求迭代同时开发,且不同的迭代可能会修改同一个项目,代码的冲突可以通过不同的分支解决,但开发阶段的联调都在同一个开发环境上的话会存在相互影响,造成开发效率低。

许多迭代的代码在同一个开发环境上联调会造成许多问题,研发人员解决这些问题开销的时间和精力成本很大。

这样的环境管理时间一久便造成了开发环境的联调不太稳定,研发人员转而将开发阶段的联调放到了测试环境,从而污染了测试环境,进而影响了测试阶段的效率。我们期望保证研发同学能够在不同的迭代情况下能够独立开发联调,测试同学期望保证测试环境的稳定。

"泳道",顾名思义是可以让不同的迭代开发能够在其自己的"泳道"上玩,不会影响其他的"泳道"。

我们选择了kratos框架,它本来就已经支持节点染色的功能,根据请求节点染色来进行负载能友好的解决上面提到的一些问题,在discovery注册到的节点中有个metadata用来存放节点的一些扩展字段,其中color就用来表示每个节点的染色环境:


在发送http请求的时候将需要访问的染色请求 设置到http header里面,在interface层解析放到ctx中,当去调用其他provider服务的时候,client端进行负载均衡进行节点选择,优先根据ctx中color选择对应染色的节点,不存在则默认color为空的节点进行调用。

上面说的这种情况我们只需要一套测试的基准环境,所有服务的color都是空,当同一个服务不同的需求变更就部署不同的color的多个节点,就能根据上面的方式进行测试。

好了,今天的分享就到这,喜欢的同学可以四连支持:


想要更多交流可以加我微信:




推荐阅读
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 在单位的一台4cpu的服务器上部署了esxserver,挂载了6个虚拟机,目前运行正常。在安装部署过程中,得到了cnvz.net论坛精华区 ... [详细]
  • php网站设计实验报告,php网站开发实训报告
    本文目录一览:1、php动态网站设计的关键技术有哪些软件,及搭建步骤需要哪些页面,分别完成 ... [详细]
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 31.项目部署
    目录1一些概念1.1项目部署1.2WSGI1.3uWSGI1.4Nginx2安装环境与迁移项目2.1项目内容2.2项目配置2.2.1DEBUG2.2.2STAT ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • 一次上线事故,30岁+的程序员踩坑经验之谈
    本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
  • 2021最新总结网易/腾讯/CVTE/字节面经分享(附答案解析)
    本文分享作者在2021年面试网易、腾讯、CVTE和字节等大型互联网企业的经历和问题,包括稳定性设计、数据库优化、分布式锁的设计等内容。同时提供了大厂最新面试真题笔记,并附带答案解析。 ... [详细]
  • 基于分布式锁的防止重复请求解决方案
    一、前言关于重复请求,指的是我们服务端接收到很短的时间内的多个相同内容的重复请求。而这样的重复请求如果是幂等的(每次请求的结果都相同,如查 ... [详细]
  • 有意向可以发简历到邮箱内推.简历直达组内Leader.能做同事的话,内推奖励全给你. ... [详细]
  • 域名解析系统DNS
    文章目录前言一、域名系统概述二、因特网的域名结构三、域名服务器1.根域名服务器2.顶级域名服务器(TLD,top-leveldomain)3.权威(Authoritative)域名 ... [详细]
  • RabbitMQ的消息持久化处理
    1、RabbitMQ的消息持久化处理,消息的可靠性是RabbitMQ的一大特色,那么RabbitMQ是如何保证消息可靠性的呢——消息持久化。2、auto ... [详细]
  • 目录Atlas介绍Atlas部署Atlas基本管理Atlas结合MHA故障恢复读写分离建议Atlas介绍Atlas是由Qihoo360Web平台部基础架构团队开发维护的一个基于My ... [详细]
author-avatar
thofarq
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有