0%

Shiro 简介:轻量级 Java 安全框架的核心与实现

Apache Shiro 是一款功能强大且易于使用的开源安全框架,专注于解决 Java 应用中的身份认证、授权、会话管理和加密等安全问题。与 Spring Security 相比,Shiro 以其简洁的 API、灵活的配置和较低的学习成本,成为中小型应用和快速开发场景的首选安全框架。

Shiro 的核心功能

Shiro 围绕 “安全” 提供四大核心功能,覆盖了大多数应用的安全需求:

核心功能 说明
Authentication(身份认证) 验证用户身份(“你是谁”),如用户名密码登录、第三方登录(OAuth)等。
Authorization(授权) 控制用户权限(“你能做什么”),如判断用户是否有权限访问某个接口或按钮。
Session Management(会话管理) 管理用户会话(即使在非 Web 环境中),支持会话过期、存储、失效等。
Cryptography(加密) 提供安全的加密算法(如 MD5、SHA),用于密码加密、数据脱敏等。

Shiro 的架构与核心对象

架构

Shiro 的架构设计清晰,通过一系列核心对象协同工作,实现安全功能。其整体架构如图所示,核心对象包括SubjectSecurityManagerRealms等。

1. 核心对象详解

(1)Subject
  • 定义:与应用交互的 “当前操作用户”(可以是人类用户、第三方服务等)。
  • 特点:
    • 所有操作都通过Subject发起(如登录、权限验证);
    • 内部绑定到SecurityManager,实际功能由SecurityManager代理实现;
    • 可通过SecurityUtils.getSubject()获取当前线程的Subject实例。
(2)SecurityManager
阅读全文 »

即时编译器(JIT):Java 性能优化的核心引擎

即时编译器(Just-In-Time Compiler,JIT)是 HotSpot 虚拟机提升代码执行效率的关键组件。它通过将 “热点代码”(频繁执行的代码)编译为本地机器码,弥补了解释器执行效率低的缺陷,使 Java 既能保持跨平台性,又能接近原生代码的运行速度。

解释器与编译器的协同:混合模式的优势

Java 采用 “解释器 + 即时编译器” 的混合架构(mixed mode),两种组件各有侧重,协同工作:

解释器的角色

解释器是 JVM 执行代码的基础组件,其工作方式是逐行翻译字节码为机器码并立即执行

  • 优点:启动速度快(无需提前编译),适合程序启动阶段或低频执行的代码(如初始化代码)。
  • 缺点:执行效率低(每条指令需重复翻译),不适合高频执行的代码(如循环、核心业务方法)。

即时编译器的角色

JIT 编译器的核心目标是将热点代码编译为优化后的本地机器码并缓存,避免重复解释。

  • 优点:执行效率高(机器码直接运行,无需重复翻译),适合高频执行的热点代码。
  • 缺点:编译过程本身耗时(需分析代码、优化、生成机器码),不适合启动阶段(可能拖慢启动速度)。

混合模式的价值

混合模式结合了两者的优势:

阅读全文 »

IP 地址存储方案:IPv4 与 IPv6 的高效处理方式

在开发中,IP 地址(尤其是用户访问日志、设备管理场景)需要高效存储和查询。直接存储字符串形式的 IP 不仅占用空间大,还不利于范围查询(如判断某个 IP 是否在指定网段内)。本文将详细讲解 IPv4 和 IPv6 地址的数字化存储方案,包括转换原理、代码实现及应用场景。

IPv4 地址的存储:使用 long 类型

IPv4 地址由 4 个 0-255 的整数组成(如 192.168.1.1),总长度为 32 位(4×8 位),刚好可以用一个 64 位的 long 类型存储。

转换原理

