java面试常见问题知识

一.常见名词注解

1.mysql索引,索引数据结构,hash,二叉树,B树,B+树,红黑树,

mysql索引:帮助mysql高效获取数据的数据结构,通俗来说,数据库索引就好比一本书的目录,可以加快数据库查询的速度。

索引数据结构:hash,B+,二叉树。

hash:以键值对存储数据,只要输入key就可以找到相应的Value

二叉树:每个节点最多有两个子树的树结构

B树:每个节点都是按递增排序存放,左小右大,一个子结点可以有多个数据

B+树:改良版的B树,每个就叶子节点,连成一条链表

红黑树:是一种二叉搜索树,红黑树确保没有一条路径是其他路径的两倍,因而接近平衡。

2.进程和线程

进程:程序运行的资源分配的基本单元,一个程序有多个进程,一个进程有多个线程,进程在执行过程中有独立的内存单元

线程:多个线程共享内存资源,线程是进程的一个实体,是cpu调度的基本单元。

3.堆,栈

堆:是一种数据接口,自己控制一段储存空间,叫做堆空间,实在程序运行时申请的动态内存,

栈:又称为堆栈,是操作系统在创建某个进程时或线程,为了这个线程创建的储存区域,在编译时候可以指定需要的栈大小,它是一种运算受限的线性表,先进后出。

4.线程安全,synchronized,lock锁

synchronized:关键字,同步锁,可以修饰静态方法,普通方法,代码块,修饰静态方法时锁住的是类对象,修饰普通方法是锁住的是实例对象,当一个线程获取锁是,其他线程想要访问只能等当前线程释放锁,

lock锁:接口,只能用在代码里,synchronized在代码执行完或出现异常时会自动释放锁,Locl不会自动释放,需要在finally中释放。 synchronized会导致线程拿不到锁一直等待,Lock可以设置获取锁失败的超时时间。 synchronized无法获知是否获取锁成功,Lock则可以通过tryLock判断是否加锁成功

5.redis五种数据结构

string:底层是一个简单的动态字符串。

list:存储先行有序且可重复的元素,底层是双向链表/压缩列表

set:存储不可重复的元素,底层是hash和整数数组

zset:存储有序不可重复的元素,为每个元素添加一个score属性作为排序依据,底层是ziplist和跳表

hash:存储的是键值对,底层是ziplist和hash

6.集合,数组,链表,队列

集合:用于储存无序元素,值不能重复,

数组:数组是内存开辟的一段连续空间,长度固定,元素固定,

链表:是一种线性表,在一个节点上有一个指针指向下一个节点

队列:先进先出。

7.ArrayList和LinkedList

ArrayList:底层是数组实现,数组是一组连续的内存单元,读取快,插入删除慢,

LinkedList:底层基于双向链表,读取慢,插入删除快,链表的每个节点都保存了数据值,和前后节点的指针,占内存。

8.ConcurrentHashMap,HashMap,HashTable

ConcurrentHashMap:底层数据结构也是数组+链表+红黑树,采用锁定头部结点的方式降低锁粒度,在初始化数组时未加锁,但当插入数据就会给槽的头节点上锁,支持多线程

HashMap:数组+链表+红黑树,集合put时,计算key键的哈希值放入元素,若有key值相同的哈希值是就会用链表进行存放,链表长度达到8是就会开辟红黑树进行存放,以此提高查询效率。非线程安全。

HashTable:性能不如hsahmap,但是线程安全,,不允许存入null,内部使用大量的synchronized关键字,所以无论是key还是value为null都会引发异常。

9.String、StringBuffer、Stringbuilder

String:不可变字符序列,效率低,每创建一个string对象,就会分配一个空间,

StringBuffer:可变字符序列,效率高(增删),线程安全,只分配一个空间,改变值而不改变地址。

Stringbulider:可变字符序列,效率最高,线程不安全,只分配一个空间,改变值而不改变地址。

10.==和equals(),hashCode()

==:比较基本数据类型时,比较的是两个数值是否相等; 比较引用类型是,比较的是对象的内存地址是否相等。equals():equals() 没有重写时,Object默认以==来实现,即比较两个对象的内存地址是否相等; 重写以后,按照对象的内容进行比较

hashCode():主要用途是获取哈希码

