JVM 分代GC策略分析

我们以Sun HotSpot VM来进行分析,首先应该知道,如果我们没有指定任何GC策略的时候,JVM默认使用的GC策略。Java虚拟机是按照分代的方式来回收垃圾空间,我们应该知道,垃圾回收主要是针对堆(Heap)内存进行分代回收,将对内存可以分成新生代(Young Generation)、年老代(Tenured Generation)和永久代(Permanent Generation)三个部分。 分代GC 分代GC包括如下三代: 新生代(Young Generation) 新生代有划分为Eden、From Survivor和To Survivor三个部分,他们对应的内存空间的大小比例为8:1:1,也就是,为对象分配内存的时候,首先使用Eden空间,经过GC后,没有被回收的会首先进入From Survivor区域,任何时候,都会保持一个Survivorq区域(From Survivor或To Survivor)完全空闲,也就是说新生代的内存利用率最大为90%。From Survivor和To Survivor两个区域会根据GC的实际情况,进行互换,将From Survivor区域中的对象全部复制到T

开发JAX-WS 2.0 Web服务

实现一个Web服务的过程,大概有3个基本的过程: Web服务提供者设计并开发Web服务 Web服务提供者发布Web服务 Web服务请求者调用Web服务 下面,我通过一个例子,来实现上述过程: 假设一个Web服务提供者提供一个对域名进行探测解析的服务,给定一个域名,可以给出改域名解析后对应的IP地址列表。Web服务提供者设计并开发这个Web服务,然后将服务发布出去,并可以让Web服务请求者进行调用。 开发Web服务 服务接口文件DetectionService.java代码如下所示: package org.shirdrn.server.webservices.jaxws; public interface DetectService { DetectedResult detect(String domain); } 对应的实现类DomainDetectionService.java,如下所示: package org.shirdrn.server.webservices.jaxws; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Date; import javax.jws.WebMethod; import ja

Hadoop Job使用第三方依赖jar文件

当我们实现了一个Hadoop MapReduce Job以后,而这个Job可能又依赖很多外部的jar文件,在Hadoop集群上运行时,有时会出现找不到具体Class的异常。出现这种问题,基本上就是在Hadoop Job执行过程中,没有从执行的上下文中找到对应的jar文件(实际是unjar的目录,目录里面是对应的Class文件)。所以,我们自然而然想到,正确配置好对应的classpath,MapReduce Job运行时就能够找到。 有两种方式可以更好地实现,一种是设置HADOOP_CLASSPATH,将Job所依赖的jar文件加载到HADOOP_CLASSPATH,这种配置只针对该Job生效,Job结束之后HADOOP_CLASSPATH会被清理;另一种方式是,直接在构建代码的时候,将依赖jar文件与Job代码打成一个jar文件,这种方式可能会使得最终的jar文件比较大,但是结合一些代码构建工具,如Maven,可以在依赖控制方面保持一个Job一个依赖的构建配置,便于管理。下面,我们分别说明这两种方式。 设置HADOOP_CLASSPATH 比如,我们有一个使用HBas

CentOS 6.4上HAProxy-1.4.24安装配置

HAProxy是一款免费、快速并且可靠的一种代理解决方案,支持高可用性、负载均衡特性,同时适用于做基于TCP和HTTP的应用的代理。对于一些负载较大的Web站点,使用HAProxy特别合适。HAProxy能够支撑数以万计的并发连接。它的配置简单,能够很容易整合大我们现有的应用架构之中。 下面,我们在CentOS 6.4上进行安装配置HAProxy。 安装配置 按照如下步骤进行安装: wget http://haproxy.1wt.eu/download/1.4/src/haproxy-1.4.24.tar.gz tar xvzf haproxy-1.4.24.tar.gz cd haproxy-1.4.24 make TARGET=linux26 make install 默认安装,HAProxy对应的配置文件的存放路径为/etc/haproxy/haproxy.cfg。 我们看一下,默认安装的配置文件内容,如下所示: #--------------------------------------------------------------------- # Example configuration for a possible web application. See the # full configuration options online. # # http:

