Java微服务

image-20240314203146347

微服务01

微服务:一种软件架构风格,他是专注于单一职责的很多小型项目为基础,组合出复杂的大型项目

单体架构

将业务的所有功能都集中在一个项目中开发,打包成一个包部署

优点:

架构简单;部署成本低

缺点:

团队协作成本高;系统的发布效率低;系统可用性差

微服务

微服务架构,是服务化思想指导下的一套最佳实践架构方案。

服务化,**==就是把单体架构中的功能模块拆分为多个独立项目。==**

  • 粒度小

  • 团队自治

  • 服务自治:分别编译打包;分别部署;数据隔离

    image-20240314205902699

SpringCloud

SpringCloud是目前国内使用最广泛的微服务框架。官网地址:https://spring.io/projects/spring-cloud。

SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验:

image-20240314211045953

SpringCloud****版本 SpringBoot****版本
2022.0.x aka Kilburn 3.0.x
2021.0.x aka Jubilee 2.6.x, 2.7.x (Starting with 2021.0.3)
2020.0.x aka Ilford 2.4.x, 2.5.x (Starting with 2020.0.3)
Hoxton 2.2.x, 2.3.x (Starting with SR5)
Greenwich 2.1.x
Finchley 2.0.x
Edgware 1.5.x
Dalston 1.5.x

微服务拆分

image-20240314211735588

image-20240314211911736

服务拆分原则

什么时候拆分

创业型项目:先采用单体架构,快速开发,快速试错。随着规模扩大,逐渐拆分。

确定的大型项目:资金充足,目标明确,可以直接选择微服务架构,避免后续拆分的麻烦。

怎么拆分

从拆分目标来说,要做到:

  • 高内聚:每个微服务的职责要尽量单一,包含的业务相互关联度高、完整度高。
  • 低耦合:每个微服务的功能要相对独立,尽量减少对其它微服务的依赖。

从拆分方式来说,一般包含两种方式:

  • 纵向拆分:按照业务模块来拆分
  • 横向拆分:抽取公共服务,提高复用性

拆分服务

独立project

Maven聚合

image-20240314214402573

dto :表单交互

远程调用

Spring给我们提供了一个RestTemplate工具,可以方便的实现Http请求的发送。使用步骤如下:

①注入RestTemplate到Spring容器

image-20240315141015868

②发起远程调用

image-20240315141033725

requestArgsConstructor注解 ,对于所有的final的字段创建构造函数

服务治理

服务远程调用时存在的问题

image-20240315151455307

在远程调用的时候,不知道调哪个服务器,如果那个服务器挂了也不知道怎么换

注册中心原理

所有的服务提供者都会在注册中心注册,然后当服务调用者要调用的时候,就会把注册的信息传输过去;

为了实现负载均衡,可能使用了轮询等

image-20240315152502417

image-20240315152553563

心跳续约

所有的服务都会定期和注册中心请求一下,说明自己还活着

总结

服务治理中的三个角色分别是什么?

​ ==服务提供者:暴露服务接口,供其它服务调用==

​ ==服务消费者:调用其它服务提供的接口==

​ ==注册中心:记录并监控微服务各实例状态,推送服务变更信息==

消费者如何知道提供者的地址?

​ 服务提供者会在启动时注册自己信息到注册中心,消费者可以从注册中心订阅和拉取服务信息

消费者如何得知服务状态变更?

​ 服务提供者通过心跳机制向注册中心报告自己的健康状态,当心跳异常时注册中心会将异常服务剔除,并通知订阅了该服务的消费者

当提供者有多个实例时,消费者该选择哪一个?

​ ==消费者可以通过负载均衡算法,从多个实例中选择一个==

Nacos注册中心

Nacos是目前国内企业中占比最多的注册中心组件。它是阿里巴巴的产品,目前已经加入SpringCloudAlibaba中。

image-20240315154400243

image-20240315155652332

服务注册

服务注册步骤如下:

①引入nacos discovery依赖:

image-20240315160950577

