Dubbo
一、 架构简介
1 各架构简图
2 单体架构
单体架构也称之为单体系统或者是单体应用。就是一种把系统中所有的功能、模块耦合在一个应用中的架构方式,一般只操作一个数据库。代表技术:Struts2、SpringMVC、Spring、MyBatis 等。
2.1特点
打包成一个独立的单元(导成一个唯一的 jar 包或者是 war 包)会一个进程的方式来运行 - javaw
2.2单体架构的优点、缺点
2.2.1 优点
项目易于管理、部署简单
2.2.2 缺点
测试成本高、可伸缩性差、可靠性差、迭代困难、跨语言程度差、团队协作难
3 RPC 架构
RPC(Remote Procedure Call):远程过程调用。他一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。代表技术:Thrift(Facebook 开发的系统内部各语言之间协调通讯的 RPC 框架,带有强大的代码生成引擎,支持跨语言、多平台调用的。Apache 官网有资料)、Hessian(基于 HTTP协议的 RPC 框架,提供 RMI 功能,且采用二进制协议的轻量级框架)等等。
3.1特点:
应用直接调用服务,服务之间是隔离的。
3.2缺点
服务过多时,管理成果高昂。服务治理,服务注册、发现,服务容错,服务跟踪,服务网关,IP 暴露等都是此架构无法避免的问题。
4 SOA 架构
SOA(Service oriented Architecture):面向服务架构
ESB(Enterparise Service Bus):企业服务总线,服务中介。主要是提供了一个服务于服务之间的交互。
ESB 包含的功能如:负载均衡,流量控制,加密处理,服务的监控,异常处理,监控告急等等。
代表技术:Mule(Java 为核心的消息框架和整合平台,提供服务中介、数据转换、消息路由、服务创建和托管等功能。不是开源的技术,是付费产品。)、WSO2(开源的服务总线,提供了 SOA 基础设施的搭建,内置数据服务支持,服务角色管理等功能)。
5 微服务架构
5.1什么是微服务
微服务是一种架构风格。一个大型的复杂软件应用,由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好的完成该任务。
微服务就是一个轻量级的服务治理方案。对比 SOA 架构,使用注册中心代替 ESB 服务总线。注册中心相比服务总线来说,更加轻量级。
代表技术:SpringCloud、Dubbo 等等。
5.1.1 架构风格
所谓的架构风格就是项目的一种设计模式。常见的架构风格有:
客户端与服务端的:在使用之前需要安装客户端的应用。如:QQ,网络游戏等。
基于组件模型的架构:如:EJB(Session Bean 实现业务逻辑的、Entity Bean 域模型、Manager Driven Bean 驱动管理模型等)
分层架构(单体架构):典型的就是 MVC 架构
面向服务架构:将系统拆分为若干服务,业务功能基于服务实现,服务可独立配置、维护、运行,且多服务有统一的管理平台(ESB、注册中心)
5.2微服务架构特点
系统是由多个服务构成
每个服务可以单独独立部署
每个服务之间是松耦合的。服务内部是高内聚的,外部是低耦合的。高内聚就是每个服务只关注完成一个功能。低耦合就是服务之间没有直接关联。
5.3微服务优缺点
5.3.1 优点
测试容易:服务高内聚低耦合,每个服务可以独立测试
可伸缩性强:服务相对独立,可随时增删服务实现系统服务变化,可针对某服务独立水平扩展
可靠性强:服务出现问题,受影响的位置是当前服务,不会影响其他服务。应用健壮性有更好的保证。
跨语言程度会更加灵活:可针对服务特性使用不同的语言开发,尽可能发挥出每种语言的特性。
团队协作容易:团队专注自主研发的服务,对其他服务的了解可局限在服务的调用上。
系统迭代容易:当服务发生变更时,只需针对单一服务进行系统升级迭代。
5.3.2 缺点
运维成本过高,部署数量较多:服务过多导致运维成本成倍提升。
接口兼容多版本:因服务可独立升级迭代,所以会导致接口版本过多。
分布式系统的复杂性:系统分部,导致通讯成本提升,系统复杂度提升。
分布式事务:分布式系统会引出分布式事务的出现,现在有很多的分布式事务解决方案,分布式事务不是不可解决的,这不会影响微服务架构的应用。
二、 Dubbo 简介
Dubbo 是阿里巴巴开发的一个基于 SOA 结构基础的,实现 RPC 远程调用的微服务框架.
Dubbo 框架,是基于容器运行的. 容器是 Spring.
在编写服务和客户端的时候, 需要注册中心实现服务的发布和订阅. 注册中心中有服务端发布的服务全部信息,包括请求地址,参数命名,参数数量,参数限制,参数是否加密等. 客户端通过注册中心订阅服务,获取服务的所有信息,实现 RPC 远程访问.
官方网站 : http://dubbo.apache.org/
1 Dubbo 框架结构
1.1registry
注册中心. 是用于发布和订阅服务的一个平台.用于替代 SOA 结构体系框架中的 ESB 服务总线的。
1.1.1 发布
开发服务端代码完毕后, 将服务信息发布出去. 实现一个服务的公开.
发布的信息包括但不限于: 服务端所在位置(URL), 要调用的接口命名, 接口中有什么方法, 方法需要什么参数, 方法有什么返回, 调用过程超时时长是多少, 调用过程自动重试多少次, 参数数据和返回数据长度有多少等.
1.1.2 订阅
客户端程序,从注册中心下载服务内容, 就是发布的服务信息. 这个过程是订阅.
订阅服务的时候, 会将发布的服务所有信息,一次性下载到客户端.
客户端也可以自定义, 修改部分服务配置信息. 如: 超时的时长, 调用的重试次数等.
1.1.3 常用注册中心
1.1.3.1 Zookeeper
官方推荐使用的注册中心.
Zookeeper 是 apache 开发的一个 java 工程. 是 hadoop 工程的子工程. 主体功能是用于实现其他应用管理的一个管理平台。
1.1.3.2 multicast
广播实现服务发布和订阅的注册方式. 不需要启动任何的注册中心平台.
只适用于小型的项目. 在大型工程中会有通讯阻塞问题.(广播风暴.)
1.1.3.3 redis
KV 服务器. 高速缓存服务器. 是一个内存结构的类似数据库的缓存服务器. 也可以称为NoSQL 数据库.
实际就是通过键值对的形式, 在 redis 中保存服务的发布数据. 客户端通过 key 查询value,订阅服务.
效率高, 且可搭建集群. 适用部分大型商业开发. 但是稳定性不保证.
1.2consumer
服务的消费者, 就是服务的客户端.
消费者必须使用 Dubbo 技术开发部分代码. 基本上都是配置文件定义.
1.3provider
服务的提供者, 就是服务端.
服务端必须使用 Dubbo 技术开发部分代码. 以配置文件为主.
1.4protocol
协议. 在Dubbo 技术中, 客户端和服务器的通讯方式, 都是建立在协议通讯基础之上的.
dubbo 技术支持若干协议. 如: dubbo 协议(阿里自主开发的协议), http 协议, tcp 协议等.
1.5container
容器. Dubbo 技术的服务端(Provider), 在启动执行的时候, 必须依赖容器才能正常启动.
默认依赖的就是 spring 容器. 且 Dubbo 技术不能脱离 spring 框架.
在 2.5.3 版本的 dubbo 中, 默认依赖的是 spring2.5 版本技术. 可以选用 spring4.5 以下版本.
在 2.5.7 版本的 dubbo 中, 默认依赖的是 spring4.3.10 版本技术. 可以选择任意的 spring版本
1.6monitor
监控中心. 是 Dubbo 提供的一个 jar 工程.
主要功能是监控服务端(Provider)和消费段(Consumer)的使用数据的. 如: 服务端是什么,有多少接口,多少方法, 调用次数, 压力信息等. 客户端有多少, 调用过哪些服务端, 调用了多少次等
1.7管理控制台
是 dubbo 提供的一个 war 工程。(dubbo-admin)
用于实现 dubbo 的 provider 和 consumer 管理的。如:集群负载,均衡策略,provider
的有效性等功能。
三、 ZooKeeper 注册中心简介及搭建
1 ZooKeeper 简介
顾名思义 zookeeper 就是动物园管理员,他是用来管 hadoop(大象)、Hive(蜜蜂)、pig(小猪)的管理员, Apache Hbase 和 Apache Solr 的分布式集群都用到了 zookeeper;Zookeeper:是一个分布式的、开源的程序协调服务,是 hadoop 项目下的一个子项目。
2 ZooKeeper 的作用
2.1配置管理
在我们的应用中除了代码外,还有一些就是各种配置。比如数据库连接等。一般我们都是使用配置文件的方式,在代码中引入这些配置文件。但是当我们只有一种配置,只有一台服务器,并且不经常修改的时候,使用配置文件是一个很好的做法,但是如果我们配置非常多,有很多服务器都需要这个配置,而且还可能是动态的话使用配置文件就不是个好主意了。这个时候往往需要寻找一种集中管理配置的方法,我们在这个集中的地方修改了配置,所有对这个配置感兴趣的都可以获得变更。比如我们可以把配置放在数据库里,然后所有需要配置的服务都去这个数据库读取配置。
但是,因为很多服务的正常运行都非常依赖这个配置,所以需要这个集中提供配置服务的服务具备很高的可靠性。一般我们可以用一个集群来提供这个配置服务,但是用集群提升可靠性,那如何保证配置在集群中的一致性呢? 这个时候就需要使用一种实现了一致性协议的服务了。Zookeeper 就是这种服务,它使用 Zab 这种一致性协议来提供一致性。现在有很多开源项目使用 Zookeeper 来维护配置,比如在 HBase 中,
客户端就是连接一个 Zookeeper,获得必要的 HBase 集群的配置信息,然后才可以进一步操作。还有在开源的消息队列 Kafka 中,也使用 Zookeeper 来维护 broker 的信息。在 Alibaba开源的 SOA 框架 Dubbo 中也广泛的使用 Zookeeper 管理一些配置来实现服务治理。
2.2名字服务
名字服务这个就很好理解了。比如为了通过网络访问一个系统,我们得知道对方的 IP地址,但是 IP 地址对人非常不友好,这个时候我们就需要使用域名来访问。但是计算机是不能是域名的。怎么办呢?如果我们每台机器里都备有一份域名到 IP 地址的映射,这个倒是能解决一部分问题,但是如果域名对应的 IP 发生变化了又该怎么办呢?于是我们有了 DNS这个东西。我们只需要访问一个大家熟知的(known)的点,它就会告诉你这个域名对应的 IP是什么。在我们的应用中也会存在很多这类问题,特别是在我们的服务特别多的时候,如果我们在本地保存服务的地址的时候将非常不方便,但是如果我们只需要访问一个大家都熟知的访问点,这里提供统一的入口,那么维护起来将方便得多了。
2.3分布式锁
其实在第一篇文章中已经介绍了 Zookeeper 是一个分布式协调服务。这样我们就可以利用 Zookeeper 来协调多个分布式进程之间的活动。比如在一个分布式环境中,为了提高可靠性,我们的集群的每台服务器上都部署着同样的服务。但是,一件事情如果集群中的每个服务器都进行的话,那相互之间就要协调,编程起来将非常复杂。而如果我们只让一个服务进行操作,那又存在单点。
通常还有一种做法就是使用分布式锁,在某个时刻只让一个服务去干活,当这台服务出问题的时候锁释放,立即 fail over 到另外的服务。这在很多分布式系统中都是这么做,这种设计有一个更好听的名字叫 Leader Election(leader 选举)。比如 HBase的 Master 就是采用这种机制。但要注意的是分布式锁跟同一个进程的锁还是有区别的,所以使用的时候要比同一个进程里的锁更谨慎的使用。
2.4集群管理
在分布式的集群中,经常会由于各种原因,比如硬件故障,软件故障,网络问题,有些节点会进进出出。有新的节点加入进来,也有老的节点退出集群。这个时候,集群中其他机器需要感知到这种变化,然后根据这种变化做出对应的决策。比如我们是一个分布式存储系统,有一个中央控制节点负责存储的分配,当有新的存储进来的时候我们要根据现在集群目前的状态来分配存储节点。这个时候我们就需要动态感知到集群目前的状态。
还有,比如一个分布式的 SOA 架构中,服务是一个集群提供的,当消费者访问某个服务时,就需要采用某种机制发现现在有哪些节点可以提供该服务(这也称之为服务发现,比如 Alibaba 开源的SOA 框架 Dubbo 就采用了 Zookeeper 作为服务发现的底层机制)。还有开源的 Kafka 队列就采用了 Zookeeper 作为 Cosnumer 的上下线管理。
3 ZooKeeper 安装
3.1安装 JDK
略,找 maven 相关资料。
3.2安装 ZooKeeper 集群
本环境中使用 3 个 Zookeeper 应用搭建一个伪集群。应用部署位置是:192.168.199.175。
服务监听端口分别为:2181、2182、2183。投票选举端口分别为 2881/3881、2882/3882、2883/3883。
3.2.1 上传安装包
官方资源包可在 zookeeper.apache.com 站点中下载。最新发布版本为:3.4.12。3.2.2 解压并维护目录
tar -zxf zookeeper-3.4.12.tar.gz
将解压后的 Zookeeper 应用目录重命名,便于管理
mv zookeeper-3.4.12 zookeeper01
3.2.3 提供数据缓存目录
在 zookeeper01 应用目录中,创建 data 目录,用于缓存应用运行数据
cd zookeeper01
mkdir data
3.2.4 复制应用
复制两份 Zookeeper 应用。用于模拟集群中的 3 个节点。
cp -r zookeeper01 zookeeper02
cp -r zookeeper01 zookeeper03
3.2.5 提供配置文件
在 zookeeper 应用目录中有子目录 conf。其中有配置文件模板:zoo_sample.cfg
cp zoo_sample.cfg zoo.cfg
zookeeper 应用中的配置文件为 conf/zoo.cfg
3.2.6 修改配置文件 zoo.cfg - 设置数据缓存路径
dataDir 参数值为应用运行缓存数据保存目录。是 3.2.3 步骤中创建的目录。使用绝对路径赋值。不同的应用路径不同。
dataDir=/root/upload/zookeeper01/data
3.2.7 提供应用唯一标识
在 Zookeeper 集群中,每个节点需要一个唯一标识。这个唯一标识要求是自然数。且唯一标识保存位置是:$dataDir/myid。其中 dataDir 为配置文件 zoo.cfg 中的配置参数
在 data 目录中创建文件 myid : touch myid
为应用提供唯一标识。本环境中使用 1、2、3 作为每个节点的唯一标识。
vi myid
简化方式为: echo [唯一标识] >> myid。 echo 命令为回声命令,系统会将命令发送的数据返回。 '>>'为定位,代表系统回声数据指定发送到什么位置。 此命令代表系统回声数
据发送到 myid 文件中。 如果没有文件则创建文件。
3.2.8 修改配置文件 zoo.cfg - 设置服务、投票、选举端口
vi zoo.cfg
clientPort=2181 #服务端口根据应用做对应修改,zk01-2181,zk02-2182,zk03-2183
server.1=192.168.199.175:2881:3881 #投票选举配置 3 个节点一致
server.2=192.168.199.175:2882:3882
server.3=192.168.199.175:2883:3883
3.2.9 启动 ZooKeeper 应用
bin/zkServer.sh start
ZooKeeper 集群搭建后,至少需要启动两个应用才能提供服务。因需要选举出主服务节点。启动所有 ZooKeeper 节点后,可使用命令 bin/zkServer.sh status 来查看节点状态。如下:
Mode: leader - 主机
Mode: follower - 备份机
3.2.10 关闭 ZooKeeper 应用
bin/zkServer.sh stop 命令为关闭 ZooKeeper 应用的命令。
3.2.11 控制台访问 ZooKeeper 应用
bin/zkCli.sh -server 192.168.199.175:2181
命令格式为: zkCli.sh -server host:port。默认连接 localhost:2181。
3.2.12 控制台客户端常用命令
本课程只介绍常用命令。
connect host:port - 连接其他的 ZooKeeper 应用。
ls path - 列表路径下的资源。在 ZooKeeper 控制台客户端中,没有默认列表功能,必须指定要列表资源的位置。 如: ls /
; ls /path 等。
create [-e] [-s] path data - 创建节点,如: create /test 123 创建一个/test 节点,节点携带数据信息 123。 create -e /test 123 创建一个临时节点/test,携带数据为 123,临时节点只在当前会话生命周期中有效,会话结束节点自动删除。 create -s /test 123 创建一个顺序节
点/test,携带数据 123,创建的顺序节点由 ZooKeeper 自动为节点增加后缀信息,如
-/test00000001 等。-e 和-s 参数可以联合使用。
get path - 查看指定节点的数据。 如: get /test。结果如下:
[zk: 192.168.199.175:2181(CONNECTED) 22] get /test
123
cZxid = 0xd # 创建节点时的事务 ID,由 ZooKeeper 维护。
ctime = Tue Jun 12 07:45:53 PDT 2018
mZxid = 0x1f # 当前节点携带数据最后一次修改的事务 ID。
mtime = Tue Jun 12 07:52:53 PDT 2018
pZxid = 0x21 # 子节点列表最后一次修改的事务 ID。
cversion = 1 # 节点版本号,当节点的子节点列表发生变化时,版本变更。
dataVersion = 2 # 数据版本号,当节点携带数据发生变化时,版本变更。
aclVersion = 0
ephemeralOwner = 0x0 # 此数据值不是 0x0 时,代表是临时节点
dataLength = 3 # 节点携带数据长度
numChildren = 1 # 子节点数量
set path data [version] - 设置对应位置节点的数据。如: set /test 'test data'。 如果要设置的数据中有空格,则使用单引号界定数据的范围。每次修改数据后,dataVersion 属性自增。那么在 set 命令中可以指定 version,version 数据必须与上次查询的值一致,用于保证本次修改命令执行时,没有其他会话修改此数据。
delete path [version] - 删除指定节点,此命令不能删除有子节点的节点。如:delete /test。其中 version 参数和 set 命令的 version 含义一致
rmr path - 删除指定结点,包括子节点。
quit - 退出控制台
七、 服务集群与负载均衡
1 服务集群
Dubbo 框架本身支持服务集群。只要相同的服务(同一个服务接口)注册多份,即实现集群。注册的多份服务要求必须有唯一的访问标志,即 IP+PORT 必须唯一。
在使用服务集群时,建议提供集群容错配置。基于集群容错特性,建议开发时将读写操作分离定义在不同的接口中,提高服务集群的健壮性。
建议企业级开发中,同一个服务策略根据读写定义两个不同的服务工程。如:电商平台中商品管理服务,定义为:商品管理读服务(R)、商品管理写服务(CUD)
1.1集群容错配置
各节点关系:
这里的 Invoker 是 Provider 的一个可调用 Service 的抽象,Invoker 封装了 Provider 地址及 Service 接口信息
Directory 代表多个 Invoker,可以把它看成 List<Invoker> ,但与 List 不同的是,它的值可能是动态变化的,比如注册中心推送变更
Cluster 将 Directory 中的多个 Invoker 伪装成一个 Invoker,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个
Router 负责从多个 Invoker 中按路由规则选出子集,比如读写分离,应用隔离等
LoadBalance 负责从多个 Invoker 中选出具体的一个用于本次调用,选的过程包含了负载均衡算法,调用失败后,需要重选
1.1.1 配置标签
<dubbo:service>、<dubbo:provider>、<dubbo:reference>、<dubbo:consumer>
其中<dubbo:provider>和<dubbo:consumer>粒度太粗,不推荐使用。
1.1.2 配置标签属性
cluster。 此属性为字符串属性,可选值有:failover、failfast、failsafe、failback、forking。
默认值为:failover
failover:失败转移,即调用远程 Provider 失败后,自动转移调用其他服务。通常用于读操作。失败转移是通过重新调用远程 Provider,重试会影响调用效率。重试次数可以通过retries 属性来配置。retries 默认值为 2,即最多重试 2 次(加上首次调用,总计会尝试远程
调用 3 次)。
<dubbo:service interface="" ref="" retries="2" cluster="failover"/>
或:
<dubbo:service interface="" ref="" cluster="failover">
<dubbo:method name="" retries="2"/>
</dubbo:service>
failfast:快速失败,只发起一次调用,失败立即报错。 通常用于非幂等性的写操作,
比如新增记录。
<dubbo:service cluster="failfast" />
或:
<dubbo:reference cluster="failfast" />
failsafe:失败安全,出现异常时,直接忽略,通常 用于写入审计日志等操作
<dubbo:service cluster="failsafe"/>
或:
<dubbo:reference cluster="failsafe"/>
failback:失败自动恢复,后台记录失败请求,定时重发,通常用于消息通知操作。
<dubbo:service cluster="failback"/>
或:
<dubbo:reference cluster="failback"/>
forking:并行调用多个服务,只要一个成功即返回,通常用于实时要求较高的读操作,但
需要浪费更多的服务器资源。
<dubbo:service cluster="forking">
或:
<dubbo:reference cluster="forking"/>
1.1.3 成熟度对比
2 负载均衡
在集群负载均衡时,Dubbo 提供了多种均衡策略,缺省为 random 随机调用。
可选的负载均衡策略有:Random、RoundRobin、LeastActive、ConsistentHash
一般在开发中,很少通过配置的方式定义权重和负载均衡策略。使用管理控制台动态设置更加方便,且后期维护成本也会降低。
2.1负载均衡配置
2.1.1 配置标签
<dubbo:service>、<dubbo:provider>、<dubbo:reference>、<dubbo:consumer>
其中<dubbo:provider>和<dubbo:consumer>粒度太粗,不推荐使用。
2.1.2 配置标签属性
loadbalance 属性,此属性为字符串属性,可选值有:random、roundrobin、leastactive、consistenthash。默认值为:random。
Random:随机,按权重设置随机概率。权重可以使用管理控制台即时调整或通过配置标签<dubbo:service interface="..." weight="100"/>来设定。
在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
<dubbo:service interface="..." loadbalance="random" />
或:
<dubbo:reference interface="..." loadbalance="random" />
RoundRobin:轮循,按公约后的权重设置轮循比率。
存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
<dubbo:service interface="..." loadbalance="roundrobin" />
或:
<dubbo:reference interface="..." loadbalance="roundrobin" />
LeastActive:最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
<dubbo:service interface="..." loadbalance="leastactive" />
或:
<dubbo:reference interface="..." loadbalance=" leastactive" />
ConsistentHash:一致性 Hash,相同参数的请求总是发到同一提供者。
当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
算法参见:http://en.wikipedia.org/wiki/Consistent_hashing缺 省 只 对 第 一 个 参 数 Hash , 如 果 要 修 改 , 请 配 置 <dubbo:parameter
key="hash.arguments" value="0,1" />
缺省用 160 份虚拟节点,如果要修改,请配置 <dubbo:parameter key="hash.nodes"value="320" />
<dubbo:service interface="..." loadbalance="consistenthash" />
或:
<dubbo:reference interface="..." loadbalance=" consistenthash" />
2.1.3 成熟度对比
3 线程模型
如果事件处理的逻辑能迅速完成,并且不会发起新的 IO 请求,比如只是在内存中记个标识,则直接在 IO 线程上处理更快,因为减少了线程池调度。
但如果事件处理逻辑较慢,或者需要发起新的 IO 请求,比如需要查询数据库,则必须派发到线程池,否则 IO 线程阻塞,将导致不能接收其它请求。
如果用 IO 线程处理事件,又在事件处理过程中发起新的 IO 请求,比如在连接事件中发起登录请求,会报“可能引发死锁”异常,但不会真死锁。
因此,需要通过不同的派发策略和不同的线程池配置的组合来应对不同的场景。
3.1配置方式如下:
<dubbo:protocol name="dubbo" dispatcher="all" threadpool="fixed" threads="100" />
3.1.1 dispatcher 属性
all 所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。(缺省)
direct 所有消息都不派发到线程池,全部在 IO 线程上直接执行。
message 只有请求响应消息派发到线程池,其它连接断开事件,心跳等消息,直接在 IO线程上执行。
execution 只请求消息派发到线程池,不含响应,响应和其它连接断开事件,心跳等消息,直接在 IO 线程上执行。
connection 在 IO 线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池。
3.1.2 threadpool 属性
fixed 固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省)
cached 缓存线程池,空闲一分钟自动删除,需要时重建。
limited 自增长线程池,但池中的线程数只会增长不会收缩。只增长不收缩的目的是为了避免收缩时突然来了大流量引起的性能问题。
eager 优先创建 Worker 线程池。在任务数量大于 corePoolSize 但是小于 maximumPoolSize时,优先创建 Worker 来处理任务。当任务数量大于 maximumPoolSize 时,将任务放入阻塞队列中。阻塞队列充满时抛出 RejectedExecutionException。(相比于 cached:cached 在任务数
量超过 maximumPoolSize 时直接抛出异常而不是将任务放入阻塞队列)
3.1.3 threads 属性
服务线程池的大小,用于 fixed 类型的线程池。默认 100。
3.2线程配置经验分享
因 Linux 操 作 系 统 对 用 户 线 程 数 的 限 制 , 而 导 致 的 应 用 异 常 :
java.lang.OutOfMemoryError:unable to create new native thread
可以通过对 Linux(Centos6.5 为例,其他版本请自行百度)系统配置文件的修改来增加用户可创建线程数,避免异常的发生。
vi /etc/security/limits.d/90-nproc.conf
配置文件默认信息:
# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz
#432903 for reasoning.
* soft nproc 1024 # 所有用户的线程数限制
root soft nproc unlimited # root 用户无限制
# 可根据情况具体调节
注意:
尽量不要使用 root 用户来部署启动应用程序,避免资源耗尽导致无法登录操作系统。
普通用户的线程数限制值,根据具体业务情况和物理内存来配置。
最大线程数常用计算方案:
计算公式 - default_nproc = total_memory/128k
使用命令:
cat /proc/meminfo | grep MemTotal
echo "内存总数/128" | bc
ulimit -u
(解释: ulimit -a : 显示目前资源限制信息, ulimit -u : 显示用户最多可
开启的程序数目)
根据计算结果、应用数、业务场景、用户数量等,修改配置文件具体内容后重启生效-
reboot