服务连接的历史传承

1. 逻辑关联

ABC,逻辑实现的时候,即使采用异步的实现办法,但逻辑上依旧是瀑布式的串行逻辑,有一定的先后顺序。不论是最细节的功能实现,还是业务流程的跳转,都遵循着一个步进式的逻辑方向,各操作之间都会逻辑的先后顺序。

2. 服务模块

对于细节的操作流程,我们提取为方法,然后按照流程进行方法的调用。

这样,对于小功能的实现,变成了这样的步骤:

  1. 小模块的实现
  2. 模块功能的逻辑组合调用

尤其是那些经常用到的方法,这样就提高了代码的复用率。

从服务的角度来说,也是如此。把服务进行拆解之后,最后的形态也是如此。

唯一的不同,那就是进程化,代码中的变化,重新修改,影响的功能就得全部重启,因为都是一体的。

但是,通过服务模块的解放,接口的解耦,我们修改针对的部分之后,其他部分能衔接上即可。

也就是:修改后启动的范围,影响的范围。

如果一个大服务,全部是在一个进程内,那么服务模块不过是大一点的方法汇总,除此之外,别无区别。

解耦之后,部署多个服务模块,多进程间,共同完成整个服务功能。

3. 功能的拆分

或许仍然没有明晰一个关键点:逻辑顺序的限制。

为了解决这个问题,我们采用模块化来进行解决。抽取成方法,或者抽取成服务模块。

从而形成插件化的调用形式,当修复问题是,就变成了插件的修复。

这个就存在一个问题:我们的插件是否足够小。

也即是我们插件化之后,是否真的能够做到只修改插件一处,从而做到全局的更新。

问题的核心,就在于逻辑的细粒度。

如果我们拆分的不够细,在不同的模块中,仍然有相同的逻辑实现,想要变动的时候,我们就不得不针对诸多的模块进行修改。从代码的角度无可厚非,但是从服务的角度而言,这对于服务的影响未免过大,毕竟服务不只是程序的问题。

4. 扁平化模块管理

恩,操作拆的够细致,那就是外部引用的方法包。

服务拆的够细致,那就是服务的功能模块。

  1. 模块化:插件化,把问题更局限,更易维护,更易管理,影响也更小。
  2. 细粒度:完善模块化的一些不足,让模块化理念更彻底。

接下来的问题,就是如何去进行逻辑的组织。

有两个疑问:

  1. 接口解耦是否够彻底
  2. 模块管理是否够稳定

接口解耦

接口解耦不够彻底么?

这是一个微妙的问题,不过性质完全不同,需要明确一下接口的位置。

  • 程序接口

对程序接口而言,程序解耦了,目的也达到了。

单从服务角度而言,这种解耦仍然具有一定的耦合性。

  • 服务接口

类似百度地图人脸识别等服务的http接口

说实话,你可以内嵌,但是两者之间没有一个必要的关联性。

存在业务的逻辑关联,却各自为战。

从管理的角度,我们需要它们分离的更彻底,只要能对接上就行,我们需要的是服务接口

模块管理

最终,我们的服务,都是逻辑组织,基石在于模块(插件)的稳定保障。

对于这些模块,我么需要如下手段

  1. 监控
  2. 管理

不过,这两者并未引入更多的影响,全部都是已有的概念和知识。

它最深远的影响,在于接口的统一

当全部模块都收归于它之下时,我们的模块不外乎两种。

  1. 供别的模块调用
  2. 调用别的模块

或者两者兼有,不过也没有别的花样了。

以前多个模块都调用的部件,拆分之后获得了独立。

所处的位置或高或低,后来不可避免的出现重复。

但是在这里,一切都是平级的,只是调用或者被用的角色差异。

弱化了逻辑顺序业务逻辑,强调了模块特性

似乎背道而驰,却把焦点聚焦于了逻辑组织,更便利的完成开发。

5. 结构变化

  • 模块化
  • 细粒度
  • 扁平化
  • 服务化
  1. 为什么模块化?

聚焦逻辑组织,减少重复工作,提高工作效率。

  1. 为什么细粒度?

完善模块化,更进一步贴近模块化理念要求。

  1. 为什么扁平化?

模块管理和组织,最终表现成模块统一对注册中心的接口对接。

  1. 为什么服务化?

模块间彻底解耦,不再作为功能模块,而是作为服务,提供功能调用。

6. 轨迹

  • 程序

服务 -> 小服务 -> 功能块 -> 小功能块 -> 单一功能

  • 服务

功能 -> 维护 -> 开发 -> 管理

从程序来看,越来越支离破碎;但是从服务上看,却是不断进步。

  • 逻辑

逻辑结果 -> 逻辑流程 -> 逻辑维护 -> 逻辑重组 -> 新逻辑实现

从粗浅的结果,然后思考实现,深入到今后的维护,甚至于重构。

