2. 简单HTTP协议
HTTP 协议用于客户端和服务器端之间的通信应用 HTTP 协议时,必定是一端担任客户端角色,另一端担 任服务器端角色
有时候,按实际情况,两台计算机作为客户端和服务器端的角色有可能会互换。但就仅从一条通信路线来说,服务器端和客户端的角色是确定的,而用HTTP协议能够明确区分哪端是客户端,哪端是服务器端
通过请求和响应的交换达成通信HTTP 协议规定,请求从客户端发出,最后服务器端响应该请求并返回
示例:
请求报文123GET /index.htm HTTP/1.1 Host: hackr.jp
GET表示请求访问服务器的类型,称为:方法(method)
字符串 /index.htm 指明了请求访问的资源对象,叫做请求 URI(request-URI)
最后的 HTTP/1.1,即 HTTP 的版本号,用来提示客户端使用的 HTTP 协议功能。
这段请求内容的意思是:请求访问某台 HTTP 服务器上的 /index.htm 页面资源。
请求报文是由请求方法、请求URI、协议版本、可选的请求首部字段和内容实体构成的。
返回报文123456 ...
2. Redis 的线程模型
Redis 在单线程下还可以支持高并发的一个重要原因就是 Redis 的线程模型:基于非阻塞的IO多路复用机制。这篇文章就 Redis 的线程模型做详细说明。
Redis 是基于 reactor 模式开发了网络事件处理器,这个处理器叫做文件事件处理器(file event handler)。由于这个文件事件处理器是单线程的,所以 Redis 才叫做单线程的模型。采用 IO 多路复用机制同时监听多个 Socket,根据 socket 上的事件来选择对应的事件处理器来处理这个事件。模型如下图:
从上图可知,文件事件处理器的结构包含了四个部分:
多个 Socket
IO 多路复用程序
文件事件分派器
事件处理器
多个 socket 会产生不同的事件,不同的事件对应着不同的操作,IO 多路复用程序监听着这些 Socket,当这些 Socket 产生了事件,IO 多路复用程序会将这些事件放到一个队列中,通过这个队列,以有序、同步、每次一个事件的方式向文件时间分派器中传送。当事件处理器处理完一个事件后,IO 多路复用程序才会继续向文件分派器传送下一个事件。
在 Redis 中,Socket ...
2. nginx event配置
123456789101112131415events { # 设置网络连接序列化,防止惊群现象发生,默认on accept_mutex on; # 设置一个进程是否同时接受多个网络连接,默认off multi_accept on; # 事件驱动模型 # use epoll; # 允许的连接数 worker_connections 51200; client_header_buffer_size 4k; open_file_cache max=2000 inactive=60s; open_file_cache_valid 60s; open_file_cache_min_uses 1;}
accept_mutex on
惊群现象:一个网路连接到来,多个睡眠的进程被同时叫醒,但只有一个进程能获得链接,这样会影响系统性能。设置网路连接序列化,防止惊群现象发生,默认为on
multi_accept on
是否允许同时接受多个网络连接
只能在events模块设置,Nginx服务器的每个工作进程可以同时接受多个新的网络连接,但是需要在配置文 ...
2. 二叉树
每一个节点最多含有两个子树的树称为二叉树。在二叉树的概念下又衍生出满二叉树和完全二叉树的概念。
满二叉树除最后一层无任何子节点外,每一层上的全部结点都有两个子结点。也能够这样理解,除叶子结点外的全部结点均有两个子结点。节点数达到最大值,全部叶子结点必须在同一层上
完全二叉树若设二叉树的深度为h,除第 h 层外,其它各层 (1~(h-1)层) 的结点数都达到最大个数,第h层全部的结点都连续集中在最左边,这就是完全二叉树。
二叉树的遍历方式:遍历顺序
先序遍历:先根节点->遍历左子树->遍历右子树
中序遍历:遍历左子树->根节点->遍历右子树
后序遍历:遍历左子树->遍历右子树->根节点
示例:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 ...
3. 容器的初始化(三)之 Servlet 3.0 集成
Servlet 3.0 新特性servlet3.0 首先提供了 @WebServlet ,@WebFilter 等注解,这样便有了抛弃 web.xml 的第一个途径,凭借注解声明 servlet 和 filter 来做到这一点。
除了这种方式,servlet3.0 规范还提供了更强大的功能,可以在运行时动态注册 servlet ,filter,listener。以 servlet 为例,过滤器与监听器与之类似。ServletContext 为动态配置 Servlet 增加了如下方法:
ServletRegistration.Dynamic addServlet(String servletName,Class<? extends Servlet> servletClass)
ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet)
ServletRegistration.Dynamic addServlet(String servletName, String clas ...
3. 类加载机制
类加载机制是指.class文件加载到JVM,并形成Class对象的机制,之后应用就可对Class对象进行实例化并调用,类加载机制可在运行时动态加载外部的类、远程网络下载过来的class文件等。除了该动态化的优点外,还可通过JVM的类加载机制来达到类隔离的效果,例如Application Server中通常要避免两个应用的类互相干扰。
JVM将类加载过程划分为三个步骤:装载、链接和初始化。装载和链接过程完成后,即将二进制的字节码转换为Class对象;初始化过程不是加载类时必须触发的,但最迟必须在初次主动使用对象前执行,其所作的动作为给静态变量赋值、调用()等。
加载的步骤如下所示:
装载(Load)->链接(Link)[校验(Verify)->准备(Prepare)->解析(Resolve)]->初始化(Initialize)
装载装载过程负责找到二进制字节码并加载至JVM中,JVM通过类的全限定名(com.bluedavy. HelloWorld)及类加载器(ClassLoaderA实例)完成类的加载,同样,也采用以上两个元素来标识一个被加载了的类:类的全 ...
3. 内存调优及内存分配与回收策略
内存分配与回收策略对象的内存分配,往大方向讲,就是在堆上分配,对象主要分配在新生代的Eden区,如果启动了本地县城分配缓存,将按照线程优先在TLAB上分配,少数情况下也可能会直接分配在老年代中,分配规则并不是百分百固定的,其细节决定于当前使用的是哪一种垃圾收集器组合,还有虚拟机中与内存相关的参数的设置。
对象优先在Eden分配大多数情况下,对象在新生代Eden区中分配,当Eden区没有足够空间进行分配时,虚拟机将进行一次Minor GC
Minor GC和Full GC有什么不一样吗-新生代GC(Minor GC):指发生在新生代的垃圾收集动作,因为java对象大多都具备朝生夕灭的特性,所以Minor GC非常频繁,一般回收速度也比较快。
-老年代GC(Major GC/Full GC):指发生在老年代的GC,出现了Major GC,经常会伴随着至少一次的Minor GC(但非绝对,在Parallel Scavenge收集器的手机策略里有直接进行Major GC的策略选择过程)Major GC的速度一般会比Minor GC慢10倍以上。
大对象直接进入老年代所谓的 ...
3. 网络IO消耗分析
对于分布式JAVA,网络IO消耗值得关注。尤其要注意网卡中断是不是均衡的分配到各个CPU的。 可通过
1cat /proc/interrupts 查看
linux中可以通过sar来分析网络IO的消耗情况
sar输入
1sar -n FULL 1 2 //以1秒为频率,总共输出2次网络IO消耗情况
对于JAVA应用而言,使用的主要是tcpsck和udpsck
用JAVA实现的网络通信,通常要将对象序列化为字节流进行发送,或者读取字节流,并反序列化为对象。 这个过程需要消耗JVM堆内存,而堆内存大小是有限的,因此一般JAVA不会造成网络IO的消耗严重
总结
如果网络IO过高,表明有线程在频繁的序列号发送字节流
可先用sar -n full 1 3 查看tcpsck,udpsck等参数确认,然后结合pidstat和jstack找到对应的代码进行分析。(序列化和反序列化会消耗JVM堆内存,且一般局域网速率都至少千M,一般很少出现网络IO高的问题)
解决方法:限流,调整发送数据包的频率
3. 执⾏插件逻辑
Plugin 实现了 InvocationHandler 接口,因此它的 invoke 方法会拦截所有的方法调用。invoke 方法会对所拦截的方法进行检测,以决定是否执行插件逻辑。该方法的逻辑如下:
12345678910111213141516171819// -☆- Pluginpublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { // 获取被拦截方法列表,比如:signatureMap.get(Executor.class), // 可能返回 [query, update, commit] Set<Method> methods = signatureMap.get(method.getDeclaringClass()); // 检测方法列表是否包含被拦截的方法 if (methods != null && method ...
3. LruCache
LruCache,顾名思义,是一种具有 LRU 策略的缓存实现类。除此之外,MyBatis 还提供了具有 FIFO 策略的缓存 FifoCache。不过并未提供 LFU 缓存
源代码:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869public class LruCache implements Cache { private final Cache delegate; private Map<Object, Object> keyMap; private Object eldestKey; public LruCache(Cache delegate) { this.delegate = delegate; setSize(1024); } publi ...