微服务-SpringCloud

一、基础组件简介-基于Nacos组件,整合Dubbo框架

1、Dubbo框架

Dubbo服务化治理的核心框架,之前几年在国内被广泛使用,后续由于微服务的架构的崛起,更多的公司转向微服务下成熟的技术栈,但是Dubbo本身确实是非常优秀的框架。

常见的应用迭代和升级的过程基本如下:

  • 当应用访问量逐渐增大,单一应用增加机器带来的加速度越来越小,提升效率的方法之一是将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。
  • 随着垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
  • 伴随业务发展,服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。

而Dubbo框架的核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。正好可以解决上述业务发展的痛点。

2、微服务框架

SpringCloud是一系列框架的有序集合。它利用SpringBoot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用SpringBoot的开发风格做到一键启动和部署。

后续AliCloud微服务系列组件也不断被使用起来,其中最基础的组件Nacos注册中心,更是直接支持Dubbo框架,这样Cloud和Dubbo两大框架就成功的整合在了一起。

3、Nacos注册中心

Nacos注册中心主要用于发现、配置、管理微服务。并且提供一组简单易用的特性集,快速实现动态服务发现、服务配置、服务元数据及流量管理。

如上图Nacos无缝支持一些主流的开源生态框架,例如SprinCloud,Dubbo两大框架。在AliCloud的系列组件中,还包含了Seata,RocketMQ,Sentinel等一系列组件。

二、服务结构图解

SpringCloud和Dubbo整合的结构示意图如下,使用的Nacos中心:

Provider提供方:提供核心的Dubbo服务接口;

Consumer消费方:消费注册的Dubbo服务接口;

Nacos注册中心:配置、发现和管理Dubbo服务;

通过上述流程不难发现,不管从架构上看,还是用法过程,基于核心Dubbo框架和微服务原生框架是十分相似,上述流程也遵循这样一个规则:dubbo-server连接自己的业务库DB,并通过dubbo-facade中接口向外提供服务,如果不同dubbo-server需要访问其他服务接口,也必须要通过其他服务的facade接口操作,dubbo-client作为接口服务消费端,可以通过facade接口访问很多业务模块的服务,整体架构层次十分明了。

三、编码案例实现

1、案例结构和依赖

案例结构

包含三个模块:server、facade、client。

核心依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-dubbo</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>

2、服务端配置

配置文件

主要是Nacos注册中心和Dubbo两个核心配置。

server:
  port: 9010
spring:
  application:
    name: node10-dubbo-server
  cloud:
    nacos:
      discovery:
        server-addr: http://localhost:8848
      config:
        server-addr: http://localhost:8848
        file-extension: yaml
# Dubbo服务配置
dubbo:
  scan:
    base-packages: com.cloud.dubbo.service
  protocol:
    name: dubbo
    port: -1
  registry:
    address: spring-cloud://localhost

服务接口实现

这里DubboService即dubbo-facade包中对外提供的接口。

import org.apache.dubbo.config.annotation.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Service
public class DubboServiceImpl implements DubboService {

    private static final Logger LOGGER = LoggerFactory.getLogger(DubboServiceImpl.class) ;

    @Override
    public String getInfo() {
        LOGGER.info("node10-dubbo-server start ...");
        return "node10-dubbo-server";
    }
}

注意:@Service是Dubbo框架中的注解,不是Spring框架的注解。

3、消费端配置

配置文件

主要配置是链接Nacos注册中心,订阅注册中心的node10-dubbo-server服务。

server:
  port: 9011
spring:
  application:
    name: node10-dubbo-client
  cloud:
    nacos:
      discovery:
        server-addr: http://localhost:8848
      config:
        server-addr: http://localhost:8848
# Dubbo服务配置
dubbo:
  protocol:
    name: dubbo
    port: -1
  registry:
    address: spring-cloud://localhost
  cloud:
    subscribed-services: node10-dubbo-server

Dubbo接口调用

同样,这里DubboService即dubbo-facade包中对外提供的接口。

