微服务入门

这是一篇介绍分布式微服务的入门文章,文字朴实易懂,内容丰富 ,不用花很多时间就能大致了解什么是微服务?什么是SpringCloud?什么是dubbo?全文不涉任何的编码内容,笔者完完全全站在一个初学者的角度来进行叙述。适合人群:在校学生,刚入行的互联网从业者。如果你对分布式微服务架构已经很了解了,那么本文对你的帮助不大。
@在校学生:我现在自己本人就是一名学生,自然很清楚学校课程与生产实际情况存在脱节的情况,本文不会加重学业负担,有益无害。
@刚入行的互联网从业者:本文能帮助快速了解关于微服务的一些知识,纯干货分享。

初衷于体会

在正文之前,请耐心的容我啰嗦一会。
回顾自己学习Dubbo与SpringCloud的历程,我最深的体会就是,孰能生巧,学会容易,学精很难。其实将任何一个技术拆开来,它里面的任何一个小功能都是非常简单的,只要熟练使用这些小技术,就不会有难学的技术。对于技术的学习,一句话与大家共勉“I hear and I forget,I see and I remember,I do and I understand”。自己最近看一本书叫《淘宝技术这10年》,最直接的体会就是,自己之前一直执着于技术,没有从产品的层次去考量一些因素,怎么将将技术成熟的运用到实际中,,给项目带来什么样的收益?才是一个想要进阶的Java程序员更加应该注重的事情。 我也在反思怎么样认真的审视每一个流行的技术,站在一个更高的角度去思考这些,将我们的代码变加简洁?运行的更加稳定?系统更加安全?数据存取更加快速?功能实现之后,怎么取提升性能?
站在初学者的角度去梳理这些知识可能让会我有新的收获,另一方面我也要考量自己是否将基础概念都学到位、吃透了。

下面进入正文部分。

微服务

最近几年,分布式系统与微服务异常火爆,两大框架先后出现在各大互联网企业中,一个叫 Dubbo (可以跟dubble读音一样),另一个叫SpringCloud /sprɪŋ klaʊd/。稍后会详细解释这两个框架。分布式微服务的前提是:现在的任何一个互联网项目不可能单独仅仅使用一台机器撑起整个系统,一定是多台机器,也就是服务器集群。你可以简单的理解为由服务器集群撑起的互联网服务系统就是就是分布式系统,当然官方的定义肯定不是这么简单,但像我说的这样理解也没太大毛病。
有了这个前提,我们开始思考一些问题,咱们网站(先假设是我们互联网项目就是一个网站,当然Java语言能做的不止是web服务,它可厉害了)的数据在多个机器上是怎么存的?咱们的代码是每一个机器上都有相同的一份还是一个机器负责一个功能,只有一部分的代码?(这里说代码也不太对,其实应该是编译之后可以执行的二进制文件,只要理解这个意思即可,下文我将不再纠正这些不太准确的说法,毕竟初学者一开始就知道太多会畏难),一个用户请求我们需要多个机器来提供响应,他们是这么传递数据的?
好了,带着这三个问题接着往下走,再整理一下这三个问题,很重要!
1、数据到了服务器集群上怎么存?
2、代码到了集群上怎么放?
3、数据在集群的服务器之间怎么传递?

微服务基础概念 micro service
微服务的思想是2014年马丁福勒在他博客上提出的,原文链接:https://martinfowler.com/articles/microservices.html
当然是英文的(我猜你一听说英文可能就不去看了),所以我找到了一篇原文的中文翻译:https://blog.csdn.net/u010579482/article/details/80005330
简单来说,就是它提倡将单一应用程序划分成一组小的服务,每个服务运行在其自己独立的进程中,服务之间相互协调配合,为用户提供最终价值。微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底地去耦合,每一个微服务提供单个业务功能的服务,一个服务做一件事,从技术角度看就是一种小而独立的处理过程,类似进程概念,能够自行单独启动或销毁,拥有自己独立的数据库。
照这个思想,第二个问题的答案就是将整个系统的功能拆分成若干的小功能,以一个电商项目来说,我们拆成订单、商品信息管理、支付、物流管理等。所以,我们的集群上是一个机器只存放一个功能的代码。
至于上文说的第一个问题,数据是怎么在集群上存储的,聪明的你应该能够想到不是存在一个机器上的了吧,对没错,我们会将数据分库分表,存储在不同的机器上。但是又跟你想的不太一样,笔者简单说一下,有些数据是不会经常动它的,比如商品信息,商家店铺信息,这种数据叫做冷数据,我们可以使用关系数据库存储起来。而像浏览次数,购买人数,就会经常更新,这些热点数据我们存储在关系数据库里是不合适的,一般存在高性能的内存数据库中。所以,咱们的数据是存在不同的机器上。我接着抛出一个问题,像图片这种数据呢?图片不像文字那样方便,但是数量绝对不少哦,可以动脑筋想一想哦。图片可以用二进制存储,但是在电商项目中图片的数据量要占掉80%以上的数据存储容量,并且单看一张图片仅有几十几百KB,图片是非常典型的“大量小文件”,所以大家在京东、淘宝买东西的时候,网速不好的时候是先看见下面的商品信息,再看见图信息片的,因为处理起来很头疼。(想要知道处理办法的可以学习Hadoop生态圈中HDFS相关的知识,大量小文件的优化使用它做处理挺合适的)
了解了微服务是将网站的服务拆分成小的服务,然后让专业的服务干专业的事情,那么为什么会先后出现Dubbo和 SpringCloud呢?

