@

一、分布式基本理论

1.1、分布式基本定义

《分布式系统原理与范型》定义:

“分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统”

分布式系统(distributed system)是建立在网络之上的软件系统。

1.2 架构发展演变

架构的发展是由最初的单一应用架构构建的,一般就是ORM框架方便数据库操作。

不过随着系统越来越复杂,单一应用架构会变得难以维护,所以架构逐渐演变出了垂直应用架构,所谓垂直应用架构其实就是安装业务模板进行拆分,比如可以安装业务将一个电商系统分为订单模块,用户信息管理模块,商品管理模块等等,这时候MVC框架就派上用场,MVC框架可以协助系统更好的按业务拆分,不过业务拆分后虽然是比单一应用架构更好维护了。

不过随着系统越来约复杂,发现很多共用的模块很难复用起来,这时候分布式服务架构登场了,分布式架构是将一些核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,当应用需要时,就去服务中心调服务就可以,而实现这种服务注册的肯定是RPC框架了。

当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率,这时候就需要流动计算架构(SOA)[ Service Oriented Architecture],用于提高机器利用率的资源调度,SOA是一个治理中心,综上所述,到目前,软件系统架构演变经历了:单一应用架构->垂直应用架构->分布式应用架构->流动计算架构,下面Dubbo官网的图片可以很好的描述

1.3、RPC简介

RPC概念

RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。

RPC核心模块

RPC有两个核心模块:通信和序列化

二、Dubbo理论简介

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

官网:

http://dubbo.apache.org/



Dubbo的服务治理:

Dubbo原理图片,图片来自Dubbo官网:

Dubbo角色:

  • Provider:暴露服务的服务提供者

  • Container:服务运行的容器

  • Consumer:调用远程服务的消费者

  • Registry:服务注册和发现的注册中心

  • Minitor:统计服务调用次数和时间的监控中心

调用过程:

下面根据我的理解说明一下

  • 0:服务器容器负责启动、加载、运行服务提供者

  • 1:服务提供者在启动后就可以向注册中心暴露服务

  • 2:服务消费者在启动后就可以向注册中心订阅想要的服务

  • 3:注册中心向服务消费者返回服务调用列表

  • 4:服务消费者基于软负载均衡算法调用服务提供者的服务,这个服务提供者有可能是一个服务提供者列表,调用那个服务提供者就是根据负载均衡来调用了

  • 5:服务提供者和服务消费者定时将保存在内存中的服务调用次数和服务调用时间推送给监控中心

三、Dubbo环境搭建

3.1 Zookeeper搭建

搭建Zookeeper,首先是搭建分布式架构的注册中心Zookeeper,当然也可以用Redis等等来做服务注册中心,不过本博客只介绍Zookeeper的,因为没有linux服务器,所以只介绍window版的搭建

  • 1、下载Zookeeper:

    网址 https://archive.apache.org/dist/zookeeper/zookeeper-3.4.13/

  • 2、解压Zookeeper

    解压Zookeeper之后,运行bin目录里的zkServer.cmd,发现报错了,提示找不到配置文件,所以需要继续步骤3

  • 3、配置Zookeeper

    因为Zookeeper的conf文件夹下面只提供zoo_sample.cfg文件,需要自己修改命名为zoo.cfg

对于配置文件需要注意:

dataDir=./ 临时数据存储的目录(可写相对路径)

clientPort=2181 zookeeper的端口号

  • 4、使用zkCli.cmd测试

    修改配置文件后,重新启动zkServer.cmd,启动bin目录下面的zkCli.cmd,很显然这是个客户端程序,注意zkServer.cmd是服务端程序,必须启动

ok,简单在zkCli.cmd敲几个命令测试一下:

ls /:列出zookeeper根下保存的所有节点

create –e /testNode 12345678:创建一个testNode节点,值为12345678

get /testNode:获取/testNode节点的值

3.2 Dubbo管理页面搭建

搭建了服务注册中心后,就需要搭建Dubbo-admin了,最近看了一下,dubbo的Github项目已经进行了更新,管理平台已经做了比较大的改动,而我学习的时候,平台是比较简单的,所以本dubbo-admin搭建是以旧版master的为准,不过以学习为目的的,只需要知道具体原理和操作技巧就可以