import com.cloud.dubbo.service.DubboService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DubboWeb {

    @Reference
    private DubboService dubboService ;

    @GetMapping("/getInfo")
    public String getInfo () {
        return dubboService.getInfo() ;
    }
}

注意:@Reference也是Dubbo框架中的注解。

如上流程开发完成,先后启动dubbo-server服务和dubbo-client服务,查看注册中心服务列表:

通过上述getInfo接口请求测试,即可看到完整的案例效果。

四、技术选型

很少有选择SpringCloud+Dubbo框架的架构模式,这里简单说明一下为何,因为这两个框架都是相当复杂的,学习成本是一个方面,风险是最主要原因,这两个框架同时使用,就意味要面对和解决两个框架下产生的问题,在任何一个框架都可以稳定的解决业务问题时,完全没必要花里胡哨。

=============================================================================

一、阿里微服务-开源组件Nacos,服务和配置管理

1、基础描述

Alibaba-Cloud致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过SpringCloud编程模型轻松使用这些组件来开发分布式应用服务。只需要添加一些注解和少量配置,就可以将SpringCloud应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。

2、核心功能

  • 服务限流降级

默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、SpringCloudGateway,Zuul,Dubbo和RocketMQ限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。

  • 服务注册与发现

适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。

  • 分布式配置管理

支持分布式系统中的外部化配置,配置更改时自动刷新。

  • 消息驱动能力

基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。

  • 分布式事务

使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。

  • 分布式任务调度

