搜索引擎选型调研文档

Elasticsearch简介*

Elasticsearch是一个实时的分布式搜索和分析引擎。它可以帮助你用前所未有的速度去处理大规模数据。

它可以用于全文搜索,结构化搜索以及分析,当然你也可以将这三者进行组合。

Elasticsearch是一个建立在全文搜索引擎 Apache Lucene™ 基础上的搜索引擎,可以说Lucene是当今最先进,最高效的全功能开源搜索引擎框架。

但是Lucene只是一个框架,要充分利用它的功能,需要使用JAVA,并且在程序中集成Lucene。需要很多的学习了解,才能明白它是如何运行的,Lucene确实非常复杂。

Elasticsearch使用Lucene作为内部引擎,但是在使用它做全文搜索时,只需要使用统一开发好的API即可,而不需要了解其背后复杂的Lucene的运行原理。

当然Elasticsearch并不仅仅是Lucene这么简单,它不但包括了全文搜索功能,还可以进行以下工作:

  • 分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索。

  • 实时分析的分布式搜索引擎。

  • 可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。

这么多的功能被集成到一台服务器上,你可以轻松地通过客户端或者任何你喜欢的程序语言与ES的RESTful API进行交流。

Elasticsearch的上手是非常简单的。它附带了很多非常合理的默认值,这让初学者很好地避免一上手就要面对复杂的理论,

它安装好了就可以使用了,用很小的学习成本就可以变得很有生产力。

随着越学越深入,还可以利用Elasticsearch更多高级的功能,整个引擎可以很灵活地进行配置。可以根据自身需求来定制属于自己的Elasticsearch。

使用案例:

  • 维基百科使用Elasticsearch来进行全文搜做并高亮显示关键词,以及提供search-as-you-type、did-you-mean等搜索建议功能。

  • 英国卫报使用Elasticsearch来处理访客日志,以便能将公众对不同文章的反应实时地反馈给各位编辑。

  • StackOverflow将全文搜索与地理位置和相关信息进行结合,以提供more-like-this相关问题的展现。

  • GitHub使用Elasticsearch来检索超过1300亿行代码。

  • 每天,Goldman Sachs使用它来处理5TB数据的索引,还有很多投行使用它来分析股票市场的变动。

但是Elasticsearch并不只是面向大型企业的,它还帮助了很多类似DataDog以及Klout的创业公司进行了功能的扩展。

Elasticsearch的优缺点**:

优点

  1. Elasticsearch是分布式的。不需要其他组件,分发是实时的,被叫做”Push replication”。
  2. Elasticsearch 完全支持 Apache Lucene 的接近实时的搜索。
  3. 处理多租户(multitenancy)不需要特殊配置,而Solr则需要更多的高级设置。
  4. Elasticsearch 采用 Gateway 的概念,使得完备份更加简单。
  5. 各节点组成对等的网络结构,某些节点出现故障时会自动分配其他节点代替其进行工作。

缺点

  1. 只有一名开发者(当前Elasticsearch GitHub组织已经不只如此,已经有了相当活跃的维护者)
  2. 还不够自动(不适合当前新的Index Warmup API)

Solr简介*

Solr(读作“solar”)是Apache Lucene项目的开源企业搜索平台。其主要功能包括全文检索、命中标示、分面搜索、动态聚类、数据库集成,以及富文本(如Word、PDF)的处理。Solr是高度可扩展的,并提供了分布式搜索和索引复制。Solr是最流行的企业级搜索引擎,Solr4 还增加了NoSQL支持。

Solr是用Java编写、运行在Servlet容器(如 Apache Tomcat 或Jetty)的一个独立的全文搜索服务器。 Solr采用了 Lucene Java 搜索库为核心的全文索引和搜索,并具有类似REST的HTTP/XML和JSON的API。Solr强大的外部配置功能使得无需进行Java编码,便可对 其进行调整以适应多种类型的应用程序。Solr有一个插件架构,以支持更多的高级定制。

因为2010年 Apache Lucene 和 Apache Solr 项目合并,两个项目是由同一个Apache软件基金会开发团队制作实现的。提到技术或产品时,Lucene/Solr或Solr/Lucene是一样的。

Solr的优缺点

优点

  1. Solr有一个更大、更成熟的用户、开发和贡献者社区。
  2. 支持添加多种格式的索引,如:HTML、PDF、微软 Office 系列软件格式以及 JSON、XML、CSV 等纯文本格式。
  3. Solr比较成熟、稳定。
  4. 不考虑建索引的同时进行搜索,速度更快。

缺点

  1. 建立索引时,搜索效率下降,实时索引搜索效率不高。

Elasticsearch与Solr的比较*

当单纯的对已有数据进行搜索时,Solr更快。

Search Fesh Index While Idle

当实时建立索引时, Solr会产生io阻塞,查询性能较差, Elasticsearch具有明显的优势。

search_fresh_index_while_indexing

随着数据量的增加,Solr的搜索效率会变得更低,而Elasticsearch却没有明显的变化。

search_fresh_index_while_indexing

综上所述,Solr的架构不适合实时搜索的应用。

实际生产环境测试*

下图为将搜索引擎从Solr转到Elasticsearch以后的平均查询速度有了50倍的提升。

average_execution_time

Elasticsearch 与 Solr 的比较总结

  • 二者安装都很简单;
  • Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;
  • Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;
  • Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供;
  • Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch。

Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用。

其他基于Lucene的开源搜索引擎解决方案*

  1. 直接使用 Lucene

说明:Lucene 是一个 JAVA 搜索类库,它本身并不是一个完整的解决方案,需要额外的开发工作。

优点:成熟的解决方案,有很多的成功案例。apache 顶级项目,正在持续快速的进步。庞大而活跃的开发社区,大量的开发人员。它只是一个类库,有足够的定制和优化空间:经过简单定制,就可以满足绝大部分常见的需求;经过优化,可以支持 10亿+ 量级的搜索。

缺点:需要额外的开发工作。所有的扩展,分布式,可靠性等都需要自己实现;非实时,从建索引到可以搜索中间有一个时间延迟,而当前的“近实时”(Lucene Near Real Time search)搜索方案的可扩展性有待进一步完善

说明:基于 Lucene 的,支持分布式,可扩展,具有容错功能,准实时的搜索方案。

优点:开箱即用,可以与 Hadoop 配合实现分布式。具备扩展和容错机制。

缺点:只是搜索方案,建索引部分还是需要自己实现。在搜索功能上,只实现了最基本的需求。成功案例较少,项目的成熟度稍微差一些。因为需要支持分布式,对于一些复杂的查询需求,定制的难度会比较大。

