SpringBoot 从入门到光头 第十六章 SpringBoot 与分布式


SpringBoot 从入门到光头 —— 第十六章 SpringBoot 与分布式


1. 分布式应用

在分布式系统中,国内常用 Zookeeper + Dubbo 组合,而 SpringBoot 则推荐使用全栈的 SpringCloud,也就是 SpringBoot + SpringCloud

分布式子系统:

DubboArchitectureRoadmap

  • 单一应用架构:

    ​ 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。

  • 垂直应用架构:

    ​ 当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的 Web 框架(MVC)是关键。

  • 分布式服务架构:

    ​ 当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。

  • 流动计算架构:

    ​ 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。

2. Zookeeper 和 Dubbo

  • Zookeeper(注册中心)

    ​ Zookeeper 是一个分布式的,开放源码的分布式应用程序协调服务。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

  • Dubbo(分布式服务框架)

    ​ Dubbo 是 Alibaba 开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦(或者最大限度地松耦合),从服务模型的角度来看,Dubbo 采用的是种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider) 和服务消费方(Consumer)两个角色。

  • Dubbo 架构:

    DubboArchitecture

使用步骤:

  1. 将服务提供者注册到注册中心中
    1. 引入 Dubbo 和 Zookeeper 相关依赖
    2. 配置 Dubbo 的扫描包和注册中心地址
    3. 使用 @Service (Dubbo 3.0 之后使用 @DubboService)发布服务
    4. Dubbo 3.0 以后的版本需要在 SpringBoot 引导类上加上 @EnableDubbo 才能启用 Dubbo 服务
  2. 将消费者注册到注册中心中
    1. 引入 Dubbo 和 Zookeeper 相关依赖
    2. 配置 Dubbo 的注册中心地址
    3. 使用 @Reference (Dubbo 3.0 之后使用 @DubboReferecce)引用服务

3. SpringBoot 和 SpringCloud

3.1. SpringCloud

SpringCloud 是一个分布式的整体解决方案。SpringCloud 为开发者提供了 在分布式系统(配置管理,服务发现,熔断,路由,微代理,控制总线,一次性 Token,全局锁,Leader 选举,分布式 Session,集群状态)中快速构建的工具 ,使用 SpringCloud 的开发者可以快速地启动服务或者是构建应用、同时能够快速和云平台资源进行对接

SpringCloud 分布式开发五大常用组件:

  • 服务发现:NetflixEureka
  • 服务器负载均衡:NetflixRibbon
  • 断路器:NetflixHystrix
  • 服务网关:NetflixZuul
  • 分布式配置:SpringCloudConfig

3.2. SpringCloud Eureka 注册中心使用

注册中心的使用方法:

  1. 引入 Eureka 注册中心依赖

    pom.xml

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    
  2. 编写配置文件 application.yaml,配置 Eureka 信息

    application.yaml

    server:
      port: 8761
    eureka:
      instance:
        hostname: eureka-server # Eureka instance hostname
      client:
        register-with-eureka: false # Don't register itself with Eureka
        fetch-registry: false # Do not get service registration information from Eureka
        service-url:
          defaultZone: http://127.0.0.1:8761/eureka/
    
  3. 在引导类中使用 @EnableEureka 启用 Eureka 注册中心

    com.yourname.eurekaserver.EurekaServerApplication

    /**
     * Registration Center
     * @author gregperlinli
     */
    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaServerApplication &#123;
    
        public static void main(String[] args) &#123;
            SpringApplication.run(EurekaServerApplication.class, args);
        &#125;
    
    &#125;
    
  4. 启动后打开浏览器输入地址 http://127.0.0.1:8761 (端口号可以在配置文件中设置)即可进入 Eureka 注册中心管理页面

    SpringCloudEureka

3.3. SpringCloud 服务注册

SpringCloud 注册服务方法

  1. 引入相关依赖

    pom.xml

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    
  2. 编写服务注册配置

    application.yaml

    server:
      port: 8001
    spring:
      application:
        name: provider-ticket
    eureka:
      instance:
        prefer-ip-address: true # Use the IP address of the service when registering the server
      client:
        service-url:
          defaultZone: http://127.0.0.1:8761/eureka/
    
  3. 编写要注册的服务

    com.yourname.ticket.service.TicketService

    /**
     * @author gregPerlinLi
     * @since 2022-01-21
     */
    public interface TicketService &#123;
        /**
         * Get ticket
         *
         * @return ticket
         */
        String getTicket();
    &#125;
    

    com.yourname.ticket.service.impl.TicketServiceImpl

    /**
     * @author gregPerlinLi
     * @since 2022-01-21
     */
    @Service
    public class TicketServiceImpl implements TicketService &#123;
        @Override
        public String getTicket() &#123;
            System.out.println("8001");
            return "This is an ticket";
        &#125;
    &#125;
    
  4. 编写 Controller 暴露接口

    com.yourname.ticket.controller.TicketController

    /**
     * @author gregPerlinLi
     * @since 2022-01-21
     */
    @RestController
    public class TicketController &#123;
        @Autowired
        TicketService ticketService;
    
        @GetMapping(value = "/ticket")
        public String getTicket() &#123;
            return ticketService.getTicket();
        &#125;
    &#125;
    

3.4. SpringCloud 服务发现 & 消费

SpringCloud 发现服务并消费的方法:

  1. 引入相关依赖

    pom.xml

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    
  2. 编写服务发现配置

    application.yaml

    spring:
      application:
        name: consumer-user
    server:
      port: 8200
    eureka:
      instance:
        prefer-ip-address: true # Use the IP address of the service when registering the server
      client:
        service-url:
          defaultZone: http://127.0.0.1:8761/eureka/
    
  3. 使用 @EnableDiscoveryClient 启用发现服务功能,并使用 RestTemplate 发送 HTTP 请求(通过 @LoadBalance 可以实现负载均衡)

    com.yourname.user.ConsumerUserApplication

    /**
     * &#123;@code @EnabledDiscoveryClient&#125;: Enable service discovery function
     *
     * @author gregperlinli
     */
    @SpringBootApplication
    @EnableDiscoveryClient
    public class ConsumerUserApplication &#123;
        public static void main(String[] args) &#123;
            SpringApplication.run(ConsumerUserApplication.class, args);
        &#125;
        /**
         * &#123;@code @LoadBalanced&#125;: Enable load balancing
         */
        @LoadBalanced
        @Bean
        public RestTemplate restTemplate() &#123;
            return new RestTemplate();
        &#125;
    &#125;
    
  4. 编写 Controller 调用远程服务

    com.yourname.user.controller.UserController

    /**
     * @author gregPerlinLi
     * @since 2022-01-21
     */
    @RestController
    public class UserController &#123;
        @Autowired
        RestTemplate restTemplate;
    
        @GetMapping(value = "buy")
        public String buyTicket(String name) &#123;
            return name + " bought ticket: " + restTemplate.getForObject("http://PROVIDER-TICKET/ticket", String.class);
        &#125;
    &#125;
    


文章作者: gregPerlinLi
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 gregPerlinLi !
  目录