目录

 

http get post请求的区别

Servlet的生命周期

jsp和Servlet的相同点和不同点

Session和Cookie的区别和使用场景,你在项目当中哪些地方用到了

 

简单介绍了一下Ajax

Spring MVC的执行流程

简单介绍一下Spring或者Spring的两大核心

介绍一下redis

redis的使用场景

redis存储对象的方式

redis数据淘汰机制

消息队列

为什么要使用消息队列?

使用消息队列有什么缺点?

怎么选型——ActiveMQ,RabbitMQ,RocketMQ,Kafka

如何保证消息不被重复消费?如何保证消息队列的幂等性? 

如何保证消费的可靠性传输?


http get post请求的区别

Get和post都是http的请求方式,用户可以通过不同的http请求方式完成对资源(url)的操作,get , post,put,delete,对应的是咱们对资源的,查,改,增,删,四个操作,具体的来说一般情况下,get用于获取、查询资源信息。而post一般用于更新资源信息
区别:

  1. get请求提交的数据会在地址栏显示出来,而post请求不会在地址栏显示出来
  2. 传输数据的大小。http get请求由于浏览器对地址长度有限制,所以就导致对传输的数据有限制,而post不会
  3. 安全性的问题,post的安全性要比get的安全性要高。
Servlet的生命周期

       
Servlet有良好的生命周期的定义,他包括加载和实例化、初始化、处理请求以及服务结束。这个生命周期是由javax.servlet.Servlet接口中的int 、service、destroy方法来描述。
Servlet启动时,开始加载servlet生命周期的开始,servlet被服务器实例化后,容器运行其init方法,请求到达时运行去service方法,service方法会自动派遣运行对应的doXXX等。然后当服务器决定将实例销毁的时候,这个时候调用destroy方法
 

jsp和Servlet的相同点和不同点

Jsp本质:Jsp是servlet的扩展,所有的jsp文件都会被翻译成为一个继承HttpServlet的类,然后对外提供服务
不同点
Jsp偏重于视图,而servlet只要用于控制逻辑
servlet如果想要实现html的功能,必须使用writer输出对应的html,这个比较麻烦,jsp是servlet和html组合起来的,做界面展示比较方便,但是想要嵌入逻辑比较复杂。

Session和Cookie的区别和使用场景,你在项目当中哪些地方用到了
  1. Session和cookie都是会话跟踪技术,
  2. cookie是通过在客户端记录信息来确定用户身份,
  3. session是通过服务端来记录用户的身份。但是session的实现依赖于cookie,sessionId(session的唯一标识)

区别:

  1. Session放在服务器,而cookie放在浏览器
  2. Cookie不是很安全,别人可以通过分析你本地的cookie进行cookie的欺诈,考虑到安全,我们用session
  3. Session会在服务器保存一定的时间,也就是说,当访问增多的时候,会比较占用服务器的性能,如果将来考虑到服务器压力的时候,我们要用cookie。
  4. Cookie保存的数据不能超过4k,很多浏览器都限制一个站点最多保存50个cookie

个人建议:要将个人信息保存到session当中.其他的信息,如果需要保留我们放到cookie:购物车信息。
 

  简单介绍了一下Ajax
  1. 什么是ajax:异步的js和xml
  2. 作用是什: 我们可以通过ajax来与服务器进行交互,进行数据的交换,可以实现局部刷新,这就意味着,我们可以不重新加载整个网页的情况下,对网页进行更新。
  3. 怎么实现:我们通过XmlHttpRequest这个对象,使用这个对象来异步的向服务器发送请求,获取响应,完成局部刷新。
  4. 使用场景:登录失败不跳转页面,注册时用户名是否存在。二级联动,三级联动
Spring MVC的执行流程

 

  1. 用户向服务器发送请求,请求被spring前端控制器捕获,
  2. 前端控制器对请求的url进行解析,得到url根据这个url调用HandlerMapping 获得该handler配置的相关信息(包括handler对象以及handler对象对应的拦截器)返回的是以handlerExcutionChain对象的形式进行返回
  3. 前端控制器,根据获得的handler,选择一个合适的handlerAdapter,获取到request中的数据模型,填充到handler,并开始执行整个流程,然后向前端控制器返回model and view
  4. 前端控制器根据返回的model and view,选择一个合适的ViewResolver对象。
  5. 最后一个就是通过ViewResolver对象结合model and view进行视图渲染,将渲染结果返回给客户端 