说明:Map/Reduce 模式的,分布式建索引方案,可以跟 Katta 配合使用。

优点:分布式建索引,具备可扩展性。

缺点:只是建索引方案,不包括搜索实现。工作在批处理模式,对实时搜索的支持不佳。

说明:基于 Lucene 的一系列解决方案,包括 准实时搜索 zoie ,facet 搜索实现 bobo ,机器学习算法 decomposer ,摘要存储库 krati ,数据库模式包装 sensei 等等

优点:经过验证的解决方案,支持分布式,可扩展,丰富的功能实现

缺点:与 linkedin 公司的联系太紧密,可定制性比较差

说明:基于 Lucene,索引存在 cassandra 数据库中

优点:参考 cassandra 的优点

缺点:参考 cassandra 的缺点。另外,这只是一个 demo,没有经过大量验证

说明:基于 Lucene,索引存在 HBase 数据库中

优点:参考 HBase 的优点

缺点:参考 HBase 的缺点。另外,在实现中,lucene terms 是存成行,但每个 term 对应的 posting lists 是以列的方式存储的。随着单个 term 的 posting lists 的增大,查询时的速度受到的影响会非常大

 

转载:http://blog.csdn.net/jameshadoop/article/details/44905643

posted @ 2016-03-17 15:16 小马歌 阅读(417) | 评论 (0)编辑 收藏
 
     摘要: 快的打车从2013年年底到2014年下半年,系统访问量迅速膨胀,很多复杂的问题要在短时间内解决,且不能影响线上业务,这是比较大的挑战,本文将会阐述快的打车架构演变过程遇到的一些有代表性的问题和解决方案。LBS的瓶颈和方案先看看基本的系统模型,如图1所示。图1 系统模型示意图司机每隔几秒钟上报一次经纬度,存储在MongoDB里;乘客发单时,通过MongoDB圈选出附近司机;将订单通过长连接服务推送给...  阅读全文
posted @ 2016-03-11 14:57 小马歌 阅读(474) | 评论 (0)编辑 收藏
 

0.以下在系统CentOS 6.3 x86_64上操作

1.试图运行程序,提示"libc.so.6: version `GLIBC_2.14' not found",原因是系统的glibc版本太低,软件编译时使用了较高版本的glibc引起的:

  1. [ghui@StuOS bin]$ pwd  
  2. /var/VMdisks/cross/mingw32/bin  
  3. [ghui@StuOS bin]$ ls  
  4. lrelease     QtCore4.dll         QtNetwork4.dll      QtSql4.dll     QtXml4.dll  
  5. moc          QtDeclarative4.dll  QtOpenGL4.dll       QtSvg4.dll     rcc  
  6. phonon4.dll  QtGui4.dll          QtScript4.dll       QtTest4.dll    uic  
  7. qmake        QtMultimedia4.dll   QtScriptTools4.dll  QtWebKit4.dll  
  8. [ghui@StuOS bin]$ ./qmake   
  9. ./qmake: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./qmake)  
[ghui@StuOS bin]$ pwd /var/VMdisks/cross/mingw32/bin [ghui@StuOS bin]$ ls lrelease     QtCore4.dll         QtNetwork4.dll      QtSql4.dll     QtXml4.dll moc          QtDeclarative4.dll  QtOpenGL4.dll       QtSvg4.dll     rcc phonon4.dll  QtGui4.dll          QtScript4.dll       QtTest4.dll    uic qmake        QtMultimedia4.dll   QtScriptTools4.dll  QtWebKit4.dll [ghui@StuOS bin]$ ./qmake  ./qmake: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./qmake)  

 

2.查看系统glibc支持的版本:
  1. [ghui@StuOS bin]$ strings /lib64/libc.so.6 |grep GLIBC_  
  2. GLIBC_2.2.5  
  3. GLIBC_2.2.6  
  4. GLIBC_2.3  
  5. GLIBC_2.3.2  
  6. GLIBC_2.3.3  
  7. GLIBC_2.3.4  
  8. GLIBC_2.4  
  9. GLIBC_2.5  
  10. GLIBC_2.6  
  11. GLIBC_2.7  
  12. GLIBC_2.8  
  13. GLIBC_2.9  
  14. GLIBC_2.10  
  15. GLIBC_2.11  
  16. GLIBC_2.12  
  17. GLIBC_PRIVATE  
[ghui@StuOS bin]$ strings /lib64/libc.so.6 |grep GLIBC_ GLIBC_2.2.5 GLIBC_2.2.6 GLIBC_2.3 GLIBC_2.3.2 GLIBC_2.3.3 GLIBC_2.3.4 GLIBC_2.4 GLIBC_2.5 GLIBC_2.6 GLIBC_2.7 GLIBC_2.8 GLIBC_2.9 GLIBC_2.10 GLIBC_2.11 GLIBC_2.12 GLIBC_PRIVATE
  1. [ghui@StuOS bin]$ rpm -qa |grep glibc  
  2. glibc-static-2.12-1.80.el6_3.6.x86_64  
  3. glibc-headers-2.12-1.80.el6_3.6.x86_64  
  4. glibc-common-2.12-1.80.el6_3.6.x86_64  
  5. glibc-devel-2.12-1.80.el6_3.6.x86_64  
  6. glibc-static-2.12-1.80.el6_3.6.i686  
  7. glibc-devel-2.12-1.80.el6_3.6.i686  
  8. glibc-2.12-1.80.el6_3.6.i686  
  9. glibc-2.12-1.80.el6_3.6.x86_64  
[ghui@StuOS bin]$ rpm -qa |grep glibc glibc-static-2.12-1.80.el6_3.6.x86_64 glibc-headers-2.12-1.80.el6_3.6.x86_64 glibc-common-2.12-1.80.el6_3.6.x86_64 glibc-devel-2.12-1.80.el6_3.6.x86_64 glibc-static-2.12-1.80.el6_3.6.i686 glibc-devel-2.12-1.80.el6_3.6.i686 glibc-2.12-1.80.el6_3.6.i686 glibc-2.12-1.80.el6_3.6.x86_64 