每一个天上飞的理念,必然都会有落地的实现
我们想身在远方的亲人听见我们声音,可以打电话,可以发微信语音,可以视频通话。想让亲人听见声音是天上飞的理念,电话,微信,视频通话是落地实现。关系数据库的理念之于MySQL,Oracle的实现。可以这么说,Dubbo和SpringCloud都是微服务的两个完全不同思路的落地实现。类比来说,Dubbo和SpringCloud的关系就就类比于mysql和oracle的关系。(当然这也说还是有失偏颇,在文章的末尾我们可以听听Dubbo的负责人事怎么说这两者的关系的)
记不记得上面的3个问题笔者还有一个没有回答?剩下的那个是:集群之间的通讯机制?机器之间是怎么通过网络调用来传递数据的?
带着这个问题听我娓娓道来!

Dubbo

dubbo是阿里巴巴的产品,现在是apache的一个孵化项目。它的历史笔者就不细谈了(就不告诉你,超有意思,自己百度去吧)。
想讲清楚dubbo是什么,必须先讲一些概念:
1、序列化
先科普一下,计算机程序运行时候的数据是放在了本机的内存当中,int i = 1;就是在内存中为变量i开辟了一片空间,存储了数字1,当你机器断电了之后,内存断电,那么这个值就不存在了。但是大家都知道磁盘可以存储数据啊。(磁盘是电容存储电信号,内存就只有通电断电存储电信号,所以内存超级快,磁盘比较慢,电容会损耗啊,所以你手机存储空间会越来越少,内存不会损耗啊,除非摔坏了,这一次手机内存4个G,关机重启还是4个G,不过你QQ要重新打开了,因为断电了内存里面没数据了呀)
嘿嘿,这个时候你是不是有个大胆的想法,我在关机之前把我内存里面呢的数据给它想办法弄成文件存储在磁盘上,下一次我关机重启之后直接读那个文件不是就会把内存数据“保存”了么?
事实上,大名鼎鼎的Redis就是这么干的哦,就用这个思路可以实现Redis数据库的容灾备份、持久化(不信你百度:RedisRDB),Redis是用C语言写的哦。
回过头来,这个把内存数据转变成磁盘文件数据的过程就叫序列化,把磁盘文件读取到内存中的过程就叫反序列化,把数据序列化,业内就说数据“持久化”。基本上大部分的语言都会支持序列化。像Java语言的JDK就提供了一些接口或者方法(不太清楚的同学可以百度这个java关键字:transient )。