简单介绍一下Spring或者Spring的两大核心

Spring是将j2EE的应用程序框架,轻量级,可以单独使用也可以整合我们

介绍一下redis


概念:Redis是一个key_value的非关系型数据库,它会先把数据放到内存中,会根据一定的策略持久化到磁盘当中,即使断电也不会丢失,支持的数据类型比较多。(数据结构)
作用:Redis主要是用来缓存数据库当中的数据,在web集群当中用作中央缓存存放session

redis的使用场景

  1. 缓存:把经常需要查询的,很少修改的数据,放到读取速度很快的空间当中(redis),来减少访问时间,减轻数据压力
  2. 计数器:Redis当中的计数器是原子性的内存操作;可以解决数据库溢出的问题。
  3. Session缓存服务器:web集群当中用作中央缓存存放session

redis存储对象的方式

1、我们需要把对象转化成json字符串,当做字符串处理,直接我们就可以使用set get来设置
优点就是:获取和设置的时候比较简单
缺点是:redis没有专门的方法去把对象转化成json形式

2.字节的形式,必要的时候,我们可以把对象序列化,转化成字节保存

我们会担心json在转化成对象的时候会消耗我们的资源的?
第一点:我们使用lib库转化成json的形式的时候,是否会存在性能问题
第二点,数据量的级别,百万级别的大对象,我们就不要用lib转json的形式,我们就直接用序列化的形式
根据应用场景结合业务---redis其实对string支持的最好,如果数据量少,我们还是要用json的形式

redis数据淘汰机制

背景:在redis当中,我们用户是可以设置最大使用内存的大小,但是内存是固定的,所以需要我们有一定的数据淘汰机制

  1. volatile_lru 从已设置过期时间的数据集中挑选最近很少使用的数据淘汰
  2. volatile_ttl 从已设置过期时间的数据集中选择将要过期的数据淘汰
  3. volatile_random: 从已设置过期时间的数据集中任意选择数据淘汰
  4. allkeys_lru:从数据集中挑选最近使用的数据淘汰
  5. allkeys_ random:从数据集当中任意选择数据淘汰
  6. no_enviction:禁止驱逐数据

 

消息队列

为什么要使用消息队列?

解耦、异步、削峰

使用消息队列有什么缺点?

  1. 系统可用性降低:你想啊,本来其他系统只要运行好好的,那你的系统就是正常的。现在你非要加个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性降低
  2. 系统复杂性增加:要多考虑很多方面的问题,比如一致性问题、如何保证消息不被重复消费,如何保证保证消息可靠传输。因此,需要考虑的东西更多,系统复杂性增大

怎么选型——ActiveMQ,RabbitMQ,RocketMQ,Kafka

建议选RabbitMQ.一方面,erlang语言天生具备高并发的特性,而且他的管理界面用起来十分方便。虽然RabbitMQ是开源的,然而国内有几个能定制化开发erlang的程序员呢?所幸,RabbitMQ的社区十分活跃,可以解决开发过程中遇到的bug,这点对于中小型公司来说十分重要。

不考虑rocketmq和kafka的原因是,一方面中小型软件公司不如互联网公司,数据量没那么大,选消息中间件,应首选功能比较完备的,所以kafka排除。不考虑rocketmq的原因是,rocketmq是阿里出品,如果阿里放弃维护rocketmq,中小型公司一般抽不出人来进行rocketmq的定制化开发,因此不推荐。
(2)大型软件公司,根据具体使用在rocketMq和kafka之间二选一。一方面,大型软件公司,具备足够的资金搭建分布式环境,也具备足够大的数据量。针对rocketMQ,大型软件公司也可以抽出人手对rocketMQ进行定制化开发,毕竟国内有能力改JAVA源码的人还是相当多的。至于kafka,根据业务场景选择,如果有日志采集功能,肯定是首选kafka了。具体该选哪个看使用场景。