将 IPv4 地址的 4 个分段视为 32 位二进制数的 4 个字节,按从左到右的顺序拼接后转换为十进制整数。例如:

  • IP 地址 192.168.1.1 可拆分为 19216811
  • 转换为二进制:11000000.10101000.00000001.00000001
  • 拼接后为 32 位二进制数,转换为十进制即 3232235777

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class IPv4Converter {  

/**
* 将 IPv4 字符串转换为 long 类型
* @param ipString IPv4 地址(如 "192.168.1.1")
* @return 对应的 long 值,转换失败返回 -1
*/
public static long ipToLong(String ipString) {
// 拆分 IP 地址为 4 个分段
String[] segments = ipString.split("\\.");
if (segments.length != 4) {
return -1; // 格式错误
}

long result = 0;
try {
// 每个分段左移相应位数后累加(第一段占最高 8 位,第四段占最低 8 位)
result += Long.parseLong(segments[0]) << 24; // 第一段:左移 24 位
result += Long.parseLong(segments[1]) << 16; // 第二段:左移 16 位
result += Long.parseLong(segments[2]) << 8; // 第三段:左移 8 位
result += Long.parseLong(segments[3]); // 第四段:不左移
return result;
} catch (NumberFormatException e) {
return -1; // 分段包含非数字
}
}

/**
* 将 long 类型转换为 IPv4 字符串
* @param ipLong 用 long 存储的 IPv4 地址
* @return 对应的 IPv4 字符串
*/
public static String longToIp(long ipLong) {
// 从 long 中提取 4 个分段(通过右移和与运算)
StringBuilder ip = new StringBuilder();
ip.append((ipLong >>> 24)).append("."); // 提取最高 8 位
ip.append((ipLong >>> 16) & 0xFF).append("."); // 提取次高 8 位(&0xFF 确保只取 8 位)
ip.append((ipLong >>> 8) & 0xFF).append("."); // 提取次低 8 位
ip.append(ipLong & 0xFF); // 提取最低 8 位
return ip.toString();
}

// 测试
public static void main(String[] args) {
String ip = "255.255.255.255";
long ipLong = ipToLong(ip);
System.out.println(ipLong); // 输出:4294967295
System.out.println(longToIp(ipLong)); // 输出:255.255.255.255
}
}

优势与应用

阅读全文 »

Elasticsearch 集群发现机制:Zen Discovery 详解

Elasticsearch 集群的节点发现机制是确保节点能够自动识别集群成员、选举主节点并维持集群一致性的核心模块。默认采用 Zen Discovery 机制,支持单播(Unicast)和多播(Multicast)两种方式,其中单播是生产环境的推荐配置。

Zen Discovery 核心功能

Zen Discovery 负责集群的以下关键流程:

  1. 节点发现:新节点加入集群时,通过预配置的节点列表找到集群中的现有节点。
  2. 主节点选举:当集群无主节点或主节点故障时,自动选举新的主节点。
  3. 集群状态同步:主节点与其他节点同步集群元数据(如索引、分片分布)。

节点发现方式

单播(Unicast):生产环境首选

单播是通过预先配置的节点列表(种子节点)进行节点发现,避免多播的网络广播开销和安全风险,是 Elasticsearch 的默认推荐方式。

配置方式

elasticsearch.yml 中指定种子节点列表:

1
2
3
4
discovery.zen.ping.unicast.hosts:
- "node1.example.com:9300" # 节点1的地址和Transport端口(默认9300)
- "node2.example.com:9300" # 节点2的地址和端口
- "192.168.1.100:9300" # 可直接使用IP
工作原理
  1. 新节点启动时,向 discovery.zen.ping.unicast.hosts 中的种子节点发送 ping 请求。
  2. 种子节点回应集群中的其他节点信息,新节点据此加入集群。
  3. 无需配置所有节点,只需包含集群中少量节点(如主节点候选节点),新节点会自动发现其他成员。

多播(Multicast):不推荐用于生产

多播通过网络广播寻找集群节点,无需预先配置节点列表,但存在以下问题:

  • 网络广播占用带宽,不适合大规模集群。
  • 存在安全风险(非集群节点可能收到广播)。
  • 部分网络环境(如云服务)禁用多播。
配置方式(已过时,6.x 后逐步移除)
1
2
3
discovery.zen.ping.multicast.enabled: true  # 启用多播(默认关闭)
discovery.zen.ping.multicast.group: "224.2.2.4" # 多播组地址
discovery.zen.ping.multicast.port: 54328 # 多播端口