3.可以看到最高只支持2.12版本,所以考虑编译解决这个问题:

       a. 到http://www.gnu.org/software/libc/下载最新版本,我这里下载了glibc-2.14.tar.xz 这个版本,解压到任意目录准备编译

       b.这里解压到/var/VMdisks/glibc-2.14/

  1. [ghui@StuOS bin]$ cd /var/VMdisks/glibc-2.14/  
  2. [ghui@StuOS glibc-2.14]$ pwd  
  3. /var/VMdisks/glibc-2.14  
  4. [ghui@StuOS glibc-2.14]$ ls  
  5. abilist            config.h.in           intl           README.libm  
  6. abi-tags           config.log            io             resolv  
  7. aclocal.m4         config.make.in        libc-abis      resource  
  8. aout               configure             libidn         rt  
  9. argp               configure.in          libio          Rules  
  10. assert             conform               LICENSES       scripts  
  11. autom4te.cache     CONFORMANCE           locale         setjmp  
  12. bits               COPYING               localedata     shadow  
  13. BUGS               COPYING.LIB           login          shlib-versions  
  14. build              cppflags-iterator.mk  mach           signal  
  15. CANCEL-FCT-WAIVE   crypt                 Makeconfig     socket  
  16. CANCEL-FILE-WAIVE  csu                   Makefile       soft-fp  
  17. catgets            ctype                 Makefile.in    stdio-common  
  18. ChangeLog          debug                 Makerules      stdlib  
  19. ChangeLog.1        dirent                malloc         streams  
  20. ChangeLog.10       dlfcn                 manual         string  
  21. ChangeLog.11       elf                   math           sunrpc  
  22. ChangeLog.12       extra-lib.mk          misc           sysdeps  
  23. ChangeLog.13       extra-modules.mk      NAMESPACE      sysvipc  
  24. ChangeLog.14       FAQ                   NEWS           termios  
  25. ChangeLog.15       FAQ.in                nis            test-skeleton.c  
  26. ChangeLog.16       gmon                  NOTES          time  
  27. ChangeLog.17       gnulib                nptl           timezone  
  28. ChangeLog.2        grp                   nptl_db        tls.make.c  
  29. ChangeLog.3        gshadow               nscd           version.h  
  30. ChangeLog.4        hesiod                nss            Versions.def  
  31. ChangeLog.5        hurd                  o-iterator.mk  wcsmbs  
  32. ChangeLog.6        iconv                 po             wctype  
  33. ChangeLog.7        iconvdata             posix          WUR-REPORT  
  34. ChangeLog.8        include               PROJECTS  
  35. ChangeLog.9        inet                  pwd  
  36. conf               INSTALL               README  
[ghui@StuOS bin]$ cd /var/VMdisks/glibc-2.14/ [ghui@StuOS glibc-2.14]$ pwd /var/VMdisks/glibc-2.14 [ghui@StuOS glibc-2.14]$ ls abilist            config.h.in           intl           README.libm abi-tags           config.log            io             resolv aclocal.m4         config.make.in        libc-abis      resource aout               configure             libidn         rt argp               configure.in          libio          Rules assert             conform               LICENSES       scripts autom4te.cache     CONFORMANCE           locale         setjmp bits               COPYING               localedata     shadow BUGS               COPYING.LIB           login          shlib-versions build              cppflags-iterator.mk  mach           signal CANCEL-FCT-WAIVE   crypt                 Makeconfig     socket CANCEL-FILE-WAIVE  csu                   Makefile       soft-fp catgets            ctype                 Makefile.in    stdio-common ChangeLog          debug                 Makerules      stdlib ChangeLog.1        dirent                malloc         streams ChangeLog.10       dlfcn                 manual         string ChangeLog.11       elf                   math           sunrpc ChangeLog.12       extra-lib.mk          misc           sysdeps ChangeLog.13       extra-modules.mk      NAMESPACE      sysvipc ChangeLog.14       FAQ                   NEWS           termios ChangeLog.15       FAQ.in                nis            test-skeleton.c ChangeLog.16       gmon                  NOTES          time ChangeLog.17       gnulib                nptl           timezone ChangeLog.2        grp                   nptl_db        tls.make.c ChangeLog.3        gshadow               nscd           version.h ChangeLog.4        hesiod                nss            Versions.def ChangeLog.5        hurd                  o-iterator.mk  wcsmbs ChangeLog.6        iconv                 po             wctype ChangeLog.7        iconvdata             posix          WUR-REPORT ChangeLog.8        include               PROJECTS ChangeLog.9        inet                  pwd conf               INSTALL               README  

      c.在glibc源码目录建立构建目录,并cd进入构建目录
  1. [ghui@StuOS glibc-2.14]$ mkdir build  
[ghui@StuOS glibc-2.14]$ mkdir build
  1. [ghui@StuOS glibc-2.14]$ cd build  
[ghui@StuOS glibc-2.14]$ cd build 

    d.运行configure配置,make && sudo  make install
  1. [ghui@StuOS build]$ ../configure --prefix=/opt/glibc-2.14  
  2. [ghui@StuOS build]$ make -j4   
  3. [ghui@StuOS build]$ sudo make install  
  4. [sudo] password for ghui:   
[ghui@StuOS build]$ ../configure --prefix=/opt/glibc-2.14 [ghui@StuOS build]$ make -j4  [ghui@StuOS build]$ sudo make install [sudo] password for ghui:   

4.临时修改环境变量
  1. [ghui@StuOS bin]$ export LD_LIBRARY_PATH=/opt/glibc-2.14/lib:$LD_LIBRARY_PATH  
[ghui@StuOS bin]$ export LD_LIBRARY_PATH=/opt/glibc-2.14/lib:$LD_LIBRARY_PATH 
  1. [ghui@StuOS glibc-2.14]$ cd /var/VMdisks/cross/mingw32/bin/  
[ghui@StuOS glibc-2.14]$ cd /var/VMdisks/cross/mingw32/bin/ 

  1. [ghui@StuOS bin]$ ./qmake   
  2. Usage: ./qmake [mode] [options] [files]  
  3.   
  4. QMake has two modes, one mode for generating project files based on  
  5. some heuristics, and the other for generating makefiles. Normally you  
  6. shouldn't need to specify a mode, as makefile generation is the default  
  7. mode for qmake, but you may use this to test qmake on an existing project  

From:

http://blog.csdn.net/cpplang/article/details/8462768

posted @ 2016-03-10 10:14 小马歌 阅读(1430) | 评论 (0)编辑 收藏
 

致命错误出现的时候,JVM生成了hs_err_pid<pid>.log这样的文件,其中往往包含了虚拟机崩溃原因的重要信息。因为经常遇 到,在这篇文章里,我挑选了一个,并且逐段分析它包含的内容(文件可以在文章最后下载)。默认情况下文件是创建在工作目录下的(如果没权限创建的话JVM 会尝试把文件写到/tmp这样的临时目录下面去),当然,文件格式和路径也可以通过参数指定,比如:

  1. java -XX:ErrorFile=/var/log/java/java_error%p.log 