如何保证消息不被重复消费?如何保证消息队列的幂等性? 

回答:先来说一下为什么会造成重复消费?
  其实无论是哪种消息队列,造成重复消费原因其实都是类似的。正常情况下,消费者在消费消息时候,消费完毕后,会发送一个确认信息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除。只是不同的消息队列发送的确认信息形式不同,例如RabbitMQ是发送一个ACK确认消息,RocketMQ是返回一个CONSUME_SUCCESS成功标志,kafka实际上有个offset的概念,就是每一个消息都有一个offset,kafka消费过消息后,需要提交offset,让消息队列知道自己已经消费过了。那造成重复消费的原因?,就是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将该消息分发给其他的消费者。
如何解决?这个问题针对业务场景来答分以下几点
  (1)比如,你拿到这个消息做数据库的insert操作。那就容易了,给这个消息做一个唯一主键,那么如果出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。
  (2)再比如,你拿到这个消息做redis的set的操作,那就容易了,不用解决,因为你无论set几次结果都是一样的,set操作本来就算幂等操作
  (3)如果上面两种情况还不行,上大招。准备一个第三方介质,来做消费记录。以redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>以K-V形式写入redis。那消费者开始消费前,先去redis中查询有没消费记录即可。

如何保证消费的可靠性传输?

回答:其实这个可靠性传输,每种MQ都要从三个角度来分析:生产者弄丢数据、消息队列弄丢数据、消费者弄丢数据
RabbitMQ
(1)生产者丢数据
从生产者弄丢数据这个角度来看,RabbitMQ提供transaction和confirm模式来确保生产者不丢消息。
transaction机制就是说,发送消息前,开启事物(channel.txSelect()),然后发送消息,如果发送过程中出现什么异常,事物就会回滚(channel.txRollback()),如果发送成功则提交事物(channel.txCommit())。
然而缺点就是吞吐量下降了。因此,生产上用confirm模式的居多。一旦channel进入confirm模式,所有在该信道上面发布的消息都将会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后,rabbitMQ就会发送一个Ack给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了.如果rabiitMQ没能处理该消息,则会发送一个Nack消息给你,你可以进行重试操作。
(2)消息队列丢数据
处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。
那么如何持久化呢,这里顺便说一下吧,其实也很容易,就下面两步
1、将queue的持久化标识durable设置为true,则代表是一个持久的队列
2、发送消息的时候将deliveryMode=2
这样设置以后,rabbitMQ就算挂了,重启后也能恢复数据

消费者丢数据
消费者丢数据一般是因为采用了自动确认消息模式。这种模式下,消费者会自动确认收到信息。这时rahbitMQ会立即将消息删除,这种情况下如果消费者出现异常而没能处理该消息,就会丢失该消息。
至于解决方案,采用手动确认消息即可。
KAFKA
(1)生产者丢数据
在kafka生产中,基本都有一个leader和多个follwer。follwer会去同步leader的信息。因此,为了避免生产者丢数据,做如下两点配置
1.    第一个配置要在producer端设置acks=all。这个配置保证了,follwer同步完成后,才认为消息发送成功。
2.    在producer端设置retries=MAX,一旦写入失败,这无限重试
(2)消息队列丢数据
针对消息队列丢数据的情况,无外乎就是,数据还没同步,leader就挂了,这时zookpeer会将其他的follwer切换为leader,那数据就丢失了。针对这种情况,应该做两个配置。
1.    replication.factor参数,这个值必须大于1,即要求每个partition必须有至少2个副本
2.    min.insync.replicas参数,这个值必须大于1,这个是要求一个leader至少感知到有至少一个follower还跟自己保持联系
这两个配置加上上面生产者的配置联合起来用,基本可确保kafka不丢数据
(3)消费者丢数据
这种情况一般是自动提交了offset,然后你处理程序过程中挂了。kafka以为你处理好了。再强调一次offset是干嘛的
解决方案也很简单,改成手动提交即可。