那时候刚好下着雨,柏油路面湿冷冷的,还闪烁着青、黄、红颜色的灯火。



如何基于Golang设计一套微服务架构


如何基于Golang设计一套微服务架构

微服务(Microservices),这个近几年我们经常听到。那么现在市面上的的微服务架构技术有很多,比如比较成熟的 Spring Boot、Spring Cloud 全家桶。如果在非 Java 体系里如何实现微服务架构呢?

经过几个月的折腾,我们就来聊聊Golang在微服务架构是如何实现?

What are microservices?

微服务 —— 也称为微服务架构 —— 是一种架构风格,它将应用程序构建为松散耦合服务的集合,这些服务实现了各种业务功能。微服务体系结构支持大型复杂应用程序的持续交付/部署。它还使组织能够发展其技术堆栈。

  • 狭义来讲就是体积小
  • 服务 相对较小且独立的功能单元

简单来说,微服务架构就是将一个完整的应用从数据存储开始垂直拆分多个不同的服务,每个服务能独立部署、独立维护、独立扩展。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。通常,每个任务代表着一个小的业务能力。

传统单体式应用

我们先来看看传统的单体式应用架构:

Java 应用程序被打包成 WAR 文件部署在如 Tomcat上,他们很容易开发、部署,因为我们的 IDE 和其他工具就是专注于构建单体应用。 这种简单的方法有很大的局限性,我们来看看这种单体式架构它有哪些问题。

  1. 复杂性逐渐变高

    项目有几十万行代码,各个模块之间区别比较模糊,逻辑比较混乱,代码越多复杂性越高,越难解决遇到的问题。

  2. 技术债务逐渐上升

    人员流动问题

  3. 部署速度逐渐变慢

    代码越多编译越慢,部署越慢

  4. 阻碍技术创新

    想要改变些什么,但历史包袱太重

  5. 无法按需伸缩

    比如cpu密集型的模块,比如大内存模块等

一旦应用程序成了一个庞大、复杂的单体,开发会陷入一个痛苦的境地,敏捷开发和交付的任何一次尝试都将原地徘徊。主要问题是应用程序实在非常复杂,其对于任何一个开发人员来说显得过于庞大。最终,正确修复 bug 和实现新功能变得非常困难而耗时。

为了解决这个问题,就诞生了一个新的概念”微服务”

微服务 — 解决复杂问题

  1. 每个服务通常实现一组不同的特性或功能
    • 例如订单管理、客户管理等。每一个微服务都是一个迷你应用,它自己的六边形架构包括了业务逻辑以及多个适配器。
  2. 每个微服务会暴露一个供其他微服务或应用客户端消费的 API
    • 其他微服务可能实现了一个 web UI。在运行时,每个实例通常是一个云虚拟机(virtual machine,VM)或者一个 Docker 容器。

一个单体应用拆分成微服务

应用程序的每个功能区域现在都由自己的微服务实现,每个后端服务暴露 API,大部分服务消费的 API 由其他服务提供。一系列独立运行的微服务共同构建起了整个系统。

每个服务为独立的业务开发,一个微服务一般完成某个特定的功能

比如:订单管理,用户管理等;每个服务都拥有各自的数据库

开发和交付中的伸缩立方

微服务架构模式相当于此伸缩立方的 Y 轴坐标,另外两个坐标轴是由运行多个相同应用程序副本的负载均衡器组成的 X 轴坐标和 Z 轴坐标,其中请求的属性(例如,一行记录的主键或者客户标识)用于将请求路由到特定的服务器。应用程序通常将这三种类型的坐标方式结合一起使用。Y 轴坐标将应用分解成微服务 X 坐标轴上运行着服务的多个实例,每个服务配合负载均衡器以满足吞吐量和可用性。某些应用程序也有可能使用 Z 坐标轴来进行分区服务。

微服务架构特点

  1. 易于开发和维护
  2. 启动较快
  3. 局部修改容易部署
  4. 技术栈不受限
  5. 按需伸缩

微服务架构模式可以实现每个微服务独立部署,独立扩展。

微服务的架构优势

  1. 快速度发布
  2. 独立扩展
  3. 快速试错
  4. 快速应用新技术
快速发布

功能简单,测试简单,无过多依赖,配置简单,发布简单。

快速试错-小步快跑

快速开发,快速上线,快速调整。

微服务的劣势

  1. 性能损失,微服务之间都是通过restfull或grpc的方式进行通信。
  2. 系统复杂,一个应用或多个应用有非常多的服务
  3. 服务太多监控复杂。
  4. 微服务架构不适用于
    • 对单机性格要求高
    • 例如:操作系统,数据库
  5. 对运维要求比较高
  6. 接口调整成本高

Golang 微服务架构技术

好了,不扯那么多,咱们来说今天的主题吧。Go在微服务架构中使用的一些技术方案。

既然是以Golang为主,那必然我们尽量全使用golang的技术架构。

首先我们需要解决一个问题!

假设我们的应用微服务化了,我们会遇到哪些问题?

要微服务架构需要面临的一些问题

  1. 如何发现服务
  2. 如何对服务链路进行追踪
  3. 如何管理配置
  4. 如何对服务API进行控制
  5. 如何部署(持续交付)

带着这些问题我们找一些这些开源的解决方案。

那么如何将这些工具利用并组合起来呢?

我们先来看看这些工具都是什么?在微服务架构中担任着什么样的角色?

Consul

Consul是一个服务管理软件。它主要特点:

  • Service Discovery

    服务发现和配置的工具。分布式, 高度可用,并且具有非常好的可伸缩性。

  • Failure Detection

    将服务发现与健康检查配对,可以防止路由请求对不健康的主机,并使服务能够轻松地提供断路器。

  • Multi Datacenter

    在没有复杂的配置的情况下,Consul调度到多个数据中心。在其他数据中心查找服务,或保持请求本地。

  • KV Storage

    灵活的Key/Value存储动态配置,功能标记,协调,Leader选举等。配置更改和即时通知。

