1、微服务
单体架构
集成在一个项目中开发,打成一个包部署
优点:简单、成本低
缺点:团队协作成本高、系统发布率低、系统可用性差
微服务架构
把单体架构拆分为多个功能模块拆分为多个独立项目
颗粒小、团队自治、服务自治
SpringCloud(最广泛的微服务框架)
登录拦截器
获取请求头中的Token中的authorization来确认登录信息
2、拆分原则
创业型项目:先采用单体架构、快速开发、快速试错。随着规模扩大、逐渐拆分
确定的大型项目:资金充足、目标
之前我们说过,微服务拆分时粒度要小,这其实是拆分的目标。具体可以从两个角度来分析:
-
高内聚:每个微服务的职责要尽量单一,包含的业务相互关联度高、完整度高。
-
低耦合:每个微服务的功能要相对独立,尽量减少对其它微服务的依赖,或者依赖接口的稳定性要强。
-
纵向拆分(垂直):按照业务模块拆分
-
横向拆分:抽取公共服务,提高复用性
工程结构有两种
1、独立的project(太松散麻烦、特别大型的)
2、Maven聚合(不同moudle、中小型)
开始拆分
创建moudle、之后pom复制原本的pom (dependencies到build完)
需要的保留、不需要的删除
问题1:不同service之间数据库是分割的如何注入
解决:物理上隔离、但网络上可以联通、服务器上可以通过网络请求
通过网络再次请求再返回(原来如此)
问题1.1java如何发请求获取数据
前端是通过http协议我还以为是啥呢这两天面试问我不就是ajax服了
前端数据和后端交互采用的是http协议的方式
Request URL:请求路径(http、ip、端口、资源路径、参数)
Request Method:请求方式
也java去模拟!!!!!!!!牛!
RestTemplate可以模仿Http请求
首先将RestTemplate注册到Spring容器中(这里是直接写入是springboot启动类,因为Springboot启动类也是一个简单配置文件)
package com.hmall.cart.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RemoteCallConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
查漏补缺 :什么是注册到Spring容器
在Spring框架中,将一个Java对象纳入Spring容器的管理称为"注册到Spring容器中"。通过注册到Spring容器,这些对象可以由Spring框架进行实例化、依赖注入和生命周期管理,从而实现对象的解耦和管理。
通常情况下,将对象注册到Spring容器有两种方式:
- 基于XML配置方式:通过在XML配置文件中定义对象的配置信息,包括类名、属性值、依赖关系等,然后由Spring容器根据配置文件进行对象的实例化和管理。在XML配置文件中使用
<bean>
标签定义对象,并指定相应的属性和依赖关系。 - 基于注解方式:通过在Java类上使用注解,如
@Component
、@Service
、@Repository
等,告诉Spring容器这个类是一个Spring管理的组件。Spring容器会扫描这些注解,自动将带有注解的类注册到容器中。 - 无论是XML配置方式还是注解方式,一旦对象被注册到Spring容器中,Spring容器就会负责管理这些对象的生命周期、依赖注入和其他相关操作,使得开发者可以更加专注于业务逻辑的实现,而不用过多关注对象的创建和管理。
再远程调用
public <T> ResponseEntity<T> exchange(
String url,//请求路径
HttpMethod method,//请求方式
@Nullable HttpEntity<?> requestEntity,//请求实体,可以为空
Class<T> responseType,//返回值类型
Map<string,?> uriVariables//请求参数
)
//利用RestTemplate发起http请求,得到http的响应
ResponseEntity<List<ItemDTO>> response = restTemplate.exchange(
"http://localhost:8081/items?ids={ids}",
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<ItemDTO>>() {
},//参数类型引用、一般如果使用字节码会被擦除、但是我们使用对象、通过反射反射对象的类型从而知道了参数的类型
Map.of("ids", CollUtil.join(itemIds, ","))
);//CollUtil.join集合拼接,自动将ids集合用,号拼接成字符串
//白学警告:后面用openfeign
//解析响应
response.getBody()//还有很多协议
//但是请求有成功也有失败不是100%成功所以我们需要加一个判断
if(!response.getStatusCode().is2xxSuccessful()){
return;
}//如果不成功就响应失败
Springboot的启动类也是配置类,可以写一些简单的配置
查漏补缺:Lombok
Lombok是一个Java库,可以通过简单的注解来减少Java代码的冗长,提高开发效率。Lombok的主要作用包括:
1. **减少样板代码**:Lombok通过注解来自动生成getter、setter、构造函数、equals、hashCode等方法,减少了开发者需要手动编写的重复代码,简化了代码结构。
2. **简化Java Bean开发**:使用Lombok可以通过注解快速生成Java Bean的属性、构造函数和其他标准方法,使得Java Bean的开发更加简洁和高效。
3. **提高代码可读性**:由于减少了冗长的样板代码,使用Lombok可以使代码更加简洁、清晰,提高了代码的可读性和维护性。
4. **方便地实现不可变对象**:通过`@Value`注解可以方便地创建不可变对象,避免对象状态被修改,提高代码的健壮性。
5. **简化日志记录**:使用`@Slf4j`注解可以方便地引入Slf4j日志框架,简化了日志记录的操作。
6. **简化异常处理**:使用`@SneakyThrows`注解可以将受检异常转换为不受检异常,简化了异常处理的代码。
总的来说,Lombok可以帮助开发者简化Java代码的编写,减少样板代码,提高开发效率,同时提升代码的可读性和可维护性。然而,需要注意的是,使用Lombok可能会增加代码的隐式性,降低了代码的可控性,因此在使用时需要谨慎考虑。
Spring不推荐使用@Auto去注入
而是推荐使用构造函数
但是使用
@AllArgsConstructor
会使得所有成员变量都自动生成构造函数显然不行
所以使用@RequiredArgsConstructor
他可以为所以带final的成员变量自动创建构造函数
白雪了夫了
开始改进rest
3、注册中心
流程如下:
-
服务启动时就会注册自己的服务信息(服务名、IP、端口)到注册中心
-
调用者可以从注册中心订阅想要的服务,获取服务对应的实例列表(1个服务可能多实例部署)
-
调用者自己对实例列表负载均衡,挑选一个实例
-
调用者向该实例发起远程调用
当服务提供者的实例宕机或者启动新实例时,调用者如何得知呢?
-
服务提供者会定期向注册中心发送请求,报告自己的健康状态(心跳请求)
-
当注册中心长时间收不到提供者的心跳时,会认为该实例宕机,将其从服务的实例列表中剔除
-
当服务有新实例启动时,会发送注册服务请求,其信息会被记录在注册中心的服务实例列表
-
当注册中心服务列表变更时,会主动通知微服务,更新本地服务列表
nacos注册中心
首先配置nacos(nacos/custom.env)中
之后制作docker镜像
docker run -d \
--name nacos \
--env-file ./nacos/custom.env \
-p 8848:8848 \
-p 9848:9848 \
-p 9849:9849 \
--restart=always \
nacos/nacos-server:v2.1.0-slim
账号密码都是nacos
服务注册
导入依赖
<!--nacos 服务注册发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置nacos地址
spring:
application:
name: item-service # 服务名称
cloud:
nacos:
server-addr: 81.70.150.253:8848 # nacos地址
实现同一台机器多端口
服务发现
服务的消费者要去nacos订阅服务,这个过程就是服务发现,步骤如下:
-
引入依赖
-
配置Nacos地址
-
发现并调用服务
1、引入依赖
<!--nacos 服务注册发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2、配置nacos地址
spring:
cloud:
nacos:
server-addr: ip:8848
3、服务发现
跨时代(我们不再手写地址,而是动态的选择地址来进行负载均衡)
// 2.查询商品
// List<ItemDTO> items = itemService.queryItemByIds(itemIds);
// 2.1.根据商品的名称获取服务的实例列表
List<ServiceInstance> instances = discoveryClient.getInstances("item-service");
// 2.2.手写负载均衡,从服务列表中挑选一个实例
if (CollUtil.isEmpty(instances))
return;
ServiceInstance instance = instances.get(RandomUtil.randomInt(instances.size()));
System.out.println(itemIds);
ResponseEntity<List<ItemDTO>> response = restTemplate.exchange(
instance.getUri()+"/items?ids={ids}",
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<ItemDTO>>() {
},
Map.of("ids", CollUtil.join(itemIds, ","))
);
手写了负载均衡
太帅了卧槽注册中心