导学

课程结构

image-20231222182735801
image-20231222183130374
image-20231222183304652

微服务引入

单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部署。

分布式架构:根据业务功能对系统进行拆分,每个业务模块作为独立项目开发,称为一个服务。

分布式架构的要考虑的问题:

•服务拆分粒度如何?

•服务集群地址如何维护?

•服务之间如何实现远程调用?

•服务健康状态如何感知?

解决方案:微服务技术

image-20231222184523717
DubboSpringCloudSpringCloudAlibaba
注册中心zookeeper、RedisEureka、ConsulNacos、Eureka
服务远程调用Dubbo协议Feign(http协议)Dubbo、Feign
配置中心SpringCloudConfigSpringCloudConfig、Nacos
服务网关SpringCloudGateway、ZuulSpringCloudGateway、Zuul
服务监控和保护dubbo-admin,功能弱HystixSentinel
image-20231222185753880

SpringCloud版本问题: image-20231222190057899

服务拆分注意事项

1.单一职责:不同微服务,不要重复开发相同业务

2.数据独立:不要访问其它微服务的数据库

3.面向服务:将自己的业务暴露为接口,供其它微服务调用

如何执行远程调用?

Order order = orderMapper.findById(orderId);
        //2.利用RestTemplate发起HTTP请求,查询用户
        //2.1url
        String  url="http://localhost:8081/user/" + order.getUserId();
        //2.2发送HTTP请求,实现远程调用
        User user = restTemplate.getForObject(url, User.class);
        //3.封装User到order
        order.setUser(user);

提供者与消费者

服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)

服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)

Eureka注册中心

image-20231222194330119

启动类编写:

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class,args);
    }
}

注册E-server

image-20231222195401523
image-20231222202032144

注册E-client

image-20231222202255381

Eureka控制中心不显示实例,错误产生原因:

模拟多实例部署:

image-20231223111139053
img
--server.port=8090

order-service完成服务拉取

image-20231223112435878

负载均衡实现

image-20231223112709668

原理: image-20231223113350053

image-20231223113657994
内置负载均衡规则类规则描述
RoundRobinRule简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。
AvailabilityFilteringRule对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的..ActiveConnectionsLimit属性进行配置。
WeightedResponseTimeRule为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。
BestAvailableRule忽略那些短路的服务器,并选择并发数较低的服务器。
RandomRule随机选择一个可用的服务器。
RetryRule重试机制的选择逻辑

自定义负载均衡策略

image-20231223123149990

前者针对全局,后者针对方法。

Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。

而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

image-20231223123913237

Nacos注册中心

安装后启动:

startup.cmd -m standalone
image-20231223125411056

默认账号密码:nacos

image-20231223131619353
image-20231223131935469

服务集群

Nacos服务分级存储模型

image-20231223132241903

服务调用尽可能选择本地集群的服务,跨集群调用延迟较高

本地集群不可访问时,再去访问其它集群

image-20231223133647939
image-20231223133541687
image-20231223133610851
image-20231223141540980

NacosRule负载均衡策略

①优先选择同集群服务实例列表

②本地集群找不到提供者,才去其它集群寻找,并且会报警告

③确定了可用实例列表后,再采用随机负载均衡挑选实例

根据权重负载均衡

服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求

image-20231223142800527

①Nacos控制台可以设置实例的权重值,0~1之间

②同集群内的多个实例,权重越高被访问的频率越高

③权重设置为0则完全不会被访问

环境隔离 - namespace

image-20231223143148545
image-20231223143158316
image-20231223143205508
image-20231223143211435
image-20231223143239855
image-20231223143614290

此时访问order-service,因为namespace不同,会导致找不到userservice,控制台会报错

image-20231223143717573

nacos注册中心细节分析(与Eureka不同之处)

服务提供者的健康检测

临时实例: image-20231223160755900

image-20231223160818176

1.Nacos与eureka的共同点

①都支持服务注册和服务拉取

②都支持服务提供者心跳方式做健康检测

2.Nacos与Eureka的区别

①Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式

②临时实例心跳不正常会被剔除,非临时实例则不会被剔除

③Nacos支持服务列表变更的消息推送模式,服务列表更新更及时

④Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式

Nacos配置管理

统一配置管理

image-20231223161925255
image-20231223163132667

其中,配置内容项只用填写需要热更新(有热更新需求)的配置。

image-20231223163644336

