nekolr's blog

爱吃咖喱棒的打字员DA☆ZE~

0%

我们知道,Session 是由服务端生成的,在生成 Session 的同时还会生成一个唯一的 Session Id。一般的 Web 应用会在服务器内存当中开辟一部分内存用来存储 Session,同时这个 Session Id 会以 Cookie 的形式发送给浏览器,浏览器会将它保存到本地磁盘当中,在下次请求同一个域时会一并提交。然而当系统架构升级为分布式架构或者微服务架构时,作为流量入口的网关会通过负载均衡策略将用户的请求转发到不同的 Web 容器当中,这就可能会出现用户登录系统后,再次发送请求则被告知没有登录的情况。此时就需要某种机制来确保所有的 Web 容器能够共享用户的 Session 信息。

Read more »

像 Tomcat、Jetty、Undertow 等这些 Web 容器(也可以看作是 Servlet 容器),它们既可以运行动态程序(Servlet/JSP),又可以处理静态资源,但是一般情况下,它们处理静态资源的能力与 Apache、Nginx 等这些 HTTP Server 相比要弱很多,因此在很多系统中会采用动静分离的设计,即使用 HTTP Server 作为入口网关,所有的静态资源由 HTTP Server 直接处理,而其他的动态内容则转发给 Servlet 容器。

Read more »

Dubbo 良好的扩展性得益于它的 SPI 机制,在 Dubbo 中,几乎所有的功能组件都是基于 SPI 机制实现的。由于 Java SPI 机制存在一些问题,且无法满足 Dubbo 的需求,于是 Dubbo SPI 就在 Java SPI 的思想上做了改进,形成了一套自己的配置规范和特性。

Read more »

一个最简单的 RPC 需要满足几个基本的要求。首先是通信,一般可选的有 HTTP 和 TCP,这里选择 TCP,直接使用 Java Socket 处理通信。然后就是寻址,也就是如何找到要调用的方法。这里根据服务消费者提供的基本调用信息,然后利用 Java 的反射机制进行调用。服务消费者在进行远程调用时就像调用本地方法一样的效果则依靠 Java 的动态代理机制来实现。最后是参数序列化和反序列化,这里使用最简单的 Java 原生的序列化机制。

Read more »

虚拟机把描述类的数据从 Class 文件加载到内存,并对数据进行校验、解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型,这就是虚拟机的类加载机制。Java 类型的加载、连接和初始化都是在程序运行期间完成的,这种方式虽然会增加类加载时的性能开销,但是能够为 Java 应用提供更好的灵活性,Java 天生可以动态扩展的语言特性就是依靠运行期动态加载和动态连接这个特点实现的。例如,我们编写一个面向接口的应用,可以等到运行时再指定它的实现类;我们可以通过 Java 预定义的或者我们自定义的类加载器,从网络或者其他地方加载一个二进制的流作为应用程序代码的一部分。

Read more »

代理模式也叫做委托模式,许多其他的模式,比如状态模式、策略模式、访问者模式等本质上都是在更加特殊的场景中采用了委托模式。有时候我们可能会把代理模式与装饰器模式搞混,简单来说,装饰器模式更加专注于向对象动态地添加或增强功能,而代理模式则更专注于控制对对象的访问。装饰器模式强调的是增强自身,在被装饰之后你能够在被增强的类上使用增强后的功能,但是增强后的你还是你,只不过能力更强了而已。代理模式则强调要让别人帮你去做一些与你本身没有太大关联的职责,比如记录日志、设置缓存等。

Read more »

好久不用 MyBatis,都快忘了怎么使用了,重新看一遍文档并简单记录下来,方便下次查阅。

Read more »

应用程序与数据库软件进行交互可以有多种方式,其中常见的就是 JDBC 和 ODBC,它们都是在 X/Open SQL CLI(Call Level Interface)的基础上完成,但是 JDBC 更适合在 Java 应用中使用。JDBC 提供了一套用于 Java 程序与 DBMS 进行交互的 API,即只是制定了这个规范,具体的实现则交给了不同的数据库软件厂商。

Read more »

我们知道,HashMap 是非线程安全的,在多线程环境下我们可能需要使用线程安全的 Map 容器,可选的有 HashTable 和 ConcurrentHashMap。HashTable 将所有可能出现线程安全问题的方法都使用 synchronized 来修饰,这种做法虽然简单粗暴,但是由于锁的粒度较大(所有访问 HashTable 的线程都在竞争同一把锁),导致它的并发性能较差。而 ConcurrentHashMap 则不同,在 JDK 7 中,它将锁细化为多把锁,每一把锁只用于锁定容器中的一部分数据,那么当多线程访问容器中不同数据段的数据时,线程之间是不存在锁竞争的,这就是我们常说的锁分段技术。但是到了 JDK 8,ConcurrentHashMap 又出现了很大的变化,最大的变化就是不再使用锁分段技术,转而使用 CAS 和 synchronized,这在文章中会具体介绍。

Read more »

我们可以把锁理解成门票,只有当线程拿到了门票才能进入临界区。我们可以用一个状态变量 state 表示锁,当 state 为 true 时就表示已经获取到了锁,为 false 时就表示锁已经被其他线程占用。那么当锁被占用时,应该怎么处理?基本上有两种思路,其中一种就是循环检测直到锁可用,也就是自旋锁;另一种就是让出 CPU 时间片,等待唤醒通知。这里主要讨论自旋的算法,为深入学习 AQS 做铺垫。

Read more »