继续看java基础进阶的思想,之前学的很多都忘了。
优质的微服务架构说明文章
微服务 是分布式架构的一种,分布式架构就是把服务做一个拆分,springcloud就是解决拆分过程的服务治理问题
微服务相关的技术栈
1注册中心 一个业务一般需要多个服务来实现,a调用b,b调用c,c调用d,当业务变得很复杂的时候,这些服务之间调用关系很复杂,就需要一个注册中心用来记录每一个服务的ip、端口以及他们能完成的功能,然后这些服务之间相互调用的时候,不需要记录服务的ip,只要到注册中心就可以了;
2配置中心
每一个服务都有配置文件,而一个上线的项目可能存在成百上千的服务,这些配置文件不能一个个去修改,需要一个配置中心。用来统一管理整个服务集群成千上百的配置,需要某个配置的时候,只要找到配置中心即可
3网关
所有请求进来,不能直接访问对应的服务,需要通过一个网关服务,由它来路由对应的服务
4分布式缓存
即使数据库是集群部署的,也很难抵抗高并发,还需要一个缓存集群。把数据库的数据搬到内存中以提高访问效率。请求先查询缓存,缓存为命中再查询数据库
5分布式搜索
对于一些复杂的数据搜索、统计、分析,我们还需要使用搜索集群
6消息队列
一个业务可能调用多个服务,不能等到所有服务都执行完成再返回相应数据,使用消息队列,让服务发送消息通知其他服务去执行指定的认为,而自己可以结束运行,提高响应速度。
7分布式日志服务
分布式日志服务:主要用来统计成百上千的服务的运行日志,方便系统出问题时的定位。
8系统监控链路追踪
系统监控链路追踪:可以实时监控整个服务集群的所有节点的运行状态。
不同微服务,不要重复开发相同的业务;
微服务数据独立,不要访问其他微服务的数据库;
微服务可以将自己的业务暴露为接口,供其他微服务调用。
单一职责:
微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发;
面向服务:
微服务对外暴露业务接口;
自治:
团队独立,技术独立,数据独立,部署独立;
隔离性强:
服务调用做好隔离、容错、降级、避免出现级联问题。
在上面的图解中其实是存在问题的,比如Tomcat存在单点故障问题,一旦Tomcat所在的服务器宕机不可用了,我们就无法提供服务了,所以针对单点故障问题,我们会使用集群来解决.那什么是集群模式呢
单机处理到达瓶颈的时候,你就把单机复制几份,这样就构成了一个“集群”。集群中每台服务器就叫做这个集群的一个“节点”,所有节点构成了一个集群。每个节点都提供相同的服务,那么这样系统的处理能力就相当于提升了好几倍(有几个节点就相当于提升了这么多倍)。
但问题是用户的请求究竟由哪个节点来处理呢?最好能够让此时此刻负载较小的节点来处理,这样使得每个节点的压力都比较平均。要实现这个功能,就需要在所有节点之前增加一个“调度者”的角色,用户的所有请求都先交给它,然后它根据当前所有节点的负载情况,决定将这个请求交给哪个节点处理。这个“调度者”有个牛逼了名字——负载均衡服务器(Nginx)。
spring的两大核心功能 控制反转ioc,可以降低系统之间的耦合度。
Spring IOC(Inversion of Control,控制反转)是Spring框架的核心概念之一,它是一种设计原则和模式,旨在降低系统之间的耦合度,提高代码的可维护性和可测试性。
IOC的基本思想是由容器负责对象的创建和管理,而不是由程序员显式地创建和管理对象。在传统的应用程序中,程序员通常通过使用 new 关键字在代码中直接创建对象,并且对象之间的依赖关系也是在代码中硬编码的,这样导致了程序之间的紧密耦合。
而使用IOC,它将创建和管理对象的责任委托给了一个称为IOC容器的机制。在Spring框架中,IOC容器负责创建、组装和管理应用程序中的对象,以及解决对象之间的依赖关系。程序员只需通过配置文件或注解等方式来描述对象之间的依赖关系,然后由IOC容器根据这些描述来创建和装配对象。
通过IOC,对象之间的关系变得松散耦合,代码变得更加灵活和可扩展。它有以下几个关键概念:
Bean:在Spring中,Bean是指由IOC容器管理的对象。它们是应用程序的基本构建块,由Spring容器创建、组装和管理。
容器:Spring IOC容器负责创建、组装和管理Bean。常见的容器实现包括ApplicationContext和BeanFactory。
配置:通过XML配置文件、注解或Java配置方式,描述Bean之间的依赖关系和其他配置信息。
依赖注入(Dependency Injection,DI):IOC容器通过依赖注入为Bean提供它们所需要的依赖项,即创建对象并将依赖项设置到对象中。依赖注入可以通过构造函数、Setter方法或字段注入来实现。
生命周期管理:IOC容器负责管理Bean的生命周期,包括创建、初始化、使用和销毁等阶段。
通过使用IOC,我们可以实现松散耦合的组件化开发,并使得对象的创建和管理更加灵活。它提供了很多好处,如简化对象创建、易于测试和维护、提高代码的可读性和可维护性等。Spring框架通过IOC容器的实现,使得IOC的使用变得更加便捷和强大。
切面编程
不修改源代码的请跨下,给程序动态统一添加额外功能的一种技术。
aop的一些核心概念
苍穹外卖是采用Aspectj实现切面,基于注解的方式
定义注解AutoFill,用于标识需要进行公共字段自动填充的方法
自定义切面类,统一拦截加入AutoFill的方法,通过反射为公共字段赋值
技术点 枚举 注解 反射 AOP;
自定义注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
OperationType value(); //指定数据库曹操作类型
}
切面类
package com.sky.aspect;
import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
/**
* 自定义切面,实现公共字段自动填充处理逻辑
*/
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
/**
* 切入点
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut(){}
/**
* 前置通知,在通知中进行公共字段的赋值
*/
@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint){
log.info("开始进行公共字段自动填充...");
//获取到当前被拦截的方法上的数据库操作类型
MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象
OperationType operationType = autoFill.value();//获得数据库操作类型
//获取到当前被拦截的方法的参数--实体对象
Object[] args = joinPoint.getArgs();
if(args == null || args.length == 0){
return;
}
Object entity = args[0];
//准备赋值的数据
LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
//根据当前不同的操作类型,为对应的属性通过反射来赋值
if(operationType == OperationType.INSERT){
//为4个公共字段赋值
try {
Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
//通过反射为对象属性赋值
setCreateTime.invoke(entity,now);
setCreateUser.invoke(entity,currentId);
setUpdateTime.invoke(entity,now);
setUpdateUser.invoke(entity,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}else if(operationType == OperationType.UPDATE){
//为2个公共字段赋值
try {
Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
//通过反射为对象属性赋值
setUpdateTime.invoke(entity,now);
setUpdateUser.invoke(entity,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
这部分的作用是简化代码的开发。