因为我搭建时候(ps:不是博客写作时间),dubbo还没做比较大改动,所以我以比较旧的版本为例子,现在新的具体参考dubbo官方的教程,本博客只是做记录

  • 修改dubbo-admin

修改 src\main\resources\application.properties 指定zookeeper地址

  • Maven package dubbo-admin
mvn clean package -Dmaven.test.skip=true
  • 运行dubbo-admin的jar

maven打包之后,就去target里找到jar,然后cmd运行

java -jar dubbo-admin-0.0.1-SNAPSHOT.jar

运行成功之后,访问: http://127.0.0.1:7001,输入默认的账号密码root/root,登录成功

四、Dubbo服务注册发现例子

经典例子:

4.1、业务场景

某个电商系统,订单服务需要调用用户服务获取某个用户的所有地址;

我们现在 需要创建两个服务模块进行测试

模块 功能
订单服务模块 创建订单等
用户服务模块 查询用户地址等
  • 测试预期结果:

    订单服务web模块在A服务器,用户服务模块在B服务器,A可以远程调用B的功能

4.2、api工程创建

创建工程:

建议将服务接口,服务模型,服务异常等均放在 API 包中,因为服务模型及异常也是 API 的一部分,同时,这样做也符合分包原则:重用发布等价原则(REP),共同重用原则(CRP)。

创建一个API工程,将实体类和接口都放在api工程

maven新建一个shop-api-common工程:

用户地址DTO类:

package com.test.dubbo.bean;
import java.io.Serializable;
public class UserAddress implements Serializable { private Integer id;
private String userAddress; //用户地址
private String userId; //用户id
private String consignee; //收货人
private String phoneNum; //电话号码
private String isDefault; //是否为默认地址 Y-是 N-否 public UserAddress() {
super();
} public UserAddress(Integer id, String userAddress, String userId, String consignee, String phoneNum,
String isDefault) {
super();
this.id = id;
this.userAddress = userAddress;
this.userId = userId;
this.consignee = consignee;
this.phoneNum = phoneNum;
this.isDefault = isDefault;
} public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getConsignee() {
return consignee;
}
public void setConsignee(String consignee) {
this.consignee = consignee;
}
public String getPhoneNum() {
return phoneNum;
}
public void setPhoneNum(String phoneNum) {
this.phoneNum = phoneNum;
}
public String getIsDefault() {
return isDefault;
}
public void setIsDefault(String isDefault) {
this.isDefault = isDefault;
}
}

用户信息服务接口:

package com.test.dubbo.service;

import java.util.List;

import com.test.dubbo.bean.UserAddress;

/**
* 用户服务
*/
public interface UserService { /**
* 按照用户id返回所有的收货地址
* @param userId
* @return
*/
public List<UserAddress> getUserAddressList(String userId); }

订单信息服务接口:


package com.test.dubbo.service; import java.util.List; import com.test.dubbo.bean.UserAddress; public interface OrderService { /**
* 初始化订单
* @param userId
*/
public List<UserAddress> initOrder(String userId); }

ok,创建好api工程

4.3、服务提供者工程

要实现服务提供,配置文件主要需要配置如下:

Dubbo提供者加载过程(Dubbo容器的启动):



Spring加载xml配置之后暴露服务的过程:



Exporter方法主要是打开socket的监听,接收客户的请求

ok,理解了上面的理论知识后,继续创建一个user-service-provider工程:

  • maven配置:
<!-- 引入dubbo -->
<!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<!-- 注册中心使用的是zookeeper,引入操作zookeeper的客户端端 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
  • resources加一个提供者的配置文件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://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!-- 1、指定当前服务/应用的名字(同样的服务名字相同,不要和别的服务同名) -->
<dubbo:application name="user-service-provider"></dubbo:application> <!-- 2、指定注册中心的位置 -->
<!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry> <!-- 3、指定通信规则(通信协议 通信端口) -->
<dubbo:protocol name="dubbo" port="20882"></dubbo:protocol> <!-- 4、暴露服务 ref:指向服务的真正的实现对象 -->
<dubbo:service interface="com.test.dubbo.service.UserService"
ref="userServiceImpl01" timeout="1000" version="1.0.0">
<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
</dubbo:service> <!--统一设置服务提供方的规则 -->
<dubbo:provider timeout="1000"></dubbo:provider> <!-- 服务的实现 -->
<bean id="userServiceImpl01" class="com.test.dubbo.service.impl.UserServiceImpl"></bean> <!-- 连接监控中心 -->
<dubbo:monitor protocol="registry"></dubbo:monitor> </beans>
  • 加个业务实现类:
package com.test.dubbo.service.impl;

import java.util.Arrays;
import java.util.List; import com.test.dubbo.bean.UserAddress;
import com.test.dubbo.service.UserService; public class UserServiceImpl implements UserService { //@Override
public List<UserAddress> getUserAddressList(String userId) {
UserAddress address1 = new UserAddress(1, "北京市昌平区", "1", "李老师", "010-56253825", "Y");
UserAddress address2 = new UserAddress(2, "深圳市宝安区", "1", "王老师", "010-56253825", "N");
return Arrays.asList(address1,address2);
} }
  • 启动服务提供者,注册到Zookeeper:

    启动服务提供者有两种方法,一种是IOC启动:
package com.test.dubbo;

import java.io.IOException;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApplication { public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("provider.xml");
ioc.start(); System.in.read();
} }

另外一种是调dubbo的Main类,启动:

dubbo的main函数:

com.alibaba.dubbo.container.Main

com.alibaba.dubbo.container.spring.SpringContainer

服务注册成功,可以去dubbo-admin看



查看服务接口的详细信息:

4.4、服务消费者工程

然后服务已经注册了,现在创建一个消费者工程order-service-comsumer

  • maven加上配置
<!-- 引入dubbo -->
<!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<!-- 注册中心使用的是zookeeper,引入操作zookeeper的客户端端 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
  • 消费者配置文件:
<?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://dubbo.apache.org/schema/dubbo"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<context:component-scan base-package="com.test.dubbo.service.impl"></context:component-scan> <dubbo:application name="order-service-consumer"></dubbo:application> <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> <!-- 配置本地存根--> <!--声明需要调用的远程服务的接口;生成远程服务代理 -->
<!--
1)、精确优先 (方法级优先,接口级次之,全局配置再次之)
2)、消费者设置优先(如果级别一样,则消费方优先,提供方次之)
-->
<!-- timeout="0" 默认是1000ms-->
<!-- retries="":重试次数,不包含第一次调用,0代表不重试-->
<!-- 幂等(设置重试次数)【查询、删除、修改】、非幂等(不能设置重试次数)【新增】 -->
<dubbo:reference interface="com.test.dubbo.service.UserService"
id="userService" timeout="5000" retries="3" version="*">
<!-- <dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method> -->
</dubbo:reference> <!-- 配置当前消费者的统一规则:所有的服务都不检查 -->
<dubbo:consumer check="false" timeout="5000"></dubbo:consumer> <dubbo:monitor protocol="registry"></dubbo:monitor>
<!-- <dubbo:monitor address="127.0.0.1:7070"></dubbo:monitor> --> </beans>
  • 订单服务类:
package com.test.dubbo.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.test.dubbo.bean.UserAddress;
import com.test.dubbo.service.OrderService;
import com.test.dubbo.service.UserService; /**
* 让服务消费者去注册中心订阅服务提供者的服务地址
*/
@Service
public class OrderServiceImpl implements OrderService { @Autowired
UserService userService;
@Override
public List<UserAddress> initOrder(String userId) {
System.out.println("用户id:"+userId);
//查询用户的收货地址
List<UserAddress> addressList = userService.getUserAddressList(userId);
for (UserAddress userAddress : addressList) {
System.out.println(userAddress.getUserAddress());
}
return addressList;
}
}
  • IOC启动

    同样也是可以ioc启动,或者Dubbo提供的Main类启动:
package com.test.dubbo;

import java.io.IOException;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.test.dubbo.service.OrderService;

public class MainApplication {

	@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("consumer.xml");
OrderService orderService = applicationContext.getBean(OrderService.class);
orderService.initOrder("1");
System.out.println("调用成功....");
System.in.read();
} }

调用成功,console打印:


用户id:1
北京市昌平区
深圳市宝安区
调用成功....