基于Dubbo的Hessian协议实现远程调用

Dubbo基于Hessian实现了自己Hessian协议,可以直接通过配置的Dubbo内置的其他协议,在服务消费方进行远程调用,也就是说,服务调用方需要使用Java语言来基于Dubbo调用提供方服务,限制了服务调用方。同时,使用Dubbo的Hessian协议实现提供方服务,而调用方可以使用标准的Hessian接口来调用,原生的Hessian协议已经支持多语言客户端调用,支持语言如下所示: Java:http://hessian.caucho.com/#Java Flash/Flex:http://hessian.caucho.com/#FlashFlex Python:http://hessian.caucho.com/#Python C++:http://hessian.caucho.com/#C C#:http://hessian.caucho.com/#NETC D:http://hessian.caucho.com/#D Erlang:http://hessian.caucho.com/#Erlang PHP:http://hessian.caucho.com/#PHP Ruby:http://hessian.caucho.com/#Ruby Objective-C:http://hessian.caucho.com/#ObjectiveC 下面,我们的思路是,先基于Dubbo封装的Hessian协议,实现提供方服务和

Dubbo实现RPC调用使用入门

使用Dubbo进行远程调用实现服务交互,它支持多种协议,如Hessian、HTTP、RMI、Memcached、Redis、Thrift等等。由于Dubbo将这些协议的实现进行了封装了,无论是服务端(开发服务)还是客户端(调用服务),都不需要关心协议的细节,只需要在配置中指定使用的协议即可,从而保证了服务提供方与服务消费方之间的透明。 另外,如果我们使用Dubbo的服务注册中心组件,这样服务提供方将服务发布到注册的中心,只是将服务的名称暴露给外部,而服务消费方只需要知道注册中心和服务提供方提供的服务名称,就能够透明地调用服务,后面我们会看到具体提供服务和消费服务的配置内容,使得双方之间交互的透明化。 示例场景 我们给出一个示例的应用场景: 服务方提供一个搜索服务,对服务方来说,它基于SolrCloud构建了搜索服务,包含两个集群,ZooKeeper集群和Solr集群,然后在前端通过Nginx来进行反向代理,达到负载均衡的目的。 服务消费方就是调用服务进行查询,给出查

Hadoop Streaming原理及实践

Hadoop Streaming提供了一个便于进行MapReduce编程的工具包,使用它可以基于一些可执行命令、脚本语言或其他编程语言来实现Mapper和 Reducer,从而充分利用Hadoop并行计算框架的优势和能力,来处理大数据。需要注意的是,Streaming方式是基于Unix系统的标准输入输出来进行MapReduce Job的运行,它区别与Pipes的地方主要是通信协议,Pipes使用的是Socket通信,是对使用C++语言来实现MapReduce Job并通过Socket通信来与Hadopp平台通信,完成Job的执行。任何支持标准输入输出特性的编程语言都可以使用Streaming方式来实现MapReduce Job,基本原理就是输入从Unix系统标准输入,输出使用Unix系统的标准输出。 Hadoop是使用Java语言编写的,所以最直接的方式的就是使用Java语言来实现Mapper和Reducer,然后配置MapReduce Job,提交到集群计算环境来完成计算。但是很多开发者可能对Java并不熟悉,而是对一些具有脚本特性的语言,如C++、Shell、Python、 Ruby、PHP、

Dubbo架构设计详解

Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。关于注册中心、协议支持、服务监控等内容,详见后面描述。 总体架构 Dubbo的总体架构,如图所示: Dubbo框架设计一共划分了10个层,而最上面的Service层是留给实际想要使用Dubbo开发分布式服务的开发者实现业务逻辑的接口层。图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口, 位于中轴线上的为双方都用到的接口。 下面,结合Dubbo官方文档,我们分别理解一下框架分层架构中,各个层次的设计要点: 服务接口层(Service):该层是与实际业务逻辑相关的,根据服务提供方和服务消费方的

Mina框架IoSession详解