两个对象相等,他们必须有相同的哈希码,有相同的哈希码;哈希码相同的话,他们不一定相等

11:static,final

static:修饰符,static修饰变量:属于静态变量也叫类变量,直属于类对象而不是实例,可以通过类名访问,它一般会在类加载过程中被初始化。生命周期贯穿整个程序。存储在方法区中。 static修饰方法:即静态方法,一个类中的静态方法不能访问该类的实例变量,只能访问静态变量。同时还存在一个静态初始化块,他在类加载过程中被调用用于对该类中的静态变量进行操作。 static修饰类:即静态内部类,他只能以内部类的形式存在,可通过外部类的类名调用。它是他也只能访问到外部的的静态成员。

final:关键字,final可以修饰类,方法,变量。 final修饰类,该类不可被继承。 final修饰方法,该方法不能被重写。 final修饰变量,如果是基本变量则值不能再改变,如果是引用变量则引用地址不能改变,但值可以改变。可以修饰成员变量,修饰后可重写,不能重新赋值。

12.SpringBoot注解

@springBootApplication:springboot的核心注解,用在springboot的主类上,用来开启springboot的各项能力,

@EnableAutoConfiguration:允许springboot自动配置注解,开启后,springboot就根据当前类路径包或者类来配置springbean

@Configuration 用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法

@Bean 相当于XML中的<Bean></Bean>,放在方法的上面,而不是类,意思是产生一个bean,并交给

@Service:用来修饰Service层的组件

@RequestBody 参数前加上这个注解之后,认为该参数必填。表示接受json字符串转为对象 List等

@RequestMapping 用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径

@Controller 用于标注是控制层组件,需要返回页面时请用@Controller而不是@RestController

@ResponseBody 表示该方法的返回结果直接写入HTTP response body中,一般在异步获取数据时使用,比如异步获取json数据

@RestController 用于标注控制层组件,包含@Controller和@ResponseBody

@RequestMapping 用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径

@GetMapping、@PostMapping 相当于@RequestMapping(value=”/”,method=RequestMethod.Get/Post/Put/Delete等) 。是个组合注解

@AutoWired byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作 当加上(required=false)时,就算找不到bean也不报错

13.@Autowired和@Resource

@Autowired:Spring提供的注解,@Autowired只能按照类型装配,默认情况下必须按照依赖对象存在,如果允许null值,可以设置他的required属性为false,如果想使用名称装配可以结合@Qualifier注解使用,

@Resource:JDK提供的注解,默认按照名称装配,名称可以通过name属性进行指定,如过没有指定name属性,当注解写在字段上是,默认取字段名进行名称查找。

14.java基本数据类型和引用数据类型

基本数据类型:byte(8), short(16), int(32), long(64), float(32), double(64), char(16), boolean

这基本数据类型在声明之后就会立刻在栈上被分配内存空间

引用数据类型:类,接口,数组,String等,这些变量在声明时不会被分配内存空间,只是存储了一个内存地址

15.mysql常用命令

获取当前日期和时间:now()

获取当前日期:curdate()

获取当前时间:curtime()

返回date年份,time小时,分钟: year(date),hour(time),minute(time)

返回两个时间相隔天数:datediff(date1,date2)

返回指定多少i行:limit 数字

平均数:AVG

返回字段行数:COUNT

16.重载和重写

重载:

重写

17.linux常见命令

ll 查看当前目录下内容(LL的小写)

mkdir aaa 在当前目录下创建aaa目录,相对路径;(创建 目录)

touch testFile (创建文件)

vim a.java 进入一般模式 (修改文件)

cat a.java more a.java less a.java (查看文件)

find / -name 'b' 查询根目录下名以b的目录和文件;(查询) mv 原先目录 文件的名称 (改名,剪切)

cp -r /aaa /bbb (拷贝)

rm -rf /bbb (强制删除)

rm -r /bbb (普通删除)

tar -cvf (.tar ) tar -zcvf (.tar) (压缩)

tar -xvf (.tar ) tar -zxvf (.tar) (解缩)

telnet 49.32.587.164 8093 (查看服务器指定端口是否可用)

lsof -i:8080 (用于查看某一端口的占用情况)

service iptables stop 临时关闭防火墙

