文档章节

《分布式Java应用基础与实践》读书笔记

stefanzhlg
 stefanzhlg
发布于 2014/08/29 16:26
字数 4015
阅读 265
收藏 9

列出来个大体的框架,脑子里有个总体的概念。

一,分布式java应用———NIO,MINA
     1,基于消息方式实现系统间通信
          tcp/ip  udp/ip   nio/bio
     2,基于远程调用方式实现系统间的通信
          rmi  webservice
     1.1 基于消息方式实现系统间的通信
          1.1.1 基于java自身技术实现
               TCP/IP+BIO,TCP/IP+NIO,UDP/IP+BIO,UDP/IP+NIO

               基于MulticastSocket和DatagramPacket来实现多播网络通信
               SRM ,URGCP

          1.1.2 基于开源框架实现消息方式的系统间通信
               MINA,jboss netty
            
     1.2 基于远程调用方法实现系统间的通信
          1.2.1 基于java自身技术实现远程调用方式
               RMI ,webService
          1.2.2 基于开源框架实现远程调用
               Spring RMI,CXF,Axis,JMS ,EJB

二,大型分布式java 应用与SOA
     2.1 基于SCA实现SOA平台
          service compoment architecture
          发布服务
          调用服务
          支持的通信和交互方式
     2.2 基于ESB实现SOA平台
     2.3 基于Tuscany实现
     2.4 基于Mule实现