提供秒级、精准、高可靠、高可用的定时(基于Cron表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。

3、功能组件

  • Nacos

一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

  • Sentinel

把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

  • RocketMQ

一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。

  • Dubbo

Apache Dubbo 是一款高性能 Java RPC 框架。

  • Seata

阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。

  • OSS

阿里云对象存储服务(Object StorageService,简称OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。

  • SchedulerX

阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。

4、环境和依赖

  • Nacos服务

Nacos 致力于发现、配置和管理微服务。帮助开发者快速实现动态服务发现、服务配置、服务元数据及流量管理。敏捷构建、交付和管理微服务平台。首先下载 Nacos 并启动 Nacos server。

参考文章:Nacos组件,环境搭建和入门案例详解

  • 版本关系

版本 2.1.x.RELEASE 对应的是 SpringBoot2.1.x版本。版本2.0.x.RELEASE对应的是SpringBoot2.0.x版本。PS通常学习新的东西,最容易让人犯迷糊的地方就是版本对应关系,问题不好排查,一般都可以参考官网的给的样例。

二、服务中心管理

1、案例结构

  • 服务端:node08-nacos-server
  • 客户端:node08-nacos-clien

2、配置文件

配置内容如下:

my:
  name: cloud
  info: alibaba
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      driverClassName: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/data_one
      username: root
      password: 123

核心内容:DataID、文件格式、文件内容的配置。这里还配置了一个MySQL数据源。

3、服务注册发现

(1)、服务端配置

  • 核心依赖
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>
  • 配置文件
spring:
  application:
    name: node08-nacos-server
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

这里的name配置和上面DataID一致,就可以读取上述配置内容。

  • 提供服务接口
@RestController
public class ServerWeb {
    private static Logger logger = LoggerFactory.getLogger(ServerWeb.class) ;
    @RequestMapping(value = "/web/getMsg",method = RequestMethod.GET)
    public String getMsg (@RequestParam("name") String name){
        logger.info("8001 服务被调用...");
        return "Hello:" + name ;
    }
}
  • 启动类注解
@SpringBootApplication
// SpringCloud原生注解@EnableDiscoveryClient开启服务注册发现功能
@EnableDiscoveryClient
public class ApplicationServer {
    public static void main(String[] args) {
        SpringApplication.run(ApplicationServer.class,args) ;
    }
}

(2)、客户端配置

  • 核心依赖
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>
<!-- Feign组件 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>

这里也可以基于Feign模式,访问上述服务端提供的接口服务 。

  • 基于Rest接口访问

提供接口配置

@Configuration
public class RestConfig {
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

这里用法和SpringCloud原生框架生态相同 。

请求方法

@RestController
public class ClientWeb {
    @Resource
    private RestTemplate restTemplate ;
    @RequestMapping(value = "/web/getMsgV1/{name}",method = RequestMethod.GET)
    public String getMsgV1 (@PathVariable String name){
        String reqUrl = "http://node08-nacos-server:8001/web/getMsg/"+name ;
        return restTemplate.getForObject(reqUrl,String.class) ;
    }
}
  • 基于Feign接口访问

Feign接口配置

@FeignClient("node08-nacos-server")
public interface MsgFeign {
    @GetMapping("/web/getMsg")
    String getMsg (@RequestParam(name = "name") String name);
}

这里用法依旧和SpringCloud原生框架生态相同 。

请求方法

@RestController
public class ClientWeb {
    @Resource
    private MsgFeign msgFeign ;

    @RequestMapping(value = "/web/getMsgV2/{name}",method = RequestMethod.GET)
    public String getMsgV2 (@PathVariable String name){
        return msgFeign.getMsg(name) ;
    }
}
  • 启动类配置
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages={"cloud.nacos.client.feign"})
public class ApplicationClient {
    public static void main(String[] args) {
        SpringApplication.run(ApplicationClient.class,args) ;
    }
}

三、配置中心管理

通过Nacos的配置管理可以将整合架构体系内配置,集中统一在Nacos中存储管理。分离的多环境配置,灵活的权限管理。

1、核心依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>

2、服务端配置

spring:
  application:
    name: node08-nacos-server
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml

这里的核心配置是config配置。

3、配置读取方式

这里就是Spring框架原生的读取方式。

@RestController
@RefreshScope
public class ValueWeb {

    @Value("${my.name:}")
    private String myName ;

    @Value("${my.info:}")
    private String myInfo ;

    @RequestMapping("/getNameInfo")
    public String getNameInfo (){
        return myName+":"+myInfo ;
    }
}

4、数据库连接

配置JDBC连接

这里基于Druid连接池,配置JdbcTemplate数据库访问API。

@Configuration
public class DruidConfig {

    @Value("${spring.datasource.druid.url}")
    private String dbUrl;
    @Value("${spring.datasource.druid.username}")
    private String username;
    @Value("${spring.datasource.druid.password}")
    private String password;
    @Value("${spring.datasource.druid.driverClassName}")
    private String driverClassName;

    /**
     * Druid 连接池配置
     */
    @Bean
    public DruidDataSource dataSource() {
        DruidDataSource datasource = new DruidDataSource();
        datasource.setUrl(dbUrl);
        datasource.setUsername(username);
        datasource.setPassword(password);
        datasource.setDriverClassName(driverClassName);
        return datasource;
    }
    /**
     * JDBC操作配置
     */
    @Bean(name = "jdbcTemplate")
    public JdbcTemplate jdbcTemplate (@Autowired DruidDataSource dataSource){
        return new JdbcTemplate(dataSource) ;
    }
}

测试方法

@RestController
public class JdbcWeb {
    @Resource
    private JdbcTemplate jdbcTemplate ;
    @RequestMapping("/getJdbc")
    public List<String> getJdbc (){
        String sql = "select phone from d_phone" ;
        List<String> phoneEntityList = jdbcTemplate.queryForList(sql,String.class) ;
        return phoneEntityList ;
    }
}

四、案例总结

上面两个使用案例走下来,感觉和原生SpringCloud的用法区别不大,整体上手难度也不太高,毕竟AlibabaCloud框架是在SpringCloud框架基础上。适配了阿里很多开源组件,在微服务框架组件选择上,根据业务需求和团队的熟悉程序选择即可。

==================================================================================

一、Sentinel哨兵组件,管理服务限流和降级

1、概念描述

Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。包括核心的独立类库,监控台,丰富的使用场景验证。(这似乎是阿里开源组件的一贯作风,极其有特点,且特点很规律)

基本特性图:

补刀一句:这种图很多人可能不在意,但是一般官方给这个图就是该中间件的基本使用思路,与核心功能点。

2、基础性概念

  • 资源管理

资源是Sentinel组件中的核心概念之一。应用服务器上脚本,静态页面,API接口,文件图片等都可以理解为资源,对于Java开发者而言,API接口就是这里资源的概念。

  • 规则配置

Sentinel组件通过流控规则的配置,来指定允许该资源(API接口)通过的请求次数,IP黑白名单,应用服务等。

  • 测试效果

QPS:每秒查询率,是一台服务器每秒能够处理的查询次数。

TPS:每秒处理事务数,事务处理整体倾向于整个过程。

二、框架环境整合

这里的环境主要整合Nacos注册中心,Feign服务,Sentinel哨兵,和Sentinel控制台。

1、基本依赖

这里的依赖需要参考官方文档,不同的环境使用不同的依赖,这里主要适配SpringCloud环境,所以使用如下包即可。

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>

2、控制台面板

这里直接从GitHub下载一个控制台服务包即可,也可以自己下载源码,按照需求修改后自行打包。

java -jar sentinel-dashboard-1.7.1.jar

下载并启动控制台服务。

3、服务配置

这里主要是把用到的两个服务9001和9002连接到监控台。

spring:
  application:
    name: node09-nacos-9001
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
    sentinel:
      transport:
        port: 9001
        dashboard: localhost:8080

最下面四行文件是哨兵控制台的主要配置,注意刚启动之后控制台是看不到连接的,有资源被触发之后才能看到。(附一张首页效果图)

三、流量控制

1、基本描述

流量控制(flow control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

2、限流规则

限流规则主要由下面几个因素组成。

  • resource:资源名,即限流规则的作用对象,对于Java服务端开发而言就是执行的方法;
  • count: 限流阈值,单位时间内能按照规则通过的请求量;
  • grade: 限流阈值类型,QPS 或并发线程数 ;
  • limitApp: 流控限制的指定应用来源,若为default则不区分调用来源;
  • strategy: 调用关系限流策略,直连,链路等;
  • controlBehavior: 流量控制效果,直接拒绝、Warm Up、匀速排队;

3、基本案例

  • 硬编码

配置规则

public class FlowRuleConfig {

    public static void initFlowQpsRule(String resourceName) {
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule(resourceName);
        // 修改这里参数,查看效果
        rule.setCount(100);
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setLimitApp("default");
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }
}

该规则参考上面的限流因素,不难理解。

使用方式

@RequestMapping(value = "/web/getOrder",method = RequestMethod.GET)
public String getOrder (@RequestParam("id") Integer id){
    FlowRuleConfig.initFlowQpsRule("getOrder");
    Entry entry = null;
    try {
        // 定义资源,埋点
        entry = SphU.entry("getOrder");
        // 保护的业务逻辑
        return "Order=" + id ;
    } catch (Exception e){
        e.printStackTrace();
    } finally {
        if (entry != null){entry.exit();}
    }
    return "Order Error" ;
}

测试的时候修改规则中count值,测试效果明显。

  • 编码简化

SphU.entry中可以设置处理类型,限流阈值。

@RequestMapping(value = "/web/getState",method = RequestMethod.GET)
public String getState (@RequestParam("id") Integer id){
    Entry entry = null;
    try {
        entry = SphU.entry("getOrder",EntryType.IN,2);
        return "state=" + id;
    }
    catch (BlockException e){
        e.printStackTrace();
    } finally {
        if (entry != null){entry.exit();}
    }
    return "State Error" ;
}

不过这种模式依旧是代码入侵严重,不太符合现在编程的大趋势。Sentinel支持通过@SentinelResource注解定义资源并配置。

4、测试效果

请求上述的两个测试接口,之后看控制台中9001服务的簇点链路。

可以基于控制台实时配置资源的:流控、降级、热点、授权等核心功能,服务重启之后配置也会重置。

四、服务熔断降级

1、注解详解

核心注解SentinelResource

用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource 注解包含以下属性:

  • value

资源名称,核心概念不能为空;

  • entryType

entry 类型,可选项默认为 EntryType.OUT;

  • blockHandler

对应处理BlockException的函数名称,可选项。blockHandler函数访问范围需要是public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为BlockException。blockHandler函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass为对应的类的Class对象,注意对应的函数必须为 static 函数,否则无法解析。

  • fallback

fallback函数名称,可选项,用于在抛出异常的时候提供fallback处理逻辑。fallback函数可以针对所有类型的异常(除了 exceptionsToIgnore里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:返回值类型必须与原函数返回值类型一致;方法参数列表需要和原函数一致,或者可以额外多一个;

注意:这里可以这样理解blockHandler和fallback,fallback处理业务逻辑的异常,服务降级,blockHandler处理sentinel组件控制的阻断异常。

2、使用案例

9001接口服务

@Service
public class FlowServiceImpl implements FlowService {
    @Resource
    private JdbcTemplate jdbcTemplate ;
    @SentinelResource(value = "getPhone",blockHandler = "exceptionHandler", fallback = "fallback")
    @Override
    public String getPhone(Integer id) {
        String sql = "select phone from d_phone WHERE id="+id ;
        Integer.parseInt("hand") ;
        return jdbcTemplate.queryForList(sql,String.class).get(0) ;
    }
    // 降级处理
    public String fallback(Integer id) {
        return "服务降级,id="+id ;
    }
    // 异常处理
    public String exceptionHandler(Integer id,BlockException be) {
        be.printStackTrace();
        return "服务抛异常,id="+id ;
    }
}

9002请求服务

@RequestMapping(value = "/web/getJdbc",method = RequestMethod.GET)
public String getJdbc () {
    return msgFeign.getJdbc() ;
}

3、效果测试

通过控制台配置9001的限流规则,然后刷接口看效果。

注意阻断异常和业务异常的返参区别。

4、对比Hystrix组件

Hystrix的核心点在于以隔离和熔断为主的容错机制,超时或被熔断的调用将会快速失败,并可以提供 fallback 机制;

Sentinel核心点在于流量控制多样化,熔断降级服务,系统负载保护,实时监控和控制台;

补刀一句:对于流量控制类的组件,大部分场景是使用限流,服务降级这两块核心功能。

===============================================================================

一、实现Shard-Jdbc的分库分表模式,数据库扩容方案 

1、工程结构

2、模块命名

shard-common-entity:   公共代码块
shard-open-inte:        开放接口管理
shard-eureka-7001:      注册中心
shard-two-provider-8001: 8001 基于两台库的服务
shard-three-provider-8002:8002 基于三台库的服务

3、代码依赖结构

4、项目启动顺序

1)shard-eureka-7001:        注册中心
(2)shard-two-provider-8001:  8001 基于两台库的服务
(3)shard-three-provider-8002:8002 基于三台库的服务

按照顺序启动,且等一个服务完全启动后,在启动下一个服务,不然可能遇到一些坑。

二、核心代码块

1、8001 服务提供一个对外服务

基于Feign的调用方式
作用:基于两台分库分表的数据查询接口。

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import shard.jdbc.common.entity.TableOne;
/**
 * shard-two-provider-8001
 * 对外开放接口
 */
@FeignClient(value = "shard-provider-8001")
public interface TwoOpenService {
    @RequestMapping("/selectOneByPhone/{phone}")
    TableOne selectOneByPhone(@PathVariable("phone") String phone) ;
}

2、8002 服务提供一个对外服务

基于Feign的调用方式
作用:基于三台分库分表的数据存储接口。

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import shard.jdbc.common.entity.TableOne;

/**
 * 数据迁移服务接口
 */
@FeignClient(value = "shard-provider-8002")
public interface MoveDataService {
    @RequestMapping("/moveData")
    Integer moveData (@RequestBody TableOne tableOne) ;
}

3、基于8002服务数据查询接口

查询流程图

代码块

/**
 * 8001 端口 :基于两台分库分表策略的数据查询接口
 */
@Resource
private TwoOpenService twoOpenService ;
@Override
public TableOne selectOneByPhone(String phone) {
    TableOne tableOne = tableOneMapper.selectOneByPhone(phone);
    if (tableOne != null){
        LOG.info("8002 === >> tableOne :"+tableOne);
    }
    // 8002 服务没有查到数据
    if (tableOne == null){
        // 调用 8001 开放的查询接口
        tableOne = twoOpenService.selectOneByPhone(phone) ;
        LOG.info("8001 === >> tableOne :"+tableOne);
    }
    return tableOne ;
}

4、基于 8001 数据扫描迁移代码

迁移流程图

代码块

/**
 * 8002 端口开放的数据入库接口
 */
@Resource
private MoveDataService moveDataService ;
/**
 * 扫描,并迁移数据
 * 以 库 db_2 的 table_one_1 表为例
 */
@Override
public void scanDataRun() {
    String sql = "SELECT id,phone,back_one backOne,back_two backTwo,back_three backThree FROM table_one_1" ;
    // dataTwoTemplate 对应的数据库:ds_2
    List<TableOne> tableOneList = dataTwoTemplate.query(sql,new Object[]{},new BeanPropertyRowMapper<>(TableOne.class)) ;
    if (tableOneList != null && tableOneList.size()>0){
        int i = 0 ;
        for (TableOne tableOne : tableOneList) {
            String db_num = HashUtil.moveDb(tableOne.getPhone()) ;
            String tb_num = HashUtil.moveTable(tableOne.getPhone()) ;
            // 只演示向数据新加库 ds_4 迁移的数据
            if (db_num.equals("ds_4")){
                i += 1 ;
                LOG.info("迁移总数数=>" + i + "=>库位置=>"+db_num+"=>表位置=>"+tb_num+"=>数据:【"+tableOne+"】");
                // 扫描完成:执行新库迁移和旧库清理过程
                moveDataService.moveData(tableOne) ;
                // dataTwoTemplate.update("DELETE FROM table_one_1 WHERE id=? AND phone=?",tableOne.getId(),tableOne.getPhone());
            }
        }
    }
}

三、演示执行流程

1、项目流程图

2、测试执行流程

(1)、访问8002 数据查询端口

http://127.0.0.1:8002/selectOneByPhone/phone20
日志输出:
8001 服务查询到数据
8001 === >> tableOne :+{tableOne}

(2)、执行8001 数据扫描迁移

http://127.0.0.1:8001/scanData

(3)、再次访问8002 数据查询端口

http://127.0.0.1:8002/selectOneByPhone/phone20
日志输出:
8002 服务查询到数据
8002 === >> tableOne :+{tableOne}

=============================================================================

SpringCloud基础组件总结,与Dubbo框架、SpringBoot框架对比分析

1、文章阅读目录

1)、基础组件

Eureka组件,服务注册与发现

Ribbon和Feign组件,实现负载均衡

Hystrix组件,实现服务熔断

Turbine组件,实现微服务集群监控

Zuul组件,实现路由网关控制

Config组件,实现配置统一管理

Zipkin组件,实现请求链路追踪

2)、应用案例

基于Shard-Jdbc分库分表,数据库扩容方案

基于SpringCloud实现Shard-Jdbc的分库分表扩容

3)、后续更新