chkconfig iptables off 防火墙开启不启动

service iptables status 查看防火墙状态

二、面试常见题

1.线程的状态

线程的状态有六种:

初始:线程被创建但是话没有调用start()方法。

运行(就绪和运行),线程正在执行,但是也可能在等待操作系统的调度。

阻塞:线程正在等待获取监视器

等待:线程正在等待其他线程的中断或者通知。

超时等待:在等待的基础上增加了超时时间,超出时间后自动返回

终止:线程运行结束

2.说说多线程

1.线程是程序执行的最小单元,一个进程可以拥有多个线程

2.各个线程之间共享程序的内存空间(代码段、数据段和堆空间)和系统分配的资源(CPU,I/O,打开的文件),但是各个线程拥有自己的栈空间

3.多线程优点:减少程序响应时间;提高CPU利用率;创建和切换开销小;数据共享效率高;简化程序结构

3.线程的创建方式

创建线程有3种方式:

1.继承Thread类,重写run()方法;

2.实现Runnable接口,并实现该接口的run()方法;

3.实现Callable接口,重写call()方法。前两种方式线程执行完后都没有返回值,最后一种带返回值;一般推荐实现Runnable接口的方式。

4.线程与进程的区别

1.线程是进程的子集,一个进程可以包含多个线程,每个线程执行不同的任务

2.每个进程使用不同的内存空间,所有的线程共享一个相同的内存空间 3.每个线程用单独的栈内存来存储本地数据

5.线程安全的集合

hashTable/vector/concurrentHasmap是线程安全的。 另外Collections工具类提供了相应的方法,可以将不安全的集合类包装成安全的集合类。

6.线程通信方式

线程的通信方式有两种:

monitor和condition两种。具体使用那种通信方式与线程同步的方式有关。对于Synchronized来说,使用的是monitor的同步方式。尝试用的方法有waite(),notify(),notifyAll().对于lock锁接口来说,使用的是condition,依赖于lock锁的创建而创建。常使用的方法有await(),signal(),signalAll();

7.进程通信方式

  1. 通过管道 2. 信号量 3. 消息队列 4. 共享内存 5. 套接口

8.线程池的理解

线程池可以有效的管理线程:管理线程数量、线程复用、 线程池的生命周期包含5个状态: RUNNING、SHUTDOWN、STOP、TIDING、TERMINATED。这5种状态的状态值分别是:-1、0、1、2、3。在线程池的生命周期中,它的状态只能由小到大迁移,是不可逆的。

9.Redis的了解

Redis是一款基于键值对的NoSQL数据库,Redis中拥有string(字符串),hash(哈希)、list(列表)、set(集合)等多种数据结构,redis将数据写进内存的性能很快,不仅如此,如遇到系统崩溃,内存中的数据不会丢失;redis访问速度快、支持的数据类型丰富,很适合用来储存热点数据、 而且适用业务广,如可以运用expire命令来做限时业务,设置一个键的生存时间,到时间后redis会自动删除它,,如排行榜可以借住redis的SortedSet进行热点数据的排序,还有分页查询,模糊查询,点赞好友等

10.Redis如何与数据库保持双写一致性

先更新数据库再删除缓存,若有错误需要重试

11.Redis的单线程架构

redis的网络IO和键值对读写是单线程的,而其他功能如持久化、异步删除等是依赖其他线程来执行的。事实上他底层并不是单线程的。

1.对于服务端程序来说,线程切换和锁通常很影响性能,redis采用单线程则避免了线程间的切换和锁,减小了消耗。

2.redis的大部分操作实在内存上的完成的,因此它的性能很高。

3.redis采用IO多路复用机制,使其能够处理并发请求。

12.Redis高可用

高可用即需要有多个副本而不是单体支撑,主节点不可用可以替换成副节点,那么多个副本需要合理同步机制,做到这两点即可实现高可用,redis通过哨兵模式,集群模式来扩展单节点支撑。同时做好数据同步即实现了高可用

13.Redis的主从同步机制

任何从节点都能在主节点复制数据,从节点发送psync指令,主节点开启后台线程将生成的rdb文件给从节点,从节点接受存储在磁盘在加载如内存,主节点在发送完成rdb后还会向从节点发送缓存中新出现的写命令