三,深入理解JVM
     3.1 java代码的执行机制
          1,java源码编译机制
               分析和输入到符号表—注解处理—-语义分析和生成class文件
               class信息包括结构信息,元数据,方法信息。
          2,类加载机制
               装载  链接  初始化
               装载–将二进制字节码装载如jvm
               链接–对二进制字节码进行校验,初始化装载类中的静态变量以及解析类中调用的接口,类。
               初始化–执行类中的静态初始化代码,构造器代码以及静态属性的初始化。
               Bootstrap ClassLoader,Extension ClassLoader,System ClassLoader,User-defined ClassLoader
               Bootstrap ClassLoader–rt.jar,c++实现,代码中无法拿到此对象
               Extension ClassLoader–ext/*.jar
               System ClassLoader–classpath中的jar
               按照树形结构加载,先从parent classLoader进行加载,jvm保证同一个classLoader实例对象只能
               加载一次同样名称的class。
               classNotFoundException     —–当前classLoader中加载类时未找到类文件。
               NoClassDefFoundException—–定义的A类中的B类  未找到。
               LinkageError—此类已经加载过了。
               classCastException—合理的使用泛型。
          3,类执行机制
               字节码解释执行
                    中间码,jvm有一套自己的指令
                    1,指令解释执行
                    2,栈顶缓存
                    3,部分栈帧共享
               编译执行
                    解释执行效率低,sun提供将字节码编译为机器码,JIT编译器
                    对执行频率高的代码进行编译,对频率低的代码进行解释执行。
               反射执行
                 
     3.2 内存管理
          3.2.1 内存空间
               方法区:存放了要加载的类的信息(名称,修饰符等),类中的静态变量,定义的final类型的常量,类中的field信息,类中的方法信息。
                         全局共享,使用的内存不足的时候抛出OutOfMemory的错误信息。
                         对应Permanet Generation 持久代,通过-XX:PermSize 以及-XX:MaxPermSize指定最小值和最大值。
               堆:     存储对象实例以及数组值,新创建的对象。通过-Xms(1/64)和-Xmx(1/4)来控制,-XX:MinHeapFreeRatio来指定比例;通常他们设置的值一样。
                    分代管理方式:Eden—S0—-S1—Old Generation  1,新生代 -Xmn 2,旧生代 -Xmx–Xmn
               本地方法栈:支持native方法的执行,存储每个native方法调用的状态。
               PC寄存器和jvm方法栈:每个线程均会创建PC寄存器和jvm方法栈。当jvm方法栈空间不足时,会抛出StackOverFlowError.通过-Xss指定大小。
          3.2.2 内存分配
               TLAB
          3.2.3 内存回收
               收集器
                    1,引用计数收集器   jdk未采取这种方式
                    2,跟踪收集器
                         复制
                         标记-清除
                         标记-压缩
               JDK中可用的GC
                    新生代可用GC  minor GC
                         基于复制来实现对新生代对象的回收。
                         1,串行GC(Serial GC)
                              单线程方式
                         2,并行回收GC
                              多线程方式,动态调整eden,s0,s1的比例
                         3,并行GC
                              需配合旧生代使用CMS GC
                    旧生代和持久代可用的GC
                         1,串行
                              基于mark-sweep-compact实现
                         2,并行
                              mark-compact
                         3,并发 CMS:concurrent mark-sweep GC
                 3.2.4  jvm内存状况查看方法以及分析工具
                 JProfile
                 1,输出GC日志
                 2,GC portal
                 3,JConsole
                 4,   JVisualVM
                 5,   JMap
                 6,   JHat
                 7,   JStat
                 8,   Eclipse Memory Analyzer
     3.3 JVM线程资源同步以及交互机制
          3.3.1 线程资源同步机制
               synchronized  ,volatile , lock/unlock
          3.3.2 线程交互机制
               wait/notify/notifyAll
               Semphore的acquire和release
               Condition的await和signal,CountDownLatch的await和countDown
          3.3.3 线程状态以及分析
               1,kill -3 pid
               2, jstack
               3,JConsole
               4,ThreadXMBean
               5,TDA
               6,TOP + ThreadDump
                    top   [shift+h]  查看线程id  ,消耗cpu状况
四,分布式java应用以及Sun JDK类库
     4.1 集合包
          4.1.1 ArrayList
          4.1.2 LinkedList
          4.1.3 Vector
          4.1.4 Stack
          4.1.5 HashSet
          4.1.6 TreeSet
          4.1.7 HashMap
          4.1.8 TreeMap
               红黑树实现
     4.2 并发包
          4.2.1 ConcurrentHashMap
               volatile  value,(final key final next,final hash)HashEntry的不变性,  lock
          4.2.2  CopyOnWriteArrayList
               ReetrantLock保证了增加元素和删除元素动作的互斥。在读数据上没有做任何锁操作。
               应用在读多写少的情形下。
                        
               1)ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入先出)顺序排序的.

               2)LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的 BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含 的对象是以FIFO(先入先出)顺序排序的

               3)PriorityBlockingQueue:类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序.

               4)SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的.    
          4.2.3 CopyOnWriteArraySet
          4.2.4 ArrayBlockingQueue
               为一个基于固定大小数组,ReentrantLock以及Condition实现的可阻塞的先进先出的Queue。
               LinkedBlockingQueue在高并发读写操作都多的情况下,性能会较ArrayBlockingQueue好很多,在遍历以及删除元素
               则要两把锁都锁住。
          4.2.5 AtomicInteger
               IncrementAndGet()
                    –compareAndSet(current,next)
                    CAS由cpu比较内存位置上的值是否是当前值。
          4.2.6 ThreadPoolExecutor
          4.2.7 Executors
                 newFixedThreadPool(int)
                   启动的corePoolSize数量的线程启动后会一直运行。并不会因为keepAliveTime时间到达
                   仍没有任务执行而退出。缓冲任务的队列为LinkedBlockingQueue.
                 newSingleThreadPool
                   1,LinkedBlockingQueue
                 newCachedThreadPool
                   SynchronousQueue—进行offer时,如没有其他线程调用poll,则直接返回false
                   corePoolSize为0,最大的线程数为整数的最大数,keepAliveTime为1分钟,缓存任务的
                   队列为SynchronousQueue的线程池。
                 newScheduledThreadPool(int)
                   创建corePoolSize为传入参数,最大线程为整数最大值,线程keepAliveTime为0,缓存任务
                   放在DelayWorkQueue的线程池中。codition的awaitNanos来等待唤醒。
            4.2.8 FutureTask
                 可用于异步获取执行结果或取消执行任务的场景,通过传入的Callable或Runnable的任务给FutureTask
                 直接调用run方法或放入线程池执行,在外部可以通过FutureTask的get方法获得执行结果。
            4.2.9 Semaphore
                 信号量 —五个坑
            4.2.10 CountDownLatch
                 可以控制多个线程同时开始执行某个动作
                 countdown()
            4.2.11 CyclicBarrier
                 当await到达一定的数量后,才继续往下执行。
                 和CountDownLatch实现上不同,它是基于ReentrantLock和Condition来实现。
            4.2.12 ReentrantLock
                 lock()  NonfairSync基于CAS将state从0设置为1,设置成功,说明没有其他线程持有锁;如果失败,说明已经有其他线程
                 持有锁,继续尝试。。。
                   FairSync的lock方法的实现方式和NonFairSync的区别在于它并不尝试基于CAS将state从0设置为1,而是直接进入
                   NonfairSync在设置失败后的处理步骤。
                 ReentrantLock也是一个基于AbstractQueuedSynchronizer的实现,AbstractQueuedSynchronizer为基于整数状态值实现的
                 资源的并发访问控制很好的支持。
            4.2.13 Condition   
                 ReentrantLock提供了一个newCondition方法,以便用户在同一个锁的情况下可以根据不同的情况执行等待或唤醒动作。
                 ReentrantLock.newCondition(); .newCondition().await();.newCondition().signal()
            4.2.14 ReentrantReadWriteLock
                 提供读锁ReadLock和写锁WriteLock,读多写少的场景中可以大幅度提升读的性能。实现主要是基于AbstractQueueSynchronizer
                 来实现,自行判断是否可以获取读锁或写锁,

                 总的来说,基于CAS,拆分锁,volatile以及AbstractQueueSynchronizer是这些类的主要实现方法,这些方法都是为了尽量
                 减少高并发时的竞争现象。

          4.3 序列化  发序列化
            writeObject    ,readObject

五,性能调优
     5.1 寻找性能瓶颈
          5.1.1 CPU消耗分析
               上下文切换
                    文件IO操作,网络IO操作,锁等待,线程sleep,当前线程会进入阻塞或休眠状态,
                    从而触发上下文切换
               运行队列
               利用率
                    cpu在用户进程,内核,中断处理,io等待以及空闲五部分使用百分比。
                    1,top
                    2,pidstat
                         vmstat
                         sar
                    us
                         jstack [pid] |grep ‘nid=ox…’
                    sy 
                         kill -3 [javapid] 或jstack -l [javapid]
          5.1.2 文件IO消耗分析
               pidstat      -d -t -p [pid]  1  100
               iostat    -x [device]  3 5
          5.1.3 网络IO消耗分析
               cat /proc/interrupts
               sar
                    sar -n FULL 1 2
          5.1.4 内存消耗分析
               (jmap,jstat,mat,visualvm)
               对于JVM堆意外的内存方面的消耗,最为值得关注的是swap的消耗以及物理内存的消耗。
               通过vmstat,sar,top,pidstat等方式来查看swap和物理内存的消耗状况。
               vmstat
               [root@slave2  ~]# vmstat
                    procs ———–memory———- —swap– —–io—- –system– —–cpu—–
                    r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
                    0  0 295392  68632  77760 175892    0    0     1    10    0    1  0  0 100  0  0
                    swpd值过高是由于物理内存不够用,只要jvm的内存设置不是过大,是不会操作到swap区域的。
               sar
                    sar -r 2 5
                    [root@slave2  ~]# sar -r 2 5
                    Linux 2.6.32-220.el6.x86_64 (slave2)    2013年03月06日  _x86_64_        (2 CPU)
                   
                    11时15分05秒 kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit
                    11时15分07秒     68012    952588     93.34     78204    175664   1755668     33.67
                    11时15分09秒     67880    952720     93.35     78204    175672   1755692     33.67
               top
               pidstat
                    pidstat -r -p [pid] [interval] [times]
                    分析pid所占用物理内存和虚拟内存的大小。
          5.1.5 程序执行慢的原因分析
               1,锁竞争激烈
                    线程池
               2,未充分分配硬件资源
               3,数据量增长
          5.2 调优
               硬件,操作系统,jvm,程序
               5.2.1 JVM调优
                    主要是内存管理方面的调优,包括各代的大小,GC策略等
                    -Xms -Xmx -Xmn -XX:SurvivorRatio -XX:MaxTenuringThreshold
                    1,避免新生代大小设置过小
                    2,避免新生代设置过大
                         -Xmn   =   JVM Heap区大小的33%左右。
                    3,避免Survivor区过大或过小
                         -XX:SurvivorRatio     8:1:1
                    4,合理设置新生代存活周期
                         -XX:MaxTenuringThreshold   表示新生代存活周期的值
                              决定了新生代的对象经过多少次Minor GC进入旧生代默认为15
                    GC策略的调优
                         并行和并发GC   -CMS GC 不错的选择
                              -Xms680M  -Xmx680M -Xmn80M -XX:+UseConcMarkSweepGC -XX:+
                              PrintGCApplicationStoppedTime -XX:+UseCMSCompactAtFullCollection
                              -XX:CMSMaxAbortablePrecleanTime=5
               5.2.2 程序调优
                    CPU消耗严重的解决方法
                         1.CPU us高的解决方法
                              主要是执行线程无任何挂起动作,且一直执行,导致CPU没有机会去调度
                              执行其他的线程,造成线程饿死的现象。
                                   Thread.sleep().以释放cpu的执行权,降低cpu的消耗。
                                   采用wait/notify机制
                         2.cpu sy高的解决方案
                              启动线程数过多
                              线程竞争激烈,造成线程状态切换。
                              协成的框架kilim–执行一项任务时,不创建Thread,而是改为Task,轻量级的。
                                   阻塞时,killim会保存task之后执行需要的对象信息,并释放task执行所占用的线程资源。
                    文件IO消耗严重的解决方法
                         多个线程在写大量的数据到同一文件,导致文件很快变得很大,从而写入速度越来越慢,并造成各线程
                         激烈争抢文件锁。
                         1,异步写文件
                         2,批量读写
                         3,限流
                         4,限制文件大小
                    网络IO消耗严重的解决方案
                         限流
                    内存消耗严重解决方案
                         1,释放不必要的引用
                         2,使用对象缓存池
                         3,采用合理的缓存失效算法
                              FIFO,LRU,LFU
                         4,合理使用SoftReference和WeakReference
          5.2.3 对于资源消耗不多,但程序执行慢的情况
               锁竞争激烈及未充分发挥硬件资源
               1,锁竞争激烈
                    1),使用并发包中的类
                    2),使用Treiber算法
                         Stack
                    3),使用Michael-Scott非阻塞队列算法
                    4),尽可能少用锁
                    5),拆分锁
                    6),去除读写操作的互斥锁
               2,未充分使用硬件资源
                    未充分使用cpu
                         在能并行处理的场景中未使用足够的线程。
                    未充分使用内存
                         数据缓存,耗时缓存,页面片段缓存
六,构建高可用系统
     6.1 避免系统中出现单点
          6.1.1 负载均衡技术
               选择实际业务处理机器的方式
                    1,随即选择
                    2,hash选择
                    3,Round-Robin选择  地址列表按顺序选择
                    4,按权重选择
                    5,按负载选择
                    6,按连接选择
               响应返回方式
                    1,响应通过负载均衡机器返回
                    2,响应直接返回至请求发起方 Ip  Tunneling
               硬件负载设备
                    F5 ,Netscalar
                    注意点:
                    1,负载设备的流量
                    2,长连接
               软件负载方案
                    LVS  linux virtual server
                    LVS + Keepalived
                    HAProxy
               去中心化实现负载均衡
                    Gossip
          6.1.2 热备
               使用多机房
                    难点:1, 跨机房的状态同步
                    2,两阶段提交保持一致
                    3,三阶段提交保持一致
                    4,基于paxos保持一致
     6.2 提高应用自身的可用性
          6.2.1 尽可能地避免故障
               明确使用场景
               设计可容错的系统 fail fast原则;保证接口和对象设计的严谨
               设计具备自我保护能力的系统
               限制使用资源
                    限制内存使用
                         集合容量过大  LRU
                         未释放已经不用的对象引用
                    限制文件的使用
                         日志频繁写入文件
                    限制网络使用
                         链接资源
                         操作系统sendBuffer区资源
                    限制线程的使用
          6.2.2 及时发现故障
               报警系统
                    nagios的snmp方式定时扫描远程机器的报警信息文件
               日志记录和分析系统
          6.2.3 及时处理故障
               1,自动修复
               2,执行风险点应对措施
               3,全局资源调整
               4,功能降级
               5,降低对资源的使用量
          6.2.4 访问量以及数据量不断上涨的应对策略
               拆分系统以及水平伸缩 读写分离  增加机器
七,构建可伸缩的系统
     7.1 垂直伸缩
          7.1.1 支撑高访问量
               1,增加cpu
               2,内存增加
          7.1.2 支撑大数据量
               分表(DAL开发,分页复杂)
          7.1.3 提升计算能力
               并行多线程计算
     7.2 水平伸缩
          7.2.1 支撑高访问量
               缓存状态的水平伸缩方法
                    1,广播同步Multicast
                         JGroups
                    2,分布式缓存
                         一致性hash  虚节点保证节点的均匀分布
                         memcached
                         Terracotta
               文件的水平伸缩方法
                    1,直连式存储DAS
                    2,网络存储NAS,SAS
                    3,分布式文件系统GFS
               应用的水平伸缩方法
                    拆分应用
               水平伸缩后带来的数据库问题
                    避免由于数据库连接资源不够限制了系统的水平伸缩能力:
                    1,缓存
                         页面静态化  页面片段缓存  数据缓存
                    2,分库
                    3,异步数据库访问JBoss Netty
                    4,DAL  data access layer  分表 分库
          7.2.2 支撑大数据量
               读写分离
               多master
          7.2.3 提升计算能力
               垂直伸缩场景中采取的方法是将计算任务拆分,多线程并行计算然后汇总结果。
               水平伸缩场景中可演变为将计算任务拆分,然后分派给不同的机器进行计算,最后汇总。
               MapReduce和MPI


© 著作权归作者所有

stefanzhlg

stefanzhlg

粉丝 67
博文 110
码字总数 85559
作品 4
浦东
程序员
私信 提问
读书笔记之《Java并发编程的艺术》-并发编程基础

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
4K
8
读书笔记之《Java并发编程的艺术》-线程池和Executor的子孙们

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
756
1
读书笔记之《Java并发编程的艺术》-并发编程容器和框架(重要)

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
724
1
读书笔记之《Java并发编程的艺术》-java中的锁

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
409
0
Android--面试中遇到的问题总结(三)

《Android 开发工程师面试指南 LearningNotes 》,作者是陶程,由梁观全贡献部分。大家可以去知乎关注这两位用心的少年。这份指南包含了大部分Android开发的基础、进阶知识,不仅可以帮助准备...

sealin
2017/02/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

JMM内存模型(一)&volatile关键字的可见性

在说这个之前,我想先说一下计算机的内存模型: CPU在执行的时候,肯定要有数据,而数据在内存中放着呢,这里的内存就是计算机的物理内存,刚开始还好,但是随着技术的发展,CPU处理的速度越...

走向人生巅峰的大路
16分钟前
30
0
你对AJAX认知有多少(2)?

接着昨日内容,我们几天继续探讨ajax的相关知识点 提到ajax下面几个问题又是必须要了解的啦~~~ 8、在浏览器端如何得到服务器端响应的XML数据。 通过XMLHttpRequest对象的responseXMl属性 9、 ...

理性思考
26分钟前
4
0
正则表达式基础(一)

1.转义 转义的作用: 当某个字符在表达式中具有特殊含义,例如字符串引号中出现了引号,为了可以使用这些字符本身,而不是使用其在表达式中的特殊含义,则需要通过转义符“\”来构建该字符转...

清自以敬
28分钟前
4
0
idea中@Data标签getset不起作用

背景:换电脑以后在idea中有@data注解都不生效 解决办法:idea装个插件 https://blog.csdn.net/seapeak007/article/details/72911529...

栾小糖
34分钟前
4
0
Apache Kudu 不能删除不存在的数据

使用Apache Kudu客户端,对KafkaConnect Sink 进行扩展。 使用的Apache Kudu 的Java 客户端。突然有天发现作业无法提交,一直报错。 后来才发现这是Kudu自身的一种校验机制。为了忽略这种校验...

吐槽的达达仔
44分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部