最终形成一套只需要需求,便能够适应一切的开发方法。

要的只是葫芦,但今后各种葫芦,甚至于各种植物,也能够百分百的获取。

eureka

1. 结构

  • 模块划分
模块 作用
server 维护服务模块,供客户端调用
client 进行服务注册和发现
  • 角色扮演
角色 功能
center server
provider 生产者,注册到center
consumer 消费者,从center发现服务

2. 实现

具体的话请参看简单例子,在这里补充一下原来的错漏点。

    @Autowired
    DiscoveryClient client;
    @GetMapping("/consumer")
    public void consumerProduct(@RequestParam("name") String name){
        List<String> services = client.getServices();
        for(String service : services){
            List<ServiceInstance> instances = client.getInstances(service);
            for(ServiceInstance instance:instances){
                instance.getHost();
                instance.getPort();
                instance.getUri();
                instance.getServiceId();
                instance.getScheme();
                instance.getMetadata();
            }
        }
    }

DiscoveryClient:正确的一体化方式是利用client进行服务发现。

getServices:获取服务名称列表,如果知道服务名称,可以直接获取实例进行调用。

getInstances:主体实例,统一名称可能多个实例,自行选择调用。

3. 配置

spring: 
	application: 
  		name: appName
server:
  	port: port
eureka:
 	client:
  		fetch-regiestry: false
  		regiester-with-eureka: false
  	service-Url: 
   		defaultZone: http://localhost:8761/eureka/
 instance:
  	prefer-ip-address: true
  	appname: server
 server:
    enable-self-preservation: false

port:每个rest服务,必定有自己的占用端口。

regiester-with-eurekaeureka自己都不放过,也经常把作为服务的自己注册进去,可以不注册。

fetch-regiestry:服务发现,server和单纯的consumer都可以不启用,减少开销。

service-Url:服务地址,eureka服务的注册和发现地址,而不是我们的当前服务地址。

接下来先看一张图SpringCloud-eureka

application.name:对应的就是1,为了区别这个还是要的。

instance.name2对应的名称,不定就会自动生成,实在有点丑。

prefer-ip-addresstrue就容易定位ipport了,一直是localhost哪台机器出问题都不知道。

至于SpringCloud-eureka

不得不说AP,算是一种安全策略。

服务可以注册发现,还有注销。这种注销通过心跳进行确认,超时无响应的就注销移除

如果是网络波动,心跳发了没收到这种,就会保留而不会注销。

enable-self-preservation:就是AP的开关了。

学习中觉得碍眼就关掉吧,但是工作中这东西最好还是要保留,不过关掉了还是有红字,哈哈。

4. 集群

SpringCloud-eureka

defaultZone: http://godme.com:8761/eureka/,http://judas.com:8762/eureka/

service-Url,逗号隔开也可以配置多个,当在server中配置多个时,此时就成了集群。

集群的话,目前自我理解有两种

  1. 容灾集群
  2. 功能集群
  • 容灾

对于第一种,也是我接触到的,类似于实现切换管理的容灾。

之下有诸多的同实例服务,对外而言,集群中使用的却只是其中之一。

但是当前的服务异常时,又会切换到另一个,保证服务稳定运行。

比如redis的哨兵,也正如现在的eureka集群。

  • 功能

如果说上面是1+1,第二种就是2了。

虽然是几台计算机,但是集群所产生的威力和效能,远不是之前所能衡量的。

这方面的技术偶是没啥了解,但是为了明晰概念,先划分一把。

第一种的话或许叫做服务集群比较贴切,容灾只是其中的好处之一。

正如负载均衡,它不只是调用单个服务,而是服务轮询

某种程度而言,介于服务容灾和功效提升之间。

不过更常见的服务集群只是多个实例干同样的事情,以便于容灾。

类比于多个实例共同干同一件事的功能集群,一个追求稳定,一个追求效能。

CAP

名词 性能
Consistency 一致性
Availablity 可用性
Partition tolerance 分区容错性

实际情况,三者不能够同时满足,于是产生三种组合

  • CA
  • AP
  • CP

考虑到网络通讯中的丢包P又必须得到满足,因此只有

  • AP
  • CP

两种选择。

Zookeepereureka的根源性质,在于设计理念的不同

服务 理念
zookeeper CP
eureka AP

zookeeper的一致性,确保了服务的准确状态传达和调用,却丢失了A(可用性)。

当节点选举时,服务处于不可用状态,影响服务调用,对业务造成巨大影响。

eureka的可用性,会导致局部节点的信息不一致。但是对外层的服务调用而言,没有影响。

而且通过对节点的轮询,也能够保证信息的获取,不过并非每个节点信息一致这个问题实在明显。

同样的,两者的沟通也有一定区别

服务 沟通
zookeeper RPC
eureka rest

沟通方式各有千秋,仁者见仁了。

小结

统一接口层,就是它了。

相关文章: