Dubbo

SOA思想

SOA介绍

SOA(Service-Oriented Architecture,面向服务的架构)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和协议联系起来.接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台,操作系统和编程语言,这使得构建在各种各样的系统中服务可以以一种统一和通用的方式进行交互.

面向服务架构,它可以根据需求通过网络对松散耦合的粗粒度应用组件进行分布式部署,组合和使用.服务层是SOA的基础,可以直接被应用调用,从而有效控制系统中与软件代理交互的认为依赖性

SOA是一种粗粒度,松耦合服务架构,服务之间通过简单,精确定义接口进行通讯,不涉及底层编程接口和通讯模型,SOA可以看作是B/S模型,XML(标准通用标记语言的子集)/Web Service技术之后的自然延伸

SOA将能够帮助软件工程师们站在一个新的高度理解企业级架构中的各种组件的开发,部署形式,它将帮助企业系统架构者以更迅速,更可靠,更具重用性架构整个业务系统,较之以往,以SOA架构的系统能够更加从容地面对业务的急剧变化

为何使用SOA

不同种类的操作系统,应用软件,系统软件和引用基础结构(application infrastructure)相互交织,这便是IT企业的现状,一些现存的应用程序被用来处理当前的业务流程(business processes),因此从头建立一个新的基础环境是不可能的,企业应该能对业务的变化做出快速的反应,利用对现有的应用程序和应用基础结构的投资来解决新的业务需求,为客户,商业伙伴以及供应商提供新的互动渠道,并呈现一个可以支持有机业务(organic business)的架构,SOA凭借其松耦合的特性,使得企业可以按照模块化的方式来添加新服务或更新现有服务,以解决新的业务需要,提供选择从而可以通过不同的渠道提供服务,并可以把企业现有的或已有的应用作为服务,从而保护了现有的IT基础建设投资

一个使用SOA的企业,可以使用一组现有的应用来创建一个供应链复合应用(supply chain composite application),这些现有的应用通过标准接口来提供功能

SOA的优势

SOA的概念并非什么新东西,SOA不同于现有的分布式技术之处在于大多数软件商接收它并又可以实现SOA的平台或应用程序.SOA伴随着无处不在的标准,为企业的现有资产或投资带来了更好的重用性,SOA能够在最新的和现有的应用之上创建应用,SOA能够使客户或服务消费者免于服务实现的改变所带来的影响,SOA能够升级单个服务或服务消费者而不需重写整个应用,也无需保留已经不再适用于新需求的现有系统,总而言之,SOA以借助现有的应用来组合产生新服务的敏捷方式,提供给企业更好的灵活性来构建应用程序和业务流程


RPC协议

RPC介绍

RPC是远程过程调用(Remote Procedure Call)的缩写形式,允许一台计算机调用另一台计算机上的程序得到结果,而代码中不需要做额外的编程,就像在本地调用一样

现在互联网应用的量级越来越大,单台计算机的能力有限,需要借助可扩展的计算机集群来完成,分布式的应用可以借助RPC来完成机器之间的调用

RPC: 实现系统之间的通信,用户不需要了解低层原理

RPC框架原理

在RPC框架中主要有三个角色:Provider,Consumer和Registry,

节点角色说明:

  • Server: 暴露服务的服务提供方
  • Client: 调用远程服务的服务消费方
  • Registry: 服务注册与发现的注册中心

RPC基本流程图

一次完整的RPC调用流程(同步调用,异步另说)如下:

  1. 服务消费方(client)以本地调用方式调用服务
  2. client stub 接收到调用后负责将方法,参数等组装成能够进行网络传输的消息体
  3. client stub 找到服务地址,并将消息发送到服务端
  4. server stub 收到消息后进行解码
  5. server stub根据解码结果调用本地的服务
  6. 本地服务之星并将结果返回给server stub
  7. server stub 将返回结果打包成消息并发送给消费方
  8. client stub 接收到消息,并进行解码
  9. 服务消费方得到最终结果

RPC框架的目的就是要将2~8这些步骤都封装起来,让用户对这些细节透明

服务注册&发现

服务提供者启动后主动向注册中心注册机器IP,port以及提供的服务列表

服务消费者启动时向注册中心获取服务踢动方地址列表,可实现软负载均衡和Failover

使用到的技术

1, 动态代理

生成client stub 和server stub 需要用到java动态代理技术,我们可以使用JDK原生的动态代理机制,可以使用一些开源字节码工具框架如:Cglib,Jacassist等

2,序列化

为了能在网络上传输和接收java对象,我们需要对它进行序列化和反序列化操作

序列化: 将java对象转换为byte[]的过程,也就是编码的过程

反序列化:将byte[]转换为java对象的过程

可以使用java原生的序列化机制,但是效率非常低,推荐使用一些开源的,成熟的序列化技术,例如:protobuf,Thrift,hessian,Kryo,Msgpack

3,NIO

当前很多PRC框架都直接基于netty这一IO通信矿建,比如阿里巴巴的HSF,Dubbo,Hadoop,Avro,推荐使用Netty作为底层通信框架

4,服务注册中心

可选技术:Redis , Zookeeper, Consul, Etud

RPC与HTTP区别

网络7层协议如图所示

层级关系与对应的协议

OSI层功能TCP/IP协议设备
应用层文件传输,电子邮件,文件服务,虚拟终端TFTP,HTTP,SNMP,SMTP.DNS.Telnet 
表示层数据格式化,代码转换,数据解密  
会话层解除或建立与其他节点的联系  
传输层提供端对端的接口TCP.UDP四层交换机
网络层为数据包选择路由IP,ICMP.RIP.OSPE.BGP.IGMP路由器,三层交换机
数据链路层传输有地址的帧,错误检测功能SLIP,CSLIP,PPP,ARP,RARP,MTU网桥,网卡,以太交换机
物理层以二进制数据形式在物理媒体上传输数据ISO2110,IEEE802中继器,集线器

区别:

  1. RPC是传输层协议(4层),而HTTP协议是应用层协议(7层)
  2. RPC协议可以直接调用中立接口,HTTP协议不可以
  3. RPC通信协议是长连接,HTTP协议一般采用短连接需要3次握手(可以配置长连接添加请求头Keep-Alive: timeout=20)(长连接,指在一个连接上可以连续发送多个数据包,在连接保持期间如果没有数据包发送,需要双方发链路检测包)
  4. RPC协议传递数据时加密压缩传输,HTTP协议需要传递大量的请求头信息
  5. RPC协议一般都有注册中心,有丰富的监控机制

   



Dubbo

介绍:

Apache Dubbo 是一款高性能,轻量级的开源Java RPC框架,它提供了三大核心功能:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现

注册中心

传统程序调用存在的问题

现在整体的结构都是通过用户调用nginx的负载均衡实现后台程序的调用,并且我们要实现后台程序的调用,就得把Tomcat后台程序的信息写到nginx的服务器当中去,而要做反向代理,我们还得去配置nginx的配置文件,

nginx有一种策略就是,安装正常的访问顺序,当用户访问服务器都正常,那万一服务器A宕机了怎么办呢?那么首先用户还是会去访问服务器A,但是服务器A宕机了,那肯定会访问不同,那么nginx会自动去访问它的下一台服务器B,并且同时在指定周期内把服务器A标记为宕机,那么你标识为宕机,那么以后的访问就不会去访问服务器A,直到下一个周期,在去访问服务器A,看看你是不是修好了,如果好了,就可以继续提供服务了,这个过程都是自动的,不需要人为干涉

但是现在有一个问题,我觉得三台服务器不够用,想要加5台服务器,那么怎么加呢?必须得到nginx配置文件中添加两台Tomcat服务去的配置信息,这就不是自动的了,必须人为添加,那么用几天之后觉得5台服务器有点大,用不着,那么怎么办呢?是不是要撤掉这两台服务器啊,那你撤能不能直接宕掉这两台服务器啊?不能吧!那nginx就得定期开启高可用策略啊,nginx得长时间去检测这两台服务器啊,会影响程序的性能,只能去配置文件中将这两台服务器的配置信息删掉,那又得人为的干预,这就是传统程序存在的问题