1.引入Nacos的配置管理客户端依赖:

image-20231223164201840

2.添加bootstrap.yml,引导文件,读取优先级高于application.yml

image-20231223164132303

测试案例: image-20231223165100541

配置自动刷新

方式一:通过@Value注解注入,结合@RefreshScope来刷新

image-20231223200548214

方式二:通过@ConfigurationProperties注入,自动刷新(推荐)

image-20231223165559194

实现热更新: image-20231223165919539

多环境配置共享

微服务启动时会从nacos读取多个配置文件:

[spring.application.name]-[spring.profiles.active].yaml,例如:userservice-dev.yaml

[spring.application.name].yaml,例如:userservice.yaml

无论profile如何变化,[spring.application.name].yaml这个文件一定会加载,因此多环境共享配置可以写入这个文件

优先级: image-20231223201438613

Nacos集群搭建

image-20231223201606496

集群搭建步骤:

①搭建MySQL集群并初始化数据库表

②下载解压nacos

③修改集群配置(节点信息)、数据库配置

④分别启动多个nacos节点(不用-m配置)

⑤nginx反向代理

搭建成功: image-20231223202527341

注意:需要注释掉热更新配置

image-20231223205823901

(不对劲就重启下浏览器?)

http客户端Feign

restTemplate存在问题

•代码可读性差,编程体验不统一

•参数复杂URL难以维护

Feign

Feign是一个声明式的http客户端

1.引入依赖:

image-20231223221229901

2.在order-service的启动类添加注解开启Feign的功能:

image-20231223221242060

3.编写Feign客户端(注意包放在启动类同级下):

image-20231223221312756

基于SpringMVC的注解来声明远程调用的信息

4.用Feign客户端代替RestTemplate

image-20231223221333193

自定义Feign的配置

类型作用说明
feign.Logger.Level修改日志级别包含四种不同的级别:NONE、BASIC、HEADERS、FULL
feign.codec.Decoder响应结果的解析器http远程调用的结果做解析,例如解析json字符串为java对象
feign.codec.Encoder请求参数编码将请求参数编码,便于通过http请求发送
feign. Contract支持的注解格式默认是SpringMVC的注解
feign. Retryer失败重试机制请求失败的重试机制,默认是没有,不过会使用Ribbon的重试

方式一:配置文件方式

image-20231224115741451

方式二:java代码方式,需要先声明一个Bean:

image-20231224115859529

①而后如果是全局配置,则把它放到@EnableFeignClients这个注解中:

image-20231224115912595

②如果是局部配置,则把它放到@FeignClient这个注解中:

image-20231224115925792

Feign的性能优化

Feign底层的客户端实现:

•URLConnection:默认实现,不支持连接池

•Apache HttpClient :支持连接池

•OKHttp:支持连接池

因此优化Feign的性能主要包括:

①使用连接池代替默认的URLConnection

日志级别,最好用basic或none

Feign添加HttpClient的支持:

引入依赖:

image-20231224120418023配置连接池:

image-20231224120427027

Feign的最佳实践

方式一(继承):给消费者的FeignClient和提供者的controller定义统一的父接口作为标准。

服务紧耦合

父接口参数列表中的映射不会被继承

image-20231224121451708

方式二(抽取):将FeignClient抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用

image-20231224121508709

实现最佳实践方式二的步骤如下:

1.首先创建一个module,命名为feign-api,然后引入feign的starter依赖

2.将order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中

3.在order-service中引入feign-api的依赖

4.修改order-service中的所有与上述三个组件有关的import部分,改成导入feign-api中的包

5.重启测试

当定义的FeignClient不在SpringBootApplication的扫描包范围时,这些FeignClient无法使用。有两种方式解决:

方式一:指定FeignClient所在包

image-20231224122632318

方式二:指定FeignClient字节码

image-20231224122650472

统一网关Gateway

网关功能:

身份认证和权限校验

服务路由、负载均衡

请求限流

Zuul是基于Servlet的实现,属于阻塞式编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux,属于响应式编程的实现,具备更好的性能。

创建新的module,引入SpringCloudGateway的依赖和nacos的服务发现依赖:

image-20231224141542718

编写路由配置及nacos地址

image-20231224141559351

断言:规则判断布尔表达式

uri: lb://orderservice

路由断言工厂Route Predicate Factory

断言规则交给此工厂处理

