- 背景
网址:http://dubbo.io
随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。
- 单一应用架构
- 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。
- 此时,用于简化增删改查工作量的 数据访问框架(ORM) 是关键。
- 垂直应用架构
- 当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。
- 此时,用于加速前端页面开发的 Web框架(MVC) 是关键。
- 分布式服务架构
- 当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求,其他系统需要调用本系统相关数据,本系统需要提供接口。
- 此时,用于提高业务复用及整合的 分布式服务框架(RPC) 是关键。
- 流动计算架构
- 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。
- 此时,用于提高机器利用率的 资源调度和治理中心(SOA) 是关键。
- dubbo架构
节点角色说明:
- Provider: 暴露服务的服务提供方。
- Consumer: 调用远程服务的服务消费方。
- Registry: 服务注册与发现的注册中心。
- Monitor: 统计服务的调用次数和调用时间的监控中心。
- Container: 服务运行容器。
调用关系说明:
- 0. 服务容器负责启动,加载,运行服务提供者。
- 1. 服务提供者在启动时,向注册中心注册自己提供的服务。
- 2. 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
- 监控中心安装
- 安装环境
jdk1.7、zookeeper3.4.6、centos6.8
- 上传监控中中心安装包至服务器
- 创建安装目录,并解压至安装目录
-C参数用于指定tar命令解压目标的目录,可为绝对路径,也可以是相对路径。
- 配置,指定注册地址-重点
vi dubbo.properties
- 启动
- 关闭防火墙,访问
service iptables stop
管理控制台安装
- 环境
jdk1.7、zookeeper3.4.6
- 上传安装包至服务器
- 解压tomcat
- 将dubbo-admin解压至tomcat/webapps中
删除tomcat中ROOT目录
将dubbo-admin解压至tomcat
-d是directory的首字母,参数用于指定unzip命令解压的目标路径
如果没有unzip命令,可交给tomcat自动解压
- 修改dubbo-admin中的dubbo.properties配置文件
其中zk1,zk2,zk3是在hosts文件中已配置
- 修改tomcat端口,启动
Tomcat涉及端口:8005、8080、8009
启动命令
- 关闭防火墙,访问
service iptables stop
访问默认用户名和密码:root/root
1.duboo服务提供者(provider)-编程
- 步骤
- 添加依赖:dubbo、zookeeper
- 编写service(正常编写)
- 添加applicationContext-dubbo-provider.xml
- 启动dubbo(启动spring容器)
- 实现
- 添加依赖
<!-- dubbo依赖 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version> <exclusions> <!-- 排除spring 2.5.6依赖 --> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> </exclusions> </dependency> <!-- zookeeper依赖 --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.9</version> </dependency> |
- 编写service
正常编写代码即可。service的实现对象,无需要添加@Service注解。
原因:统一在applicationContext-dubbo-provider.xml中指定。
- applicationContext-dubbo-provider.xml
zookeeper.properties
#zookeeper地址、端口 zk1.address=192.168.88.20:2181 zk2.address=192.168.88.20:2182 zk3.address=192.168.88.20:2183 |
applicationContext-dubbo-provider.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!-- 1.配置application 指定名称 用于计算依赖 此名称不能consumer配置application名称相同 --> <dubbo:application name="ego-manager-dubbo-provider"/> <!-- 2.指定注册 中心地址 --> <dubbo:registry address="${zk1.address},${zk2.address},${zk3.address}" protocol="zookeeper"/> <!-- 3.暴露服务接口端口号 并指定协议 --> <dubbo:protocol name="dubbo" port="20880" />
<!-- 4.与spring一样,配置service bean --> <bean id="fileUploadService" class="com.lk.service.impl.FileUploadServiceImpl"/> <bean id="goodsCategoryService" class="com.lk.service.impl.GoodsCategoryServiceImpl"/> <bean id="goodsService" class="com.lk.service.impl.GoodsServiceImpl"/>
<!-- 5.dubbo暴露服务接口与service bean进行关联 --> <dubbo:service interface="com.lk.service.FileUploadService" ref="fileUploadService"/> <dubbo:service interface="com.lk.service.GoodsCategoryService" ref="goodsCategoryService"/> <dubbo:service interface="com.lk.service.GoodsService" ref="goodsService"/> </beans> |
- 启动dubbo
ProviderRun.java
public class ProviderRun {
private static final Logger logger = LoggerFactory.getLogger(ProviderRun.class);
public static void main(String[] args) { //1.加载配置文件 ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring/applicationContext-*.xml"); //2.启动 ctx.start();
while(true){ try { System.out.println("ego-manager-dubbo-provider正在运行"); Thread.sleep(60*1000); } catch (InterruptedException e) { //记录日志 logger.error("ego-manager-dubbo-provider服务出错了:"+e.getMessage()); } } } } |
- 查看注册的服务
- 关于元素 'constructor-arg' 中不允许出现属性 'name'问题
根本原因:旧版本spring不支持在constructor-arg添加name属性。
解决办法:将dubbo自动关联的spring排除
2.dubbo服务消费者(consumer)-编程
- 依赖
<!-- dubbo依赖 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version> <exclusions> <!-- 排除spring 2.5.6依赖 --> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> </exclusions> </dependency> <!-- zookeeper依赖 --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.9</version> </dependency> |
2.配置applicationContext-dubbo-consumer.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!-- 1.配置application 指定名称 用于计算依赖 此名称不能provider配置application名称相同 --> <dubbo:application name="ego-manager-dubbo-consumer"/> <!-- 2.指定注册 中心地址 --> <dubbo:registry address="${zk1.address},${zk2.address},${zk3.address}" protocol="zookeeper"/> <!-- 3.引用服务 --> <dubbo:reference interface="com.lk.service.FileUploadService" id="fileUploadService" timeout="60000"/> <dubbo:reference interface="com.lk.service.GoodsCategoryService" id="goodsCategoryService" timeout="60000"/> <dubbo:reference interface="com.lk.service.GoodsService" id="goodsService" timeout="60000"/> </beans> |
3.直接启动web项目即可。
解决dubbo上传文件失败问题
原因:dubbo协议不支持InputStream、File对象。
- 方式1-使用hessian协议
- 在消费者(consumer)添加hessian依赖
<dependency> <groupId>com.caucho</groupId> <artifactId>hessian</artifactId> <version>4.0.7</version> </dependency> |
- 在服务提供者(provider)端添加hessian、jetty依赖、添加hessian协议
<dependency> <groupId>com.caucho</groupId> <artifactId>hessian</artifactId> <version>4.0.7</version> </dependency> <dependency> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty</artifactId> <version>6.1.26</version> </dependency> |
修改applicationContext-dubbo-provider.xml
默认容器使用jetty,如果指定为serlvet,产生问题:由于当前项目是java project,不是web项目,如果是servlet,当前项目启动会报错。
- 方式3-交inputStream转换为byte[]
- 工具
- 修改消费者(consumer)端
FileUploadController.java
- 修改服务提供者(provider)端
FileUploadServiceImpl.java