《Spring Cloud微服务:全栈技术与案例解析》读书笔记
第一部分 准备篇
第一章 spring cloud 与微服务概述
单体应用的缺点;
dubbo基于Netty的TCP及二进制的数据传输,SC基于HTTP,HTTP需要创建连接,传输文本内容,性能不好。(待验证)
微服务的定义:去中心化数据管理,柔性事务的最终一致性;
spring cloud介绍
第二章 实战准备
JDK,spring boot等。
读取配置文件的三种方式:
environment的getProperty方法,@Value,自定义配置类(POJO类,加上类注解@ConfigurationProperties(prefix=""))。
热部署:
统一异常处理:
异步执行:
随机端口:
第二部分 基础篇
第三章 Eureka注册中心
第四章 客户端负载均衡Ribbon
第五章 声明式REST客户端Feign
第六章 Hystrix服务容错处理
第七章 API网关
第三部分 实战篇
第八章 分布式配置管理
SC config,支持配置的加解密,自动更新(手动调用接口触发,也可以利用消息总线和Git的WebHook来实现配置修改的自动更新)。
百度开源Disconf。sc config 不能推送配置到指定节点?自研Smconf:java + zookeeper + mongodb + sb。
功能:
MongoDb,启动–fork,守护进程运行。
SpringFactoriesLoader是spring框架的一种扩展方案,从指定的配置文件META-INF/spring.factories加载配置。
配置修改及时推送到各节点,实现方法:客户端轮询获取、server写长连接推送。
第九章 Sleuth服务跟踪
所有需要跟踪的服务都需要添加依赖sleuth。log格式[appname, traceId,spanId,exportable]
spanId:基本的工作单元,发起一次远程调用就是一个span。
exportable:是否导入数据到zipkin。
整合LogStash:输出json格式的数据需要添加依赖logstash-logback-encoder,配置文件logback-spring.xml,配置LogStash需要收集的数据格式。
整合zipkin:致力于收集所有服务的监控数据的分布式跟踪系统,提供收集数据和查询数据两大接口。zipkin的数据条数和调用接口次数默认比例是0.1,可配置。
数据发送采用HTTP协议影响性能。用MQ替换HTTP发送调用链数据。
第十章 安全认证
第十一章 Spring boot Admin
sb Admin基于actuator,可以集成别的页面组件。
服务注册到sb Admin,添加依赖spring-boot-admin-starter-client,增加配置:
spring.boor.admin.url= management.security.enabled=false
在admin查看各个服务的日志:在监控的服务中增加日志文件的路径的配置信息。
开启认证:集成security,添加依赖,增加配置信息,自定义安全配置类,监控的服务也需要增加用户名密码的配置信息。
集成eureka:上面的方式,需要每个被监控的服务实例配置admin的地址信息。可以将admin注册到eureka中,然后自动获取Eureka中已注册的服务信息统一查看。
集成Turbin:admin提供Turbin扩展插件,用于整合展示整个集群的熔断器信息。
admin的邮件警告功能,自定义钉钉警报(具体实现有需求再去细看,总归需要接入方的支持,以及申请token之类的唯一码),接入其他警报消息触达平台(微信)类似。
第十二章 服务API文档管理
前后端分离;
swagger提供在线测试功能;
常用注解:
@Api
@ApiModel
@ApiModelProperty
@ApiParam
@ApiOperation
@ApiResponse & @ApiResponses
@ApiImplicitParam & @ApiImplicitParams
Eureka控制台快速查看swagger文档:
在application.properties文件增加配置:
eureka.instance.status-page-url=http://${spring.cloud.client.ipAddress}:${server.port}/swagger-ui.html
第四部分 高级篇
第十三章 API网关扩展
第十四章 缓存
第十五章 存储
MongoDb 内嵌文档;
@Field注解可以自定义字段名称,可以缩写减少存储空间。MongoDb的存储方式是k-v形式,每个key都会重复存储,占用空间。
@Indexed字段加索引,参数unique=true创建唯一索引,background=true以后台方式创建索引。
@CompoundIndexes用于类,创建组合索引,def表示组合索引的字段和升(1)降(-1)序。
MongoDb内置文件系统GridFS,文件块切割为256kb,单独存放。GridFSTemplate。
自增ID,ObjectID,自增ID不要用Long包装类型,监听模式,MongoTemplate的findAndModify是原子操作,不用担心并发问题,继承AbstractMongoEventListener类,重写方法onBeforeConvert。
批量更新扩展:mongo-java-driver的update方法只能执行一个更新条件,参数不支持集合,即不支持批量更新(待确认)。
MySQL
jdbcTemplate提供5类方法:execute:执行DDL语句;update;batchUpdate;query;call。
ES
@Document指定index和type,@Field指定type类型,index是否使用分词器,是否存储store,分词器配置analyzer,searchAnalyzer。原生的driver,transport client。
将MySQL或者MongoDb中数据导入到ES,建立索引信息,第三方工具:Elasticsearch-jdbc、mongo-connector。ElasticsearchTemplate的bulkIndex来构建索引,其save方法基于bulkIndex。
第十六章 分布式事务
第十七章 分布式任务调度
第十八章 分库分表解决方案
sharding-jdbc
项目定位:
功能列表:
概念:
LogicTable:数据分片的逻辑表,对于水平拆分的数据库表,同一类表的总称。
ActualTable:分片数据库中的物理表。
DataNode:数据分片最小单元,有数据源和数据表组成,
集成实战,读写分离实战,Hint强制路由主库(问题:写主库查从库,数据同步耗时期间查不到数据),Hint强制读主库。
分库分表实战,垂直拆分(类似微服务,用户表user和订单表order在不同的server上面)能够解决表之间的资源竞争问题,不能解决单表数据增加过快的问题,水平拆分将一个表拆分为多个,分布在不同的server上。
常用分片算法:
范围分片:根据主键的范围来分片;
取模分片:根据表的数量来取模;
hash分片:通过某个字段进行hash,一致性hash可以解决数据扩容问题;
时间分片。
sharding-jdbc默认提供单分片键算法和多分片键算法。根据数据源策略和表策略,一共有4种算法接口:
单分片键数据源分片算法SingleKeyDatabaseShardingAlgorithm
单分片表分片算法SingleKeyTableShardingAlgorithm
多分片健数据源分片算法MultipleKeyDatabaseShardingAlgorithm
多分片表分片算法MultipleKeyTableShardingAlgorithm
接口中的方法
@Override
public String doEqualSharding(final Collection<String> availableTargetNames,final ShardingValue<Integer> shardingValue);
@Override
public Collection<String> doInSharding(final Collection<String> availableTargetNames,final ShardingValue<Integer> shardingValue);
@Override
public Collection<String> doBetweenSharding(final Collection<String> availableTargetNames,final ShardingValue<Integer> shardingValue);
这三种算法作用如下:
- doEqualSharding
在WHERE使用=作为条件分片键。算法中使用shardingValue.getValue()获取等=后的值。 - doInSharding
在WHERE使用IN作为条件分片键。算法中使用shardingValue.getValues()获取IN后的值。 - doBetweenSharding
在WHERE使用BETWEEN作为条件分片键。算法中使用shardingValue.getValueRange()获取BETWEEN后的值。
多分片建算法适用于比较复杂的场景,为了提高灵活性故只提供一个方法实现:
public Collection<String>doSharding(final Collection<String> availableTargetNames,final Collection<ShardingValue<?>> shardingValues);
算法实现的时候根据shardingValue.getType来获取条件是= .IN还是between。
在spring的配置文件中,inline表达式使用groovy语法,