14.Redis的缓存淘汰策略

惰性删除:客户端访问一个key的时候,redis先检查它的过期时间,如果已经过期了就立刻删除这个key 定期删除:redis会将设置了过期时间的key保存到一个字典里面,然后每过十秒就扫描一次。这个定期删除也不扫描字典中所有的key,而是采用了一种简单的弹性策略。

定期删除对内存更加友好,而惰性删除对CPU更加友好,所以redis采用的是定期删除+惰性/懒汉式删除。

15.Redis的持久化策略

1.RDB: redis database 在指定的时间间隔内,将内存中的数据集的快照写入磁盘,文件名dump.rdb 适合大规模的数据恢复,对数据库的完整性和一致性要求不是很高 一定时间间隔备份一次,如果数据库意外down掉,就会失去最后一次快照的所有修改

2.AOF: append only file 以日志的形式记录每个写操作,只允许追加文件,不允许改写文件,redis启动时会读取这个文件,并从头到尾执行一遍,以此来恢复数据,文件名appendonly.aof 在最恶劣的环境下,也丢失不会超过2秒的数据,完整性较高,但是会对磁盘持续的进行IO,代价太大。企业级最少需要5G才能支持 如果.aof文件大小超过原来的一倍,会进行重写压缩,保留最小的指令集合

3.优先级 aof>rdb

###

项目

nginx

一、Nginx是什么?

Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
Nginx 是高性能的 HTTP 和反向代理的web服务器,处理高并发能力是十分强大的,能经受高负 载的考验,有报告表明能支持高达 50,000 个并发连接数。
Nginx支持热部署,启动简单,可以做到7*24不间断运行。几个月都不需要重新启动。

二、Nginx的反向代理(扩展:正向代理)

首先,看一张关于正向代理和反向代理的图片 在这里插入图片描述 在这里,用通俗易懂的方式解释一下:

正向代理: 我们平时需要访问国外的浏览器是不是很慢,比如我们要看推特,看GitHub等等。我们直接用国内的服务器无法访问国外的服务器,或者是访问很慢。所以我们需要在本地搭建一个服务器来帮助我们去访问。那这种就是正向代理。(浏览器中配置代理服务器)

反向代理: 那什么是反向代理呢。比如:我们访问淘宝的时候,淘宝内部肯定不是只有一台服务器,它的内部有很多台服务器,那我们进行访问的时候,因为服务器中间session不共享,那我们是不是在服务器之间访问需要频繁登录,那这个时候淘宝搭建一个过渡服务器,对我们是没有任何影响的,我们是登录一次,但是访问所有,这种情况就是 反向代理。对我们来说,客户端对代理是无感知的,客户端不需要任何配置就可以访问,我们只需要把请求发送给反向代理服务器,由反向代理服务器去选择目标服务器获取数据后,再返回给客户端,此时反向代理服务器和目标服务器对外就是一个服务器,暴露的是代理服务器地址,隐藏了真实服务器的地址。(在服务器中配置代理服务器)

三、Nginx的负载均衡

什么是负载均衡?

负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。 负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

简单来说就是:现有的请求使服务器压力太大无法承受,所有我们需要搭建一个服务器集群,去分担原先一个服务器所承受的压力,那现在我们有ABCD等等多台服务器,我们需要把请求分给这些服务器,但是服务器可能大小也有自己的不同,所以怎么分?如何分配更好?又是一个问题。

Nginx给出来三种关于负载均衡的方式:

轮询法(默认方法):
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
适合服务器配置相当,无状态且短平快的服务使用。也适用于图片服务器集群和纯静态页面服务器集群。
weight权重模式(加权轮询):
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的
情况。
这种方式比较灵活,当后端服务器性能存在差异的时候,通过配置权重,可以让服务器的性能得到充分发挥,有效利用资源。weight和访问比率成正比,用于后端服务器性能不均的情况。权重越高,在被访问的概率越大
ip_hash:
上述方式存在一个问题就是说,在负载均衡系统中,假如用户在某台服务器上登录了,那么该用户第二次请求的时候,因为我们是负载均衡系统,每次请求都会重新定位到服务器集群中的某一个,那么已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息将会丢失,这样显然是不妥的。
我们可以采用ip_hash指令解决这个问题,如果客户已经访问了某个服务器,当用户再次访问时,会将该请求通过哈希算法,自动定位到该服务器。每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。