这个文件将包括:

  • 触发致命错误的操作异常或者信号;
  • 版本和配置信息;
  • 触发致命异常的线程详细信息和线程栈;
  • 当前运行的线程列表和它们的状态;
  • 堆的总括信息;
  • 加载的本地库;
  • 命令行参数;
  • 环境变量;
  • 操作系统CPU的详细信息。

首先,看到的是对问题的概要介绍:

  1. #  SIGSEGV (0xb) at pc=0x03568cf4, pid=16819, tid=3073346448 

一个非预期的错误被JRE检测到,其中:

  • SIGSEGV是信号名称
  • 0xb是信号码
  • pc=0x03568cf4指的是程序计数器的值
  • pid=16819是进程号
  • tid=3073346448是线程号

如果你对JVM有了解,应该不会对这些东西陌生。

接下来是JRE和JVM的版本信息:

  1. # JRE version: 6.0_32-b05 
  2.   
  3. # Java VM: Java HotSpot(TM) Server VM (20.7-b02 mixed mode linux-x86 ) 

运行在mixed模式下。

然后是问题帧的信息:

  1. # Problematic frame: 
  2.   
  3. # C  [libgtk-x11-2.0.so.0+0x19fcf4]  __float128+0x19fcf4 
  • C:帧类型为本地帧,帧的类型包括: 
    • C:本地C帧
    • j:解释的Java帧
    • V:虚拟机帧
    • v:虚拟机生成的存根栈帧
    • J:其他帧类型,包括编译后的Java帧
  • libgtk-x11-2.0.so.0+0x19fcf4:和程序计数器(pc)表达的含义一样,但是用的是本地so库+偏移量的方式。

接下去第一部分是线程信息:

  1. Current thread (0x09f30c00):  JavaThread "main" [_thread_in_native, id=16822, stack(0xb72a8000,0xb72f9000)] 

当前线程的:

  • 0x09f30c00:指针
  • JavaThread:线程类型,可能的类型包括: 
    • JavaThread
    • VMThread
    • CompilerThread
    • GCTaskThread
    • WatcherThread
    • ConcurrentMarkSweepThread
  • main:名字 
    • _thread_in_native:线程当前状态,状态枚举包括:
    • _thread_uninitialized:线程还没有创建,它只在内存原因崩溃的时候才出现
    • _thread_new:线程已经被创建,但是还没有启动
    • _thread_in_native:线程正在执行本地代码,一般这种情况很可能是本地代码有问题
    • _thread_in_vm:线程正在执行虚拟机代码
    • _thread_in_Java:线程正在执行解释或者编译后的Java代码
    • _thread_blocked:线程处于阻塞状态
    • …_trans:以_trans结尾,线程正处于要切换到其它状态的中间状态
  • id=16822:线程ID
  • 0xb72a8000,0xb72f9000:栈区间
  1. siginfo:si_signo=SIGSEGV: si_errno=0, si_code=1 (SEGV_MAPERR), si_addr=0x00000010 

这部分是导致虚拟机终止的非预期的信号信息,含义前面已经大致提到过了。其中si_errno和si_code是Linux下用来鉴别异常的,Windows下是一个ExceptionCode。

  1. EAX=0x00000000, EBX=0x0375dd84, ECX=0x00000000, EDX=0x00000000 
  2. ESP=0xb72f0fa0, EBP=0xb72f0fb8, ESI=0x00000000, EDI=0x0a6c1800 
  3. EIP=0x03568cf4, EFLAGS=0x00010246, CR2=0x00000010 

这是寄存器上下文。

 

  1. Top of Stack: (sp=0xb72f0fa0) 
  2. 0xb72f0fa0:   00000000 00402250 0040217f 0375dd84 
  3. 0xb72f0fb0:   00000000 0a6c1800 b72f0fe8 0356c2c0 
  4. 0xb72f0fc0:   00000000 0a6c1800 b72f0fe8 003b3e77 
  5. 0xb72f0fd0:   003e6c8b 0a1a70d0 0a193358 0375dd84 
  6. 0xb72f0fe0:   0a276418 0a276418 b72f1048 03536c56 
  7. 0xb72f0ff0:   0acad000 0b3ca978 0000000c 00dd0674 
  8. 0xb72f1000:   00000003 0a2c7d50 b72f1038 0000330c 
  9. 0xb72f1010:   ffffffff ffffffff 00000001 00000001 
  10.   
  11. Instructions: (pc=0x03568cf4) 
  12. 0x03568cd4:   89 14 24 89 75 f8 89 d6 89 7d fc 89 c7 e8 7e 1b 
  13. 0x03568ce4:   ea ff 89 34 24 89 87 d4 02 00 00 e8 30 00 ea ff 
  14. 0x03568cf4:   8b 40 10 89 3c 24 c7 44 24 08 00 00 00 00 89 87 
  15. 0x03568d04:   d0 02 00 00 8b 83 88 24 00 00 89 44 24 04 e8 dd 

栈顶程序计数器旁的操作码,它们可以被反汇编成系统崩溃前执行的指令。

  1. Register to memory mapping: 
  2.   
  3. EAX=0x00000000 is an unknown value 
  4. EBX=0x0375dd84: <offset 0x394d84> in /usr/lib/libgtk-x11-2.0.so.0 at 0x033c9000 
  5. ECX=0x00000000 is an unknown value 
  6. EDX=0x00000000 is an unknown value 
  7. ESP=0xb72f0fa0 is pointing into the stack for thread: 0x09f30c00 
  8. EBP=0xb72f0fb8 is pointing into the stack for thread: 0x09f30c00 
  9. ESI=0x00000000 is an unknown value 
  10. EDI=0x0a6c1800 is an unknown value 

寄存器和内存映射信息。

  1. Stack: [0xb72a8000,0xb72f9000],  sp=0xb72f0fa0,  free space=291k 
  2. Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) 
  3. C  [libgtk-x11-2.0.so.0+0x19fcf4]  __float128+0x19fcf4 
  4. C  [libgtk-x11-2.0.so.0+0x1a32c0]  __float128+0xc0 
  5. ... ... 
  6. C  [libswt-pi-gtk-3738.so+0x33f6a]  Java_org_eclipse_swt_internal_gtk_OS__1Call+0xf 
  7. J  org.eclipse.swt.internal.gtk.OS._Call(III)I 
  8. J  org.eclipse.swt.internal.gtk.OS.Call(III)I 
  9.   
  10. Java frames: (J=compiled Java code, j=interpreted, Vv=VM code) 
  11. J  org.eclipse.swt.internal.gtk.OS._Call(III)I 
  12. J  org.eclipse.swt.internal.gtk.OS.Call(III)I 
  13. j  org.eclipse.swt.widgets.Widget.fixedSizeAllocateProc(II)I+5 
  14. j  org.eclipse.swt.widgets.Display.fixedSizeAllocateProc(II)I+17 
  15. v  ~StubRoutines::call_stub 

