- 博客(63)
- 收藏
- 关注
原创 Apache HttpClient 模拟 SSO 登陆丢失 cookie 问题解决
背景 需要用 Java 访问一个被 SSO 保护的特殊接口获取信息。 方案设计 假如我们用浏览器来实现这个功能,步骤简单如下: 输入目标 API 地址 (浏览器自动重定向到 SSO 登陆页面) 输入用户名密码登陆 (浏览器重定向回到 API 地址,并附带认证信息) 获取目标 API 的资源信息 其中需要用户操作的是步骤 1 和步骤 3。 但要求是用 Java 来实现上述功能,关键点在于如何获取认证信息。有了认证信息,我们便能直接 call 目标 API。 所以我们需要模拟浏览器的登陆行为,此时的初步想法
2022-04-16 22:06:39
2084
原创 Mybatis 批量插入 Oracle 记录
基本环境 语言:Java 8 数据库:Oracle ORM 框架:MyBatis 3.4.5 需求 批量插入数据,数据需要有自增 id。每次插入有一个唯一的 sessionId 来标记这些记录,插入完成之后返回这个 sessionId。 方案 循环插入单条记录,伪代码: int sessionId = dao.querySessionId(); for (Record record : recordList) { dao.insertRecord(record, sessionId); } re
2022-01-06 14:25:12
947
原创 Big Key 导致 Redis 频繁重连的问题排查
背景 监控是系统的重要模块,我们给产线的 Redis 机器配置了全方位的监控,包括机器性能指标测试以及 Redis 服务测试等等。今天收到了 PagerDuty 告警,报告说 Redis 服务间歇性异常。 问题描述 Redis 是一个集群,三主三从,每个节点各配置了一个监控,监控的测试逻辑大致是,用 INFO,CLUSTER SLOTS,CLUSTER NODES 等命令查看节点以及集群的基本信息是否正常,然后给主节点(master) set 一个 dummy key,看是否在规定时间内能同步到从节点(sl
2021-11-30 16:25:59
1670
原创 博客搬家日记--搭建基于Docker的LNMP环境
背景 由于云主机马上就要到期了,所以最近对比了几家云服务器提供商。最终决定尝试一下 UCloud。于是不得不把原博客(typecho)迁移过来。下面是流水账式地记录一下过程。 过程记录 本想尝试按照以前的笔记重新搭建一套环境,然后再把数据导过来,但是一想到这一长串的步骤,以及可能碰到的问题就头疼,于是决定构建一个基于容器的 LNMP 环境,一劳永逸,也方便日后继续做博客迁移。当然如果有同学也想搭建基于 LNMP 的博客如 Typecho,则可以参考我的模板:-)(文末有 Github 链接)。 注:以下命令
2021-11-21 15:44:27
2588
原创 如何用 ThreadGroup 记录线程创建链路
背景 我们维护一个监控平台,平台跑着各种各样的插件来测试不同的场景。平台捕获插件的标准输出来得到日志,获取退出码来知道运行结果。 Java 插件就是一个可执行的 .jar 文件,它会被加载到平台的 JVM 中,运行在一个线程池里面。针对 Java 插件,我们提供了一个 SDK 给客户以降低开发难度,主要包括一些工具方法,定义标准执行流程,异常捕获等功能。 难点 在 Java SDK 中,我们希望提供一个工具方法,来统一打印标准输出。在 Java 插件中,只需要调用类似 PluginLogger.print(
2021-11-21 15:42:48
319
原创 用 maven dependency plugin 优化 maven 依赖
layout: post title: 优化 maven 依赖实践 date: 2020-06-28 categories: Handbook tags: Maven 背景 Maven 是非常优秀的项目管理工具,我们可以方便地在 pom 文件里配置 Java 工程的依赖。但是随着项目的迭代和时间推移,pom 文件在新老需求的不断增删改之下变得越来越臃肿,到后来连自己都不知道哪些是有效依赖。 下面将简单介绍如何用 Maven 插件 maven dependency plugin 来解决这个问题。 ma.
2021-07-06 16:23:51
1286
原创 浅谈分布式
前言 互联网时代,分布式是一个绕不过去的话题。本文将简单谈谈个人对分布式的理解。 何为分布式 维基百科上对分布式系统(Distributed System)的定义如下: A distributed system is a system whose components are located on different networked computers, which communicate and coordinate their actions by passing messages to one
2021-04-02 10:19:28
352
1
原创 漫谈zookeeper watcher单次触发特性
架构师 Hooya 正带领着他的团队着手开发一款高性能分布式协调工具,暂名 zookeeper。 Hooya开场白:同学们,作为一个分布式协调软件,通知功能是必不可少的。今天我们来 brainstorm 一下如何设计咱 zookeeper 的通知机制吧。 攻城狮小A抢先道:这简单呀,不就是实现一个大号的观察者模式嘛,Client 注册 watcher,Server 在数据改动的时候通知 Client,目测不会太复杂。 Hooya:再简单也要从头开始,我们先定义一下通知的事件吧。 小A一拍脑门:zookeep
2021-04-01 14:54:24
304
1
原创 zookeeper的watcher是一次性的吗?!
zookeeper zookeeper 是流行的高性能分布式协调工具,它提供了分布式环境中需要的命名服务,配置管理,分布式锁,注册中心,Leader 选举等等功能,应用十分广泛。 zookeeper 的 watcher Client 可以在 zookeeper 的节点(znode)上设置监听器(watcher),当节点被修改时,zookeeper 会向客户端发送一个相应的通知。 可以通过 getData(),getChildren() 和 exists() 三个方法来设置 watcher。以 getData
2021-03-31 17:54:28
1157
原创 Connection Timeout 问题排查
背景 我们组开发维护了一个 Agent 工程,帮客户采集一些客户有用的网络数据。客户需要下载一个 MSI,然后安装并注册。 问题描述 某个客户下载安装 Agent 之后,提示注册失败。其实 Agent 注册就是一个用户登陆验证服务,然后创建一个 Machine ID 的过程。所谓 Machine ID,就跟用户帐号一样,是 Agent 的一个唯一标识。注册的流程大致如下: 注册的主要目的是为 Agent 创建一个 Machine ID,为此需要获取一个 token,而这个 token 可以通过用户登陆来获
2021-03-01 16:54:36
13341
7
原创 MyBatis内置DataSource的连接池实现原理
前言 MyBatis是一个流行的ORM框架,它简单易用,支持自定义SQL、存储过程以及高级映射。MyBatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。 作为一款优秀的持久层框架,连接池是必不可少的。本文将分析MyBatis内置的数据源是如何实现连接池功能的(源码基于MyBatis3.4.5)。 JDBC对数据库的操作 回忆一下,我们用原生的JDBC来操作数据库的一般流程: public class JDBCExample { // JDBC driver name and dat
2020-12-12 14:29:19
1139
原创 Hotspot早期的垃圾收集器简介
前言 很多人的博文里面会提到JVM三种垃圾收集器:串行,并行和并发。这么分类也不能说错,但事实上也没有这么简单。本文简要介绍Hotspot早期的垃圾收集器(Garbage Collector)。 名词解释 年轻代和老年代:JVM中不同的对象,生命周期是不同的。比如线程中的临时变量,在方法结束之后便会被销毁;而静态变量,则会一直存在直到其所对应的类被销毁为止。基于这样的事实,才有了分代收集的概念:将JVM堆分为年轻代和老年代。年轻代存放刚被创建的对象,老年代存放经过多次GC之后依然存活的对象。一般年轻代空间
2020-12-10 17:38:36
199
原创 Redis的键过期策略及内存淘汰策略简介
Redis Redis是高性能的基于内存的NoSQL数据库。因为内存是比较宝贵的资源,无法无限制使用,所以Redis提供了: 键过期策略来防止内存饱和。 内存淘汰策略来使得内存饱和之后继续对外提供服务。 内存过期策略 expire命令 Redis提供了expire命令来给一个键(key)设置过期时间: redis> SET foo "bar" "OK" redis> EXPIRE foo 10 (integer) 1 redis> TTL foo (integer) 10 类似set
2020-11-08 17:47:20
318
原创 Netty的ChannelPool导致内存泄漏的排查经历
背景 接到了线上机器的报警,登上服务器,发现是Java进程挂了,看日志报了OOM: java.lang.OutOfMemoryError: Java heap space 问题描述 内存溢出,那当然是看dump文件了。这里推荐大家在产线机器上都加上JVM参数-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath={path}/{to}/{dump},这样,JVM在OOM的时候,会自动做一个内存dump,相当于保存现场。 拿到dump文件,放到MAT里面分析,以下是
2020-08-31 10:07:56
1648
原创 自定义Classloader导致ClassCastException:不要轻易破坏双亲委派模型
背景 java.lang.ClassCastException: cn.com.nightfield.Plugin cannot be cast to cn.com.nightfield.Plugin 相同的class,竟然不能cast?这是什么鬼? 问题描述 自定义类加载器(Classloader)是很常见的,它可以让我们从自定义的文件系统目录,网络甚至是数据库的各种文件类型(jar, war, zip等)中加载class文件。 我们项目中使用了一个开源的类管理工具PF4J,来加载指定目录下的class
2020-08-15 16:19:05
1264
原创 深入理解Linux, NIO和Netty中的零拷贝(Zero-Copy)
背景 零拷贝(Zero Copy)是一个耳熟能详的术语,众多高性能的网络框架如Netty,Kafka,Rocket MQ都将零拷贝标榜为其特性。那么究竟什么是零拷贝? 零拷贝 Wikipedia上对零拷贝的解释如下: “Zero-copy” describes computer operations in which the CPU does not perform the task of copying data from one memory area to another. This is freq
2020-06-10 10:04:25
2193
原创 Quartz Task在Tomcat中重复运行问题解决
问题描述 Spring Quartz是很常用的定时任务框架。把一个Quartz的工程部署到Tomcat中启动,意外地发现,每个Task都在同一时间跑了两次,而本地在开发的过程中却没有问题。 问题排查 为了防止多线程问题,有部分Task上是加了锁的,类似如下方式: @Component public class ExampleTask{ private ReentrantLock lock = new ReentrantLock(); protected void executeInternal()
2020-06-09 16:12:15
489
原创 设计模式总结
经过了两个多月的时间,终于,将常见的设计模式结合例子过了一遍,在此做一个简单的小结。 设计模式小结 不难发现,应用各种设计模式所带来的好处,都会提到解耦二字。开闭原则要求我们的系统对扩展开放,对修改关闭。高内聚,低耦合的系统,有更高的稳定性与灵活性,也更易于维护。如何来解耦模块之间的关系呢?如果只用一句话来概括的话,那就是:将变与不变分离。细看下来,设计模式通常通过增加一个中间抽象层的方式,来封装会变的部分。创建型模式中,将对象的创建模块抽离出来,使客户端不需要关心对象如何创建;几乎所有的结构模式和行为模式
2020-06-06 17:04:34
219
原创 设计模式,行为模式之责任链模式
1 概述 责任链模式(Chain of Responsibility Pattern)是常见的行为模式,它将处理器封装成一条处理链,让请求可以在链上传递。链上的处理器自行决定是否对请求进行处理。 2 责任链模式 一个典型的责任链模式的使用场景是,当一个事件或请求需要被多个处理器处理时。应用责任链模式,将所有的处理器串在一起,然后把请求从链的头部开始传送。各个处理器可以对请求进行判断,选择执行相关逻辑,或者将它传递给下一个处理器。如此一来,解耦了请求者和接收者(所有的处理器)。 一般情况下,链上的处理器需要持
2020-06-06 16:01:09
339
原创 设计模式,行为模式之备忘录模式
1 概述 备忘录模式(Memento Pattern),又叫Token模式,它提供了一种方式,来捕捉对象某一时刻的内部状态,并将其保存成备忘录(Memento),如此一来,对象可以根据此备忘录恢复到之前的状态。 2 备忘录模式 几乎所有的编辑器都支持撤销功能,这其实就是备忘录模式的例子,撤销操作,使得文本得以恢复到之前的状态。面向对象设计中,备忘录模式的实现一般需要三个角色: 发起人(Originator):主对象,提供将内容保存成备忘录,或者从备忘录恢复状态的功能。 备忘录(Memento):备忘录对象
2020-06-04 11:39:54
237
原创 设计模式,行为模式之命令模式
1 概述 命令模式(Command Pattern),是将请求封装成一系列命令对象,以解耦请求发起者和请求接收者的一种行为模式。 2 命令模式 正常情况下,请求发送者和请求接收者是相互耦合的,发送者直接调用接收者相关的方法,直接交互。 用命令模式进行改造,将两者交互的媒介----命令单独抽离出来,使得发送者和接收者相互独立,只依赖于命令对象,提高了扩展性和可维护性。同时,通过命令模式,我们还能完成一些高级操作,如撤销命令,方法参数化,命令入队,批量命令等等。 3 案例 通过一个简单的例子加深对命令模式的理解
2020-06-03 13:10:06
231
原创 设计模式,行为模式之访问者模式
1 概述 访问者模式(Visitor Pattern)是一种行为模式,不常用。它可以将作用在对象上的算法逻辑,与对象本身分离开来。 2 访问者模式 当需要对一组相似类型的对象执行操作时,我们可以将操作逻辑分别维护在每个对象内部,但这违背了单一职责原则。 访问者模式就是来应对这种情况的:将所有的算法逻辑移动到一个新的类----访问者(Visitor)中,统一维护,如果其中的逻辑发生了变化,那么我们只需要在访问者实现中进行更改,而不用影响到原对象。同时,在访问者模式中,扩展变得很容易,增加新的对象以及操作逻辑,
2020-05-31 13:56:07
263
原创 设计模式,行为模式之模板方法模式
1 概述 模板方法模式(Template Method Pattern)是一种很常见的行为模式。在超类/抽象类中创建一个模板方法,方法中定义一个算法步骤或框架,让子类在不修改主结构的情况下,重写其中的子步骤。 2 模板方法模式 假如存在一系列对象的方法,他们的步骤是大体一致的,区别只是其中的一个子步骤。这种情况会导致大量重复冗余的代码,当公共部分需要改变时,不得不修改所有相关的对象。如果用模版方法模式改造,可以简化逻辑:将其中不变的部分抽离出来,作为一个模板方法,然后让子类只实现差异化的部分代码。 比如,前
2020-05-31 08:17:59
307
原创 设计模式,行为模式之中介者模式
1 概述 中介者模式(Mediator Pattern)是一种行为模式,通过定义一个中介对象,来管理一系列对象之间的依赖,从而解耦原有对象之间的关系。 2 中介者模式 大量的对象相互依赖,会大大增加系统复杂度,提高维护成本。中介者模式(Mediator Pattern)是迪米特原则的一个很好体现,它通过将对象的依赖关系维护在一个中介者中,使原本耦合在一起的对象变得相互独立。 交通信号灯是一个很常见的例子,如果没有信号灯,十字路口的车子必须知道互相之间要去的方向,来决定什么时候踩油门,什么时候踩刹车,如此一来
2020-05-30 12:25:58
528
原创 设计模式,行为模式之状态模式
1 概述 状态模式(state Pattern)是行为模式之一,一般用在对象的行为依赖于内部状态的场景。 2 状态模式 考虑一个场景:对象有状态,而且根据状态不同,对象的行为也会不同。对于该情况,最简单的方式是,对状态做if-else或者swith-case判断,根据状态调用相应的行为。但是这种做法,把对象和状态耦合在了一起,难于扩展和维护。更好的做法是,用状态模式将状态抽离出来形成一个接口,而目标对象依赖该状态接口,来完成对应的行为,由此达到解耦的目的。 状态模式跟策略模式非常相像,可视为策略模式的扩展。
2020-05-28 17:12:47
236
原创 设计模式,行为模式之策略模式
1 概述 策略模式(Strategy Pattern)是行为模式的一种,复杂度并不高,当完成某项任务的方式有多种时,可以考虑使用策略模式。 2 策略模式 在策略模式中,我们需要定义一族算法,并将算法放入独立的类中,每种算法代表完成任务的一种方法。如计算器,我们可以定义基本的加,减,乘,除四种策略,对于任意输入的两个数字,调用不同的策略,将得到不同的结果;又如网上购物结算,我们可以定义一系列支付策略,支付宝支付,微信支付,信用卡支付,储值卡支付…顾客可以根据自己的喜好选择相应的支付方式。 策略模式解耦了算法的
2020-05-24 16:12:56
388
原创 设计模式,行为模式之观察者模式
layout: post title: 行为模式之观察者模式 date: 2020-05-04 categories: Handbook Design Patterns tags: Java Design Patterns 1 概述 观察者模式(observer Pattern),也叫发布-订阅模式,是一种很重要的行为模式,它被广泛运用在异步编程之中,可以说是异步编程的基础。 2 观察者模式 当我们需要关注某个对象的状态时,可以不断地轮询,查看状态是否变化,这也就是我们熟知的同步方式。然而这样的方式.
2020-05-10 15:52:08
309
2
原创 设计模式,行为模式之迭代器
1 概述 迭代器模式(iterator Pattern)是最常见的设计模式之一,一般使用过Java集合的人,都接触过这种模式。 2 迭代器模式 集合(Collection)是编程中常用的一种类型,它们是存储元素的容器。集合有多种类型,如列表(List),集合(Set),栈(Stack),树(Tree)等等,对于使用者来说,需要有一种统一的方式来遍历集合中的元素。除此之外,使用者有时还需要不同的元素...
2020-05-04 12:27:11
155
原创 设计模式,结构模式之享元模式
1 概述 享元模式(flyweight Pattern)是通过重用元素来降低内存开销的一种设计模式。 2 享元模式 所谓享元,意思是共享元素。当程序需要创建大量元素,或创建一些占用大量内存的元素时,对服务器的内存资源是很大的挑战。这时可以应用享元模式,将元素拆分成变量与不变量两部分。其中不变量,是所有的元素共通的部分,可以共享;变量,可以做为不同的元素的区分。比如要渲染一片森林,我们不需要为每一颗...
2020-04-25 14:22:40
223
原创 设计模式,结构模式之装饰模式
1 概述 装饰模式(Decorator Pattern),意在不改变原有对象的情况下,改变/增强它的方法。 2 装饰模式 在不违反开闭原则的前提下,要改变某个对象的行为,可以使用继承。然而继承不适用于类/方法被final修饰的情况,而且一般需要了解类内部的情况,违反了迪米特法则。 装饰模式体现了组合优先于继承的思想,通过组合的方式,“装饰”对象的功能,也能达到改变对象行为的目的。装饰模式的实现模式...
2020-04-19 11:15:35
212
原创 设计模式,结构模式之代理模式
1 概述 代理模式(Proxy Pattern)是Javaer们最熟悉的设计模式之一,大名鼎鼎的AOP就是通过代理模式来实现的。 2 代理模式 现实中,如果要邀请某个明星参加活动,我们不是跟这个明星直接沟通,而是找他的经纪人。因为明星只需要负责表演就可以了,其他的事情由经纪人来安排。代理模式就是类似思想的体现:构造一个代理对象作为中间层,当我们需要调用某个功能时,不是直接调用功能本身,而是通过代理...
2020-04-16 22:58:29
202
原创 设计模式,结构模式之组合模式
1 概述 组合模式(Composite Pattern),是指把一类有共同抽象的对象组合在一起,形成树状结构,来表示部分-整体的关系。 2 组合模式 我们经常会遇到一些对象有相同的行为,同时对象之间又有层级结构。像这种情况,使用组合模式可以使系统高内聚,低耦合。通过把类组合成树形结构,调用者能够以统一的方式对待单个对象和整体结构,忽略个体和整体之间的差异。实现组合模式一般需要: 定义一个接口/抽...
2020-04-05 21:49:58
207
原创 设计模式,结构模式之适配器模式
1 概述 适配器模式(adapter pattern),从名字就可以看出,工作模式类似于适配器:将原本不兼容的两样事物连接,以协同工作。 2 适配器模式 充电器(电源适配器)是日常生活中常见的例子。大多手机要求输入电压是5V,而家用交流电的电压都是220V,充电器作为适配器,将220V的电压转为目标电器需要的电压。适配器模式也类似,通过适配器,将类的接口转换为目标所期望的另一个接口。 适配器模式是...
2020-04-04 14:53:59
259
原创 设计模式,结构模式之桥接模式
1 概述 上一篇文章 介绍了外观模式,接下来介绍桥接模式。桥接模式有时也被称为桥梁模式,也是一种常见结构模式,它主要体现了面向对象设计中的两个思想: 面向接口编程。 合成复用原则,即组合优先于继承。 2 桥接模式 桥接模式的目的是将抽象与实现分离,使二者能独立变化。说白了,其实就是: 给对象定义接口,来充当桥梁的作用。 调用者要依赖于目标对象的抽象(接口)而不是具体实现,更不是继承目标对象。...
2020-03-30 20:49:00
269
原创 设计模式,结构模式之外观模式
layout: post title: 结构模式之外观模式 date: 2020-03-29 categories: Handbook Design Patterns tags: Java Design Patterns 1 概述 外观模式,也叫门面模式,是一种常见结构模式,它是面向对象设计封装思想的体现。 2 外观模式 所谓外观,其实是一个额外的类,它包含了复杂多变的子系统,并只对外提供...
2020-03-29 14:32:43
300
原创 设计模式,创建型模式之单例模式
1 概述 单例模式应该是最简单,同时又是最复杂的一种创建型模式。因为大家都知道这个模式:无非就是保证某个对象在系统中只存在一个实例。然而想要真正实现一个完美的单例模式,却不简单。 2 单例模式 一般单例模式的实现,都需要包含两个步骤: 将类的构造函数私有化。 提供一个public的方法,以供外界获取唯一的实例。 下面将一一介绍单例模式的各种实现方式。 3 案例 3.1 注册表式 提供一个注册表...
2020-03-28 22:19:47
172
原创 设计模式,创建型模式之原型模式
1 概述 原型模式比较好理解,即以某个对象为原型,创建该对象的副本。我们可以不用知道对象内部的属性以及内部的状态,是迪米特法则的很好体现。 2 原型模式 原型模式一般用在较为复杂对象的创建,并且希望保留对象所持有的状态。Java对这种对象的创建方式也是提供了原生的支持——Object.clone()方法。 public class Object { protected native Obj...
2020-03-26 21:17:19
226
原创 设计模式,创建型模式之建造者模式
1 概述 前面我们说了工厂模式和抽象工厂模式,下面来说说建造者模式。 建造者模式也是一种极为常见的创建型模式,前面提到的两类工厂模式隐藏了类的属性与构造细节,而建造者模式通过Builder类,适当地暴露了类的属性,使得类的创建更具有灵活性和可读性。 2 建造者模式 当一个类的构造函数包含很多参数,或者参数之间有很多种组合(如肯德基的套餐),调用构造函数来创建类将会变得不方便,可读性也很差。对于多种...
2020-03-22 14:09:00
227
原创 设计模式,创建型模式之抽象工厂模式
1 概述 上一篇文章讲到了工厂方法模式,它提供了一种在不指定具体实现的情况下,创建类实例的解决方案。那为什么还需要抽象工厂模式呢? 2 抽象工厂模式 抽象工厂模式本质上,也是定义一个工厂,用来作为类创建的入口,拥有工厂方法模式的优点:如隐藏类的构造细节,降低类的使用复杂度,与调用者解耦等等。 而它与工厂方法模式最大的区别在于,抽象工厂模式更强调创建一族的元素。比如对于不同的浏览器,有不同的按钮,选...
2020-03-21 13:25:45
171
原创 设计模式,创建型模式之工厂模式
1 概述 创建型模式,提供了一种创建对象的最佳实践。工厂方法模式的核心思想,是通过统一的工厂类来获取对象,而不需要调用类的构造方法。 2 优点 可以将类的实例化过程延缓到子类。调用者无需知道接口/抽象类的具体实现是什么,利用工厂方法即可获取类的实例,降低与调用者的耦合度。 隐藏类的构造细节,降低类创建的复杂度,提高程序可读性。 可以根据不同环境/参数,从工厂构造不同的方法。 3 案例 有一个饭...
2020-03-20 22:31:40
158
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