mageek 发布的文章

后端好书阅读与推荐(续七)


后端好书阅读与推荐系列文章:
后端好书阅读与推荐
后端好书阅读与推荐(续)
后端好书阅读与推荐(续二)
后端好书阅读与推荐(续三)
后端好书阅读与推荐(续四)
后端好书阅读与推荐(续五)
后端好书阅读与推荐(续六)
后端好书阅读与推荐(续七)

Spring微服务实战

Spring微服务实战 (豆瓣): https://book.douban.com/subject/30233791/

Spring体系用来做微服务在当下可谓是风头正劲,这本书就用一个实例来手把手教我们实现微服务。实战系列的口碑一直不错,这本也不例外,看完就可以对微服务的概念有一个完整的理解,并且想上手也有路可寻。

亮点:

  • 编码就像艺术,是一种创造性活动。构建分布式应用就像指挥一个管弦乐队演奏音乐,是一件令人惊奇的事情
  • 微服务是一个小的、松耦合的分布式服务,分解和分离大型复杂应用程序的功能,使它们独立,这样负责每个功能的团队都拥有自己的代码库和基础设施,技术不限,能灵活地独立开发部署,职责分离,降低团队协作成本。随着云的普及,微服务单元的增减(每个服务单元都是完整的)变得非常容易,使得整个应用更具弹性伸缩能力。Spring勇于自我革新,当初出场取代了沉重的J2EE,后面的Spring Boot使用简单注解去掉了自己原本繁重的配置,后来的Spring Cloud更是为分布式服务提供了一套完整的解决方案,所以Spring体系是我们构建微服务的绝佳选择
  • 微服务构建的一个关键是划分,而划分的一个关键是粒度,这个没有绝对标准,但是有几个原则:开始可以让服务设计范围大一些,后续可以重构至更小的服务;重点关注服务之间如何交互;随着对问题域的理解变化,服务的职责也要变化(演化思维)。需要注意微服务的几个坏味道(太粗;太细):职责过多,跨表超过5个,URL太长,测试用例太多;数量巨大、彼此依赖严重、成为简单的curd、只在一个表操作等
  • 微服务没有标准,但是作者提出了12种最佳实践:独立代码库、显式依赖、配置存储、后端可切换、构建发布运行必须完整、进程无状态、端口命令行制定、横向扩展并发、可down可up、环境一致、日志流式处理、管理脚本化。微服务的生命周期:装配、引导、发现、服务和监控、关闭
  • 少量程序可以使用低层级文件(YAML、json、XML)来存储配置,将其与代码分开,但是到了数百单元(每个单元可能有多个实例)时就不行了。手动管理既慢又复杂还可能配置漂移,这时应该引入配置管理工具(etcd、eureka、consul、zookeeper、spring cloud config等),服务启动时通过环境变量注入配置或者从集中式存储中获取
  • 服务发现提供了快速水平伸缩的能力,且当服务不健康时可以快速删除,还能取代传统的手动管理负载均衡。主要涉及服务注册、客户端服务地址查找、信息共享、健康监测4个方面
  • 一般大家关注高可用都是某个组件彻底不可用(容易检测)的情况,但是一个性能不佳而没有完全垮掉(不易检测)的服务也可以彻底拖垮整个应用,因此也需要保护这些不佳服务,避免连锁效应,导致彻底不可用。一般有客户端负载均衡(Ribbon)、断路器、后备、舱壁(Hystrix)等四个弹性模式来实现保护缓冲区
  • AOP的思想帮我们分离关注点,那么要在微服务中实现靠啥?答案就是网关(比如Zuul,核心就是反向代理)了,我们可以在网关中实现验证授权、数据搜集与日志等关注点,但是要注意,避免网关成为单点要注意使其轻量且无状态(无状态就可以很容易扩展,而服务发现必须有状态,所以要扩展还要用Gossip等协议来同步状态数据,保障一致性和可用性
  • 安全注意事项:都要使用HTTPS\SSL、所有服务都要经过网关、将服务划分为公共API和私有API、封锁不必要的端口来限制微服务的攻击面
  • 微服务不是单体,其好处是灵活,代价就是解决问题时难以定位,所以需要追踪并聚合日志,最终定位问题。spring cloud 给每一个事务开启之前注入关联ID(一般由网关完成),每个服务都可以传播关联ID并将其添加进日志中,这些日志被统一发送到日志聚合点中,就可以供我们统一检索了,常见实现有ELK、Splunk等。光能检索还不够,一张直观的事务流图抵过1万条日志,Sleuth和ZipKin一起可以实现该功能
  • 微服务强调灵活迅速,所以一个成熟的构建与部署管道(引入CI/CD)必不可少:提交代码、自动构建(钩子实现)、构建期间进行单元测试集成测试后获得一个jar(自包含tomcat)、用jar构建并提交机器镜像、在新环境中拉取机器镜像并进行平台测试后启动镜像、每个新环境都要重复前面一个步骤

书很厚,所以很多具体工具可以跳过,尝试几个即可,将来使用的时候知道这本书里有就行了。


后端好书阅读与推荐(六)


后端好书阅读与推荐系列文章:
后端好书阅读与推荐
后端好书阅读与推荐(续)
后端好书阅读与推荐(续二)
后端好书阅读与推荐(续三)
后端好书阅读与推荐(续四)
后端好书阅读与推荐(续五)
后端好书阅读与推荐(续六)

Elasticsearch权威指南

Elasticsearch: The Definitive Guide (豆瓣): https://book.douban.com/subject/25868239/

Elasticsearch是一个强大的开源搜索引擎(不仅如此,还是一个分布式存储实时分析系统),作为后端开发者,我们常常需要用到它,甚至是借鉴其原理来实现自己特定的功能,因为了解一下是很有必要的。这本书不仅讲了使用方法,还讲了原理,很适合我们学习与查阅。

亮点:

  • Elasticsearch使用Java开发并使用 Lucene 作为其核心来实现所有索引和搜索的功能,它的目的是通过简单的 RESTful API 来隐藏 Lucene 的复杂性。也对用户隐藏了分布式系统的复杂性,而且提供了一系列运行良好的默认值,从而让全文搜索变得简单,达到开箱即用的效果
  • ES与传统RDB的对比:
    • Relational DB -> Databases -> Tables -> Rows -> Columns
    • Elasticsearch -> Indices -> Types -> Documents -> Fields
  • ES的自动实现了分片、负载均衡、发现、冗余、选主、同步、扩展迁移、容错等功能。一个节点(node)就是一个Elasticsearch实例,而一个集群(cluster)由一个或多个节点组成,它们具有相同的cluster.name,集群中一个节点会被选举为主节点(master),它将临时管理集群级别的一些变更,例如新建或删除索引、增加或移除节点等。索引只是一个用来指向一个或多个分片(shards,是一个 Lucene 实例)的逻辑命名空间(logical namespace),分片可以是主分片(primary shard)或者是复制分片(replica shard)。索引中的每个文档属于一个单独的主分片,所以主分片的数量决定了索引最多能存储多少数据,复制分片只是主分片的一个副本,它可以防止硬件故障导致的数据丢失,同时可以提供读请求,启动新节点时集群会重新组织并均匀分配各个分片
  • ES提供了丰富的数据操纵功能,不仅有简单的查询字符串搜索(含通配符),还有DSL,可以构建更复杂、强大的查询
  • 批量请求可以减少网络往返次数开销,以及日志数量,可以提升性能(mysql也有这种做法),这个批量的大小要根据你的硬件来定制
  • 倒排索引是全文搜索的核心技术,也就是按照每个单词(经过分词后)划分归属集,存储包含这个单词的文档,检索是按照单词的,所以可以很快返回相关文档
  • ......

此外需要注意的是Elasticsearch发展太快,书籍只是用来系统性的学习的,如果真的要使用起来,还是要去官网看最新的用法,但是基本原理和思想变化是不多的。


消息队列二三事


最近在看kafka的代码,就免不了想看看消息队列的一些要点:服务质量(QOS)性能扩展性等等,下面一一探索这些概念,并谈谈在特定的消息队列如kafka或者mosquito中是如何具体实现这些概念的。

服务质量

服务语义

服务质量一般可以分为三个级别,下面说明它们不同语义。

At most once

至多一次,消息可能丢失,但绝不会重复传输。
生产者:完全依赖底层TCP/IP的传输可靠性,不做特殊处理,所谓“发送即忘”。kafka中设置acks=0
消费者:先保存消费进度,再处理消息。kafka中设置消费者自动提交偏移量并设置较短的提交时间间隔。


源码分析Kafka之Producer


Kafka是一款很棒的消息系统,可以看看我之前写的 后端好书阅读与推荐来了解一下它的整体设计。今天我们就来深入了解一下它的实现细节(我fork了一份代码),首先关注Producer这一方。

要使用kafka首先要实例化一个KafkaProducer,需要有brokerIP、序列化器必要Properties以及acks(0、1、n)、compression、retries、batch.size非必要Properties,通过这个简单的接口可以控制Producer大部分行为,实例化后就可以调用send方法发送消息了。

核心实现是这个方法:

public Future<RecordMetadata> send(ProducerRecord<K, V> record, Callback callback) {
    // intercept the record, which can be potentially modified; this method does not throw exceptions
    ProducerRecord<K, V> interceptedRecord = this.interceptors.onSend(record);//①
    return doSend(interceptedRecord, callback);//②
}

通过不同的模式可以实现发送即忘(忽略返回结果)、同步发送(获取返回的future对象,回调函数置为null)、异步发送(设置回调函数)三种消息模式。


Raft论文读书笔记


Raft是当前分布式领域最重要的一致性算法之一,今天我们就来好好研究研究这个算法的论文, 还有对应网站, 动画, 不想看英文的也有中文的翻译,所以我这边就不翻译了,主要还是记录一下论文重点和自己的心得。

Raft算法作者的初衷是对标Paxos算法(过去十年分布式一致性的事实标准),但是要比它更易理解,主要手段有:

  1. 分解,把整个一致性问题拆分为Leader选举日志复制安全机制三大方面还有角色改变这个小方面。所以模块化是一个软件系统可维护、理解和扩展的不二手段。
  2. 减少状态空间的状态,相比于Paxos,Raft减少了非确定性和服务器之间可以处于不一致的方式。所以在复杂的问题上做减法,可以减少很多不必要的繁琐的步骤。

Raft使用了更强的Leader,感觉这和我之前看的OceanBase是相似的,就是增强Leader(UpdateServer)或者说单点的作用,加重中心化(这也是社会的运作方式,没有Leader就是大家一盘散沙,文明是达不到今天这个程度的),要做决策就先选择一个Leader,然后让他去协调所有的决议,会更加简单快速,而Paxos就是P2P或者说弱Leader的方式。事实上,我们之所以使用分布式系统也是迫不得已,如果单台机器能搞定还要这么多系统干嘛?所以我们也要看到单点系统的好处,那就是一致性很容易保证,所以在分布式系统中使用一个增强(能力和责任)的单点既利于一致性的保证也能获得分布式的优势。