该案例主要基于SpringCloud2版本,演示微服务在实际开发中的应用。

<modules>
    <!-- 客户端接口层 -->
    <module>storey-client-web</module>
    <!-- 公共代码块层 -->
    <module>storey-block-code</module>
    <!-- 中间件管理层 -->
    <module>storey-middle-soft</module>
    <!-- 数据 中 心层 -->
    <module>storey-data-center</module>
    <!-- 微服务组件层 -->
    <module>storey-cloud-ware</module>
</modules>

采用版本

  • Spring: 5.0+
  • SpringBoot: 2.0+
  • SpringCloud: 2.0+

2、常用组件概念

  • Eureka组件

Eureka是一种基于REST的服务,主要用于AWS云,用于定位服务,以实现中间层服务器的负载平衡和故障转移。此服务称为EurekaServer。客户端组件EurekaClient,它使与服务的交互变得更加容易。

  • Ribbon和Feign组件

Ribbon是一个客户端的负载均衡(Load Balancer,简称LB)器,它提供对大量的HTTP和TCP客户端的访问控制。

Feign 是一个声明式的 Web Service 客户端。它的出现使开发 Web Service 客户端变得很简单。使用 Feign 只需要创建一个接口加上对应的注解,比如:@FeignClient 接口类注解。

  • Hystrix组件

