帆的博客

扬帆起航

volatile

先说结论,volatile是非常常用的东西,他保证了可见性和有序性。这2个特性分别涉及了JVM的底层原理,最常用的场景,就是共享变量加volatile修饰,这样不同的线程来修改的时候,才能即时的识别到改变,比如标志位、开关等。

阅读全文 »

线程

线程篇知识,主要包括并发编程方面,JUC并发包下的类的源码学习。

Thread

执行main方法后,就会开启一个jvm进程了,进程里,又有很多线程,main线程就是执行程序的第一个线程,然后我们又创建了一个子线程,来执行另外的任务。

1
2
3
4
5
6
7
8
9
10
11
12
public class HelloWorld {
public static void main(String[] args) {
new Thread() {

@Override
public void run() {
System.out.println("子线程。。");
}

}.start();
}
}
阅读全文 »

Map源码

Map是集合里一个非常重要的数据结构,面试也是会经常问到源码的。

HashMap

简单描述一下HashMap的原理,它的结构就是数组+链表+红黑树。

put的时候,对key进行hash,找到对应的数组位置放在里面,然后hash冲突了就组成链表往后追加。查询的时候也是一样,对key进行hash,然后用equals去比较链表上key的值。

JDK1.8优化了hashmap的数据结构,如果链表过长,达到8以后,就会转变成红黑树。

数据结构

这个数组的初始化长度,是16,和ArrayList不一样。

1
2
3
4
5
6
7
// 数组变量
transient Node<K,V>[] table;
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
// 初始数组大小,默认是16
int threshold;
// 数组长度
transient int size;
阅读全文 »

JDK集合源码

准备写一些文章,把集合、并发、网络相关的JDK工具的使用和源码都在这里记录一下。首先从简单的集合源码开始。

List

ArrayList

基于数组的集合,默认的构造函数,给了一个空数组,Object[], {},默认的初始化大小为10。

1
2
3
4
5
6
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

一般在构造ArrayList,建议指定一个大小,避免频繁扩容带来的开销。

每次往ArrayList中插入数据的时候,都会判断当前数组的元素是否塞满了,如果塞满的话,此时就会扩容这个数组,然后将老数组中的元素拷贝到新数组中去,确保说数组一定是可以承受足够多的元素的。

阅读全文 »

记一次线上故障排查并解决(Spring Cloud健康检查的坑)

今天下班在回家路上的时候,同事反馈他们的生产环境项目不停的在输出错误日志,一时半会没有找到原因,让我帮忙看看。我到家后登录VPN,打开了kibana查看日志,确实一直在报错,错误日志如下:

阅读全文 »

服务注册生产实践

服务注册的时效性(毫秒级)

服务在启动后,会向eureka server发起注册,应该是在1秒以内的。

会通过SpringCloud额外封装的EurekaAutoServiceRegistration#start()发起注册,这个类的实例被EurekaClientAutoConfiguration定义。

服务发现的时效性(毫秒级和分钟级)

一个服务启动后,发现其他所有的服务需要多长时间?如果其他服务新增了机器,那么又需要多长时间才能发现。

  1. 服务启动后,会主动拉取全量注册表,可以发现已经注册的服务列表(毫秒级)
  2. 服务每隔30秒会拉取增量注册表(先走ALL_APPS_DELTA缓存,读不到查queue)
  3. eureka server 二级缓存,定时任务30秒从readWriterCacheMap同步到readOnlyCacheMap
  4. 一个服务启动注册后,要30秒才会被其他服务发现(1分钟以内)
阅读全文 »

为什么微服务需要网关

在微服务架构中,通常会有多个服务提供者。设想一个电商系统,可能会有商品、订单、支付、用户等多个类型的服务,而每个类型的服务数量也会随着整个系统体量的增大也会随之增长和变更。作为UI端,在展示页面时可能需要从多个微服务中聚合数据,而且服务的划分位置结构可能会有所改变。网关就可以对外暴露聚合API,屏蔽内部微服务的微小变动,保持整个系统的稳定性。

阅读全文 »

HystrixCommand.execute源码细节

HystrixCommand会将任务丢到异步线程池里去执行,通过Future获取执行完毕的结果。

1
2
3
4
5
6
7
8
// HystrixCommand.java
public R execute() {
try {
return queue().get();
} catch (Exception e) {
throw Exceptions.sneakyThrow(decomposeException(e));
}
}

queue()方法,是用来异步执行的command逻辑的,他会将command扔到线程池里去执行,但是这个方法不会等待线程执行完毕command,他会拿到一个Future对象,通过Future对象去获取command执行完毕的响应结果。

阅读全文 »

背景

在zuul网关中,有关于配置连接数量的配置:

1
2
3
4
zuul:
host:
max-per-route-connections: 20 #默认值
max-total-connections: 200 #默认值

这个是只是的zuul调用静态路由配置的Http连接池数量,按照实际情况设置就好(请注意不要和Tomcat的maxConnections搞混了)。

这个配置并不会对基于Ribbon的下游服务访问生效,如果要配置Ribbon相关的配置,需要配置以下的配置:

1
2
3
ribbon:
MaxConnectionsPerHost: 50 #默认值
MaxTotalConnections: 200 #默认值
阅读全文 »
0%