深度解析springcloud分布式微服务的实现(上)

深度解析springcloud分布式微服务的实现(上)_第1张图片

作者|George

编辑|包包  

分布式系统

微服务就是原来臃肿的项目拆分为多个模块互不关联。如:按照子服务拆分、数据库、接口,依次往下就更加细粒度,当然运维也就越来越难受了。

分布式则是偏向与机器将诺大的系统划分为多个模块部署在不同服务器上。

微服务和分布式就是作用的“目标不一样”。

微服务与Cloud

微服务是一种概念,spring-cloud是微服务的实现。

微服务也不一定必须使用cloud来实现,只是微服务中有许多问题,如:负载均衡、服务注册与发现、路由等等。

而cloud则是将这些处理问题的技术整合了。

Spring-Cloud 组件

Eureka

Eureka是Netifix的子模块之一,Eureka有2个组件,一个EurekaServer 实现中间层服务器的负载均衡和故障转移,一个EurekaClient它使得与server交互变得简单。

Spring-Cloud封装了Netifix公司开发的Eureka模块来实现服务注册和发现。

通过Eureka的客户端 Eureka Server维持心跳连接,维护可以更方便监控各个微服务的运行。

角色关系图

Eureka使用

客户端


org.springframework.cloud
spring-cloud-starter-netflix-eureka-client

server:
port: 4001
eureka:
client:
serviceUrl:
defaultZone: http://localhost:3000/eureka/ #eureka服务端提供的注册地址 参考服务端配置的这个路径
instance:
instance-id: admin-1 #此实例注册到eureka服务端的唯一的实例ID
prefer-ip-address: true #是否显示IP地址
leaseRenewalIntervalInSeconds: 10 #eureka客户需要多长时间发送心跳给eureka服务器,表明它仍然活着,默认为30 秒 (与下面配置的单位都是秒)
leaseExpirationDurationInSeconds: 30 #Eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认为90秒


spring:
application:
name: server-admin #此实例注册到eureka服务端的name

服务端


org.springframework.cloud
spring-cloud-starter-
netflix-eureka-server

yml文件声明 
server:
port: 3000
eureka:
server:
enable-self-preservation: false #关闭自我保护机制
eviction-interval-timer-in-ms: 4000 #设置清理间隔
(单位:毫秒 默认是60*1000)
instance:
hostname: localhost 
client:
registerWithEureka: false #不把自己作为一个客户端注册到自己身上
fetchRegistry: false #不需要从服务端获取注册信息
(因为在这里自己就是服务端,而且已经禁用自己注册了)
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
在SpringBoot 启动项目中加入注解:@EnableEurekaServer 
就可以启动项目了,访问对应地址就可以看到界面。


Eureka 集群

服务启动后Eureka Server会向其他服务server 同步,当消费者要调用服务提供者,则向服务注册中心获取服务提供者的地址,然后将提供者的地址缓存到本地,下次调用时候直接从本地缓存中获取

yml 服务端

server:
port: 3000
eureka:
server:
enable-self-preservation: false #关闭自我保护机制
eviction-interval-timer-in-ms: 4000 #设置清理间隔
(单位:毫秒 默认是60*1000)
instance:
hostname: eureka3000.com 
client:
registerWithEureka: false #不把自己作为一个客户端
注册到自己身上
fetchRegistry: false #不需要从服务端获取注册信息
(因为在这里自己就是服务端,而且已经禁用自己注册了)
serviceUrl:
defaultZone: http://eureka3001.com:3001/eureka,
http://eureka3002.com:3002/eureka
(这里不注册自己,注册到其他服务上面以为会同步。)

yml 客户端

server:
port: 4001
eureka:
client:
serviceUrl:
defaultZone:http://localhost:3000/eureka/,http://
eureka3001.com:3001/eureka,http://eureka3002.com:3 002
/eureka #eureka服务端提供的注册地址 参考服务端配置的这个路径
instance:
instance-id: admin-1 #此实例注册到eureka服务端的唯一的实例ID
prefer-ip-address: true #是否显示IP地址
leaseRenewalIntervalInSeconds: 10 #eureka客户需要多长时间发
送心跳给eureka服务器,表明它仍然活着,默认为30 秒 (与下面配置的单位都是秒)
leaseExpirationDurationInSeconds: 30 #Eureka服务器在
接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认为90秒