微服务架构中某个微服务发生故障时,要快速切断服务,提示用户,后续请求,不调用该服务,直接返回,释放资源,这就是服务熔断。

  • Turbine组件

微服务架构中为了保证程序的可用性,防止程序出错导致网络阻塞,出现了断路器模型。断路器的状况反应程序的可用性和健壮性,它是一个重要指标。HystrixDashboard是作为断路器状态的一个组件,提供了数据监控和直观的图形化界面。

  • Zuul组件

Zuul 网关主要提供动态路由,监控,弹性,安全管控等功能。在分布式的微服务系统中,系统被拆为了多个微服务模块,通过zuul网关对用户的请求进行路由,转发到具体的后微服务模块中。

  • Config组件

在微服务系统中,服务较多,相同的配置:如数据库信息、缓存、参数等,会出现在不同的服务上,如果一个配置发生变化,需要修改很多的服务配置。spring cloud提供配置中心,来解决这个场景问题。

  • Zipkin组件

Zipkin是SpringCloud微服务系统中的一个组件,实现了链路追踪解决方案。可以定位一个请求到底请求了哪些具体的服务。在复杂的微服务系统中,如果请求发生了异常,可以快速捕获问题所在的服务。

二、Boot 对比Cloud

SpringBoot专注于快速开发单个微服务。SpringCloud是关注全局的微服务协调框架,它将SpringBoot开发的单个微服务整合管理,并为微服务之间提供,配置管理、服务发现、断路器、路由网关等集成服务,SpringCloud依赖SpringBoot。