说明: 虽然nginx 可以实现Tomcat服务器高可用,但是如果后期需要扩展/更新服务器数量时,需要手动的修改nginx的配置文件,并且重启服务器,需要人为的干预

注册中心实现原理

当前的注册中心独立于任何的服务器,它是一个第三方的服务器(第三方服务器的优点在于,每个用户都可以去访问这个第三方服务器),

注册中心:就是维护信息用的,Tomcat启动时会主动的把自己的用户信息(ip/port/服务器名字)写入注册中心,之后注册中心会去维护服务器信息,会将服务器信息保存到自己的服务列表当中,并且进行动态的维护,

那么用户在进行调用的时候,它首先去注册中心获取数据(目的是,假如用户直接去访问服务器,正常情况下没有问题,但是万一服务器宕机了呢?那你就连不通了,那么我们就想要保证用户访问的服务器都是正常的,怎么办呢?那么我们在进行连接之前,我们不自己进行冒然的连接,我们先询问一下注册中心(管理者),我们想要访问购物车信息,你告诉我购物车分别有谁啊!那么这时候注册中兴会自己去检测自己的服务列表中维护了几个购物车,现在有两个购物车,那么他会告诉用户现在有两台购物车能够为用户提供服务,就会将购物车信息发给用户 ,这样就能保证用户访问的购物车都是正常运行的(这也只能保证当前时有效的,注册中心也有可能会出现失误)),注册中心会将服务列表发送给用户,用户将服务列表保存到本地(目的是为了第一次访问会去注册中心访问,以后就不用去访问注册中心了,可以在本地直接读取),然后用户回去访问购物车,但是现在有两个购物车服务,那么该访问那个购物车呢?得通过负载均衡策略来实现,所以现在用jt-web来做负载均衡的.用户访问服务器 ,服务器返回数据给用户,这就是正常的服务流程

那么突然有一天一台服务器宕机了呢?,用户访问这台服务器会有风险,但是好在注册中心有心跳检测机制,它会定期向服务器发送信息检测服务器有没有正常运行,那么如果注册中心一检查,发现这台服务器已经宕机了,那么它会在自己的服务列表信息中这台服务器的信息标识为down(宕机),而且注册中心会进行全网广播,告知用户这台服务器宕机了,这样所有连接着注册中心用户都知道那台服务器宕机了,然后用户会将自己的服务列表中的服务器标识为宕机,这样用户在访问购物车时,根据负载均衡策略,回去服务列表查看服务信息,发现一台服务器已经宕机,它就会去访问另一台服务器,这样用户就能正常运行了!

还没完!那么突然有一天注册中心宕机了呢?程序能不能正常工作呢?

当然可以!为什么呢?

因为在第一次进行访问时,注册中心会将服务列表发送给用户,用户会将服务列表保存到本地,之后用户访问时就不会访问注册中心了,所以注册中心宕机了,程序也能正常运行,但是也是存在风险的,万一其中一台服务器也宕机了呢?这样就会出现问题,但是问题也不大,程序还能正常运行,用户可以自己维护服务列表将当前宕机的服务器标记为down,然后去访问下一台服务器,那么程序正常运行一段时间后,第二天服务器也宕机了呢?那就问题大了,程序就不能正常运行了

那么用户能不能直接访问服务器信息?

不能!因为浏览器是基于HTTP协议进行访问的,而服务器基于RPC协议的,所以不能直接访问

具体实现步骤:

  1. 当服务生产者(提供者)启动时会将自己的服务信息(服务名称/ip/port),写入注册中心
  2. 注册中心当接收到用户服务数据时会动态的维护服务列表数据
  3. 当服务消费者启动时会连接到注册中心,获取全部的服务列表数据并且保存到本地(本地内存)
  4. 当用户发起请求时,首先基于HTTP协议访问服务的消费者,服务消费者根据用户服务请求利用负载均衡策略发起请求访问服务提供者(正向代理:用户知道自己要访问那台服务器,但是服务器不关心是哪个用户发送的请求,这就是正向代理)
  5. 如果后台服务提供者宕机,注册中心有自己的心跳检测机制,发现后台服务器宕机,首先会维护自己的服务列表数据(树形结构),之后全网广播通知服务消费者更新服务列表

 