核心配置参数

节点发现与 ping 配置

  • discovery.zen.ping_timeout:节点间 ping 超时时间(默认 3s)。网络较慢时可增大(如 10s),避免误判节点故障。
  • discovery.zen.join_timeout:节点加入集群的超时时间(默认 60s),为 ping_timeout 的 20 倍。
  • discovery.zen.ping.unicast.concurrent_connects:单播时的最大并发连接数(默认 10),节点较多时可适当增大。

主节点选举与脑裂防护

  • discovery.zen.minimum_master_nodes:防止脑裂(集群分裂为多个子集群)的关键参数,需设置为 (主节点候选数 / 2) + 1

    例如:

    • 3 个主节点候选时,值为 2;
    • 5 个主节点候选时,值为 3。
      确保只有超过半数的主节点候选同意,才能选举新主节点。
  • discovery.zen.no_master_block:无主节点时的阻塞策略(默认 write):

    • write:阻塞写入操作,允许读取;
    • all:阻塞所有操作。

故障检测

  • discovery.zen.fd.ping_interval:主节点检测其他节点的频率(默认 1s)。
  • discovery.zen.fd.ping_retries:ping 失败重试次数(默认 3 次)。
  • discovery.zen.fd.ping_timeout:ping 超时时间(默认 30s),超时则认为节点故障。

节点加入集群的流程

  1. 新节点启动:读取 elasticsearch.yml 中的 cluster.name 和单播种子节点。
  2. 发送 ping 请求:向种子节点发送 ping,获取集群现有节点列表。
  3. 加入集群:与主节点通信,验证集群名称是否一致,成功后加入集群。
  4. 分片分配:主节点根据集群状态,为新节点分配分片(如副本分片)。

最佳实践

  1. 单播优先:生产环境禁用多播,仅使用单播配置种子节点(建议包含所有主节点候选)。
  2. 脑裂防护:严格设置 discovery.zen.minimum_master_nodes,主节点候选数建议为奇数(3、5 个)。
  3. 超时参数调优:在网络不稳定的环境(如跨机房),增大 ping_timeoutfd.ping_timeout,避免节点误判。
  4. 种子节点冗余:种子节点列表至少包含 2 个节点,防止单节点故障导致新节点无法加入。

Elasticsearch 集群主节点(Master)选举机制详解

主节点(Master)是 Elasticsearch 集群的核心管理者,负责维护集群元数据(如索引创建 / 删除、分片分配)、协调节点加入 / 退出等。主节点的选举机制直接影响集群的稳定性,尤其是在节点故障或网络波动时,合理的选举配置可避免 “脑裂” 等严重问题。

主节点选举的触发场景

主节点选举在以下情况触发:

  1. 集群首次启动:无主节点时,所有候选主节点(node.master: true)参与选举。
  2. 现有主节点故障:节点检测到主节点失联(如网络中断、进程崩溃),触发重新选举。
  3. 主节点主动退出:主节点因负载过高或配置变更主动下线。

选举核心流程

候选主节点资格

只有配置 node.master: true 的节点才有资格参与选举(主节点候选节点),其他节点(如纯数据节点)仅参与投票,不竞选主节点。

选举步骤

  1. Ping 阶段:候选节点通过 Zen Discovery 机制互相发送 ping 请求,交换集群状态和节点信息。
  2. 投票阶段:候选节点根据节点 ID、集群状态版本等信息,向 “最优” 候选节点投票(通常优先选择现有集群状态最新的节点)。
  3. 确认主节点:当某个候选节点获得 超过 discovery.zen.minimum_master_nodes 数量的投票时,成为新主节点。
  4. 集群同步:新主节点与其他节点同步集群元数据,确保全集群状态一致。

关键配置参数解析

discovery.zen.ping_timeout

  • 作用:控制候选节点间 ping 请求的超时时间(默认 3s)。

  • 场景:网络延迟较高时(如跨机房集群),需调大该值(如 10s~30s),避免因短暂网络波动误判节点故障,导致不必要的重新选举。

  • 配置示例:

    1
    discovery.zen.ping_timeout: 10s

阅读全文 »