目录
3.4.1 007-zk-userservice-provider服务 dubbo 配置文件
3.4.2 008-zk-consumer 网站 dubbo 配置文件
4.5.1 dubbo 配置文件 dubbo-userservice-multi-provider.xml
4.5.2 zk-multi-consumer 服务的dubbo配置文件
一.rpc了解
1.1 软件架构
- 单一应用架构
当网站流量很小时,应用规模小时,只需一个应用,将所有功能都部署在一起,以减少
部署服务器数量和成本。此时,用于简化增删改查工作量的数据访问框架
(ORM)
是关键。数
据库的处理时间影响应用的性能。
这种结构的应用适合小型系统,小型网站,或者企业的内部系统,用户较少,请求量不
大,对请求的处理时间没有太高的要求。 将所有功能都部署到一个服务器,简单易用。开
发项目的难度低。
缺点:
1
、性能扩展比较困难
2
、不利于多人同时开发
3
、不利于升级维护
4
、整个系统的空间占用比较大
2.
分布式服务架构
当应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形
成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用
及整合的
分布式服务框架
(RPC)
是关键。分布式系统将服务作为独立的应用,实现服务共享
和重用。
1.2 分布式系统
1.2.1 什么是分布式系统
分布式系统是若干独立计算机(服务器)的集合,这些计算机对于用户来说就像单个相
关系统,分布式系统(
distributed system
)是建立在网络之上的服务器端一种结构。
分布式系统中的计算机可以使用不同的操作系统,可以运行不同应用程序提供服务,将
服务分散部署到多个计算机服务器上。
1.2.2 RPC ?
RPC 【
Remote Procedure Call
】是指远程过程调用,是一种进程间通信方式,是一种技
术思想,而不是规范。它允许程序调用另一个地址空间(网络的另一台机器上)的过程或函
数,而不用开发人员显式编码这个调用的细节。调用本地方法和调用远程方法一样。
RPC 的实现方式可以不同。例如
java
的
rmi, spring
远程调用等。
RPC 概念是在上世纪
80
年代由
Brue Jay Nelson(
布鲁
·
杰伊
·
纳尔逊
)
提出。使用
PRC
可以
将本地的调用扩展到远程调用(分布式系统的其他服务器)。
RPC
的特点
1.
简单:使用简单,建立分布式应用更容易。
2.
高效:调用过程看起来十分清晰,效率高。
3.
通用:进程间通讯的方式,有通用的规则。
二. dubbo框架
2.1 dubbo概述
Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高性能、轻量级的开源
Java RPC
框架,它提
供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的
RPC
远程服务调用方案、
服
务治理方案。
官网:http://dubbo.apache.org/zh-cn/
面向接口代理:调用接口的方法,在
A
服务器调用
B
服务器的方法,由
dubbo
实现对
B
的
调用,无需关心实现的细节,就像
MyBatis
访问
Dao
的接口,可以操作数据库一样。不用关
心
Dao
接口方法的实现。这样开发是方便,舒服的。
2.2 基本架构
服务提供者(Provider
)
:暴露服务的服务提供方,服务提供者在启动时,向注册中心注
册自己提供的服务。
服务消费者(Consumer
)
:
调用远程服务的服务消费方,服务消费者在启动时,向注册
中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一
台提供者进行调用,如果调用失败,再选另一台调用。
注册中心(Registry
)
:注册中心返回服务提供者地址列表给消费者,如果有变更,注册
中心将基于长连接推送变更数据给消费者
监控中心(Monitor
)
:服务消费者和提供者,在内存中累计调用次数和调用时间,定时
每分钟发送一次统计数据到监控中心。
调用关系说明
:
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推 送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用, 如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计 数据到监控中心。
2.3 dubbo支持的协议
支
持多种协议:
dubbo , hessian , rmi , http, webservice , thrift , memcached , redis
。
dubbo
官方推荐使用
dubbo
协议。
dubbo
协议默认端口
20880
使用
dubbo
协议,
spring
配置文件加入:
<dubbo:protocol name="dubbo" port="20880" />
2.4 直连方式dubbo
点对点的直连项目:
消费者直接访问服务提供者,没有注册中心。消费者必须指定服务
提供者的访问地址(
url
)。
消费者直接通过 url
地址访问固定的服务提供者。这个
url
地址是不变的。
2.4.1 实现目标
用户访问
------>
【商品网站服务】访问
----->
【订单服务】
2.4.2 实现流程
(1)创建服务提供者
- 创建一个maven web工程:服务的提供者
- 创建一个实体bean查询的结果
- 提供一个服务接口:xxxx
- 实现这个服务接口:xxxxImpl
- 配置dubbo服务提供者的核心配置文件
- 声明dubbo服务提供者的名称:保证唯一
- 声明dubbo使用的协议和端口号
- 暴露服务,使用直连方式
<!--服务提供者声明名称:必须保证服务名称的唯一性,它的名称是dubbo内部使用的唯一标识--> <dubbo:application name="001-link-userservice-provider"/> <!--访问服务协议的名称及端口号,dubbo官方推荐使用的是dubbo协议,端口号默认为20880--> <!-- name:指定协议的名称 port:指定协议的端口号(默认为20880) --> <dubbo:protocol name="dubbo" port="20880"/> <!-- 暴露服务接口->dubbo:service interface:暴露服务接口的全限定类名 ref:接口引用的实现类在spring容器中的标识 registry:如果不使用注册中心,则值为:N/A --> <dubbo:service interface="com.wkcto.dubbo.service.UserService" ref="a" registry="N/A"/> <!--将接口的实现类加载到spring容器中--> <bean id="a" class="com.wkcto.dubbo.service.impl.UserServiceImpl"/>
- 添加监听器
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:dubbo-userservice-provider.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
(2)创建服务消费者
- 创建一个maven web工程:服务的消费者
- 配置pom文件:添加需要的依赖(spring,dubbo)
<!--dubbo依赖--> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.2</version> </dependency> <!--依赖服务提供者--> <dependency> <groupId>com.wkcto.dubbo</groupId> <artifactId>001-link-userservice-provider</artifactId> <version>1.0.0</version> </dependency>
- 设置dubbo的核心配置文件(引用远程服务接口)
<!--声明服务消费者的名称:保证唯一性--> <dubbo:application name="002-link-consumer"/> <!-- 引用远程服务接口: id:远程服务接口对象名称 interface:调用远程接口的全限定类名 url:访问服务接口的地址 registry:不使用注册中心,值为:N/A --> <dubbo:reference id="userService" interface="com.wkcto.dubbo.service.UserService" url="dubbo://localhost:20880" registry="N/A"/>
application.xml <!--扫描组件--> <context:component-scan base-package="com.wkcto.dubbo.web"/> <!--配置注解驱动--> <mvc:annotation-driven/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"/> <property name="suffix" value=".jsp"/> </bean>
- 编写controller
@Controller public class UserController { @Autowired private UserService userService; @RequestMapping(value = "/user") public String userDetail(Model model,Integer id) { User user = this.userService.queryUserById(id); model.addAttribute("user",user); return "userDetail"; } }
- 配置中央调度器(就是一个servlet:DispatcherServlet)
<servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:application.xml,classpath:dubbo-consumer.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
注意:dubbo官方推荐必须有一个接口工程,它就是一个maven java工程
要求接口工程存放到内容如下:
1.对外暴露的服务接口(service接口)
2.实体bean对象
2.5 dubbo服务化最佳实践
2.5.1 分包
建议将服务接口、服务模型、服务异常等均放在公共包中。
2.5.2 粒度
服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某功能的一个步骤,
否则将面临分布式事务问题,
Dubbo
暂未提供分布式事务支持。
服务接口建议以业务场景为单位划分,并对相近业务做抽象,防止接口数量爆炸。
不建议使用过于抽象的通用接口,如:Map query(Map)
,这样的接口没有明确语义,
会给后期维护带来不便。
2.5.3 版本
每个接口都应定义版本号,为后续不兼容升级提供可能,如: <dubbo:service
interface="com.xxx.XxxService" version="1.0" />
。
建议使用两位版本号,要变更服务版本。先升级一半提供者为新版本,再将消费者全
部升为新版本,然后将剩下的一半提供者升为新版本。
2.6 改造dubbo项目
抽象分散在多个项目中的公共接口,实体类,异常,工具类到一个项目中,在其他项目
如服务提供者,消费者共用公共的资源。
2.6.1 实现流程
用户访问电商网站浏览商品—
选择商品购买
用户访问电商网站—
查看用户信息(收件人地址)
项目是web应用,需要加入springweb开发jar:
maven依赖
<
dependency
>
<
groupId
>
org.springframework
</
groupId
>
<
artifactId
>
spring-webmvc
</
artifactId
>
<
version
>
4.3.16.RELEASE
</
version
>
</
dependency
>
</
dependency
>
2.6.2 创建公共资源项目
服务提供者,消费者,网站等多个服务中共用,重复使用的类单独定义在一个项目
1.创建公共的maven java project
项目名称:02-link-interface
修改version
2.编写实体类和接口类
3.安装jar到maven仓库
2.6.3 创建用户信息服务提供者
- 新建web project 项目名:04-link-userservice-provider
- maven pom.xml
- 创建UserInfoServiceImpl实体类
public class UserServiceImpl implements UserService { @Override public User queryUserById(Integer id) { User user = new User(); user.setId(id); user.setUsername("zhangsan"); return user; } @Override public Integer queryAllUserCount() { return 52; } }
- dubbo配置文件
<!--声明dubbo服务提供者的名称:保证唯一性--> <dubbo:application name="004-link-userservice-provider"/> <!--设置dubbo使用的协议和端口号--> <!-- name:dubbo使用协议的名称 port:dubbo服务的端口号 --> <dubbo:protocol name="dubbo" port="20880"/> <!-- 暴露服务接口 --> <dubbo:service interface="com.wkcto.dubbo.service.UserService" ref="userService" registry="N/A"/> <!--加载业务接口的实现类到spring容器中--> <bean id="userService" class="com.wkcto.dubbo.service.impl.UserServiceImpl"/>
- web.xml注册spring监听器
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:dubbo-userservice-provider.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
2.6.4 创建消费者
- 创建web project 项目名:05-link-consumer
- 创建页面 userDetail.jsp
- maven pom.xml
- 创建类UserController
@Controller public class UserController { @Autowired private UserService userService; @RequestMapping(value = "/userDetail") public String userDetail(Model model,Integer id) { //根据用户标识获取用户详情 User user = userService.queryUserById(id); //获取用户总人数 Integer allUserCount = userService.queryAllUserCount(); model.addAttribute("user",user); model.addAttribute("allUserCount",allUserCount); return "userDetail"; } }
- 新建spring配置文件
application.xml <!--扫描组件--> <context:component-scan base-package="com.wkcto.dubbo.web"/> <!--配置注解驱动--> <mvc:annotation-driven/> <!--视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"/> <property name="suffix" value=".jsp"/> </bean>
- 新建dubbo配置文件
<!--声明服务消费者名称:保证唯一性--> <dubbo:application name="005-link-consumer"/> <!--引用远程接口服务--> <dubbo:reference id="userService" interface="com.wkcto.dubbo.service.UserService" url="dubbo://localhost:20880" registry="N/A"/>
7.web.xml注册DispatcherServlet
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml,classpath:dubbo-consumer.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
2.7 dubbo常用标签
2.7.1 公用标签
<dubbo:application/> 和 <dubbo:registry/>
- 配置应用信息 <dubbo:application name=”服务的名称”/>
- 配置注册中心 <dubbo:registry address=”ip:port” protocol=”协议”/>
2.7.2 服务提供者标签
配置暴露的服务
<dubbo:service interface=”
服务接口名
” ref=”
服务实现对象
bean”>
2.7.3 服务消费者
配置服务消费者引用远程服务
<dubbo:reference id=”服务引用 bean 的 id” interface=”服务接口名”/>
三. 注册中心-zookeeper
3.1 注册中心概述
对于服务提供方,它需要发布服务,而且由于应用系统的复杂性,服务的数量、类型也
不断膨胀;对于服务消费方,它最关心如何获取到它所需要的服务,而面对复杂的应用系统,
需要管理大量的服务调用。
而且,对于服务提供方和服务消费方来说,他们还有可能兼具这两种角色,即需要提供
服务,有需要消费服务。 通过将服务统一管理起来,可以有效地优化内部应用对服务发布
/
使用的流程和管理。服务注册中心可以通过特定协议来完成服务对外的统一。
Dubbo
提供
的注册中心有如下几种类型可供选:
Multicast 注册中心:组播方式
Redis 注册中心:使用
Redis
作为注册中心
Simple 注册中心:就是一个
dubbo
服务。作为注册中心。提供查找服务的功能。
Zookeeper 注册中心:使用
Zookeeper
作为注册中心
推荐使用 Zookeeper
注册中心。
3.2 注册中心工作方式
3.3 Zookeeper 注册中心
Zookeeper 是一个高性能的,分布式的,开放源码的分布式应用程序协调服务。简称
zk
。
Zookeeper
是翻译管理是动物管理员。可以理解为
windows
中的资源管理器或者注
册表。他
是一个树形结构。这种树形结构和标准文件系统相似。
ZooKeeper
树中的每个节点被称为
Znode
。和文件系统的目录树一样,
ZooKeeper
树中的每个节点可以拥有子节点。每个节点表
示一个唯一服务资源。
Zookeeper
运行需要
java
环境。
3.3.1 下载安装配置Zookeeper
官网下载地址
:
http://zookeeper.apache.org/
进入官网地址,首页找到下载地址,最新版本
3.5.4
3.3.2 安装配置 Zookeeper
A、Windows 平台 Zookeeper 安装,配置
下载的文件
zookeeper-3.5.4-beta.tar.gz.
解压后到目录就可以了,例如
d:/servers/ zookeeper-
3.5.4
修改
zookeeper-3.5.4/conf/
目录下配置文件
复制
zoo-sample.cfg
改名为
zoo.cfg
文件内容:
tickTime:
心跳的时间,单位毫秒
. Zookeeper
服务器之间或客户端与服务器之间维持心跳的
时间间隔,也就是每个 tickTime 时间就会发送一个心跳。表明存活状态。
dataDir:
数据目录,可以是任意目录。存储
zookeeper
的快照文件、
pid
文件,默认为
/tmp/zookeeper,建议在 zookeeper
安装目录下创建
data
目录,将
dataDir
配置改
为/usr/local/zookeeper-3.4.10/data
clientPort:
客户端连接
zookeeper
的端口,即
zookeeper
对外的服务端口,默认为
2181
配置内容:
1.dataDir : zookeeper
数据的存放目录
2. admin.serverPort=8888
原因:
zookeeper 3.5.x
占用
8080
B
、
Linux
平台
Zookeeper
安装、配置
Zookeeper
的运行需要
jdk
。使用前
Linux
系统要安装好
jdk.
①:上传
zookeeper-3.5.4-beta.tar.gz.
并解压
解压文件
zookeeper-3.5.4-beta.tar.gz.
执行命令:
tar -zxvf zookeeper-3.5.4-beta.tar.gz. -C /usr/local/
②:配置文件
在
zookeeper
的
conf
目录下,将
zoo_sample.cfg
改名为
zoo.cfg
,
cp zoo_sample.cfg zoo.cfg
zookeeper
启动时会读取该文件作为默认配置文件。
进入
zookeeper
目录下的
conf
拷贝样例文件
zoo-sample.cfg
为
zoo.cfg
③:启动
Zookeeper
启动(切换到安装目录的
bin
目录下):
./zkServer.sh start
④:关闭
Zookeeper
关闭(切换到安装目录的
bin
目录下):
./zkServer.sh stop
3.4 改造 dubbo—使用 Zookeeper
3.4.1 007-zk-userservice-provider服务 dubbo 配置文件
3.4.2 008-zk-consumer 网站 dubbo 配置文件
3.4.3 运行应用
- 先启动注册中心 启动(切换到安装目录的 bin 目录下):./zkServer.sh start
- 再启动服务提供者tomcat,以及消费者
- 访问zk-consumer的index.jsp
四.dubbo的配置
4.1 配置原则
在服务提供者配置访问参数。因为服务提供者更了解服务的各种参数。
4.2 关闭检查
dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止
Spring
初
始化完成,以便上线时,能及早发现问题,默认
check=true
。通过
check="false"
关闭检查,
比如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动。
例
1
:关闭某个服务的启动时检查
<dubbo:reference interface="com.foo.BarService" check="false" />
例
2
:关闭注册中心启动时检查
<dubbo:registry check="false" />
默认启动服务时检查注册中心存在并已运行。注册中心不启动会报错。
4.3 重试次数
消费者访问提供者,如果访问失败,则切换重试访问其它服务器,但重试会带来更长延迟。
访问时间变长,用户的体验较差。多次重新访问服务器有可能访问成功。可通过
retries="2"
来设置重试次数
(
不含第一次
)
。
重试次数配置如下:
<dubbo:service retries="2" />
或
<dubbo:reference retries="2" />
4.4 超时时间
由于网络或服务端不可靠,会导致调用出现一种不确定的中间状态(超时)。为了避免超时
导致客户端资源(线程)挂起耗尽,必须设置超时时间。
timeout
:
调用远程服务超时时间
(
毫秒
)
4.4.1 dubbo 消费端
指定接口超时配置
<dubbo:reference interface="com.foo.BarService" timeout="2000" />
4.4.2 dubbo 服务端
指定接口超时配置
<dubbo:server interface="com.foo.BarService" timeout="2000" />
4.5 版本号
每个接口都应定义版本号,为后续不兼容升级提供可能。
当一个接口有不同的实现,项目早
期使用的一个实现类, 之后创建接口的新的实现类。区分不同的接口实现使用
version
。
特别是项目需要把早期接口的实现全部换位新的实现类,也需要使用
version.
4.5.1 dubbo 配置文件 dubbo-userservice-multi-provider.xml
<!--声明dubbo服务提供者名称:保证唯一性-->
<dubbo:application name="009-zk-userservice-multi-provider"/>
<!--声明dubbo的协议和端口号-->
<dubbo:protocol name="dubbo" port="20880"/>
<!--使用注册中心-->
<!--<dubbo:registry address="zookeeper://192.168.154.128:2181"/>-->
<dubbo:registry address="zookeeper://localhost:2181"/>
<!--不管是否一个接口有多个实现类,只要服务提供者服务接口服务的时候指定了版本号,那做为消费者引用远程接口服务的时候就必须指定版本号-->
<dubbo:service interface="com.tx.dubbo.service.UserService" ref="userServiceImpl" version="1.0.0" timeout="15000" />
<dubbo:service interface="com.tx.dubbo.service.UserService" ref="userServiceImpl2" version="2.0.0"/>
<bean id="userServiceImpl" class="com.bjpowernode.dubbo.service.impl.UserServiceImpl"/>
<bean id="userServiceImpl2" class="com.bjpowernode.dubbo.service.impl.UserServiceImpl2"/>
4.5.2 zk-multi-consumer 服务的dubbo配置文件
增加访问的version=2.0
<!--声明dubbo服务消费者名称:保证服务名称的唯一性-->
<dubbo:application name="010-zk-multi-consumer"/>
<!--指定注册中心-->
<!--<dubbo:registry address="zookeeper://192.168.154.128:2181"/>-->
<dubbo:registry address="zookeeper://localhost:2181"/>
<!--引用远程接口服务-->
<dubbo:reference id="userService" interface="com.bjpowernode.dubbo.service.UserService" version="1.0.0" />
<dubbo:reference id="userService2" interface="com.bjpowernode.dubbo.service.UserService" version="2.0.0"/>
五.监控中心
5.1 概念
dubbo 的使用,其实只需要有注册中心,消费者,提供者这三个就可以使用了,但是并不能
看到有哪些消费者和提供者,为了更好的调试,发现问题,解决问题,因此引入
dubbo-admin
。
通过 dubbo-admin 可以对消费者和提供者进行管理。可以在 dubbo 应用部署做动态的调整, 服务的管理。
dubbo-admin
图形化的服务管理页面;安装时需要指定注册中心地址,即可从注册中心中获取到所有的提
供者
/
消费者进行配置管理
5.2 发布配置中心
A、下载监控中心,https://github.com/apache/incubator-dubbo-ops
这里下载的是源代码,需要手工编译才能使用。
B
、 运行管理后台
dubbo-admin
到
dubbo-admin-0.0.1-SNAPSHOT.jar
所在的目录。执行下面命令
java -jar dubbo-admin-0.0.1-SNAPSHOT.jar
C
、 修改配置
dubbo-properties
文件
D
、运行
dubbo-admin
应用
1
) 先启动注册中心
2
) 执行提供者项目
3
)
java -jar dubbo-admin-0.0.1-SNAPSHOT.jar
启动
dubbo
管理后台
4
) 在浏览器地址栏输入
http://localhost:7001
访问监控中心
-
控制台
5.3 监控中心的数据来源
dubbo.registry.address=zookeeper://127.0.0.1:2181
5.4 应用监控中心
通过浏览器,访问监控中心主页。点击菜单访问功能选项。