搭建注册中心:

Zookeeper:

介绍:

Zookeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby的一个开源的实现,是Hadoop和Hbase的重要组件,它是一个为分布式提供 一致性服务的软件,提供的功能包括:配置维护,域名服务,分布式同步,组服务等

ZooKeeper的目的就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效,功能稳定的系统提供给用户

Zookeeper包含一个简单的原语集,提供java和c的接口

Zookeeper代码版本中,提供了分布式独享锁,选举,队列的接口,代码Zookeeper-3.4.3\src\recipes.其中分布锁和队列有java和c两个版本,选举只有java有

一致性:  假如后台服务器宕机了,注册中心会更新服务列表该服务器为down,但是用户的服务列表没有更新,那么用户就有可能去访问已经宕机的服务器,虽然不会出现大问题,但是也不好吧!那Zookeeper就讲究一致性,那么一旦注册中心一旦发生变化,就会同步到用户去,让用户现在,立刻,马上把服务列表信息该了,而客户端发来的请求统一的陷入阻塞中,不让访问,直到数据更新完后,才能进行访问,这就是Zookeeper的强一致性

总结: Zookeeper 负责服务的协调调度,当客户端发起请求时,返回正确的服务器地址

Zookeeper下载

网址: http://zookeeper.apache.org/releases.html

下载路径,点击download

下载Zookeeper地址.

Zookeeper安装

安装JDK

将JDK1.8文件上传到Linux操作系统中/src/usr/local/java/文件下(直接将文件拖入目录下),然后解压文件

tar -xvf jdk-8u51-linux-x64.tar.gz

配置JDK环境变量

JAVA_HOME=/usr/local/src/java/jdk1.8
JAVA_BIN=/usr/local/src/java/jdk1.8/bin

时JDK生效,之后检测JDK安装是否成功

source /etc/profile

上传安装文件,,然后解压

tar -xvf zookeeper-3.4.8.tar.gz

修改配置文件

在zk根目录下创建文件夹data/log

mkdir data log

进入conf文件中,复制配置文件并且修改名称,并修改配置文件

cd conf

cp zoo_sample.cfg zoo.cfg

dataDir=/usr/local/src/zookeeper/zkCluster/zk1/data #自己的文件路径
dataLogDir=/usr/local/src/zookeeper/zkCluster/zk1/log #自己的文件路径

在bin目录下启动Zookeeper

sh zkServer.sh start     或者  ./zkServer.sh start    //启动

sh zkServer.sh stop  //停止

sh zkServer.sh status  //查看状态



Zookeeper集群安装

在zookeeper根目录中创建新的文件夹zkCluster.

创建zk1/zk2/zk3文件夹.

mkdir zk1 zk2 zk3

在每个文件夹里创建data/log文件夹.

mkdir {zk1,zk2,zk3}/{data,log}

分别在zk1/zk2/zk3中的data文件夹中创建新的文件myid.其中的内容依次为1/2/3,与zk节点号对应.

[root@localhost zkCluster]# vim zk1/data/myid

1

在conf文件下将zoo_sample.cfg 复制为zoo1.cfg之后修改配置文件

修改zoo1.cfg

配置完成后将zoo1.cfg复制2份.之后需要修改对应的文件夹目录.和不同的端口即可.

通过下面的命令启动zk集群.

sh zkServer.sh start   zoo1.cfg

sh zkServer.sh start   zoo2.cfg

sh zkServer.sh start   zoo3.cfg

检查主从关系,从机情况说明.

sh zkServer.sh status  zoo1.cfg

sh zkServer.sh status  zoo2.cfg

sh zkServer.sh status  zoo3.cfg

关于zookeeper集群说明

Zookeeper 集群中leader负责监控集群状态,follower主要负责客户端链接获取服务列表信息,同时参与投票

 

 

Dubbo调用原理

registry : 注册中心