Dubbo服务注册与发现的更多相关文章

  1. Spring Cloud构建微服务架构(一)服务注册与发现

    Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁 ...

  2. Spring Cloud 系列之 Eureka 实现服务注册与发现

    如果你对 Spring Cloud 体系还不是很了解,可以先读一下 Spring Cloud 都有哪些模块 Eureka 是 Netflix 开源的服务注册发现组件,服务发现可以说是微服务架构的核心功 ...

  3. springcloud之服务注册与发现

    本次分享的是关于springcloud服务注册与发现的内容,将通过分别搭建服务中心,服务注册,服务发现来说明:现在北京这边很多创业公司都开始往springcloud靠了,可能是由于文档和组件比较丰富的 ...

  4. 记一次Dubbo服务注册异常

            公司项目重构,把dubbo版本从2.5.8升级为2.6.2.升级后在本地运行一点问题都没有:可是通过公司自研的发布系统将项目发布到测试环境的linux服务器下面后,出现了dubbo服务 ...

  5. 【三】Eureka服务注册与发现

    1.是什么 Eureka是Netflix的一个子模块,也是核心模块之一.Eureka是一个基于 REST 服务,用于定位服务,以实现云端中间层服务发现和故障转移.服务注册与发现对于微服务架构来说是非常 ...

  6. java框架之SpringCloud(3)-Eureka服务注册与发现

    在上一章节完成了一个简单的微服务案例,下面就通过在这个案例的基础上集成 Eureka 来学习 Eureka. 介绍 概述 Eureka 是 Netflix 的一个子模块,也是核心模块之一.Eureka ...

  7. Eureka服务注册与发现

    一.服务注册 注册Eureka的服务非常的简单,只需要引入spring-cloud-starter-netflix-eureka-client的jar包即可. <dependency> & ...

  8. 阿里dubbo服务注册原理解析

           阿里分布式服务框架 dubbo现在已成为了外面很多中小型甚至一些大型互联网公司作为服务治理的一个首选或者考虑方案,相信大家在日常工作中或多或少都已经用过或者接触过dubbo了.但是我搜了 ...

  9. 服务注册发现Eureka之一:Spring Cloud Eureka的服务注册与发现

    Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁 ...

随机推荐

  1. mysql三种修改密码的方式

    [root@MySQL ~]# mysqladmin -uroot -proot -S /data/3307/mysql.sock password '123'; 其中-p是现在的密码,passwor ...

  2. How to setup Assigned Access in Windows 10 (Kiosk Mode) 设置分配的访问权限(Kiosk模式)

    Let’s say you’re building some sort of ingenious mechanical contraption to be displayed in public th ...

  3. python 动态调用模块&类&方法

    转载自:http://www.cnblogs.com/bluefrog/archive/2012/05/11/2496439.html 一直想知道python里有没有类似php中的 $classnam ...

  4. Qt在Windows下的三种编程环境搭建(图文并茂,非常清楚)good

    尊重作者,支持原创,如需转载,请附上原地址:http://blog.csdn.net/libaineu2004/article/details/17363165 从QT官网可以得知其支持的平台.编译器 ...

  5. 【Linux】Linux 环境下splite以及一些正则使用

    由于在windows下,遍历目录,想查找满足条件的文件: dir /s > ..\fileresult.txt 结果得到的文件过大,999多MB的txt: split -b 10k date.f ...

  6. ansible(三)

    一.setup模块(收集信息 ) 1.ansible中的setup模块可以收集到的信息 ansible web -m setup ansible_all_ipv4_addresses # ipv4的所 ...

  7. IOS 数据存储(NSKeyedArchiver 归档篇)

    什么是归档 当遇到有结构有组织的数据时,比如字典,数组,自定义的对象等在存储时需要转换为字节流NSData类型数据,再通过写入文件来进行存储. 归档的作用 之前将数据存储到本地,只能是字符串.数组.字 ...

  8. 05-MySQL的完整性约束

    1.整体说明(1)讨论重点内容    not null 与default    unique:表中该值唯一,不能有重复值    primary    auto_increment    foreign ...

  9. 你的http需要“爱情”

    目的是为了更白话的认识http,面对业内人,还有一些吃瓜的... 故事背景描述: 男猪脚在情人节这天给他女票发送了一条信息,"I love U",女主角收到后很开心,也回复了一条信 ...

  10. BootStrap4.0Demo+轮播素材记录

    整理一些关于前端的东西: BootStrap4.0Demo: 官方DEMO:http://code.z01.com/v4/components/carousel.html 下午翻了点不错的轮播素材: ...