四、Nginx的动静分离!

Nginx的静态处理能力很强,但是动态处理能力不足,因此,在企业中常用动静分离技术。动静分离技术其实是采用代理的方式,在server{}段中加入带正则匹配的location来指定匹配项针对PHP的动静分离:静态页面交给Nginx处理,动态页面交给PHP-FPM模块或Apache处理。在Nginx的配置中,是通过location配置段配合正则匹配实现静态与动态页面的不同处理方式 目前,通过使用Nginx大大提高了网站的响应速度,优化了用户体验,让网站的健壮性更上一层楼! 在这里插入图片描述

spring ioc aop

Java 是⾯向对象的编程语⾔,⼀个个实例对象相互合作组成了业务逻辑,原来,我们都是在

代码⾥创建对象和对象的依赖。

所谓的 *IOC* (控制反转):就是由容器来负责控制对象的⽣命周期和对象间的关系。以前是

我们想要什么,就⾃⼰创建什么,现在是我们需要什么,容器就给我们送来什么。

也就是说,控制对象⽣命周期的不再是引⽤它的对象,⽽是容器。对具体对象,以前是它控

制其它对象,现在所有对象都被容器控制,所以这就叫 *控制反转*

*DI**(依赖注⼊)* :指的是容器在实例化对象的时候把它依赖的类注⼊给它。有的说法IOC和

DI是⼀回事,有的说法是IOC是思想,DI是IOC的实现。

最主要的是两个字 *解耦* ,硬编码会造成对象间的过度耦合,使⽤IOC之后,我们可以不⽤关

⼼对象间的依赖,专⼼开发应⽤就⾏。

:这道题⽼三在⾯试中被问到过,问法是“ *你有⾃⼰实现过简单的**Spring**吗?*

Spring的IOC本质就是⼀个⼤⼯⼚,我们想想⼀个⼯⼚是怎么运⾏的呢?

*⽣产产品* :⼀个⼯⼚最核⼼的功能就是⽣产产品。在Spring⾥,不⽤Bean⾃⼰来实例化,

⽽是交给Spring,应该怎么实现呢?——答案毫⽆疑问, *反射* 。 那么这个⼚⼦的⽣产管理是怎么做的?你应该也知道—— *⼯⼚模式*

*库存产品* :⼯⼚⼀般都是有库房的,⽤来库存产品,毕竟⽣产的产品不能⽴马就拉⾛。

Spring我们都知道是⼀个容器,这个容器⾥存的就是对象,不能每次来取对象,都得现场

来反射创建对象,得把创建出的对象存起来。

*订单处理* :还有最重要的⼀点,⼯⼚根据什么来提供产品呢?订单。这些订单可能五花

⼋门,有线上签签的、有到⼯⼚签的、还有⼯⼚销售上门签的……最后经过处理,指导⼯

⼚的出货。

在Spring⾥,也有这样的订单,它就是我们bean的定义和依赖关系,可以是xml形式,也 可以是我们最熟悉的注解形式。

们简单地实现⼀个mini版的Spring IOC:

*AOP*

AOP:⾯向切⾯编程。简单说,就是把⼀些业务逻辑中的相同的代码抽取到⼀个独⽴的模块

中,让业务逻辑更加清爽。

体来说,假如我现在要crud写⼀堆业务,可是如何业务代码前后前后进⾏打印⽇志和参数的

校验呢?

我们可以把 和 可重⽤的功能模块分离出来,然后在程序的执⾏的合适的地

⽅动态地植⼊这些代码并执⾏。这样就简化了代码的书写。

业务逻辑代码中没有参和通⽤逻辑的代码,业务模块更简洁,只包含核⼼业务代码。实现了 业务逻辑和通⽤逻辑的代码分离,便于维护和升级,降低了业务逻辑和通⽤逻辑的耦合性。

AOP 可以将遍布应⽤各处的功能分离出来形成可重⽤的组件。在编译期间、装载期间或运⾏ 期间实现在不修改源代码的情况下给程序动态添加功能。从⽽实现对业务逻辑的隔离,提⾼ 代码的模块化能⼒。