除了这个,再想一想我们可以把这个序列化了的数据文件干嘛?要是把它发给另外一台机器呢?刚好另外一台机器经过反序列化拿到这些数据了呢?
没错,答案就是,通过网络把这些序列化了的含有数据的文件发送给另外一台机器,另外一台机器经过反序列化算法的计算,就能拿到之前一台机器运算的结果了。我们不要只限于序列化一个数字1,要是我们序列化一个java对象呢?哇塞,简直完美有没有!!!,那么这个通过网络通信把序列化数据发送、接收的过程,这种规范的协议、这种通信方式就叫RPC。
2、RPC
我相信有了上面我对系列化的解释,你能看懂这一段官方对于RPC的标准定义了:
RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。
嘿嘿,不用自己解释概念好舒服啊。为了避免理解困难我再加一点小小的说明,有了RPC之后我们不用关心RPC的内部是怎么样去通过网络去调用另外一个服务的,我们只要知道一台机器上可以调用另外一台机器的代码了。
3、Dubbo
终于能说什么是Dubbo了,先看一看这段标准的定义:
Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。官网:http://dubbo.apache.org/
解释一下:Dubbo是基于RPC远程过程调用做好的一个分布式微服务框架,其实就是利用了序列化技术,把一台机器上运算好的数据输送到另外一台上,从而通过多台服务器去组成一个互联网服务,每个服务器只做一件事情,能极大的提升性能。并且我们再思考一个问题,假如第一次A服务器传入参数1让B服务器查询数据库ID是1的记录,然后B服务器成功的序列化返回给了A,之后由于网络问题,B服务器不小心宕机了(宕机的意思就是死掉了),下一次A还传入参数1调用B服务,但是B已经死掉了,我们能拿到数据吗?答案是,Dubbo是允许B宕机的,B死不死跟我这次调用没关系啊,我参数相同,我自己有一份B之前返回的数据了,直接用就好了呀。接着思考,这份数据可靠吗?答案是不可靠,因为这个过程中这个数据可能被别的程序改过,我们拿到的不是最新的数据,可能会出现跟数据不一致的情况。接着思考,既然数据一致性不能保证,那为什么Dubbo不放弃呢?答案是:联想一下之前说的冷数据和热数据,冷数据不经常更新,我们取到的数据对于冷数据来说就是最新的,并且可以通过别的方式来保证数据一致,比如当冷数据出现更新的时候,给这些调用方发送一个消息,利用消息中间件的技术也可以保证数据一致性,比起由于长时间等待一个宕机服务而导致集群雪崩(其实专业的说法是扇出),我们完全可以接受这个数据不正确!比起等一个已经死掉的服务,我们拿一个不太准确的数据可以接受啊。这里必须要指出,在搞并发的情况下,多余的一毫秒等待都是不容许的,1000个这样的等待阻塞起来就是1秒钟,更多呢?量变产生质变!这样一想,是不是这样的设计很有道理!
对于Dubbo标准定义里面还有一些非常重要的概念笔者解释一下:

  • 面向接口的远程方法调用:就是利用之前说过的序列化技术进一步抽象成RPC远程过程调用。
  • 负载均衡:分布式服务必有负载均衡,因为在并发的情况下,一秒钟进来了100个请求,请求显示这件商品的信息,但是我们现在有4台机器可以提供商品的信息。不使用负载均衡的时候,很可能这4台机器分担请求的情况是(80,10,5,5),这明显不合理啊,我们希望的是(25,25,25,25)每一台机器都平均分到25次。这就是负载均衡,常用的策略有,随机、轮询、重试、等等。(负载均衡策略很多,都有使用场景的,甚至可以自己定义策略)
  • 服务自动注册与发现:我是一个相亲中心,每一个想要相亲的人都给我一份关于他们的信息,我手里拿着一份相亲人员的名单和他们的信息,当有位美女来相亲了,他说想找一个身高175以上,能提供抱起我服务的男士,相亲中心就去找这样的男士。这个例子中,相亲中心就是服务注册中心,相亲的人不管是被匹配还是主动去匹配的人都是将自己的信息注册在服务注册中心,那位女士就是服务调用者(服务消费者),那位男士就是服务(服务提供者)。当然你不用管相亲中心是怎么找到这位男士的,这是RPC框架底层的通讯机制,我们使用框架的开发人员不需要管这些。(这样的服务注册中心Dubbo选用的是一个叫做Zookeeper的框架,Dubbo底层网络通讯的技术是netty)。
  • 下面这是比较官方图片和解释如下,相信经过我这接地气的解释,看懂简直so easy:

微服务入门_第1张图片
服务提供者(Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。
服务消费者(Consumer): 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
注册中心(Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
监控中心(Monitor):服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心调用关系说明
服务容器负责启动,加载,运行服务提供者。
服务提供者在启动时,向注册中心注册自己提供的服务。
服务消费者在启动时,向注册中心订阅自己所需的服务。
注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

社区:在Dubbo的官网上可以看到很多详细的使用方法,另外,Dubbo的源码是可以在github上搜到的:
微服务入门_第2张图片

Spring Cloud

2016年SpringCloud抢占全球市场,随之,服务注册中心、负载均衡、断路器、路由网管、分布式配置中心,被称之为分布式五大神兽,开始统治整个分布式应用市场。
Dubbo在将源码开放之后,更新过一段时间,之后停更。现在可能这样说,SpringCloud已经是普通互联网企业的首选分布式框架。当然,开源的东西我们不能评价谁赢谁输。阿里巴巴早在2006年就有了淘宝开放平台,给使用者能够二次开发(不理解的话,二次开发可以简单想象成类似于微信小程序的接口)。在开源上,阿里已经比国内大部分企业做的好了,当然这也给他们带来了收益。
说了这么多,从下面这张图应该不难看出Spring Cloud为什么能够具备这么大的统治力了吧!
微服务入门_第3张图片

Spring Cloud的社区活跃程度很高,可以到github上看源码:https://github.com/spring-cloud
但是我相信英语功底不是很扎实的话肯定需要我提供一些有用的学习网址:
官方中文文档: https://springcloud.cc/spring-cloud-netflix.html
官方配置文档: https://springcloud.cc/spring-cloud-dalston.html
SpringCloud中国社区: http://springcloud.cn/
SpringCloud中文网: http://springcloud.cc/

我回在接下来的篇幅中尽量站在初学者的角度用通俗的语言将清楚一些概念,毕竟自己也是一名学生,难免有失偏颇,不当之处希望得到指正!

Spring全家桶
Spring框架自从发布以来就备受欢迎,成为Java程序员必学之经典。而随后出现的SpringData(一个用来跟数据库打交道的框架)、SpringMVC(一个干掉Struts2的框架)、SpringSecurity(一个跟安全打交道的框架)、SpringBoot(一个用来跟单个服务功能打交道的框架),没错,这些都是无缝兼容Spring的,甚至咱们的Dubbo也是无缝兼容Spring的。由于Spring系列框架近几年运用越来越广泛,社区活跃程度堪称github一哥,所以业内戏称“Spring全家桶”!
且听我慢慢道来这Spring到SpringCloud的传承之路!没接触过Spring的同学可以当小说一样看就好。

restful
先回顾一个web知识,get请求和post请求,这个很基本的Http知识点大致是这样的:
get请求有长度限制,会在浏览器的URL地址留下请求的参数信息,不安全。
post请求没有长度限制,不会留下请求参数信息,比较安全。
但是当我们想对数据库进行CRUD(增删改查)的时候,能不能通过这两个请求咱们想办法添加一点什么信息就能实现一个请求里面携带增删改查信息?SpringMVC这样做了,它是这样做的:

  • 查询使用get请求,就使用原来的get请求
  • 增加使用post请求,就使用原来的get请求
  • 删除使用delete请求,修改一下post请求底层的处理
  • 修改使用put请求,修改一下post请求底层的处理

这样做了之后,我们可以通过这些get、post、delete、put这四个请求完成对数据的增删改查操作

SpringBoot
有句话在业内很流行:配置大于编码,约定大于配置。编码可以理解为你要去new一个个的对象,当有了spring之后就不需要再去new了。配置是这么回事,当我们使用了框架之后,我们在配置文件里面写一句话就可以省去很多的编码。约定是这么回事,当使用了Maven我们约定好了项目的结构,在pom文件里面写一句话就连jar包都不需要去管了,多方便呀!而SpringBoot更狠,之前我们歇一个web项目不是需要在本机上装个tomcat吗,有了这东西之后,连tomcat都省了。
上面的看不懂没关系,回到微服务的层面!
说上面这些,就是想说,有了SpringBoot之后,我们开发一个单个服务的难度降低了,我们只需要专注怎么取数据,怎么计算数据,怎么存储数据就行了,也就是将重心专业到业务逻辑上。
也就不难理解为什么SpringBoot成为企业级Java项目的一站式开发框架了,因为它是在是太方便了。

SpringCloud

微服务入门_第4张图片
我将一个简单的SpringCloud项目截图出来讲述,框中的一个就是一个java工程,它会在一个单独的机器上运行,每一个java工程都会有一个独立 的机器去运行。这个独立的项目就是一个SpringBoot项目,由此可以知道:一个SpringCloud项目是由多个SpringBoot工程组成的,单个的SpringBoot项目可以独立存在,但绝对没有不依赖SpringBoot就构建起来的SpringCloud分布式微服务项目。所以,一个SpringBoot的Java项目就是一个微服务!
大家回忆一下,在讲Dubbo的时候它是通过RPC调用另外一台机器上的服务,然后将结果系列化,调用者就拿到了运行结果,那么SpringCloud是这么实现服务调用的呢?
答案是通过resyful的方式,这里可能会有些费解,但事实是对于数据的访问、操作、SpringCloud集群之前就是发送写增删改查的请求去调用服务,调用者不需要关心是那台机器处理了我的请求,只要关系能不能拿到结果就好了。
举个例子,A想要得到user表中id是3的数据,能够提供这样服务的机器有B1,B2,B3,B4,四台。A发起请求/getUser?id=3(),会由注册中心去负载均衡,比如根据随机的负载均衡策略,随机到了B3,那么B3查询到了数据,返回就好,A只在乎收到了数据。具体的细节讲起来可能就很多,大致原理是这样就行。(服务调用者使用的是一个叫RestTemplate的模板去调用服务,只需要关心能不能提供服务,不用关心是谁提供的)

还记不记得我问题3还没有回答,数据在集群的服务器之间怎么传递?
Dubbo是通过RPC远程过程调用,而SpringCloud是通过HTTP方式。
再具体了来说,Dubbo是通过RPC得到一个服务奖数据序列化了的文件,调用者只需要反序列化就行了。
SpringCloud是通过HTTP请求的方式,只是把原来的get和post加了点东西变成可以增删改查的强悍restful请求调用形式。
这也说明,Dubbo和SpringCloud是两个完全不同的微服务落地实现,他们设计的思路都不一样。

我觉得关于SpringCloud的基础内容聊到这里就已经可以了,我肚子里的干货就不再是面向初学者的了(虽然也没多少),下面是我对”五大神兽”的介绍:
1、Eureka (伊瑞卡)
类比就相当于服务注册中心,但是Eurekaz做的更棒,它太强了,比Zookeeper好太多了。服务注册与发现对于微服务架构来说是非常重要的,有了服务注册与发现,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件。功能类似于dubbo的注册中心,如Zookeeper。
2、Ribbon (瑞本)
Ribbon 是一套客户端负载均衡的工具。(你没猜错,还有服务端的,甚至还有专门负责负载均衡的服务器哦,不过贼贵,不信可以百度:负载均衡f5价格)在SpringCloud社区中,除了Ribbon可以做负载均衡,还有个叫feign(读作:奋!)的也可以负载均衡的功能。
3、Histrix (海斯坠克斯)
假设在搞并发的情况下,有个服务的调用好长时间没有得到回应数据,这个时候为了避免崩溃,可不可以直接把这个服务停掉,然后给一个调用失败的信息?(这活你能不能干?给个信息啊,别什么站着啥都不说啊,不能干我们换人干)类似于这个意思。Hystrix断路器,也叫熔断器,程序出现异常、长时间调用失败、调用不恰当、超时等。为了避免长时间没有响应而导致全局系统的瘫痪、挂起、死机。
4、Zuul (祖鲁)
最简单的理解,就一句话Zuul提供=代理+路由+过滤三大功能。(由于本人在学校网络学的比较渣,还是听听官方怎么说的比较靠谱,一涉及网络就不自觉腿抖,生怕说错了… Ծ‸ Ծ )
Zuul包含了对请求的路由和过滤两个最主要的功能:其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础。而过滤器功能则负责对请求的处理过程和干预,是实现请求校验、服务聚合等功能的基础。Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。
5、Spring Cloud Config (这三个单词超简单哦)
微服务集群上有很多不同的SpringBoot项目,假如今天我们数据库环境迁移了怎么办,数据库地址,用户名密码改了怎么办,到这些项目下面一个个改数据库连接信息?no! 改SpringCloudConfig这一个就好啦,你可以理解这个是老大,总配置文件。一般总配置文件放哪呢?聪明的你应该不难想到,还有什么技术管理项目超级方面呢?当然是项目的github 服务器咯!
Spring Cloud Config是为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。

好了,到这五大神兽基本解释清楚了,但请到中文网上看一眼,光是罗列出来的技术就有21种之多,而笔者只是简单的说了5个,现在SpringCloud已经演变成一个生态体系、技术栈!什么意思,就是SpringCloud已经不是一种技术,而是一堆技术的集合,长路漫漫…

微服务入门_第5张图片

阿里巴巴 Dubbo重启维护之后的负责人之一是 刘军,他的说法是:
Dubbo的定位始终是一款RPC框架,而Spring Cloud的目标是微服务架构下的一站式解决方案,当前由于RPC协议,注册中心元数据不能匹配等问题,在面临微服务基础框架选型时Dubbo与Spring Cloud只能二选一。Dubbo之后会积极寻求适配到Spring Cloud生态,比如作为Spring Cloud的二进制通信方案来发挥Dubbo的性能优势,或者Dubbo通过模块化以及对HTTP的支持适配到SpringCloud。

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