缓存的失效可以定期失效,也可以在数据发生变化的时候失效,如果按数据发生变化让缓存失效,还可以分粗粒度失效和细粒度失效。
像快递送货一样,货单上填写地址的规则以及怎么根据填写的内容找到客户,这就相当于IP协议,而送货时要先打电话,然后将货物送过去,最后客户签收时要签字就相当于TCP协议。
三次握手和四次挥手保证了连接的可靠性,不过这种模式也有它的缺点,首先是在传输效率上会比较低,另外三次握手的过程中客户端需要发送两次数据才可以建立连接,这种特征可能被一些别有用心的人利用,比如,发出第一次握手后就不回应第三次握手了,这时服务端会以为是第二次握手的数据在传输过程中丢失了,然后重新发送第二次握手,默认情况下会一直发送五次,如果发送五次后还收不到第三次握手则会丢弃请求。这就是DDOS
攻击中的SYN Flood
攻击,对于这种攻击的一种应对方法是设置第二次请求的重发次数,不过重发的次数大小也可能导致正常的请求中因为网络没有收到第二次握手而连接失败的情况。
通过TCP/IP
协议、HTTP
协议已经可以得到数据了,Servlet
的作用是对接收到的数据进行处理并生成要返回给客户端的结果。
域名解析有很多种解析的类型,如常用的A记录和CNAME记录。A记录是将域名解析到IP(一个域名可以有多条A记录),CNAME记录是将域名解析到另一个域名(也就是作为另一个域名的别名),查找时会返回目标域名所对应的IP
ServerSocket
的使用可以分为三步:
- 创建ServerSocket
:
- 调用创建出来的ServerSocket
的accept
方法进行监听。accept
方法是阻塞方法,也就是说调用accept
方法后程序会停下来等待连接请求,在接收到请求之前程序都不会往下走;当接收到请求后accept
方法会返回一个Socket
- 使用accept
方法返回的Socket
与客户端进行通信
普通Socket
处理请求的模式:收到请求,处理,处理好了,收下一个请求。
NIOSocket
处理请求的模式:快递并不会一件一件地送,而是将很多件货一起拿去送,而且在中转站都有专门的分拣员负责按配送范围将货物分给不同的送货员,这样效率就提高了很多。
NIOSocket
使用中首先要创建ServerSocketChannel
,然后注册Selector
,接下来就可以用Selector
接受请求并处理了。
NIOSocket
中服务端的处理过程可以分为5步:
1、创建ServerSocketChannel
并设置相应参数
2、创建Selector
并注册到ServerSocketChannel
上
3、调用Selector
的select
方法等待请求
4、Selector
接收到请求后使用selectedKeys
返回SelectionKey
集合
5、使用SelectionKey
获取到Channel
,Selector
和操作类型并进行具体操作
// 恢复到初始状态
public final Buffer clear()
{
position = 0;
limit = capacity;
mark = -1;
return this;
}
// 开启读的模式
public final Buffer flip()
{
limit = position;
position = 0;
mark = -1;
return this;
}
Servlet
接口
- init
方法在容器启动时被容器调用(当load-on-startup
设置为负数或者不设置时会在Servlet
第一次用到时才被调用),只会调用一次
- getServletConfig
方法用于获取ServletConfig
- service
方法用于具体处理一个请求
- getServletInfo
方法可以获取一些Servlet
相关的信息,默认返回空字符串
- destroy
主要用于在Servlet
销毁(一般指关闭服务器)时释放一些资源,只会调用一次
getServletName
用于获取Servlet的名字,也就是我们在web.xml
中定义的servlet-name
;getInitParameter
方法用于获取init-param
配置的参数;getInitParameterNames
用于获取配置的所有init-param
的名字集合;getServletContext
的返回值代表的是我们这个应用本身。ServletConfig
是Servlet
级的,而ServletContext
是Context
(也就是Application
)级的。
String contextLocation = getServletConfig().getServletContext().getInitParameter("contextConfigLocation");
String servletLocation = getServletConfig().getInitParameter("contextConfigLocation");
GenericServlet
GenericServlet
是Servlet
的默认实现,主要是做了三件事:
- 实现了ServletConfig
接口,我们可以直接调用ServletConfig
里面的方法
- 提供了无参的init
方法
- 提供了log
方法
GenericServlet
实现了Servlet
的init(ServletConfig config)
方法,在里面将config
设置给了内部变量config
,然后调用了无参的init()
方法
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
HttpServlet
HttpServlet
是用HTTP
协议实现的Servlet
的基类。HttpServlet
主要重写了service
方法。在service
方法中首先将ServletRequest
和ServletResponse
转换为了HttpServletRequest
和HttpServletResponse
,然后根据Http
请求的类型不同将请求路由到了不同的处理方法
Tomcat的顶层结构
Tomcat
中最顶层的容器叫Server
,代表整个服务器,Server
中包含至少一个Service
,用于具体提供服务。Service
主要包含两部分:Connector
和Container
。Connector
用于处理连接相关的事情,并提供Socket
与request
、response
的转换,Container
用于封装和管理Servlet
,以及具体处理request
请求。
一个Tomcat
中只有一个Server
,一个Server
可以包含多个Service
,一个Service
只有一个Container
,但可以有多个Connectors
(因为一个服务可以有多个连接)
Server的启动过程
await方法处理的大概逻辑是首先判断端口号port,然后根据port的值分为三种处理方法:
- port为-2,则会直接退出,不进入循环
- port为-1,则会进入一个while(!stopAwait)的循环,只有在外部调用stop方法才会退出循环
- port为其他值,则也会进入一个while(!stopAwait)的循环,不过同时会在port所在的端口启动一个ServerSocket来监听关闭命令,如果姐收到了则会使用break跳出循环