线程栈。包含了地址、栈顶、栈计数器和线程尚未使用的栈信息,由于栈可能非常长,打印的长度有限制,但是至少本地栈和Java栈都打印出来了(很多时候本地栈打印不出来,但是Java栈一般都能打印出来)。从中可以看到,Eclipse的虚拟机崩溃了。

  1. ava Threads: ( => current thread ) 
  2.   0x0b4c1000 JavaThread "Worker-247" [_thread_blocked, id=25417, stack(0x741bc000,0x7420d000)] 
  3.   0x0a300c00 JavaThread "Worker-246" [_thread_blocked, id=25235, stack(0x7d30c000,0x7d35d000)] 
  4. ... ... 

线程信息。一目了然,不解释了。

  1. VM state:not at safepoint (normal execution) 

虚拟机状态。包括:

  • not at a safepoint:正常运行状态;
  • at safepoint:所有线程都因为虚拟机等待状态而阻塞,等待一个虚拟机操作完成;
  • synchronizing:一个特殊的虚拟机操作,要求虚拟机内的其它线程保持等待状态。
  1. VM Mutex/Monitor currently owned by a thread: None 

虚拟机的Mutex和Monitor目前没有被线程持有。Mutex是虚拟机内部的锁,而Monitor则关联到了Java对象。

  1. Heap 
  2.  PSYoungGen      total 149056K, used 125317K [0xa9700000, 0xb41a0000, 0xb41a0000) 
  3.   eden space 123520K, 95% used [0xa9700000,0xb0ac0de0,0xb0fa0000) 
  4.   from space 25536K, 26% used [0xb28b0000,0xb2f50748,0xb41a0000) 
  5.   to   space 25600K, 0% used [0xb0fa0000,0xb0fa0000,0xb28a0000) 
  6.  PSOldGen        total 261248K, used 239964K [0x941a0000, 0xa40c0000, 0xa9700000) 
  7.   object space 261248K, 91% used [0x941a0000,0xa2bf7018,0xa40c0000) 
  8.  PSPermGen       total 163328K, used 130819K [0x841a0000, 0x8e120000, 0x941a0000) 
  9.   object space 163328K, 80% used [0x841a0000,0x8c160c40,0x8e120000) 

堆信息。新生代、老生代、永久代。对JVM有了解的人应该都清楚,不解释了。

  1. Code Cache  [0xb4262000, 0xb5ac2000, 0xb7262000) 
  2.  total_blobs=5795 nmethods=5534 adapters=209 free_code_cache=25103616 largest_free_block=38336 

代码缓存(Code Cache)。这是一块用于编译和保存本地代码的内存,注意是本地代码,它和PermGen(永久代)是不一样的,永久带是用来存放Java类定义的。

  1. Dynamic libraries: 
  2. 00101000-00122000 r-xp 00000000 08:01 3483560    /usr/lib/libjpeg.so.62.0.0 
  3. 00122000-00123000 rwxp 00020000 08:01 3483560    /usr/lib/libjpeg.so.62.0.0 
  4. 00125000-00130000 r-xp 00000000 08:01 9093202    /lib/libgcc_s-4.1.2-20080825.so.1 
  5. 00130000-00131000 rwxp 0000a000 08:01 9093202    /lib/libgcc_s-4.1.2-20080825.so.1 
  6. ... ... 

内存映射。这些信息是虚拟机崩溃时的虚拟内存列表区域。在定位崩溃原因的时候,它可以告诉你哪些类库正在被使用,位置在哪里,还有堆栈和守护页信息。就以列表中第一条为例说明:

  • 00101000-00122000:内存区域
  • r-xp:权限,r/w/x/p/s分别表示读/写/执行/私有/共享
  • 00000000:文件内的偏移量
  • 08:01:文件位置的majorID和minorID
  • 3483560:索引节点号
  • /usr/lib/libjpeg.so.62.0.0:文件位置

每一个lib都有两块虚拟内存区域——代码和数据,它们的权限不同,代码区域是r-xp;数据区域是rwxp。守护页(guard page)由权限为--xp和rwxp的一对组成。

  1. VM Arguments: 
  2. jvm_args: -Dosgi.requiredJavaVersion=1.5 -XX:MaxPermSize=256m -Xms40m -Xmx512m -Dorg.eclipse.swt.browser.XULRunnerPath='' 
  3. java_command: /.../eclipse/plugins/org.eclipse.equinox.launcher_1.2.0.v20110502.jar -os linux -ws gtk -arch x86 -showsplash -launcher /.../eclipse/eclipse -name Eclipse ... 
  4. Launcher Type: SUN_STANDARD 
  5.   
  6. Environment Variables: 
  7. PATH=... 
  8. DISPLAY=:0.0 

虚拟机参数和环境变量。

  1. Signal Handlers: 
  2. SIGSEGV: [libjvm.so+0x726440], sa_mask[0]=0x7ffbfeff, sa_flags=0x10000004 
  3. SIGBUS: [libjvm.so+0x726440], sa_mask[0]=0x7ffbfeff, sa_flags=0x10000004 
  4. ... ... 

信号句柄。对于Linux下的信号机制,参阅wiki百科, 链接

 

  1. OS:Red Hat Enterprise Linux Client release 5.4 (Tikanga) 
  2.   
  3. uname:Linux 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:54 EDT 2009 i686 
  4. libc:glibc 2.5 NPTL 2.5 
  5. rlimit: STACK 10240k, CORE 0k, NPROC 65536, NOFILE 1024, AS infinity 
  6. load average:1.78 1.58 1.54 
  7.   
  8. /proc/meminfo: 
  9. ... 
  10.   
  11. CPU:total 4 (4 cores per cpu, 1 threads per core) family 6 model 42 stepping 7, cmov, cx8, fxsr, mmx, sse, sse2, sse3, ssse3 
  12.   
  13. /proc/cpuinfo: 
  14. ... 
  15.   
  16. Memory: 4k page, physical 3631860k(155144k free), swap 5124724k(5056452k free) 


已有 0 人发表留言,猛击->> 这里<<-参与讨论 


ITeye推荐 