consumer : 服务消费者

provider : 服务提供者

monitor : 监控

创建dubbo项目

Dubbo提供者配置

编辑YML配置文件

server:
  port: 9000

spring:
  datasource:
    #引入druid数据源
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    username: root
    password: root

#dubbo配置文件    
dubbo:
  scan:
    basePackages: com.jt   #定义包扫描
  application:
    name: provider-user    #定义服务名称 必须添加
  registry:
    address: zookeeper://192.168.175.129:2181  #?backup=192.168.126.176:2182,192.168.126.176:2183
  protocol:
    name: dubbo
    port: 20880  #端口号唯一

      
mybatis-plus:
  type-aliases-package: com.jt.dubbo.pojo       #配置别名包路径
  mapper-locations: classpath:/mybatis/mappers/*.xml  #添加mapper映射文件
  configuration:
    map-underscore-to-camel-case: true                #开启驼峰映射规则

编辑ServiceImpl

@Service(timeout=3000)	//3秒超时
public class UserServiceImpl implements UserService {
	
	@Autowired
	private UserMapper userMapper;
	@Override
	public List<User> findAll() {
		
		System.out.println("我是第一个服务的提供者");
		return userMapper.selectList(null);
	}
	
	@Override
	public void saveUser(User user) {
		
		userMapper.insert(user);
	}

}

 

编辑消费者

编辑消费者YML

server:
  port: 9001
dubbo:
  scan:
    basePackages: com.jt
  application:
    name: consumer-user
  registry:
    address: zookeeper://192.168.175.129:2181

 

编辑Controller

@RestController
public class UserController {
	
	@Reference(timeout=3000,check=false)
	private UserService userService;
	
	@RequestMapping("/findAll")
	public List<User> findAll(){
		
		return userService.findAll();
	}
	
	@RequestMapping("/saveUser/{name}/{age}/{sex}")
	public String saveUser(User user) {
		
		userService.saveUser(user);
		return "用户入库成功!!!";
	}
}

dubbo负载均衡算法

Nginx负载均衡机制

说明:nginx是服务端负载均衡,所有的请求都会由nginx实现负载

 

Dubbo的负载均衡模式

dubbo采用客户端负载均衡机制,并且是正向代理.

 

dubbo负载均衡的策略:

随机算法

说明:dubbo默认采用的负载均衡算法为随机

@Reference(timeout=3000,check=false,
			loadbalance = "random")
	private UserService userService;

轮询算法

@Reference(timeout=3000,check=false,
			loadbalance = "roundrobin")
	private UserService userService;

IPHASH算法

说明:根据IP绑定服务器

@Reference(timeout=3000,check=false,
			loadbalance = "consistenthash")
	private UserService userService;

最小访问算法

说明:根据当前服务器的最小访问量实现负载均衡.(压力小先访问)

@Reference(timeout=3000,check=false,
			loadbalance = "leastactive")
	private UserService userService;

 

Zookeeper 控制台搭建

 

导入dubbo控制台

修改配置文件

将id地址换成自己的

dubbo.registry.address=zookeeper://192.168.21.129:2181?backup=192.168.21.129:2182,192.168.21.129:2183
dubbo.admin.root.password=root
dubbo.admin.guest.password=guest

控制台效果

关于dubbo端口说明

zookeeper端口号: 2181/2182/2183

zk通信端口  2887/2888/2889

zk选举端口  3887/3888/3889

Dubbo框架

   PRC协议动态获取:20880手动编辑.

   消费者和提供者通信靠PRC:port

tomcat服务器:8091/8092/8093  宿主服务器.

 

Zookeeper是如何存储数据

 

Zookeeper问题

重要事项

  1. 实现类采用Service注解注意包路径
  2. 消费者注入接口时保证注入Dubbo接口. @Reference
  3. 注意YML配置文件 IP地址.
  4. 先启动服务提供者/之后启动消费者

关于热部署引发问题

说明:由于tomcat服务器热部署的因素.导致后台提供者启动了多次.中zookeeper中形成多条一致的记录.

解决方案:重启tomcat服务器即可.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值