0%

前言

两天前写了文章《「造个轮子」——cicada(轻量级 WEB 框架)》 向大家介绍了 cicada 之后收到很多反馈,也有许多不错的建议。

同时在 GitHub 也收获了 100 多颗 小♥♥(绝对不是刷的。。)

也有朋友希望能出一个源码介绍,本文就目前的 v1.0.1 版本来一起分析分析。

没有看错,刚发布就修复了一个 bug,想要试用的请升级到 1.0.1 吧。

Read more »

前言

俗话说 「不要重复造轮子」,关于是否有必要不再本次讨论范围。

创建这个项目的主要目的还是提升自己,看看和知名类开源项目的差距以及学习优秀的开源方式。

好了,现在着重来谈谈 cicada 这个项目的核心功能。

我把他定义为一个快速、轻量级 WEB 框架;没有过多的依赖,核心 jar 包仅 30KB。

也仅需要一行代码即可启动一个 HTTP 服务。

Read more »

前言

OutOfMemoryError 问题相信很多朋友都遇到过,相对于常见的业务异常(数组越界、空指针等)来说这类问题是很难定位和解决的。

本文以最近碰到的一次线上内存溢出的定位、解决问题的方式展开;希望能对碰到类似问题的同学带来思路和帮助。

主要从表现-->排查-->定位-->解决 四个步骤来分析和解决问题。

Read more »

背景

最近在做分布式相关的工作,由于人手不够只能我一个人来怼;看着这段时间的加班表想想就是够惨的。

不过其中也有遇到的不少有意思的事情今后再拿来分享,今天重点来讨论服务的注册与发现

分布式带来的问题

我的业务比较简单,只是需要知道现在有哪些服务实例可供使用就可以了(并不是做远程调用,只需要拿到信息即可)。

要实现这一功能最简单的方式可以在应用中配置所有的服务节点,这样每次在使用时只需要通过某种算法从配置列表中选择一个就可以了。

但这样会有一个非常严重的问题:

由于应用需要根据应用负载情况来灵活的调整服务节点的数量,这样我的配置就不能写死。

不然就会出现要么新增的节点没有访问或者是已经 down 掉的节点却有请求,这样肯定是不行的。

往往要解决这类分布式问题都需要一个公共的区域来保存这些信息,比如是否可以利用 Redis?

每个节点启动之后都向 Redis 注册信息,关闭时也删除数据。

其实就是存放节点的 ip + port,然后在需要知道服务节点信息时候只需要去 Redis 中获取即可。

Read more »

前言

从去年校招开始到现在负责部门的面试,从我手上流走的简历多多少少也有上百封了。

同时最近秋招又要开始了,就想着把我这一年来筛选简历的经验分享给大家,多少还是能提高一些命中率。

突出优势

「简历」自然是突出简单的好,相信大部分面试官都不是全职做面试工作;多数都是工作之余筛选简历。

就我的情况来说,每天都需要在工作中挤出一部分时间从 10 几份简历中挑选出比较靠谱的。

总共大概花费 5 分钟的时间,平均算下来差不多一份简历只有 30S。现在我终于相信当初语文老师说:“高考语文作文阅卷只有几十秒的时间”。

既然时间很短,就需要像写作文一样突出亮点。

Read more »

起因

感谢各位大佬的支持收获了人生第一个(很有可能也是唯一一个)1W star 项目。

从今年一月份创建项目至今 8 个月时间。

一共关闭了 27 个 issue,47 个 RP,总共有 11 位小伙伴参与维护。

神奇般的连续两个月上了 GitHub Java 热门榜首。

Read more »

前言

已经记不清有多少读者问过:

博主,你是怎么学习的?像我这样的情况有啥好的建议嘛?

也不知道啥时候我居然成人生导师了。当然我不排斥这些问题,和大家交流都是学习的过程。

因此也许诺会准备一篇关于学习方面的文章;所以本文其实准备了很久,篇幅较长,大家耐心看完希望能有收获。

以下内容仅代表我从业以来所积累的相关经验,我会从硬技能、软实力这些方面尽量阐述我所认为的 “不那么差的程序员” 应当做到哪些技能。

Read more »

前言

记得前段时间我们生产上的一个网关出现了故障。

这个网关逻辑非常简单,就是接收客户端的请求然后解析报文最后发送短信。

但这个请求并不是常见的 HTTP ,而是利用 Netty 自定义的协议。

有个前提是:网关是需要读取一段完整的报文才能进行后面的逻辑。

问题是有天突然发现网关解析报文出错,查看了客户端的发送日志也没发现问题,最后通过日志发现收到了许多不完整的报文,有些还多了。

于是想会不会是 TCP 拆、粘包带来的问题,最后利用 Netty 自带的拆包工具解决了该问题。

这便有了此文。

Read more »

前言

平时接触过多线程开发的童鞋应该都或多或少了解过线程池,之前发布的《阿里巴巴 Java 手册》里也有一条:

可见线程池的重要性。

简单来说使用线程池有以下几个目的:

  • 线程是稀缺资源,不能频繁的创建。
  • 解耦作用;线程的创建于执行完全分开,方便维护。
  • 应当将其放入一个池子中,可以给其他任务进行复用。

线程池原理

谈到线程池就会想到池化技术,其中最核心的思想就是把宝贵的资源放到一个池子中;每次使用都从里面获取,用完之后又放回池子供其他人使用,有点吃大锅饭的意思。

那在 Java 中又是如何实现的呢?

在 JDK 1.5 之后推出了相关的 api,常见的创建线程池方式有以下几种:

  • Executors.newCachedThreadPool():无限线程池。
  • Executors.newFixedThreadPool(nThreads):创建固定大小的线程池。
  • Executors.newSingleThreadExecutor():创建单个线程的线程池。
Read more »

前言

Map 这样的 Key Value 在软件开发中是非常经典的结构,常用于在内存中存放数据。

本篇主要想讨论 ConcurrentHashMap 这样一个并发容器,在正式开始之前我觉得有必要谈谈 HashMap,没有它就不会有后面的 ConcurrentHashMap。

HashMap

众所周知 HashMap 底层是基于 数组 + 链表 组成的,不过在 jdk1.7 和 1.8 中具体实现稍有不同。

Base 1.7

1.7 中的数据结构图:

Read more »