相关 [jvm 错误 日志] 推荐:

JVM致命错误日志(hs_err_pid.log)解读

- - 四火的唠叨
文章系本人原创,转载请保持完整性并注明出自 《四火的唠叨》. 致命错误出现的时候,JVM生成了hs_err_pid<pid>.log这样的文件,其中往往包含了虚拟机崩溃原因的重要信息. 因为经常遇到,在这篇文章里,我挑选了一个,并且逐段分析它包含的内容(文件可以在文章最后下载). 默认情况下文件是创建在工作目录下的(如果没权限创建的话JVM会尝试把文件写到/tmp这样的临时目录下面去),当然,文件格式和路径也可以通过参数指定,比如:.

Fatal Error log format,JVM 致命错误日志格式

- - 码蜂笔记
本文翻译自: http://www.oracle.com/technetwork/java/javase/felog-138657.html. 本文内容基于 Java SE 6,HotSpot JVM. 当一个致命错误发生时,一个错误日志将被创建,存储了在致命错误发生时获取到的信息和状态. 注意:这个文件的格式可能随着版本的更新而改变.

JVM日志和参数的理解

- - 开源软件 - ITeye博客
转自:http://hot66hot.iteye.com/blog/2075819. 写这篇wiki的目的:最近在调整Hbase的JVM,翻了些文档和wiki,想写点东西,给自己和想了解jvm日志和参数的同 学提供些帮助..  一:理解GC日志格式,读GC日志的方法. -XX:+UseGCLogFileRotation  启用GC日志文件的自动转储 (Since Java).

通过JVM日志来进行安全点分析

- - 并发编程网 - ifeve.com
原文链接 作者: Plumbr 译者:之诸暇. 许多事件都可能会导致JVM暂停所有的应用线程. 这类暂停又被称为”stop-the-world”(STW)暂停. 触发STW暂停最常见的原因就是垃圾回收了( github中的一个例子),但不同的JIT活动( 例子),偏向锁擦除( 例子), 特定的JVMTI操作,以及许多场景也可能会导致应用程序暂停.

【体系结构】MySQL 日志文件--错误日志

- - CSDN博客数据库推荐文章
        记录MySQL Server 启动和关闭的详细信息、以及运行过程中较为严重的警告和错误信息.        为了维护方便需要、有时候会希望将错误日志中的内容做备份并重新开始记录、那么可以:.         MySQL DBA 在遇到问题时应该首先查看该文件.         当出现 MySQL Server 不能正常启动时、第一个拷问的重点对象应该就是此人.

Oracle GoldenGate 监控工具:ggserr.log 错误日志不可忽视

- - CSDN博客推荐文章
Oracle 原厂最近在生产环境的主数据库安装了 OEM 12C 的监控插件后,主数据库对外十几个库同步同步的. Oracle GoldenGate 实例出现异常,疯狂地往 GoldenGate 根目录的 ggserr.log 输入出如下错误日志:. 2013-02-22 22:33:26  WARNING OGG-01930  Oracle GoldenGate Capture for Oracle, pcqstqz1.prm:  Datastore error in 'dirbdb': BDB0060 PANIC: fatal region error detected; run recovery.

JVM研究

- - 开源软件 - ITeye博客
每天接客户的电话都是战战兢兢的,生怕再出什么幺蛾子了. 我想Java做的久一点的都有这样的经历,那这些问题的最终根结是在哪呢. JVM全称是Java Virtual Machine,Java虚拟机,也就是在计算机上再虚拟一个计算机,这和我们使用 VMWare不一样,那个虚拟的东西你是可以看到的,这个JVM你是看不到的,它存在内存中.

学习JVM的References

- LightingMan - 淘宝JAVA中间件团队博客
本blog中列举了我学习JVM的references,会不断的更新,为了避免版权问题,就不在blog上提供references的下载了,感兴趣的同学可自行下载或购买,:). |— [ Hotspot GC论文 ]. |— [ 其他JVM GC ]. |— Linux内核源代码情景分析. |— Linux 内核中断内幕.

深入理解JVM

- 小伟 - ITeye论坛最新讨论
1   Java技术与Java虚拟机. 说起Java,人们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组成: Java编程语言、Java类文件格式、Java虚拟机和Java应用程序接口(Java API). 图1   Java四个方面的关系. 运行期环境代表着Java平台,开发人员编写Java代码(.java文件),然后将之编译成字节码(.class文件).
posted @ 2016-03-02 15:00 小马歌 阅读(604) | 评论 (0)编辑 收藏
 

from:http://www.jameswxx.com/%E4%B8%AD%E9%97%B4%E4%BB%B6/%E8%A7%A3%E5%86%B3dubbo%E9%97%AE%E9%A2%98%EF%BC%9Aforbid-consumer/


线下环境经常出现类似这种异常:

