赞
踩
推荐你阅读
互联网大厂万字专题总结
Redis总结
JUC总结
操作系统总结
JVM总结
Mysql总结
微服务总结
互联网大厂常考知识点
什么是系统调用
CPU底层锁指令有哪些
AQS与ReentrantLock原理
旁路策略缓存一致性
Java通配符看这一篇就够
Java自限定泛型
分布式架构相比于单体架构具有低耦合、业务拆分的特点,但也引入了一些问题比如数据一致性问题、复杂调用关系等等。微服务是一种分布式架构标准,微服务强调拆分粒度小、每个微服务独立程度高、每个微服务向外提供标准接口。
微服务拆分原则需要遵守:
SpringCloud 是目前国内使用最广泛的微服务框架。SpringCloud 集成了各种微服务功能组件,并基于 SpringBoot 实现了这些组件的自动装配。SpringCloud 和 SpringBoot 之间存在版本兼容关系。SpringCloud 中的各种微服务之间采用 http 协议进行接口调用。RestTemplate 接口提供了 http 接口调用的实现。
微服务注册中心支持服务提供者注册信息,支持服务消费者获取服务提供者的注册信息。相比于服务提供者的接口地址写死在服务消费者代码中的方式,微服务注册中心一方面支持服务提供者随时变动,另一方面也支持微服务调用的负载均衡。
Eureka 支持服务提供者注册服务信息,支持服务消费者定时拉取服务信息。服务提供者通过心跳的方式(默认 30s)告知 Eureka 自己的健康状态。
我们可以直接在 SpringBoot 中启动一个 Eureka 微服务(通过引入相关依赖、配置 yml 文件、配置注解),然后将其他微服务作为服务提供者注册到 Eureka(通过引入相关依赖、配置 yml 文件),最后作为服务消费者的任何微服务都可以拉取 Eureka 中的服务注册信息进行相应的微服务接口调用(通过引入相关依赖、配置 yml 文件、配置注解)。
微服务接口调用的负载均衡是通过 Ribbon 实现的,Ribbon 默认是采用懒加载。负载均衡接口 IRule 有一些默认的接口实现比如轮询(RoundRobin)、权重、区域优先等等。
Nacos 是阿里的产品,相比 Eureka 功能更丰富。Nacos 直接提供了操作系统可执行文件(但依赖 jre)。
Nacos 将一个服务分为了多个集群(通常一个集群指的是某区域的一个机房),每个集群又分为了多个实例。微服务互相访问时,应该尽可能访问同集群实例,因为本地访问速度更快。当本集群内不可用时,才访问其它集群。
我们同样可以通过引入相关依赖、配置 yml 文件、操作 Nacos 的 web 控制台的方式,完成服务提供者的集群注册、负载权重配置、服务消费者拉取信息等操作。
Nacos 注册中心对于服务提供者除了心跳检测还会主动询问,除了服务消费者会定时拉取 Nacos 注册中心信息外,Nacos 还会向服务消费者主动推送变更消息。
我们可以在 Nacos 的 web 控制台上创建 yaml 配置,并将需要热更新的配置放在其中,这样微服务的配置信息就由 bootstrap.yaml、Nacos 在线 yaml 和 application.yml 共同组成,我们通过 @Value 注解或@ConfigurationProperties 注解就可以读取热更新配置。当然上述过程还是需要通过引入相关依赖、配置 yml 文件、配置注解来完成。
Nacos 在线 yaml 配置有两种:
[spring.application.name]-[spring.profiles.active].yaml
,例如:userservice-dev.yaml[spring.application.name].yaml
,例如:userservice.yaml[spring.application.name].yaml
不包含环境,因此可以被多个环境共享。
单体应用只需要提供接口给用户即可,但微服务由于其高内聚低耦合的特点,一方面微服务接口的实现需要依赖其他微服务接口,另一方面微服务接口也需同时提供给用户和其他微服务。
Spring 官方提供的 http 接口调用框架
Feign 是一种接口声明式的 http 微服务调用框架,我们可以对每个要调用的微服务声明一个接口,在里面为该微服务每个要调用的接口声明一个方法,可以指定微服务名称(用来从注册中心拉取信息)、请求方式(Get)、资源路径、pojo 返回类型。
Feign 底层依赖的 http 请求框架有多种,如果选择支持 http 连接池的框架则可能会带来性能优化。
Gateway 基于响应式编程,提供了服务鉴权、请求路由和服务限流等核心功能。
引入相关依赖、配置 yml 文件即可启动 Gateway 网关微服务。
过滤器可以对路由的请求或响应做加工处理,比如添加请求头等。Gateway 提供了多种类型的过滤器实现,我们可以在 yml 文件中配置路由过滤器和默认过滤器(只可以使用 Gateway 提供的过滤器),我们也可以实现自己的全局过滤器,通过编写自定义逻辑实现登陆状态判断、权限校验、请求限流等功能。
多个过滤器执行的先后顺序取决于 order 值。
application.yml 中可以进行配置。
大型项目微服务很多,多个微服务之间可能存在依赖冲突,但每个微服务都单独部署在一个服务器不太实际,Docker 可以解决微服务间的依赖兼容性问题。
docker 容器的运行由 docker 引擎管理(docker 引擎由一系列负责各个功能的进程组成),根据 docker 官方推荐,大多数情况下我们只会在一个 docker 容器中运行一个进程,这个进程本质就是外部宿主机上 linux 内核的一个进程,可以直接在宿主机上查到。
docker 的关键是 linux 内核提供的隔离技术,多个 Docker 容器间通过 Namespace 技术进行进程隔离,通过 Cgroups 技术进行进程资源限制。这也是我们进入 Docker 容器内部感觉像是一个完整操作系统的原因。
docker 镜像打包的其实是文件系统中的文件、要运行的程序等等。
docker 镜像是分层的,这使得多个 Docker 镜像间可以共享相同层。
docker 的实现与虚拟化没有关系,本质就是进程隔离,因此硬盘占用低、启动速度快。
Vmware 这种虚拟化技术,是在宿主操作系统的基础上,用软件虚拟出一套计算机硬件(这个中间层称为 Hypervisor),再基于虚拟出来的这套硬件安装任何想要的操作系统。因此应用运行在虚拟机上时,想要操作底层真实硬件需要依次通过虚拟机操作系统、Hypervisor、宿主机操作系统、底层真实硬件。因此硬盘占用大、启动慢、性能差。
业务异步级联可以提高吞吐量、降低业务耦合、流量削峰填谷。缺点是架构变复杂了,需要引入 MQ 消息队列。
常见的 MQ 技术包含:
主要有五大操作:创建交换机、创建队列、绑定交换机和队列、生产消息、消费消息
实现主要包括官方 maven 依赖原生实现、SpringAMQP 封装实现。AMQP 协议是一种基于 tcp 的专门用于应用程序间传递业务消息的标准(跨语言)。SpringAMQP 是 AMQP 协议在 Spring 框架中的实现,提供了 SpringBoot 自动装配。
最后需要注意 AMQP 传输的是数据字节,如果要发送 java 对象的话则需要序列化。SpringAMQP 的默认序列化方式是 jdk 序列化,jdk 序列化效率比较低,可以换成 Json 序列化,Json 序列化先将 java 对象转换为字符串,然后把字符串编码发送,接受后先解码成字符串再反序列化成对象即可。
消息本身和队列都可以设置过期时间,达到两者的最小值时消息就会过期。
可以为队列设置死信交换机,这样队列中出现的所有死信不会被丢弃而是转到死信交换机进行重新路由,消息变成死信有三种情况:
我们可以创建一个交换机,绑定一个队列,再为这个队列设置一个死信交换机,再为死信交换机绑定一个死信队列。
如果需要消息在延迟定长时间后被消费,可以通过死信队列来实现,设置队列的消息过期时间,然后再转到死信交换机,路由到死信队列,然后消费者消费死信队列即可。
生产者和消费者的消息确认功能,用来保证可靠性。
当消息经过交换器准备路由给队列的时候,发现没有对应的队列可以投递信息,在 rabbitmq 中会默认丢弃消息,如果我们想要监测一个交换机有哪些消息没有对应的队列,可以为这个交换机绑定一个备用交换机,然后设置消费者接收备用交换机的消息,记录到日志或发送报警信息。
消息幂等性是指对同一条消息的多次执行操作的结果与一次执行的结果相同。在分布式系统中,由于网络的不确定性,可能会导致消息被重复发送或者消息的顺序发生变化。为了确保系统的一致性,消息的处理需要具备幂等性。
保证消息幂等性也就是保证消息不被重复消费,可以通过为每个消息设置**全局唯一 ID **结合 redis **记录已消费消息 id **实现。
Elasticsearch 索引库和 mysql 等关系型数据库的存储模式类似,都是存储数据条目,也存在表、字段、增删改查等概念,但是在底层存储方式上有很大区别。相比而言,mysql 的优势在于擅长事务类型操作,可以确保数据的安全与一致性,而 Elasticsearch 的优势在于擅长海量数据的高效搜索。
Elasticsearch 底层是基于 lucene 来实现的。Lucene 是 Apache 公司采用 Java 语言实现的搜索引擎类库
浏览器搜索、电商搜索、网站内部搜索等都是由 Elasticsearch 完成的。
倒排索引的概念是基于 MySQL 这样的正向索引而言的。在 mysql 数据库中,如果表中某个字段没有建立索引,那么按照字段值查找条目的操作需要扫描整张表,如果字段建立了索引,那么按照字段值查找条目的操作就非常快,但是如果是按照字段值模糊匹配来查找条目的话,仍然是需要全表扫描的。
倒排索引可以解决这个问题。创建倒排索引的过程是对每一个条目的数据利用算法进行分词,然后建立分词到条目的映射。倒排索引建立完成后,每个分词都映射了所有包含这个分词的条目,当查询某句话时,首先对这句话进行分词,然后取所有分词对应条目集合的并集。因此我们可以以 O(1) 的时间复杂度直接获取到所有和这句话有关的条目。
正向索引
倒排索引
Elasticsearch 中的条目是以 Json 格式存储的
MySQL | Elasticsearch | 说明 |
---|---|---|
Table | Index | 索引(index),就是文档的集合,类似数据库的表(table) |
Row | Document | 文档(Document),就是一条条的数据,类似数据库中的行(Row),文档都是 JSON 格式 |
Column | Field | 字段(Field),就是 JSON 文档中的字段,类似数据库中的列(Column) |
Schema | Mapping | Mapping(映射)是索引中文档的约束,例如字段类型约束。类似数据库的表结构(Schema) |
SQL | DSL | DSL 是 elasticsearch 提供的 JSON 风格的请求语句,用来操作 elasticsearch,实现 CRUD |
在企业中,往往是两者结合使用:
Elasticsearch、kibana 用 docker 部署即可,ik 分词器比较好的支持中文,有两种模式:
ik 分词器支持拓展词条和停用词条,分词器分词是依照字典来完成的,那么一些字典中没有的词语(比如最新的网络用语),就需要拓展词条,一些敏感词语则需要停用词条。
mapping 是对索引库中文档的约束,常见的 mapping 属性包括:
ES 官方提供了各种不同语言的客户端,用来操作 ES。这些客户端的本质就是组装 DSL 语句,通过 http 请求发送给 ES。
我们可以用 Java HighLevel Rest Client 客户端 API 来操作 ES,导入相关 maven 依赖后即可使用。RestClient 进行索引库 CRUD 和文档 CRUD 的具体方式可以查询笔记。
查询文档的 DSL 是一个大的 JSON 对象,包含下列属性:
RestClient 查询文档的 api 接口类似于查询文档的 DSL,具体可查笔记。
elasticsearch 默认是根据相关度算分排序,但也可以自己指定排序。
elasticsearch 默认情况下只返回 top10 的数据,修改 from、size 参数可以控制要返回的分页,类似于 mysql 中的 limit。
对于查询结果中所有匹配的关键字进行高亮显示,实现方式是给文档中的所有关键字都添加一个标签,例如<em>
标签。前端可以给<em>
标签编写 CSS 样式来高亮。
elasticsearch 的数据聚合和 mysql 的数据聚合功能类似,但是速度更快。
聚合常见的有三类:
默认情况下,Bucket 聚合是对索引库的所有文档做聚合,但真实情况下往往是对搜索结果进行聚合。
当我们在搜索框中输入一些文字时,会显示一些自动补全文字。
elasticsearch 提供了 Completion Suggester 查询来实现自动补全功能。这个查询会匹配以用户输入内容开头的词条并返回。为了提高补全查询的效率,对于文档中字段的类型有一些约束:
如果希望能根据字母提示中文汉字的话,需要安装拼音分词器,然后自定义分词器,先用 ik 分词器进行分词,对于每个分出来的词语,在用拼音分词器进行分词。
当 mysql 数据库发生增删改时,elasticsearch 也必须跟着进行增删改。
常见的数据同步方案有三种:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。