AOP 的核⼼其实就是 *动态代理* ,如果是实现了接⼜的话就会使⽤ JDK 动态代理,否则使⽤

CGLIB 代理,主要应⽤于处理⼀些具有横切性质的系统级服务,如⽇志收集、事务管理、安 全检查、缓存、对象池管理等。

*切⾯* (Aspect):类是对物体特征的抽象,切⾯就是对横切关注点的抽象

*连接点* (Joinpoint):被拦截到的点,因为 Spring 只⽀持⽅法类型的连接点,所以在

Spring中连接点指的就是被拦截到的⽅法,实际上连接点还可以是字段或者构造器

*切点* (Pointcut):对连接点进⾏拦截的定位

*通知* (Advice):所谓通知指的就是指拦截到连接点之后要执⾏的代码,也可以称作 *增*

*⽬标对象* (Target):代理的⽬标对象

(Weabing):织⼊是将增强添加到⽬标类的具体连接点上的过程。

编译期织⼊:切⾯在⽬标类编译时被织⼊

类加载期织⼊:切⾯在⽬标类加载到JVM时被织⼊。需要特殊的类加载器,它可以在

⽬标类被引⼊应⽤之前增强该⽬标类的字节码。

运⾏期织⼊:切⾯在应⽤运⾏的某个时刻被织⼊。⼀般情况下,在织⼊切⾯时,AOP

容器会为⽬标对象动态地创建⼀个代理对象。SpringAOP就是以这种⽅式织⼊切⾯。

Spring采⽤运⾏期织⼊,⽽AspectJ采⽤编译期织⼊和类加载器织⼊。

*引介* (introduction):引介是⼀种特殊的增强,可以动态地为类添加⼀些属性和⽅法

AOP ⼀般有 *5* *种* 环绕⽅式:

前置通知 (@Before)

返回通知 (@AfterReturning) 异常通知 (@AfterThrowing) 后置通知 (@After) 环绕通知 (@Around)

多个切⾯的情况下,可以通过 @Order 指定先后顺序,数字越⼩,优先级越⾼。

spring boot

*Spring* *Boot*

Spring Boot 基于 Spring 开发,Spirng Boot 本⾝并不提供 Spring 框架的核⼼特性以及扩展功

能,只是⽤于快速、敏捷地开发新⼀代基于 Spring 框架的应⽤程序。它并不是⽤来替代

Spring 的解决⽅案,⽽是和 Spring 框架紧密结合⽤于提升 Spring 开发者体验的⼯具。

Spring Boot 以 核⼼思想开展⼯作,相⽐Spring具有如下优势:

1. Spring Boot 可以快速创建独⽴的Spring应⽤程序。

2. Spring Boot 内嵌了如Tomcat,Jetty和Undertow这样的容器,也就是说可以直接跑起来,⽤ 不着再做部署⼯作了。

3. Spring Boot ⽆需再像Spring⼀样使⽤⼀堆繁琐的xml⽂件配置。

4. Spring Boot 可以⾃动配置(核⼼)Spring。SpringBoot将原有的XML配置改为Java配置,将 bean注⼊改为使⽤注解注⼊的⽅式(@Autowire),并将多个xml、properties配置浓缩在⼀个 appliaction.yml配置⽂件中。

*5.* Spring Boot 提供了⼀些现有的功能,如量度⼯具,表单数据验证以及⼀些外部配置这样 的⼀些第三⽅功能。

*6.* Spring Boot 可以快速整合常⽤依赖(开发库,例如spring-webmvc、jackson-json、 validation-api和tomcat等),提供的POM可以简化Maven的配置。当我们引⼊核⼼依赖时, SpringBoot会⾃引⼊其他依赖。

SpringApplication 这个类主要做了以下四件事情:

*1.* 推断应⽤的类型是普通的项⽬还是 Web 项⽬

*2.* 查找并加载所有可⽤初始化器 , 设置到 initializers 属性中

*3.* 找出所有的应⽤程序监听器,设置到 listeners 属性中

*4.* 推断并设置 main ⽅法的定义类,找到运⾏的主类

SpringBoot 启动⼤致流程如下 :

mabatis

mabatisplus

MyBatis-Plus

MyBatis-Plus 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

官网 MyBatis-Plus