三、Dubbo对比Cloud

1、调用方式对比

服务调用方式是 Dubbo 和 Spring Cloud 重要不同点,熟悉RPC/HTTP/REST概念,有助对比 Dubbo 和SpringCloud。RPC 是远端过程调用,其调用协议通常包含传输协议和编码协议。RPC调用是面向服务的封装,针对服务的可用性和效率等都做了优化。http是超文本传输协议,RPC 也可以用http作为传输协议,但一般是用 tcp作为传输协议。

2、执行性能对比

Dubbo 采用单一长连接和NIO异步通讯(保持连接/轮询处理),使用自定义报文的TCP协议,并且序列化使用定制Hessian2框架,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况,但不适用于传输大数据的服务调用。Spring Cloud 直接使用 HTTP 协议,在性能上弱于Dubbo。

3、注册中心对比

这里通常指ZooKeeper(Dubbo注册中心)和Eureka(Cloud注册中心)的对比。分布式领域著名的CAP理论(C:数据一致性,A:服务可用性,P:分区故障的容错性),Zookeeper保证的是CP,但对于服务发现而言,可用性比数据一致性更加重要,AP胜过CP,而 Eureka 设计则遵循 AP 原则。

4、框架生态对比

Dubbo 专注 RPC 和服务治理,Spring Cloud 则是一个微服务架构生态。

 

posted @ 2022-06-30 13:36  hanease  阅读(213)  评论(0编辑  收藏  举报