文章目录
认识微服务
-
单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部署。
- 优点:
- 架构简单
- 部署成本低
- 缺点:
- 耦合度高(维护困难、升级困难)
- 优点:
-
分布式架构:
- 优点:
- 降低服务耦合
- 有利于服务升级和拓展
- 缺点:
- 服务调用关系错综复杂
- 优点:
-
分布式架构虽然降低了服务耦合,但是服务拆分时也有很多问题需要思考:
- 服务拆分的粒度如何界定?
- 服务之间如何调用?
- 服务的调用关系如何管理?
-
微服务的架构特征
- 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责
- 自治:团队独立、技术独立、数据独立,独立部署和交付
- 面向服务:服务提供统一标准的接口,与语言和技术无关
- 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题
- 优点:拆分粒度更小、服务更独立、耦合度更低
- 缺点:架构非常复杂,运维、监控、部署难度提高
-
服务拆分原则
- 不同微服务,不要重复开发相同业务
- 微服务数据独立,不要访问其它微服务的数据库
- 微服务可以将自己的业务暴露为接口,供其它微服务调用
-
提供者与消费者
-
在服务调用关系中,会有两个不同的角色:
服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)
服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)
-
但是,服务提供者与服务消费者的角色并不是绝对的,而是相对于业务而言。如果服务A调用了服务B,而服务B又调用了服务C,服务B的角色是什么?
- 对于A调用B的业务而言:A是服务消费者,B是服务提供者,对于B调用C的业务而言:B是服务消费者,C是服务提供者
因此,服务B既可以是服务提供者,也可以是服务消费者。
-
Eureka
- Eureka的作用和zookeeper是一样的,都是注册中心。这些问题都需要利用SpringCloud中的注册中心来解决,其中最广为人知的注册中心就是Eureka
Nacos
服务注册到Nacos
- 引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
- 配置Nacos地址
spring:
cloud:
nacos:
server-addr: localhost:8848
服务分级存储模型
一个服务可以有多个实例,例如我们的user-service,可以有:
- 127.0.0.1:8081
- 127.0.0.1:8082
- 127.0.0.1:8083
假如这些实例分布于全国各地的不同机房,例如:
- 127.0.0.1:8081,在上海机房
- 127.0.0.1:8082,在上海机房
- 127.0.0.1:8083,在杭州机房
Nacos就将同一机房内的实例 划分为一个集群。
也就是说,user-service是服务,一个服务可以包含多个集群,如杭州、上海,每个集群下可以有多个实例,形成分级模型
微服务互相访问时,应该尽可能访问同集群实例,因为本地访问速度更快。当本集群内不可用时,才访问其它集群。
- 配置集群
修改application.yml文件,添加集群配置:
spring:
cloud:
nacos:
server-addr: localhost:8848
discovery:
cluster-name: HZ # 集群名称
再次复制一个user-service启动配置,添加属性:
-Dserver.port=8083
-Dspring.cloud.nacos.discovery.cluster-name=SH #不添加这个也行,在启动前两个时,配置文件写HZ,然后配置文件改成SH,在启动第三个也一样
同集群优先的负载均衡
默认的ZoneAvoidanceRule
并不能实现根据同集群优先来实现负载均衡。
因此Nacos中提供了一个NacosRule
的实现,可以优先从同集群中挑选实例。
- 给order-service配置集群信息
修改application.yml文件,添加集群配置:
spring:
cloud:
nacos:
server-addr: localhost:8848
discovery:
cluster-name: HZ # 集群名称
- 修改负载均衡规则
修改application.yml文件,修改负载均衡规则:
该规则是优先在本集群内随机选择
userservice:
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
权重配置
实际部署中会出现这样的场景:
服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求。
但默认情况下NacosRule是同集群内随机挑选,不会考虑机器的性能问题。
因此,Nacos提供了权重配置来控制访问频率,权重越大则访问频率越高。
在Nacos控制台,找到user-service的实例列表,点击编辑,即可修改权重
环境隔离
Nacos提供了namespace来实现环境隔离功能。
- Nacos中可以有多个namespace
- namespace下可以有group、service等
- 不同namespace之间相互隔离,例如不同namespace的服务互相不可见
给微服务配置namespace只能通过修改配置来实现。
例如,修改application.yml文件:
spring:
cloud:
nacos:
server-addr: localhost:8848
discovery:
cluster-name: HZ
namespace: 492a7d5d-237b-46a1-a99a-fa8e98e4b0f9 # 命名空间,填ID
Feign
基于Feign远程调用
利用RestTemplate发起远程调用代码可读性差、编程体验不统一、参数复杂URL难以维护
Feign是一个声明式的http客户端,可以帮助我们优雅的实现http请求的发送
- 使用步骤:
-
引入依赖
-
添加注解开启Feign功能:@EnableFeignClients
-
编写Feign客户端
-
使用FeignClient中定义的方法代替RestTemplate
-
Feign自定义配置
Feign运行自定义配置来覆盖默认配置:
- 配置Feign日志
-
全局生效
-
局部生效
-
Feign性能优化
- 主要两方面:
-
使用HttpClient代替默认的URLConnection
-
引入依赖
-
配置连接池
-
-
日志级别,最好用basic和none
-
两种最佳实践
- 让controller和FeignClient继承统一接口
- 将FeignClient、POJO、Feign的默认配置都定义到一个项目中,供所有消费者使用
- 创建一个模块,命名为feign-api,然后引入feign的starter依赖
- 将service中编写的UserClient,User,DefaultFeignConfiguration复制到feign-api中
- 在order-service中引入feign-api依赖
- 修改import
Gateway网关
网关的功能
- 身份认证和权限校验
- 服务路由、负载均衡
- 请求限流
搭建网关的基本步骤
-
创建新的模块,引入SpringCloudGateway依赖和nacos的服务发现依赖
-
编写路由配置及nacos地址
路由断言工厂 Route Predicate Factory
-
PredicateFactory的作用:读取用户的断言条件,对请求做出判断
-
11种基本的predicate工厂
路由过滤器 GatewayFilter
- 对进入网关的请求和微服务返回的响应做加工处理,比如添加请求头
全局过滤器 GlobalFilter
- 与GatewayFilter的区别在于:GateFwayFilter通过配置定义,处理逻辑是固定的,GlobalFilter的逻辑需要手写代码实现。定义方式是实现GlobalFilter接口
@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> params = request.getQueryParams();
String auth = params.getFirst("authorization");
if ("admin".equals(auth)) {
return chain.filter(exchange);
}
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
}
过滤器执行顺序
跨域问题处理
- 跨域:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题
- 域名不同
- 域名相同,端口不同
CORS方案:
MQ
同步通讯好比在打电话,单线操作,时效性强
异步通讯好比在微信发消息,多线操作,时效性差
-
同步调用
- 优点:时效性高
- 缺点:
- 耦合度高
- 性能下降
- 资源浪费
- 级联失败:服务提供者出现问题,所有调用方都会出问题,导致整个微服务群故障
-
异步调用
- 优点:
- 耦合度低
- 吞吐量提升
- 故障隔离
- 流量削峰
- 缺点:
- 依赖于Broker的可靠性、安全性、吞吐能力
- 架构复杂,业务没有明显的流程线,不好追踪管理
- 优点:
-
MQ:MessageQueue,消息队列,也就是事件驱动架构的Broker
常见MQ:
elasticsearch
简介
-
elasticsearch是一款非常强大的开源搜索引擎,可以帮助我们从海量数据中快速找到需要的内容
-
elasticsearch结合Kibana、Logstash、Beats(elastic stack ELK),被广泛运用在日志数据分析、实时监控等领域。elasticsearch是elastic stack的核心,负责存储、搜索、分析数据
-
Lucene:一个java语言的搜索引擎类库,提供了搜索引擎的核心API
- 优势:
- 易扩展
- 高性能(基于倒排索引)
- 缺点:
- 只限于java语言开发
- 学习曲线陡峭
- 不支持水平扩展
- 优势:
-
相比于lucene,elasticsearch具备以下优势
- 支持分布式,可水平扩展
- 提供Restful接口,可被任何语言调用
正向索引和倒排索引
- 正向索引:基于文档id创建索引,查询词条时必须先找到文档,而后判断是否包含词条
- 倒排索引:对文档内容分词,对词条创建索引,并记录词条所在文档的信息。查询时先根据词条查询到文档id,而后获取到文档
ES与MySql概念的对比
- MySql擅长事务类型操作,可以确保数据的安全和一致性
- Elasticsearch擅长海量数据的搜索、分析、计算
操作
- mapping属性
-
操作索引库
-
文档操作