②配置Nacos地址

image-20240315160955964

注意:每个微服务都要进行一个注册

在idea里配置多个启动项就能实现多个服务

用云服务器的话,记得把三个端口全部开放:8848、9848、9849,要不然会报错

image-20240315161713629

服务发现

消费者需要连接nacos以拉取和订阅服务,因此服务发现的前两步与服务注册是一样,后面再加上服务调用即可:

①引入nacos discovery依赖

②配置nacos地址

③服务发现

image-20240315162004885

1
2
3
4
5
6
7
8
9
10
11
private final DiscoveryClient discoveryClient;
private void handleCartItems(List<CartVO> vos) {
// 1.根据服务名称,拉取服务的实例列表
List<ServiceInstance> instances = discoveryClient.getInstances("item-service");
// 2.负载均衡,挑选一个实例
ServiceInstance instance = instances.get(RandomUtil.randomInt(instances.size()));
//这个是随机负载均衡
// 3.获取实例的IP和端口
URI uri = instance.getUri();
// ... 略
}

nacos为这些提供了API

image-20240315170136819

OpenFeign

快速入门

OpenFeign是一个声明式的http客户端,是SpringCloud在Eureka公司开源的Feign基础上改造而来。官方地址:https://github.com/OpenFeign/feign

其作用就是基于SpringMVC的常见注解,帮我们优雅的实现http请求的发送。

image-20240315171700078

① 引入依赖,包括OpenFeign和负载均衡组件SpringCloudLoadBalancer

1
2
3
4
5
6
7
8
9
10
11
12
<!--OpenFeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--负载均衡-->
<!--这个依赖里面有各种负载均衡的一些,早期用ribbon,后期用这个loadbalancer-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

②通过@EnableFeignClients注解,启用OpenFeign功能

1
2
3
4
@EnableFeignClients
@SpringBootApplication
public class CartApplication { // ... 略 }

③编写FeignClient

1
2
3
4
5
@FeignClient(value = "item-service")
public interface ItemClient {
@GetMapping("/items")
List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);
}

④使用FeignClient,实现远程调用

1
List<ItemDTO> items = itemClient.queryItemByIds(List.of(1,2,3));

连接池

OpenFeign对Http请求做了优雅的伪装,不过其底层发起http请求,依赖于其它的框架。这些框架可以自己选择,包括以下三种:

  • HttpURLConnection:默认实现,不支持连接池
  • Apache HttpClient :支持连接池
  • OKHttp:支持连接池

具体源码可以参考FeignBlockingLoadBalancerClient类中的delegate成员变量。

OpenFeign整合OKHttp的步骤

①引入依赖
1
2
3
4
5
6
<!--ok-http-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>

②开启连接池功能
1
2
3
4
feign:  
okhttp:
enabled: true # 开启OKHttp连接池支持

最佳实践

image-20240316093447481

image-20240316093502128

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

方式一:指定FeignClient所在包

image-20240316094114690

方式二:指定FeignClient字节码

image-20240316094121599

日志

OpenFeign只会在FeignClient所在包的日志级别为DEBUG时,才会输出日志。而且其日志级别有4级:

NONE:不记录任何日志信息,这是默认值。

BASIC:仅记录请求的方法,URL以及响应状态码和执行时间

HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息

FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

由于Feign默认的日志级别就是NONE,所以默认我们看不到请求日志。

总结

如何利用OpenFeign实现远程调用?

•引入OpenFeign和SpringCloudLoadBalancer依赖

•利用@EnableFeignClients注解开启OpenFeign功能

•编写FeignClient

如何配置OpenFeign的连接池?

•引入http客户端依赖,例如OKHttp、HttpClient

•配置yaml文件,打开OpenFeign连接池开关

OpenFeign使用的最佳实践方式是什么?

•由服务提供者编写独立module,将FeignClient及DTO抽取

如何配置OpenFeign输出日志的级别?

•声明类型为Logger.Level的Bean

•在@FeignClient或@EnableFeignClients注解上使用