基于Spring Cloud构建微服务系统之服务注册发现与负载均衡

俗话说,活到老,学到老。我们总是在学习中不断进步。微策略软件技术公司秉承的就是这个原则,浓厚的技术氛围,实用的技术分享,在这里你可以享受到各种各样的属于技术分享的盛宴。每周四,笔者所在的RESTful API和Architect组都有大组内的技术分享和读书会活动,分享的豆瓣高分技术书包括但不限于:《设计数据密集型应用Designing data-intensive applications》,《重构改善既有代码的设计》,《大话设计模式》…… 受此氛围的影响,笔者将自己学习的微服务技术知识整理成篇,与大家进行分享。至于为什么分享微服务相关的技术,很简单一个字“火”呀,如果要在诸多热门云计算技术中找出一个最火的,那非微服务莫属。

什么是微服务

>>>>

最正宗的解释(维基百科的解释)

微服务 (Microservices) 是一种软件架构风格,它是以专注于单一责任与功能的小型功能区块 (Small Building Blocks) 为基础,利用模块化的方式组合出复杂的大型应用程序,各功能区块使用与语言无关 (Language-Independent/Language agnostic) 的 API 集相互通信。

微服务的起源是由 Peter Rodgers 博士于 2005 年度云计算博览会提出的微 Web 服务 (Micro-Web-Service) 开始,Juval Löwy 则是与他有类似的前导想法,将类别变成细粒服务 (granular services),以作为 Microsoft 下一阶段的软件架构,其核心想法是让服务是由类似 Unix 管道的访问方式使用,而且复杂的服务背后是使用简单 URI 来开放接口,任何服务,任何细粒都能被开放 (exposed)。这个设计在 HP 的实验室被实现,具有改变复杂软件系统的强大力量。

2014年,Martin Fowler 与 James Lewis 共同提出了微服务的概念,定义了微服务是由以单一应用程序构成的小服务,自己拥有自己的行程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用 HTTP API 通信。同时服务会使用最小规模的集中管理 (例如 Docker) 能力,服务可以用不同的编程语言与数据库等组件实现。

>>>>

简单的理解:

微服务架构的系统是一个分布式的系统,按业务进行划分为独立的服务单元,解决单体系统的不足,同时也满足越来越复杂的业务需求。

>>>>

相比于传统集中式的应用系统,微服务的优点

  • 每个服务独立存在,所以可以单独部署,不用每次发布某个功能都经历一次全服务发布。

  • 遵循单一功能原则,服务之间可以通过RESTFUL或者RPC调用,功能解藕

  • 细粒度” 的高可扩展性,每个服务都可以单独扩展,单独负载均衡

  • 去中心化,尽可能地实现 “自服务”

  • 有利于简化单独的开发测试以及部署,对开发团队友好

>>>>

微服务缺点

  • 服务的可用性和维护性高度依赖于服务治理,如果治理得不好将会是灾难

  • 某些服务可能造成性能瓶颈,某些服务的宕机可能导致很多服务受影响

  • 服务配置繁琐

Spring Cloud构建微服务的优势

>>>>

微服务框架对比

功能点/服务框架

Netflix/SpringCloud

Motan

gRPC

Thrift

Dubbo/Dubbox

功能定位

完整的微服务框架

RPC框架但整合了ZK或者Consul,实现集群环境的基本服务注册/发现

RPC框架

RPC框架

服务框架

是否支持Rest

是,Ribbon支持多种可插拔的序列化选择

是否支持RPC

是(Hession2)

是否支持多语言

服务注册/发现

是(Eureka) Eureka服务注册表,Karyon服务端框架支持服务自注册和健康检查

是(zookeeper/consul)

负载均衡

是(服务器zuul+客户端Ribbon) zuul-服务,动态路由, 云端负载均衡, Eureka(针对中间层服务)

是(客户端)

是(客户端)

配置服务

NetflixArchaius SpringCloudConfigServer集中配置

是(zookeeper提供)

服务调用链监控

是(zuul) Zuul提供边缘服务,API网关

高可用/容错

是(服务器Hystrix+客户端Ribbon)

是(客户端)

是(客户端)

典型应用案例

Netflix

Sina

Google

Facebook


社区活跃程度

一般

一般

2012年停止维护,2017年7月以后开始维护

学习难度

中等

文档丰富度

一般

一般

一般

其他

SpringCloudBus为我们的应用程序带来了更多管理端点

支持降级

Netflix内部在开发集成gRPC

IDL定义

实践的公司比较多

Spring Cloud提供构建微服务的解决方案

微服务条目 

Spring CloudT提供与集成的技术

服务开发

Spring Boot, Spring, Spring MVC

服务配置与管理

Netflix公司的Archaius

服务注册与发现

Eureka、Zookeeper

服务调用

 REST

服务熔断器

Hystrix

负载均衡

Ribbon

服务接口调用(客户端调用服务的简化工具)

Feign

消息队列

Kafka、RabbitMQ、ActiveMQ等   

服务配置中心管理

SpringCloudConfig

服务路由(API网关)

Zuul 

服务监控  

Hystrix-Dashboard

全链路追踪

Zipkin+Sleuth

服务部署  

Docker、OpenStack、Kubernetes等

数据流操作开发包

SpringCloud Stream(封装与Redis,Rabbit,Kafka等发送接收消息)