com.alibaba.dubbo.rpc.RpcException: Forbid consumer 10.0.53.69 access service com.kuaidadi.op.api.pay.service.PayChannelConfigRemoteService from registry 10.0.50.150:2181 use dubbo version 2.5.3, Please check registry access list (whitelist/blacklist).
大致意思是当前调用者被禁止访问某个服务,请检查下注册中心访问列表,还有黑名单和白名单。
其实线下环境根本没有对服务做白名单和黑名单机制,因为线下环境给开发人员的账号是guest,没有权限做黑白名单。今天有好几个人问我这个问题,我仔细看了源码,找出了根源所在。
根据异常栈,抛出这个异常的代码在RegistryDirectory的第579行,如下:
public List<Invoker<T>> doList(Invocation invocation) {
 if (forbidden ) {
     throw new RpcException(RpcException.FORBIDDEN_EXCEPTION , ” Forbid consumer “ +  NetUtils. getLocalHost() + ” access service “ +        getInterface().getName() + ” from registry “ + getUrl().getAddress() + ” use dubbo version “ + Version.getVersion() + “, Please check registry access list (whitelist/blacklist).”);
}
如果forbidden变量为true,则抛出该异常。forbidden变量默认为false,那么什么时候变成true了呢?看RegistryDirectory的这段代码:
private void refreshInvoker(List<URL> invokerUrls){
   if (invokerUrls != null && invokerUrls.size() == 1 && invokerUrls.get(0) != null && Constants.EMPTY_PROTOCOL .equals(invokerUrls.get(0).getProtocol())) {
            this.forbidden = true; // 禁止访问
            this.methodInvokerMap = null; // 置空列表
            destroyAllInvokers(); // 关闭所有Invoker
   }
意思是如果invokerUrls的size为1,并且url的协议头是Constants.EMPTY_PROTOCOL时,则设置forbidden为false,Constants.EMPTY_PROTOCOL的值是empty。
 
 
refreshInvoker方法什么时候被调用呢?当某个服务的provider有变化时就会被调用,例如zookeeper上某个服务的provider目录里的内容发生变化,则zk监听器会被触发,由于provider的数量会发生变化,例如有一个新的provider启动了,有一个provider下线了,所以必须刷新本地的对provider的连接,具体逻辑就在refreshInvoker方法里,这个方法的调用栈如下:
image_1
可以确定的是,zookeeper推送的URL的protocol部分不可能无缘无故变成了empty,肯定是由某个地方更改了,于是看一下Constants.EMPTY_PROTOCOL到底有哪些地方调用了,如下:
image_2
见图中红色圈圈部分,当zookeeper初次订阅或者订阅的信息有变更时,都会触发toUrlsChanged方法,看看这个方法内部都做了什么,完整代码如下:
     private List<URL> toUrlsWithEmpty(URL consumer, String path, List<String> providers) {
        List<URL> urls = toUrlsWithoutEmpty(consumer, providers);
        if (urls == null || urls.isEmpty()) {
           int i = path.lastIndexOf(‘/’ );
          String category = i < 0 ? path : path.substring(i + 1);
          URL empty = consumer.setProtocol(Constants.EMPTY_PROTOCOL ).addParameter(Constants. CATEGORY_KEY, category);
            urls.add(empty);
        }
        return urls;
    }
可见如果toUrlsWithoutEmpty的结果是空或者size为0,则强制返回一个protocol为empty的url,看来源头就在这里了。传入的List<String> providers实际上就是最新的服务提供者信息,当某个服务没有任何provider时,providers就变为一个size为o的List了,导致返回一个协议头为empty的url,进而导致forbidden为true,屏蔽了consumer调用。
posted @ 2016-02-29 16:24 小马歌 阅读(1479) | 评论 (0)编辑 收藏
 
     摘要: 2012/08/28 09:49:49 No CommentsTags: bean, earlySingletonObjects, getBean, recycle reference, singletonFactories, spring, 源码分析   Posted :java开发, ...  阅读全文
posted @ 2016-01-27 14:09 小马歌 阅读(471) | 评论 (0)编辑 收藏
 
     摘要: 原文见:http://blog.csdn.net/hzzhoushaoyu/article/details/43273099一、前言部门去年年中开始各种改造,第一步是模块服务化,这边初选dubbo试用在一些非重要模块上,慢慢引入到一些稍微重要的功能上,半年时间,学习过程及线上使用遇到的些问题在此总结下。整理这篇文章差不多花了两天半时间,请尊重劳动成果,如转载请注明出处http://blog.csd...  阅读全文
posted @ 2016-01-26 17:58 小马歌 阅读(745) | 评论 (0)编辑 收藏
 

毫无疑问,现在Gradle已经成为java世界最火的构建工具,风头已经盖过了冗余的ant,落后的maven。Gradle是以Groovy语言编写的一套构建脚本的DSL,由于Groovy语法的优雅,所以导致Gradle天生就有简洁、可读性强、灵活等特性。

Gradle的命令行功能也非常强大。本人从maven转到Gradle,深深被gradle强大的命令行功能折服。通过命令行来实现Gradle的各种特性,就像魔法师在表演魔法一样。

more
  • 日志输出。 Gradle中的日志有6个层级。从高到低分别是 ERROR(错误信息)、QUIET(重要信息)、WARNGING(警告信息)、LIFECYCLE(进程信息)、INFO(一般信息)、DEBUG(调试信息)。在执行gradle task时可以适时的调整信息输出等级,以便更方便的观看执行结果。

-q(或--quiet)是启用重要信息级别,该级别下只会输出自己在命令行下打印的信息及错误信息。

-i(或--info)则会输出除debug以外的所有信息。

-d(或--debug)会输出所有日志信息。

比如一个build.gradle有这样一个task。

task hello << {      println 'hello world!' }

加入-q与不加-q的输出结果不同。

$ gradle hello :hello hello world!  BUILD SUCCESSFUL  Total time: 3.546 secs $ gradle -q hello hello world!
  • 堆栈跟踪。如果执行gradle task失败时,如果想得到更详细的错误信息,那么就可以使用-s(或--stacktrace)来输出详细的错误堆栈。你还可以使用-S(或--full-stacktrace)来输出全部堆栈信息,不过一般不推荐这样做,因为gradle是基于groovy语言,而groovy作为一门动态语言可能会输出与你的错误代码毫不相关的信息。

  • 跳过指定的测试。如果你在执行build的时候想跳过test task,那么可以使用-x命令。

$ gradle build -x test :compileJava UP-TO-DATE :processResources UP-TO-DATE :classes UP-TO-DATE :jar UP-TO-DATE :assemble UP-TO-DATE :check :build  BUILD SUCCESSFUL  Total time: 3.529 secs
  • 继续执行task而忽略前面失败的task。默认情况下,如果有某个task失败,后续的task就不会继续执行。但是有时候我们想运行所有的task来一次性得到所有的构建错误,那么我们可以使用--continue命令。使用--continue命令后即使遇到某些task失败也不会停止后续task的执行。但是需要注意的是如果某个task失败了,那么依赖于这个task的其他task依旧不会执行,因为这会带来不安全的因素。

  • 调用task时使用短名或缩写。如果一个task的名称过长,那么调用时可以只输入部分名称即可调用,无需输入全名。

task helloWorld << {      println 'hello world!' }

比如调用helloWorld可以通过全名调用、前缀调用或首字母调用。

$ gradle -q helloWorld hello world! $ gradle -q hell hello world! $ gradle -q hW hello world!
  • 使用指定的gradle文件调用task。默认情况下,如果你调用gradle task,那么首先会寻找当前目录下的build.gradle文件,以及根据settings.gradle中的配置寻找子项目的build.gradle。但是有时候我们想指定使用某个gradle文件,那么可以使用-b命令。 比如当前目录有个子目录subproject1,里面有个叫hello.gradle。
task helloWorld << {      println 'hello world!' }

那么在当前目录可以使用以下命令调用这个task。

$ gradle -b subproject1/hello.gradle  helloWorld :helloWorld hello world!  BUILD SUCCESSFUL  Total time: 3.752 secs
  • 使用指定的项目目录调用task。前面已经说过,执行gradle的task默认会在当前目录寻找build.gradle及settings.gradle文件。如果我们想在任何地方执行某个项目的task,那么可以使用-p来指定使用的项目。
gradle -q -p learnGradle helloWorld

这条命令是调用learnGradle这个项目下的helloWorld task。

  • 显示task之间的依赖关系。众所周知,使用gradle tasks可以列出当前所有可被使用的task,但是并没有显示task之间的依赖关系。我们可以加上--all来显示 task的依赖关系。
$ gradle tasks --all ………………  Other tasks ----------- task0     task1     task2     task3  …………
从上面可以看出task0依赖task1、task2及task3。
  • 查看指定阶段的依赖关系。使用gradle dependencies 可以查看项目中包的依赖关系。不过是列出了所有阶段的依赖,如果项目中依赖复杂的话看起来有点头痛。那么可以使用--configuration来查看指定阶段的依赖情况。
$ gradle -q dependencies  ------------------------------------------------------------ Root project ------------------------------------------------------------  archives - Configuration for archive artifacts. No dependencies  compile - Compile classpath for source set 'main'. No dependencies  default - Configuration for default artifacts. No dependencies  runtime - Runtime classpath for source set 'main'. No dependencies  testCompile - Compile classpath for source set 'test'. \--- junit:junit:4.11      \--- org.hamcrest:hamcrest-core:1.3  testRuntime - Runtime classpath for source set 'test'. \--- junit:junit:4.11      \--- org.hamcrest:hamcrest-core:1.3

使用gradle -q dependencies --configuration testCompile可以只查看testComiple的依赖。

$ gradle -q dependencies --configuration testCompile  ------------------------------------------------------------ Root project ------------------------------------------------------------  testCompile - Compile classpath for source set 'test'. \--- junit:junit:4.11      \--- org.hamcrest:hamcrest-core:1.3
  • 查看指定dependency的依赖情况。 假如我想查看项目中有没有引入junit,那些阶段引入了junit,那么可以使用dependecyInsight来查看。
$ gradle dependencyInsight --dependency junit --configuration testCompile :dependencyInsight junit:junit:4.11 \--- testCompile

注意dependencyInsight默认只会查看compile阶段的依赖,如果要查看其他阶段可以使用--configuration来指定。

  • 使用--profile命令行可以产生build运行时间的报告。该报告存储在build/report/profile目录,名称为build运行的时间。
$ gradle build --profile :compileJava UP-TO-DATE :processResources UP-TO-DATE :classes UP-TO-DATE :jar UP-TO-DATE :assemble UP-TO-DATE :compileTestJava UP-TO-DATE :processTestResources UP-TO-DATE :testClasses UP-TO-DATE :test UP-TO-DATE :check UP-TO-DATE :build UP-TO-DATE  BUILD SUCCESSFUL  Total time: 3.726 secs

然后在build/report/profile目录下可以看到build的report。

这个报表非常有用,尤其是在在缩短build时间时可以快速定位那些耗时长的task。

  • 试运行build。如果你想知道某个task执行时那些task会被一起执行,但是你又不想真正的执行这些task,可以使用-m来试运行。
$ gradle -m build :compileJava SKIPPED :processResources SKIPPED :classes SKIPPED :jar SKIPPED :assemble SKIPPED :compileTestJava SKIPPED :processTestResources SKIPPED :testClasses SKIPPED :test SKIPPED :check SKIPPED :build SKIPPED  BUILD SUCCESSFUL  Total time: 3.53 secs

这样我们可以一目了然的看到那些task被执行了,又不需要花太多的时间。

  • Gradle的图形界面。

其实Gradle自带一个图形界面来让习惯gui操作的人来操作Gradle。打开方式很简单。

$ gradle --gui

这样就会弹出一个gui界面。

通过这个gui界面可以很方面的执行gradle的各种命令,还可以将常用的命令保存为favorites。该gui的配置信息默认被存储在当前项目的gradle-app.setting文件中。

注意使用gradle --gui会阻塞当前终端,可以使用gradle --gui&来实现后台运行。

  • 重新编译Gradle脚本。第一次运行Gradle命令,会在项目更目录下生成一个.gradle目录来存放编译后的脚本。只有当构建脚本发生修改时采用重新编译。我们可以使用--recompile-scripts来强行重新编译。
posted @ 2016-01-20 14:46 小马歌 阅读(458) | 评论 (0)编辑 收藏
 
     摘要: 原文出处: About Rolandz对很多应用来说,时间和日期的概念都是必须的。像生日,租赁期,事件的时间戳和商店营业时长,等等,都是基于时间和日期的;然而,Java却没有好的API来处理它们。在Java SE 8中,添加了一个新包:java.time,它提供了结构良好的API来处理时间和日期。历史在Java刚刚发布,也就是版本1.0的时候,对时间和日期仅有的支持就是java.util...  阅读全文
posted @ 2016-01-20 14:34 小马歌 阅读(397) | 评论 (0)编辑 收藏
 

近来迁移了一些项目到Android Studio,采用Gradle构建确实比原来的Ant方便许多。但是编译时下载依赖的网速又着实令人蛋疼不已。
如果能切换到国内的Maven镜像仓库,如开源中国的Maven库,又或者是换成自建的Maven私服,那想必是极好的。
一个简单的办法,修改项目根目录下的build.gradle,将jcenter()或者mavenCentral()替换掉即可:
allprojects {
    repositories {
        maven{ url 'http://maven.oschina.net/content/groups/public/'}
    }
}
但是架不住项目多,难不成每个都改一遍么?
自然是有省事的办法,将下面这段Copy到名为init.gradle文件中,并保存到 USER_HOME/.gradle/文件夹下即可。
allprojects{
    repositories {
        def REPOSITORY_URL = 'http://maven.oschina.net/content/groups/public'
        all { ArtifactRepository repo ->
            if(repo instanceof MavenArtifactRepository){
                def url = repo.url.toString()
                if (url.startsWith('https://repo1.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com/')) {
                    project.logger.lifecycle "Repository ${repo.url} replaced by $REPOSITORY_URL."
                    remove repo
                }
            }
        }
        maven {
            url REPOSITORY_URL
        }
    }
}
init.gradle文件其实是Gradle的初始化脚本(Initialization Scripts),也是运行时的全局配置。
更详细的介绍请参阅 http://gradle.org/docs/current/userguide/init_scripts.html
Reference
Dependency Management
Change Gradle mavenCentral URL to My repo
What is included in JCenter repository in Gradle?

posted @ 2016-01-20 11:18 小马歌 阅读(586) | 评论 (0)编辑 收藏
仅列出标题
共95页: First 上一页 6 7 8 9 10 11 12 13 14 下一页 Last