可以用Consul来实现以下功能

  1. 分布式key/value,用于做配置中心。
  2. 分布式session,用于解决session的问题。
  3. 分布式锁,其key/value也可以用于分布式锁的问题
  4. 资源中心,动态管理redis、datasource、rabbitmq等资源

那么,我们暂时先把它当作服务注册、发现和配置中心进行使用。

什么是服务注册?

一个服务将其位置信息在“中心注册节点”注册的过程。该服务一般会将它的主机IP地址以及端口号进行注册,有时也会有服务访问的认证信息,使用协议,版本号,以及关于环境的一些细节信息。

什么是服务发现?

服务发现可以让一个应用或者组件发现其运行环境以及其它应用或组件的信息。用户配置一个服务发现工具就可以将实际容器跟运行配置分离开。常见配置信息包括:ip、端口号、名称等。

当一项服务存在于多个主机节点上时,client端如何决策获取相应正确的IP和port。

在传统情况下,当出现服务存在于多个主机节点上时,都会使用静态配置的方法来实现服务信息的注册。

而当在一个复杂的系统里,需要较强的可扩展性时,服务被频繁替换时,为避免服务中断,动态的服务注册和发现就很重要。

比如 Zookeeper,Doozer,Etcd,强一致性的项目,这些项目主要用于服务间的协调,同时又可用于服务的注册。

服务注册、发现有了,配置中心有了,网关呢?

Why an API Gateway?

下面这张图可以很好的诠释什么是网关

现在市面上的开源网关也有很多,比较Java体系的 Zuul

在众多的网关服务中,我们选择了基于Nginx的OpenResty实现的网关--> Kong

Why did choose Kong

Kong 是一个现成 的 Api Gateway 的解决方案。

Kong有以下主要特点:

  1. 众多的插件
  2. 基于OpenResty
  3. 可视化配置
  4. 与Consul搭配使用
  5. Api管理、限流、授权、降级、负载、请求分发、日志等等
  6. 性能高

当然Golang也有一些开源的网关,但都不是很完善。我们选择Kong主要是它有很多东西已经支持了,我们不需要再次进行开发。当然还有一个原因就是我们会Ngx_lua呀〜〜

链路追踪-zipkin

分布式跟踪系统,它可以帮助收集时间数据,解决在microservice架构下的延迟问题; 它管理这些数据的收集和查找;每个应用程序向Zipkin报告定时数据,Zipkin UI呈现了一个依赖图表来展示多少跟踪请求经过了每个应用程序;

如果想解决延迟问题,可以过滤或者排序所有的跟踪请求,并且可以查看每个跟踪请求占总跟踪时间的百分比。

为什么使用Zipkin

随着业务越来越复杂,系统也随之进行各种拆分,特别是随着微服务架构和容器技术的兴起,看似简单的一个应用,后台可能有几十个甚至几百个服务在支撑;一个前端的请求可能需要多次的服务调用最后才能完成;当请求变慢或者不可用时,我们无法得知是哪个后台服务引起的,这时就需要解决如何快速定位服务故障点,Zipkin分布式跟踪系统就能很好的解决这样的问题。

架构

当我们把这套架构搭建起来后,我们看看这套服务系统中的架构情况。

上图就是这套架构设计的微服务的流程

所有的应用及服务启动的时候向consul注册,然后consul会检测你服务的健康状态从图上可以看出这套微服务看起来非常复杂。

虽然复杂,但它可以做到微服务的核心思想呀!

那么问题来了

要实现上述功能,需要在代码里嵌入大量代码。

你愿意吗?

当然这只是基中大问题之一,微服务架构中还有以下一些问题。

微服务架构的问题

微服务的好处显而易见,它本身所具备的可扩展性、可升级性、易维护性、故障和资源的隔离性等

产品的生产研发效率大大提高。

这么多的微服务如何管理?

难道每部署一个微服务就得申请一个或多个虚拟机吗?那岂不是100个微服务需要好几百台虚拟机进行支持?

如何发布?

使用什么工具才能方便快速度的发布各个微服务呢?

如何监控?

如何简单的对每个服务进行监控、报警?

带着以上这些问题,我们尝试的 CloudNative + ServiceMesh 是一个很好的解决方案。这个,以后我有时间慢慢道来。

尾巴

微服务架构所涉及的技术栈很多,想入坑的或准备入坑的请谨慎。前期必须做好大量准备工作,并且要多做尝试,别怕。

老应用建议慢慢拆,一点一点拆,新的服务就大胆尝试。

后续我有空的话再更新:

  1. Consul 集群搭建、如何进行服务注册、服务发现和配置中心使用
  2. Kong 集群打搭建有配置、使用
  3. Zipkin、ES 集群搭建及golang如何接入ZipKin
  4. 我们是如何解决 服务侵入、微服务架构 的问题
  5. 关于 CloudNative 的方案
  6. 当进入 CloudNative 后,我们又掉入了另一个深坑

虽然之前我所设计的方案,在最终实践上有了大的调整,这套方案我们并没有直正实现。为了解决这些问题,我们有了更好的方案并且已成实施。

最近所积累的经验、深浅坑足够我发几个月的文了。

说了这么多,我们到底在解决什么问题?

微服务解决了什么问题?

CloudNative又解决了什么问题?

留着这些问题,我们以后再说。

最后,感谢网络上的各个大神们的文献。

谢谢大家的支持!

深情按压, 小额赞赏, 您的赞赏就是我更新的动力。


 标签 , TAG , 啦啦