通过Mina官 网文档,我们可以看到,有如下几个状态: Connected : the session has been created and is available Idle : the session hasn’t processed any request for at least a period of time (this period is configurable)Closing : the session is being closed (the remaining messages are being flushed, cleaning up is not terminated) Idle for read : no read has actually been made for a period of time Idle for write : no write has actually been made for a period of time Idle for both : no read nor write for a period of time Closed : The session is now closed, nothing else can be done to revive it. 对应的状态迁移图,如图所示: 通过上面的状态图,我们可以看出,是哪个事件的发生使得IoSession进入哪个状态,比较直观明了。下面,我们看一下IoSession对应的设计,类继承关系如下所示: 对于IoSession接

Mina框架IoHandler与IoProcessor详解

我们已经知道,IoHandler是开发网络应用程序的时候,与实际业务逻辑相关的组件,即属于Mina核心框架之外的应用层组件。从Mina 官方文档上,我们几乎没有看到对IoProcessor的说明,实际上IoProcessor对实际使用Mina框架的开发人员透明,无需你去了解它的实现逻辑,它在Mina中用来处理实际的I/O操作。 我们分析的思路是,先分别对IoHandler与IoProcessor进行单独分析,然后再阐述它们之间的不同以及联系。 IoHandler 当我们通过IoSession执行相关操作的时候,如写数据,这些事件会触发Mina框架抽象的IoService实例,从而调用Mina框架底层的相关组件进行处理。这时,配置的IoHandler就被用来处理Mina所触发的相关事件,处理这些事件的操作被抽象出来。 实际上,IoHandler的继承层次非常简单,也说明了基于Mina框架开发实际网络应用程序,对业务逻辑的处理也还是相对比较容易的。看一下 IoHandler的继承层次,如图所示: IoHandler接口所定义的操作,一共定义

Hadoop MapReduce处理海量小文件:压缩文件

在HDFS上存储文件,大量的小文件是非常消耗NameNode内存的,因为每个文件都会分配一个文件描述符,NameNode需要在启动的时候加载全部文件的描述信息,所以文件越多,对 NameNode来说开销越大。 我们可以考虑,将小文件压缩以后,再上传到HDFS中,这时只需要一个文件描述符信息,自然大大减轻了NameNode对内存使用的开销。MapReduce计算中,Hadoop内置提供了如下几 种压缩格式: DEFLATE gzip bzip2 LZO 使用压缩文件进行MapReduce计算,它的开销在于解压缩所消耗的时间,在特定的应用场景中这个也是应该考虑的问题。不过对于海量小文件的应用场景,我们压缩了小文件,却换 来的Locality特性。 假如成百上千的小文件压缩后只有一个Block,那么这个Block必然存在一个DataNode节点上,在计算的时候输入一个InputSplit,没有网络间传输数据的开销,而且是在本地进行 运算。倘若直接将小文件上传到HDFS上,成百上千的小Block分布在不同DataNode节点上,为了计算

Hadoop MapReduce处理海量小文件:基于CombineFileInputFormat

在使用Hadoop处理海量小文件的应用场景中,如果你选择使用CombineFileInputFormat,而且你是第一次使用,可能你会感到有点迷惑。虽然,从这个处理方案的思想上很容易理解,但是可能会遇到这样那样的问题。 使用CombineFileInputFormat作为Map任务的输入规格描述,首先需要实现一个自定义的RecordReader。 CombineFileInputFormat的大致原理是,他会将输入多个数据文件(小文件)的元数据全部包装到CombineFileSplit类里面。也就是说,因为小文件的情况下,在HDFS中都是单Block的文件,即一个文件一个Block,一个CombineFileSplit包含了一组文件Block,包括每个文件的起始偏移(offset),长度(length),Block位置(localtions)等元数据。如果想要处理一个CombineFileSplit,很容易想到,对其包含的每个InputSplit(实际上这里面没有这个,你需要读取一个小文件块的时候,需要构造一个FileInputSplit对象)。 在执行MapReduce任务的时候,需要读取文件的文