spring:
application:
name: server-admin #此实例注册到eureka服务端的name

CAP定理

C:Consistency 一致性
A:Availability 可用性
P:Partition tolerance 分区容错性
这三个指标不能同时达到

Partition tolerance

分区容错性,大多数分布式系统都部署在多个子网络。每一个网络是一个区。区间的通信是可能失败的如一个在本地,一个在外地,他们之间是无法通信的。分布式系统在设计的时候必须要考虑这种情况。

Consistency

一致性,写操作后的读取,必须返回该值。如:服务器A1和服务器A2,现在发起操作将A1中V0改为V1,用户去读取的时候读到服务器A1得到V1,如果读到A2服务器但是服务器

还是V0,读到的数据就不对,这就不满足一致性。

所以让A2返回的数据也对,的让A1给A2发送一条消息,把A2的V0变为V1,这时候不管从哪里读取都是修改后的数据。

Availability

可用性就是用户只要给出请求就必须回应,不管是本地服务器还是外地服务器只要接收到就必须做出回应,不管数据是否是最新必须做出回应,负责就不是可用性。

C与A矛盾

一致性和可用性不能同时成立,存在分区容错性,通信可能失败。

如果保证一致性,A1在写操作时,A2的读写只能被锁定,只有等数据同步了才能读写,在锁定期间是不能读写的就不符合可用性。

如果保持可用性,那么A2就不会被锁定,所以一致性就不能成立。

综上 无法做到一致性和可用性,所以系统在设计的时候就只能选其一。

Eureka与Zookeeper

Zookeeper遵循的是CP原则保持了一致性,所以在master节点因为网络故障与剩余“跟随者”接点失去联系时会重新选举“领导者”,选取“领导者”大概会持续30-120s的时间,且选举的时候整个zookeeper是不可用的。导致在选举的时候注册服务瘫痪。

Eureka在设计的时候遵循AP可用性。Eureka各个接点是公平的,没有主从之分,down掉几个几点也没问题,其他接点依然可以支持注册,只要有一台Eureka在,注册就可以用,只不过查询到的数据可能不是最新的。Eureka有自我保护机制,如果15分钟之内超过85%接点都没有正常心跳,那么Eureka认为客户端与注册中心出现故障,此时情况可能是

Eureka不在从注册列表移除因为长时间没有瘦到心跳而过期的服务。

Eureka仍然能够接收注册和查询,但不会同步到其他接点。

当网络稳定后,当前的 实例注册信息会更新到其他接点。

Ribbon

rebbon主要提供客户端的负载均衡,提供了一套完善的客户端的配置。Rebbin会自动帮助你基于某种规则(如:简单的轮询,随机链接等)。

服务端的负载均衡是一个url通过一个代理服务器,然后通过代理服务器(策略:轮询,随机 ,权重等等),反向代理到你的服务器。

客户端负载均衡是通过一个请求在客户端已经声明了要调用那个服务,然后通过具体算法来完成负载均衡。

Ribbon使用

引入依赖,Eureka以及把Ribbon集成在里面。

使用Ribbon只有在RestTemplate上面加入@LoadBalanced注解。

Feign负载均衡

feign是一个声明式的webService客户端,使用feign会让编写webService更简单,就是定义一个接口加上注解。

feign是为了编写java http客户端更加简单,在Ribbon+RestTemplate此基础上进一步封装,简化了使用Spring Cloud Ribbon时,自动封装服务调用客户端的开发量。

Feign使用

引入依赖

org.springframework.cloud
spring-cloud-starter-openfeign

在启动类上加@EnableFeignClients
然后在接口上加@FeignClient("SERVER-POWER")注解其中参数就是服务的名字。

Feign集成Ribbon

利用Ribbon维护服务列表信息,融合了Ribbon的负载均衡配置,与Ribbon不同的是Feign只需要定义服务绑定接口以声明的方式,实现简答的服务调用。

- - - -未完待续- - - - 

喜欢本文的朋友,欢迎关注公众号  并发编程网,收看更多精彩内容

你可能感兴趣的:(网络,分布式,运维,java,nginx)