事件消息总线

 SpringCloud Bus 

服务注册与发现

>>>>

服务注册与发现架构

基于Spring Cloud构建微服务系统之服务注册发现与负载均衡_第1张图片

>>>>

Eureka的服务注册与发现架构

基于Spring Cloud构建微服务系统之服务注册发现与负载均衡_第2张图片

  • Application Service 就相当于本书中的服务提供者(用户微服务),Application Client就相当于本书中的服务消费者(电影微服务);

  • Make Remote Call,可以简单理解为调用RESTful的接口;

  • us-east-1c、us-east-1d等是zone,它们都属于us-east-1这个region;  

  • Eureka包含两个组件:Eureka Server 和 Eureka Client。  

  • Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样Eureka Server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。

  • Eureka Client是一个Java客户端,用于简化与Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。

  • 在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。

  • Eureka Server之间将会通过复制的方式完成数据的同步。

  • Eureka还提供了客户端缓存的机制,即使所有的Eureka Server都挂掉,客户端依然可以利用缓存中的信息消费其他服务的API。  

综上,Eureka通过心跳检测、健康检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。

>>>>

Eureka基于Spring Boot的项目搭建

1. 引入第三方依赖

https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server

2. 配置文件application.properties

server.port = 6868

# 是否需要将当前应用注册到注册中心
eureka.client.registerWithEureka = false

# 是否需要从注册中心获取注册信息
eureka.client.fetchRegistry = false

# 配置eurekaserver的url地址
eureka.client.serviceUrl.defaultZone = http://127.0.0.1:${server.port}/eureka

3. 在SpringBoot启动类中使用eureka注解’@EnableEurekaServer’

基于Spring Cloud构建微服务系统之服务注册发现与负载均衡_第3张图片

4. 启动eureka server,访问eureka server主页http://localhost:6868/

基于Spring Cloud构建微服务系统之服务注册发现与负载均衡_第4张图片

>>>>

Eureka项目

笔者做了一个简单的eureka的演示项目:

https://github.com/wanghuixia/SpringCloudMicroserviceQuicklyStart

负载均衡

Spring Cloud继承了Netflix的Ribbon, 因此可以使用Ribbon来实现负债均衡。

>>>>

Ribbon内置的负载均衡策略

1) RoundRobinRule: 轮询

2) RandomRule: 随机

3) AvailabilityFilteringRule: 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问

4) WeightedResponseTimeRule: 根据平均响应时间计算所有服务的权重,响应时间越快的服务权重越大被选中的概率越高,刚启动时如果信息不足,则使用RoundRobinRule策略,等统计信息足够,会切换到WeightedResponseTimeRule

5) RetryRule:会先按照RoundRobinRule的策略获取服务,如果获取服务失败则在制定的时间内会进行重试,获取可用的服务

6) BestAvailableRule: 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务

7) ZoneAvoidanceRule: 复合判断server所在区域的性能和server的可用性选择服务器,在没有zone的情况下,类似于轮询

>>>>

Ribbon负载均衡源码

https://github.com/Netflix/ribbon/tree/master/ribbon-loadbalancer/src/main/java/com/netflix/loadbalancer

>>>>

自定义负载均衡策略

1. 继承ribbon提供的接口

“AbstractLoadBalanceRule”

2. 简单一个自定义的负载均衡策略:

public class CustomLoadBalancer extends AbstractLoadBalancerRule {

   
private int total = 0;
    private int
index = 0;

   
/**
     * Randomly choose from all living servers
     */
   
public Server choose(ILoadBalancer lb, Object key) {
       
if (lb == null) {
           
return null;
       
}
        Server server =
null;

        while
(server == null) {
           
if (Thread.interrupted()) {
               
return null;
           
}
            List upList = lb.getReachableServers()
;
           
List allList = lb.getAllServers();

            int
serverCount = allList.size();
            if
(serverCount == 0) {
               
/*
                 * No servers. End regardless of pass, because subsequent passes
                 * only get more restrictive.
                 */
               
return null;
           
}

           
//custom load balance rule
           
if (total >= 4) {
               
total = 0;
               
index++;
                if
(index >= upList.size()) {
                   
index = 0;
               
}
            }
           
total++;//count


           
server = upList.get(index);

            if
(server == null) {
               
/*
                 * The only time this should happen is if the server list were
                 * somehow trimmed. This is a transient condition. Retry after
                 * yielding.
                 */
               
Thread.yield();
                continue;
           
}

           
if (server.isAlive()) {
               
return (server);
           
}

           
// Shouldn't actually happen.. but must be transient or a bug.
           
server = null;
           
Thread.yield();
       
}

       
return server;

   
}

   
protected int chooseRandomInt(int serverCount) {
       
return ThreadLocalRandom.current().nextInt(serverCount);
   
}

   
@Override
   
public Server choose(Object key) {
       
return choose(getLoadBalancer(), key);
   
}

   
@Override
   
public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

>>>>

Ribbon项目

笔者做了一个简单的ribbon的演示项目:

https://github.com/wanghuixia/SpringCloudMicroserviceQuicklyStart

了解更多微策略最新动态,行业资讯以及程序员日常

请长按二维码关注微我们的公众号

你可能感兴趣的:(基于Spring Cloud构建微服务系统之服务注册发现与负载均衡)