连接池: 传统开发中,每一次请求都要建立一次数据库连接。每一次数据库连接,使用完后都得断开。频繁的数据库连接操作势必占用很多的系统资源,响应速度必定下降。另外,在高并发时,系统资源被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。

解决方案: 为数据库连接建立一个“缓冲池”(连接池)。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕再放回去。通过设定连接池最大连接数来防止系统无休止的数据库连接。

工作流程: 当客户端请求服务器,服务器需要使用连接对象操作数据库的数据。这时,需要从连接池中申请一个连接对象。连接池会分配一个空闲连接给该客户。如果连接池中没有空闲连接,就看有没有到达最大连接数。如果没有到达最大连接数,就创建新连接分配给客户。如果已经到达最大连接,那么,请求用户会等待一段时间,在等待时间内,有连接对象被释放,则分配给等待用户。等待时间结束后,还没有连接被释放,则返回null。

rabbitmq

RabbitMQ 使用场景

服务解耦

假设有这样一个场景, 服务A产生数据, 而服务B,C,D需要这些数据, 那么我们可以在A服务中直接调用B,C,D服务,把数据传递到下游服务即可

但是,随着我们的应用规模不断扩大,会有更多的服务需要A的数据,如果有几十甚至几百个下游服务,而且会不断变更,再加上还要考虑下游服务出错的情况,那么A服务中调用代码的维护会极为困难

这是由于服务之间耦合度过于紧密

耦合

再来考虑用RabbitMQ解耦的情况

A服务只需要向消息服务器发送消息,而不用考虑谁需要这些数据;下游服务如果需要数据,自行从消息服务器订阅消息,不再需要数据时则取消订阅即可

解耦

流量削峰

假设我们有一个应用,平时访问量是每秒300请求,我们用一台服务器即可轻松应对

低流量

而在高峰期,访问量瞬间翻了十倍,达到每秒3000次请求,那么单台服务器肯定无法应对,这时我们可以考虑增加到10台服务器,来分散访问压力

但如果这种瞬时高峰的情况每天只出现一次,每次只有半小时,那么我们10台服务器在多数时间都只分担每秒几十次请求,这样就有点浪费资源了

流量峰值

这种情况,我们就可以使用RabbitMQ来进行流量削峰,高峰情况下,瞬间出现的大量请求数据,先发送到消息队列服务器,排队等待被处理,而我们的应用,可以慢慢的从消息队列接收请求数据进行处理,这样把数据处理时间拉长,以减轻瞬时压力

这是消息队列服务器非常典型的应用场景

流量销峰

异步调用

考虑定外卖支付成功的情况

支付后要发送支付成功的通知,再寻找外卖小哥来进行配送,而寻找外卖小哥的过程非常耗时,尤其是高峰期,可能要等待几十秒甚至更长

这样就造成整条调用链路响应非常缓慢

阻塞

而如果我们引入RabbitMQ消息队列,订单数据可以发送到消息队列服务器,那么调用链路也就可以到此结束,订单系统则可以立即得到响应,整条链路的响应时间只有200毫秒左右

寻找外卖小哥的应用可以以异步的方式从消息队列接收订单消息,再执行耗时的寻找操作

异步调用

rabbitmq 基本概念

RabbitMQ是一种消息中间件,用于处理来自客户端的异步消息。服务端将要发送的消息放入到队列池中。接收端可以根据RabbitMQ配置的转发机制接收服务端发来的消息。RabbitMQ依据指定的转发规则进行消息的转发、缓冲和持久化操作,主要用在多服务器间或单服务器的子系统间进行通信,是分布式系统标准的配置。 Message Queue

消息队列。我们发送给RabbitMQ的消息最后都会到达各种queue,并且存储在其中(如果路由找不到相应的queue则数据会丢失),等待消费者来取。 Binding Key

它表示的是Exchange与Message Queue是通过binding key进行联系的,这个关系是固定。 Routing Key

生产者在将消息发送给Exchange的时候,一般会指定一个routing key,来指定这个消息的路由规则。这个routing key需要与Exchange Type及binding key联合使用才能生,我们的生产者只需要通过指定routing key来决定消息流向哪里。

rabbitmq六种工作模式

简单模式

工作模式

发布订阅模式

路由模式

主题模式

RPC模式

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小...羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值