名称说明示例
After是某个时间点后的请求- After=2037-01-20T17:42:47.789-07:00[America/Denver]
Before是某个时间点之前的请求- Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]
Between是某两个时间点之前的请求- Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]
Cookie请求必须包含某些cookie- Cookie=chocolate, ch.p
Header请求必须包含某些header- Header=X-Request-Id, \d+
Host请求必须是访问某个host(域名)- Host=.somehost.org,.anotherhost.org
Method请求方式必须是指定方式- Method=GET,POST
Path请求路径必须符合指定规则- Path=/red/{segment},/blue/**
Query请求参数必须包含指定参数- Query=name, Jack或者- Query=name
RemoteAddr请求者的ip必须是指定范围- RemoteAddr=192.168.1.1/24
Weight权重处理

(了解,用到即查)

路由过滤器 GatewayFilter

image-20231224142651020

例子

image-20231224142932709

默认过滤器

default-filters: # 默认过滤器,会对所有的路由请求都生效
    - AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头

自定义过滤器

全局过滤器 GlobalFilter

image-20231224143435055
image-20231224143920484

1.实现GlobalFilter接口,做好用户友好的返回HTTP状态码设置

2.添加@Order注解(数字越小过滤器优先级越高)或实现Ordered接口

过滤器执行顺序

每一个过滤器都必须指定一个int类型的order值,order****值越小,优先级越高,执行顺序越靠前。

GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定

路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增。

当过滤器的order值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行。

跨域问题处理

跨域:域名不一致就是跨域,主要包括:

域名不同: www.taobao.comwww.taobao.orgwww.jd.com 和 miaosha.jd.com

域名相同,端口不同:localhost:8080和localhost:8081

跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题

解决方案:CORS

image-20231224152305308

Docker

问题产生:

大型项目组件较多,运行环境也较为复杂,部署时会碰到一些问题:

•依赖关系复杂,容易出现兼容性问题

•开发、测试、生产环境有差异

Docker如何解决依赖的兼容问题的?

•将应用的Libs(函数库)、Deps(依赖)、配置与应用一起打包

•将每个应用放到一个隔离容器去运行,避免互相干扰

Docker如何解决开发、测试、生产环境有差异的问题

•Docker镜像中包含完整运行环境,包括系统函数库,仅依赖系统的Linux内核,因此可以在任意Linux操作系统上运行

image-20231225094733030

Docker与虚拟机

image-20231225095433566

Docker架构

镜像(Image):Docker将应用程序及其所需的依赖、函数库、环境、配置等文件打包在一起,称为镜像。

容器(Container:镜像中的应用程序运行后形成的进程就是容器,只是Docker会给容器做隔离,对外不可见。容器内data为镜像中data的复制,不会对镜像造成污染。

Docker是一个CS架构的程序,由两部分组成:

服务端(server):Docker守护进程,负责处理Docker指令,管理镜像、容器等

客户端(client):通过命令或RestAPI向Docker服务端发送指令。可以在本地或远程向服务端发送指令

image-20231225100253765

CENTOS7联网:

CentOs 7怎么联网_centos连网-CSDN博客

Docker基本操作

启动Docker

systemctl start docker

镜像相关命令

镜像名称一般分两部分组成:[repository]:[tag]。 在没有指定tag时,默认是latest,代表最新版本的镜像

镜像操作命令

image-20231225111101247
docker XXX --help
image-20231225111815482

容器相关命令

image-20231225124201714

创建运行一个Nginx容器

去docker hub查看Nginx的容器运行命令

image-20231225124241364

命令解读:

docker run :创建并运行一个容器

--name : 给容器起一个名字,比如叫做mn

-p :将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口

-d:后台运行容器

nginx:镜像名称,例如nginx

注意:切换到ROOT用户才能启动

image-20231225125046034

进入容器

(进入失败请更新Linux内核:yum update -y

image-20231225131030309

命令解读:

docker exec :进入容器内部,执行一个命令

-it : 给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互

mn :要进入的容器的名称

bash:进入容器后执行的命令,bash是一个linux终端交互命令

修改index.html的内容

image-20231225131312355

退出容器

exit

删除容器

•docker rm

•不能删除运行中的容器,除非添加 -f 参数

数据卷

一个虚拟目录,指向宿主机文件系统中的某个目录。

将容器与数据分离,解耦合,方便操作容器内数据,保证数据安全

数据卷操作:

•docker volume create

•docker volume ls

•docker volume inspect

•docker volume rm

•docker volume prune

挂载数据卷

image-20231225144156669

挂载成功

image-20231225150233935

•如果容器运行时volume不存在,会自动被创建出来

将宿主机目录直接挂载到容器

•-v [宿主机目录]:[容器内目录]

•-v [宿主机文件]:[容器内文件]

docker run \
    --name musql \
    -e MYSQL_ROOT_PASSWORD=123 \
    -p 3306:3306 \
    -v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf \
    -v /tmp/mysql/data:/var/lib/mtsql \
    -d \
    mysql:5.7.25 \
image-20231225162724095

链接成功

image-20231225165013911

数据卷挂载的方式对比

image-20231225165150061

1.docker run的命令中通过 -v 参数挂载文件或目录到容器中:

①-v volume名称:容器内目录

②-v 宿主机文件:容器内文件

③-v 宿主机目录:容器内目录

2.数据卷挂载与目录直接挂载的

①数据卷挂载耦合度低,由docker来管理目录,但是目录较深,不好找

②目录挂载耦合度高,需要我们自己管理目录,不过目录容易寻找查看

Dockerfile自定义镜像

镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。

image-20231225185050132

Dockerfile

包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。每一个指令都会形成一层Layer。

指令说明示例
FROM指定基础镜像FROM centos:6
ENV设置环境变量,可在后面指令使用ENV key value
COPY拷贝本地文件到镜像的指定目录COPY ./mysql-5.7.rpm /tmp
RUN执行Linux的shell命令,一般是安装过程的命令RUN yum install gcc
EXPOSE指定容器运行时监听的端口,是给镜像使用者看的EXPOSE 8080
ENTRYPOINT镜像中应用的启动命令,容器运行时调用ENTRYPOINT java -jar xx.jar
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录
ENV JAVA_DIR=/usr/local

# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar

# 安装JDK
RUN cd $JAVA_DIR \
 && tar -xf ./jdk8.tar.gz \
 && mv ./jdk1.8.0_144 ./java8

# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin

# 暴露端口
EXPOSE 8090
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar
image-20231225190239536
image-20231225190542850

注意:一定要在对应目录下执行build,否则找不到文件

java:8-alpine镜像

部署通用环境,减少重复环境部署。

DockerCompose

Docker Compose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器!

Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。

image-20231226101405071

配置DockerCompose

打包名称

image-20231226102241882

Docker镜像仓库

镜像仓库( Docker Registry )有公共的和私有的两种形式:

公共仓库:例如Docker官方的 Docker Hub,国内也有一些云服务商提供类似于 Docker Hub 的公开服务,比如 网易云镜像服务DaoCloud 镜像服务阿里云镜像服务等。

除了使用公开仓库外,用户还可以在本地搭建私有 Docker Registry。企业自己的镜像最好是采用私有Docker Registry来实现。

image-20231226111646675

在私有镜像仓库推送或拉取镜像

image-20231226104029783

服务异步通讯

简介

image-20231226143509756

异步调用方案

事件驱动模式

image-20231226143827221

异步通信的优点:

耦合度低

吞吐量提升

故障隔离

流量削峰

image-20231226144605819

异步通信的缺点:

依赖于Broker的可靠性、安全性、吞吐能力

架构复杂了,业务没有明显的流程线,不好追踪管理

RabbitMQ

MQ (MessageQueue),中文是消息队列,字面来看就是存放消息的队列。也就是事件驱动架构中的Broker。

image-20231226145250885

RabbitMQ是基于Erlang语言开发的开源消息通信中间件,官网地址:https://www.rabbitmq.com/

image-20231226153224312

Linux扩容: VMware 虚拟机根目录磁盘空间补足——给 /dev/sda3扩容 - 掘金 (juejin.cn)

VMware 虚拟机根目录磁盘空间补足——给 /dev/sda3扩容 - 掘金 (juejin.cn)

image-20231226153720378

•channel:操作MQ的工具

•exchange:路由消息到队列中

•queue:缓存消息

•virtual host:虚拟主机,是对queue、exchange等资源的逻辑分组

常见消息模型

image-20231226154725220

基本消息队列的消息发送流程:

1.建立connection

2.创建channel

3.利用channel声明队列

4.利用channel向队列发送消息

基本消息队列的消息接收流程:

1.建立connection

2.创建channel(避免队列不存在)

3.利用channel声明队列

4.定义consumer的消费行为handleDelivery()

5.利用channel将消费者与队列绑定

SpringAMQP

Advanced Message Queuing Protocol,是用于在应用程序之间传递业务消息的开放标准。该协议与语言和平台无关,更符合微服务中独立性的要求。

Features

  • Listener container for asynchronous processing of inbound messages
  • RabbitTemplate for sending and receiving messages
  • RabbitAdmin for automatically declaring queues, exchanges and bindings

案例:在publisher中编写测试方法,向simple.queue发送消息

image-20231226164000941
image-20231226164142703

SpringAMQP如何发送消息?

•引入amqp的starter依赖

•配置RabbitMQ地址

•利用RabbitTemplate的convertAndSend方法

SpringAMQP如何接收消息?

•引入amqp的starter依赖

•配置RabbitMQ地址

•定义类,添加@Component注解

•类中声明方法,添加@RabbitListener注解,方法参数就时消息

注意:消息一旦消费就会从队列删除,RabbitMQ没有消息回溯功能

Work Queue 工作队列

image-20231226183030658

消费预取(造成花费时间超过预期)限制

image-20231226184357744

发布( Publish )、订阅( Subscribe

发布订阅模式与之前案例的区别就是允许将同一消息发送给多个消费者。实现方式是加入了exchange(交换机)。

常见exchange类型包括:

Fanout:广播

Direct:路由

Topic:话题

注意:exchange负责消息路由,而不是存储,路由失败则消息丢失

image-20231226185331587
Fanout Exchange

Fanout Exchange 会将接收到的消息广播到每一个跟其绑定的queue

image-20231226185454228
image-20231226185944346
DirectExchange

Direct Exchange 会将接收到的消息根据规则路由到指定的Queue,因此称为路由模式(routes)。

image-20231227105012545

多、同key*(模拟Fanout)*

1.利用@RabbitListener声明Exchange、Queue、RoutingKey

image-20231227105545108

2.在consumer服务中,编写两个消费者方法,分别监听direct.queue1和direct.queue2

3.在publisher中编写测试方法,向itcast. direct发送消息

TopicExchange

TopicExchange与DirectExchange类似,区别在于routingKey必须是多个单词的列表,并且以 . 分割。

Queue与Exchange指定BindingKey时可以使用通配符:

#:代指0个或多个单词

*:代指一个单词

image-20231227110418907

消息转换器

Spring的对消息对象的处理是由org.springframework.amqp.support.converter.MessageConverter来处理的。而默认实现是SimpleMessageConverter,基于JDK的ObjectOutputStream完成序列化。

如果要修改只需要定义一个MessageConverter 类型的Bean即可。推荐用JSON方式序列化,步骤如下:

•在publisher服务引入依赖

image-20231227111801311

•在publisher服务声明MessageConverter:

image-20231227111804232

•注意发送方与接收方必须使用相同的MessageConverter

分布式搜索引擎(elasticsearch基础)

elasticsearch是一款非常强大的开源搜索引擎,可以帮助我们从海量数据中快速找到需要的内容

elasticsearch结合kibana、Logstash、Beats,也就是elastic stack(ELK)。被广泛应用在日志数据分析、实时监控等领域。

image-20231227120350374

初识elasticsearch

正向索引和倒排索引

Mysql采用的就是正向索引

image-20231227122531593

elasticsearch采用倒排索引:

•文档(document):每条数据就是一个文档

•词条(term):文档按照语义分成的词语

elasticsearch是面向文档存储的,可以是数据库中的一条商品数据,一个订单信息。

文档数据会被序列化为json格式后存储在elasticsearch中。

•索引(index):相同类型的文档的集合

•映射(mapping):索引中文档的字段约束信息,类似表的结构约束

image-20231227130055496

DSL是elasticsearch提供的JSON风格的请求语句,用来操作elasticsearch,实现CRUD

image-20231227130418242

安装

image-20231227145445707

分词器

ik分词器包含两种模式:

•ik_smart:最少切分,粗粒度

•ik_max_word:最细切分,细粒度

拓展词库

image-20231227204324248

索引库操作

mapping属性

mapping是对索引库中文档的约束,常见的mapping属性包括:

•type:字段数据类型,常见的简单类型有:

•字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址)

•数值:long、integer、short、byte、double、float、

•布尔:boolean

•日期:date

•对象:object

•index:是否创建索引,默认为true

•analyzer:使用哪种分词器

•properties:该字段的子字段

创建索引库

image-20231227205516078

查看、删除索引库

image-20231227205648378
image-20231227205658202

修改索引库

索引库和mapping一旦创建无法修改,但是可以添加新的字段,语法如下:

image-20231227205721139

文档操作

添加文档

image-20231227210006195

查看、删除文档

image-20231227210022997

修改

方式一:全量修改,会删除旧文档,添加新文档

image-20231227210118157

方式二:增量修改,修改指定字段值

image-20231227210132136

RestClient操作索引库

ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES。

聚合搜索

image-20231228095155168

初始化JavaRestClient

因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本:

image-20231228095338715

初始化RestHighLevelClient:

image-20231228095535159

创建索引库: image-20231228095753491

利用JavaRestClient批量导入数据到ES

image-20231228102638944

DSL查询文档

Elasticsearch提供了基于JSON的DSL(Domain Specific Language)来定义查询。常见的查询类型包括:

image-20231228104150289
image-20231228103805252

全文检索查询

match查询:全文检索查询的一种,会对用户输入内容分词,然后去倒排索引库检索,语法:

image-20231228105747376

multi_match:与match查询类似,只不过允许同时查询多个字段,语法:

image-20231228105755120

参与查询字段越多,查询性能越差

精确查询

不会对搜索条件分词

term查询:

image-20231228110023217

range查询:

image-20231228110037141

地理查询

geo_bounding_box:查询geo_point值落在某个矩形范围的所有文档

image-20231228110103408

geo_distance:查询到指定中心点小于某个距离值的所有文档

image-20231228110118591
image-20231228110334899

复合查询

•fuction score:算分函数查询,可以控制文档相关性算分,控制文档排名。例如百度竞价

算法演变

image-20231228143510432
Function Score Query
image-20231228144432518

Boolean Query

布尔查询是一个或多个查询子句的组合。子查询的组合方式有:

•must:必须匹配每个子查询,类似“与”

•should:选择性匹配子查询,类似“或”

•must_not:必须不匹配,不参与算分,类似“非”

•filter:必须匹配,不参与算分

image-20231228145132583

搜索结果处理

排序

elasticsearch支持对搜索结果排序,默认是根据相关度算分(_score)来排序。可以排序字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等。

自定义规则后,score字段为空。

分页

image-20231228150618182

ES是分布式的,所以会面临深度分页问题。例如按price排序后,获取from = 990,size =10的数据:

1.首先在每个数据分片上都排序并查询前1000条文档。

2.然后将所有节点的结果聚合,在内存中重新排序选出前1000条文档

3.最后从这1000条中,选取从990开始的10条文档

ES设定结果集查询的上限是10000

高亮

image-20231228151449881

数据聚合

聚合(aggregations可以实现对文档数据的统计、分析、运算。聚合常见的有三类:

桶(Bucket)聚合:用来对文档做分组

•TermAggregation:按照文档字段值分组

image-20231229115316250

可以限定要聚合的文档范围,只要添加query条件即可: image-20231229115450568

•Date Histogram:按照日期阶梯分组,例如一周为一组,或者一月为一组

度量(Metric)聚合:用以计算一些值,比如:最大值、最小值、平均值等

•Avg:求平均值

•Max:求最大值

•Min:求最小值

Stats:同时求max、min、avg、sum等

image-20231229125658382

管道(pipeline)聚合:其它聚合的结果为基础做聚合

RestAPI实现聚合

image-20231229130023331
image-20231229130043281

自动补全

自定义分词器

elasticsearch中分词器(analyzer)的组成包含三部分:

character filters:在tokenizer之前对文本进行处理。例如删除字符、替换字符

tokenizer:将文本按照一定的规则切割成词条(term)。例如keyword,就是不分词;还有ik_smart

tokenizer filter:将tokenizer输出的词条做进一步处理。例如大小写转换、同义词处理、拼音处理等

image-20231229164130265
image-20231229164511842

问题: image-20231229164853845

因此字段在创建倒排索引时应该用my_analyzer分词器;字段在搜索时应该使用ik_smart分词器;

completion suggester查询

对于文档中字段的类型有一些约束:

•参与补全查询的字段必须是completion类型。

•字段的内容一般是用来补全的多个词条形成的数组。

image-20231229165605302

数据同步

elasticsearch与mysql之间的数据同步

image-20231230113220026
image-20231230113234813
image-20231230113250750

elasticsearch集群

单机的elasticsearch做数据存储,必然面临两个问题:海量数据存储问题、单点故障问题。

•海量数据存储问题:将索引库从逻辑上拆分为N个分片(shard),存储到多个节点

•单点故障问题:将分片数据在不同节点备份(replica)

ES集群的节点角色

节点类型配置参数默认值节点职责
master eligiblenode.mastertrue备选主节点:主节点可以管理和记录集群状态、决定分片在哪个节点、处理创建和删除索引库的请求
datanode.datatrue数据节点:存储数据、搜索、聚合、CRUD
ingestnode.ingesttrue数据存储之前的预处理
coordinating上面3个参数都为false则为coordinating节点路由请求到其它节点 合并其它节点处理的结果,返回给用户

ES集群的脑裂

image-20231230123332886

为了避免脑裂,需要要求选票超过**(eligible节点数量+1)/2**才能当选为主,因此eligible节点数量最好是奇数。

ES集群的分布式存储

elasticsearch会通过hash算法来计算文档应该存储到哪个分片:

image-20231230125230514

•_routing默认是文档的id

•算法与分片数量有关,因此索引库一旦创建,分片数量不能修改!

image-20231230125430397

ES集群的分布式查询

elasticsearch的查询分成两个阶段:

•scatter phase:分散阶段,coordinating node会把请求分发到每一个分片

•gather phase:聚集阶段,coordinating node汇总data node的搜索结果,并处理为最终结果集返回给用户

ES集群的故障转移

集群的master节点会监控集群中的节点状态,如果发现有节点宕机,会立即将宕机节点的分片数据迁移到其它节点,确保数据安全,这个叫做故障转移。

微服务保护

Sentinel入门

雪崩问题

微服务调用链路中的某个服务故障,引起整个链路中的所有微服务都不可用,这就是雪崩

image-20240213203841975

解决雪崩问题的常见方式有四种:

•超时处理:设定超时时间,请求超过一定时间没有响应就返回错误信息,不会无休止等待

•舱壁模式:限定每个业务能使用的线程数,避免耗尽整个tomcat的资源,因此也叫线程隔离。

image-20240213204102122

•熔断降级:由断路器统计业务执行的异常比例,如果超出阈值则会熔断该业务,拦截访问该业务的一切请求。

image-20240213204328627

•流量控制:限制业务访问的QPS(Query per Second),避免服务因流量的突增而故障。

image-20240213204516919

对比:

SentinelHystrix
隔离策略信号量隔离线程池隔离/信号量隔离
熔断降级策略基于慢调用比例或异常比例基于失败比率
限流基于 QPS,支持基于调用关系的限流有限的支持
流量整形支持慢启动、匀速排队模式不支持
控制台开箱即用,可配置规则、查看秒级监控、机器发现等不完善

Sentinel安装

配置项默认值说明
server.port8080服务端口
sentinel.dashboard.auth.usernamesentinel默认用户名
sentinel.dashboard.auth.passwordsentinel默认密码

限流规则

簇点链路

就是项目内的调用链路,链路中被监控的每个接口就是一个资源。默认情况下sentinel会监控SpringMVC的每一个端点(Endpoint),因此SpringMVC的每一个端点(Endpoint)就是调用链路中的一个资源。(Controller中的方法)

流控模式

在添加限流规则时,点击高级选项,可以选择三种流控模式:

•直接:统计当前资源的请求,触发阈值时对当前资源直接限流,也是默认的模式

•关联:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流

满足下面条件可以使用关联模式:

两个有竞争关系的资源

一个优先级较高,一个优先级较低

•链路:统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流

image-20240214214658373

Sentinel默认只标记Controller中的方法为资源,如果要标记其它方法,需要利用@SentinelResource注解,示例:

image-20240214214818943

流控效果

流控效果是指请求达到流控阈值时应该采取的措施,包括三种:

•快速失败:达到阈值后,新的请求会被立即拒绝并抛出FlowException异常。是默认的处理方式。

•warm up:预热模式,对超出阈值的请求同样是拒绝并抛出异常。但这种模式阈值会动态变化,从一个较小值逐渐增加到最大阈值。

•排队等待:让所有的请求按照先后次序排队执行,两个请求的间隔不能小于指定时长

此作者没有提供个人介绍
最后更新于 2024-08-14