==> 学习汇总(持续更新)
==> 从零搭建后端基础设施系列(一)-- 背景介绍
没有看过上篇的点这里【从零搭建后端基础设施系列(十)】-- 服务发现与治理(上)
-
CODE
- RegistCenter -> master
- ServiceGovernance -> master
- Min-system-thrift-service -> feature/iterate1
- Min-system-web-service -> feature/iterate1
-
效果演示
-
启动注册中心,并将三个服务注册到注册中心
注册服务
-
启动服务治理
启动服务
-
启动最小系统thrift服务
-
启动最小系统web服务
-
再来看看服务治理的日志
已经有两个服务的机器信息上报到这里了。
-
接下来发送一个http请求看看
接口全部通了。 -
将web服务重启看看会发生什么
-
将thrift服务重启看看会发生什么
但是你会发现,web调用thrift的时候报错了
很明显,连接失效了。
-
-
现象分析
-
为什么需要按照这样的顺序启动?
注册中心必须先启动,因为它需要存储其它服务的信息
服务治理启动需要依赖注册中心,因为后续其它服务上报机器信息的时候,需要判断该服务是否已经注册。
然后到thrift服务,因为它需要依赖前面两者
最后到web服务,因为它需要依赖前面三者 -
为什么注册中心不需要上报机器信息到服务治理中心?
按道理是需要的,但是这里怕麻烦,没有做。(我在想,先有注册中心还是先有服务治理中心?小纠结,,,后续看看怎么优化) -
如何检测机器状态的?
通过客户端定时发送心跳信息到服务治理中心。
可能有人会问,为什么是客户端主动发送心跳,而不是服务端主动检测呢?
其实两种方法都可以实现,但是客户端主动发送心跳可以减少服务端的消耗,并且实现起来简单。 -
为什么重启thrift服务后,web调用thrift接口会报错?
首先thrift服务重启,那么第一次的连接肯定失效了,其次第一版非常粗糙,重试机制都没做。。。,所以会发生上面的情况。 -
使用注册中心和服务治理有什么优势?
从这个小demo都可以看出来优势,首先,以前没有RC(注册中心简称)和SG(服务治理简称)的时候,web每次连接thrift都需要手动改一下ip(因为每次重启电脑后,IP都有可能会变),如果有N个客户端要连thrift,那么就需要改N个客户端的代码,非常的不灵活。有了RC和SG后,所有服务只需要记住RC和SG的IP,就能够拿到其它服务的IP。当然了还有很多很多优势,例如限流、熔断、鉴权等等。
-
-
总结与改进
每次写完一个小demo,都会去思考,还有什么能改进的。就好比一个小公司成长为大公司,期间的架构肯定是从最简单的演化到最复杂的。例如,以前的网站架构都非常简单,使用linux+mysql+apache+php
,就可以很快的搭建出来,因为一开始流量都很小,linux机器单机,mysql机器单机,还可能不是多台机器,而是一台机器,包干所有!然后演化到现在,流量大了,场景也复杂了,什么分布式啊,集群啊,统统干上了。但是万变不离其宗,先从它祖宗十八代研究起,把它翻个底朝天不是更有趣吗?-
通过这四个服务,发现thrift的代码非常的重复
例如服务启动的代码,基本每个服务都有一个ThriftServerBean
,并且都干着同样一件事。所以,第一想法,抽出来!@Component public class ThriftServerBean implements FactoryBean<ThriftServerBean>, InitializingBean { private TServer tServer; @Value("${local.port}") private Integer port; @Value("${local.appKey}") private String appKey; @Autowired private TRegistCenterImpl tRegistCenter; @Override public ThriftServerBean getObject() throws Exception { return new ThriftServerBean(); } @Override public Class<?> getObjectType() { return ThriftServerBean.class; } @Override public void afterPropertiesSet() throws Exception { TProcessor tProcessor = new TRegistCenter.Processor<TRegistCenter.Iface>(tRegistCenter); TNonblockingServerSocket serverTransport = new TNonblockingServerSocket(port); TProtocolFactory protocolFactory = new TBinaryProtocol.Factory(); TNonblockingServer.Args tArgs = new TNonblockingServer.Args(serverTransport); tArgs.processor(tProcessor); tArgs.protocolFactory(protocolFactory); tServer = new TNonblockingServer(tArgs); System.out.println("[info] RegistCenter bootup successful -> " + NetWorkUtil.getInet4Address() + ":" + port); new Thread(()-> tServer.serve()).start(); } }
再有就是
ThriftClientConfig
,也是极为重复,抽出来!所以,很有必要对thrift进行封装,基于我们的demo(业务),进行二次开发
-
都可以将什么抽出来呢?
首先,我们要明白一件事,基础设施是为了减轻业务负担而存在的,所以目标肯定是,thrift服务和web服务就只干一件事,实现自己的业务逻辑,不需要管什么连接啊,注册啊,服务如何如何启动啊等等。
那么谁来做呢?那肯定就是通信层做了,例如A调用B的接口的时候,发生了一次远程调用,也就是网络调用,那么我们是不是可以用AOP,在A调B接口的前后做一些事情呢?所以又用到了spring的知识。 -
最后总结一下服务发现与治理(下)需要做的事情
- 基于thrift进行二次开发,目标是让每个服务专注于业务逻辑,而不需要管通信层的事情(下篇文章就干货满满哦,就不是demo级别的了)。
-