java.lang.OutOfMemoryError

当你看到OutOfMemoryError,应该怎么办?如果只是想到设置-Xmx值更大些,可能是不够的。因为有多种不同的情形,都可以导致OutOfMemory错误。

  • java.lang.OutOfMemoryError: Java heap space
  • java.lang.OutOfMemoryError: PermGen space
  • java.lang.OutOfMemoryError: unable to create new native thread
  • java.lang.OutOfMemoryError: GC Overhead limit exceeded
  • java.lang.OutOfMemoryError: Requested array size exceeds VM limit
  • java.lang.OutOfMemoryError: Metaspace
  • java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space?
  • java.lang.OutOfMemoryError: Compressed class space
  • java.lang.OutOfMemoryError: reason stack_trace_with_native_method

Java heap space
这个可能是最常见的OutOfMemory了。这个问题通过增大参数-Xmx[g|m|k]也许可以解决。当然,更踏实的做法还是要检测程序是不是有内存泄漏的问题。

PermGen space
通过参数-XX:PermSize=[g|m|k]进行调整。在JDK8之后,Permanent Generation这块heap内存已经放弃,而和Native Memory合并了。

unable to create new native thread

Java虚拟机中每创建的一个线程,就需要在操作系统中对应的创建一个线程。这个错误提示,就是说操作系统已经不能创建更多线程给JVM使用了。我们使用线程一般是基于线程池的。出现这个错误提示,那基本上说明程序执行过程中有线程被大量的创建出来,一定要好好去检查一下代码了。不同的操作系统支持的线程数不同,可以通过简单的小程序跑跑看。对于Linux系统来说,线程数的限制不是基于进程的,而是针对整个操作系统的。可以通过cat /proc/sys/kernel/threads-max查看最大线程数。

ulimit -s  256
ulimit -i  120000
echo 120000 > /proc/sys/kernel/threads-max
echo 600000 > /proc/sys/vm/max_map_count
echo 200000 > /proc/sys/kernel/pid_max 

这种类型的OOM不能通过-XX:+HeapDumpOnOutOfMemoryError参数dump出文件。

private static void createInfinitThreads() {
    long i = 0;
    while(true){
        new Thread(new Runnable(){
            public void run() {
                try {
                    Thread.sleep(10000000);
                } catch(InterruptedException e) { }
            }
        }).start();

        i ++;
        System.out.println(i);
    }
}

这个网页介绍JVM内存很清楚。Java内存区域与内存溢出异常

图一:

图二:下面中的Permanent区域在Java8中已经和method area合并。

图三:

Reference:

spring cloud config 之 consul

Reference:
使用Consul作为配置信息的Repository

类似ZooKeeper,Consul服务本事提供了Key/Value存储功能,所以很自然的通过Spring Cloud Consul Config就能完成Config Server and Client的功能。实际上,可以理解成配置信息从保存在git文件系统,变成了保存在Consul里。

1)激活Spring Cloud Consul Config,只需依赖spring-cloud-consul-config。

org.springframework.cloud:spring-cloud-consul-config

2)在bootstrap.yml(或bootstrap.property)中配置spring cloud consul config。

spring:
  cloud:
    consul:
      config:
        enabled: true
        prefix: configuration
        defaultContext: apps
        profileSeparator: '::'

3)如果你认为把原来保存在property/yml文件中的properties作为value保存在以data(作为key)下更方便些,可用通过设定format可以实现。

spring:
  cloud:
    consul:
      config:
        format: YAML


config/testApp,dev/data
config/testApp/data
config/application,dev/data
config/application/data

可以通过下面的设置,修改健data的值

spring.cloud.consul.config.data-key

4)git2consul
consul社区的开源项目git2consul可以把存在git目录里的文件导入到consule中不同的key中。缺省地,文件名就是key的名字。详细用法参见[]https://github.com/Cimpress-MCP/git2consul](https://github.com/Cimpress-MCP/git2consul)。

Spring Cloud Config 之 ZooKeeper

Reference:
使用ZooKeeper作为配置信息的Repository

Spring Cloud Config Server默认使用Git作为配置信息的存储地。zookeeper本身的namespace机制也很适合作为分布式配置信息的存储地。加上zookeeper提供的watcher接口,很容易实现配置信息变化的通知。当前版本(1.0.2)Spring-cloud-zookeeper还不支持对配置信息变化的通知。

配置信息默认地存储在path ’config‘中,后面跟application name + profile name。
下面是对于应用testApp来说,配置信息查找路径的优先级。注意,application不是应用名,而是全局的一个存放缺省配置(或是全局配置)的地方。

例一:

config/testApp,dev
config/testApp
config/application,dev
config/application

配置信息的根路径config和默认配置子路径名application都是可配置的。比如,通过下面的bootstrap.yml。

spring:
  cloud:
    zookeeper:
      config:
        enabled: true
        root: configuration
        defaultContext: apps
        profileSeparator: '::'

这样,例一,就应变成下面这样:

configuration/testApp,dev
configuration/testApp
configuration/apps,dev
configuration/apps

依赖:

org.springframework.cloud:spring-cloud-starter-zookeeper-config

To learn, To know, To use

Spring Cloud

互联网技术发展到现在,更多的是“分布式计算技术+业务领域”的实现。可以把Spring Cloud理解成一个:开发分布式应用的工具包。

针对开发一个分布式系统中常用到的模式,Spring Cloud基于Spring Boot技术向开发者提供了简单易用的API。工具包中包含以下工具:

Reactive Programming

  • RxJava
  • Akka

Spring Cloud Config 之 Git Backend

Reference:
spring-cloud-config详细讲述了使用文件系统或Git做backend时的基本使用方法,以及在复杂使用场景下的配置。
Spring Profiles 讲述了profile在configuration中的作用及使用方法。

Spring Cloud Configuration的使用包括server和client。
Configuration Server作为配置信息的统一的、集中的数据源。Configuration Client从server端获取数据。

Server端的配置

spring.cloud.config.server.git.uri=/Users/dahui/GitHub/config-repo
server.port=8888

Client端的配置

spring.application.name=reservation-service
spring.profiles.active=profile1,profile3
SpringConfigClient_GitBackend.png
spring.cloud.config.uri=http://localhost:8888

下图仅仅演示了最简单的application name、profile、label的使用。
实际场景中的图中profile一般设置为dev、qa、production等。label用于对application+profile提供标识版本的能力。

application name、profile、label的使用

Config Client端配置说明:
多个profile中重复定义

  • 在Confige Server使用的配置文件中的配置优先级高于Confige Client本地的配置。
    比如,confige client本地的bootstrap.properties中定义了server.port=8866,在git文件中定义server.port=8000,那么config client实际使用的是8000. (即使在application.properties文件中定义,也无效。)

  • 在config client项目中添加Actuator库,通过浏览器访问http://localhost:8888/mappings,就可以看到Actuator提供的REST接口。其中的POST /refresh可以用于当config server的配置信息发生变化时,让client去pull一下最新的值。

      可以同通过 curl -d {} http://localhost:8000/refresh 获取更新。