最近在模仿学习做一个企业级的项目,很想感受一下一个大而完整的项目是什么样子的。其中需要用到dubbo,查阅资料学习的时候,第一次感觉到资料相比曾经的学习不那么富足。所以直接看文档了。这里依据官网,针对一些概念,记下自己的学习笔记。
官网首页有一段话,Apache Dubbo |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
关于RPC
完整文章来自: 谁能用通俗的语言解释一下什么是 RPC 框架?
RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。
比如说,一个方法可能是这样定义的:
Employee getEmployeeByName(String fullName)
那么:
- 首先,要解决通讯的问题,主要是通过在客户端和服务器之间建立TCP连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享同一个连接。
- 第二,要解决寻址的问题,也就是说,A服务器上的应用怎么告诉底层的RPC框架,如何连接到B服务器(如主机或IP地址)以及特定的端口,方法的名称名称是什么,这样才能完成调用。比如基于Web服务协议栈的RPC,就要提供一个endpoint URI,或者是从UDDI服务上查找。如果是RMI调用的话,还需要一个RMI Registry来注册服务的地址。
- 第三,当A服务器上的应用发起远程过程调用时,方法的参数需要通过底层的网络协议如TCP传递到B服务器,由于网络协议是基于二进制的,内存中的参数的值要序列化成二进制的形式,也就是 序列化(Serialize) 或编组(marshal),通过寻址和传输将序列化的二进制发送给B服务器。
- 第四,B服务器收到请求后,需要对参数进行反序列化(序列化的逆操作),恢复为内存中的表达方式,然后找到对应的方法(寻址的一部分)进行本地调用,然后得到返回值。
- 第五,返回值还要发送回服务器A上的应用,也要经过序列化的方式发送,服务器A接到后,再反序列化,恢复为内存中的表达方式,交给A服务器上的应用
序列化是传输的关键
为什么RPC呢?就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如比如不同的系统间的通讯,甚至不同的组织间的通讯。由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用。
RPC的协议有很多,比如最早的CORBA,Java RMl,Web Service的RPC风格,Hessian,Thrift,甚至Rest APl。
关于核心功能
官网:http://dubbo.apache.org/zh-cn/index.html
因为不理解底层,所以不敢妄加揣测,直接按官网的说法对dubbo,有个浅显的认识吧。
在官方文档的首页 有一张图名称是dubbo架构 这个就比较重要了
init 初始化 : 1 ,2 ,0
async 异步 :3 ,5
sync 同步:4
0 服务容器负责启动,加载,运行服务提供者。
1 服务提供者在启动时,向注册中心注册自己提供的服务。
2 服务消费者在启动时,向注册中心订阅自己所需的服务。
3 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
这些就是官网首页的东西了。
文档部分 首先介绍了当今互联网,网站应用的规模不断扩大面临的问题,需求以及dubbo的优势,还有dubbo的架构。这部分一定要看,文档默认选项是“快速启动”,新手一定要点开上面的部分好好了解一下。
之后就可以看 “快速启动” 了,里面有相关的配置等等。
但是这些还是不够的,一般我们会用zookeeper作为我们的注册中心,会用即可,原理稍微了解一下:
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户
zookeeper的功能有:
命名服务
配置管理
集群管理
分布式锁
队列管理
命名服务
在zookeeper的文件系统里创建一个目录,即有唯一的path。在我们使用tborg无法确定上游程序的部署机器时即可与下游程序约定好path,通过path即能互相探索发现。
配置管理
程序总是需要配置的,如果程序分散部署在多台机器上,要逐个改变配置就变得困难。现在把这些配置全部放到zookeeper上去,保存在 Zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中就好
集群管理
所谓集群管理无在乎两点:是否有机器退出和加入、选举master。
对于第一点,所有机器约定在父目录GroupMembers下创建临时目录节点,然后监听父目录节点的子节点变化消息。一旦有机器挂掉,该机器与 zookeeper的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除,于是,所有人都知道:它上船了。
新机器加入也是类似,所有机器收到通知:新兄弟目录加入,highcount又有了,对于第二点,我们稍微改变一下,所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为master就好。
Zookeeper设计目的
-
最终一致性:client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的性能。
-
可靠性:具有简单、健壮、良好的性能,如果消息被一台服务器接受,那么它将被所有的服务器接受。
-
实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。
-
等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每个client都能有效的等待。
-
原子性:更新只能成功或者失败,没有中间状态。
-
顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布;偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。
Zookeeper工作原理
Zookeeper 的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。
为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。
zookeeper的四种节点类型znode
PERSISTENT-持久化目录节点 客户端与zookeeper断开连接后,该节点依旧存在
PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点 客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号
EPHEMERAL-临时目录节点 客户端与zookeeper断开连接后,该节点被删除
EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点 客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号
我们这里创建一个项目EduProject
所有的依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yuxiu.edu</groupId>
<artifactId>common-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>edu-model</module>
<module>edu-dao</module>
<module>edu-service</module>
<module>edu-manager</module>
<module>edu-api</module>
<module>edu-eb-facade-userservice</module>
<module>edu-eb-userservice-impl</module>
<module>edu-eb-web</module>
<module>edu-eb-web2</module>
</modules>
<!-- 父工程 - pom-->
<packaging>pom</packaging>
<!-- 公共的版本号管理-->
<properties>
<junit.version>4.11</junit.version>
<spring.version>4.2.6.RELEASE</spring.version>
<mybatis.version>3.4.1</mybatis.version>
<mybatis-spring.version>1.3.1</mybatis-spring.version>
<log4j.version>1.2.17</log4j.version>
<slf4j.version>1.7.12</slf4j.version>
<jstl.version>1.2</jstl.version>
<taglibs.version>1.1.2</taglibs.version>
<c3p0.version>0.9.5.2</c3p0.version>
<mysql.version>5.1.35</mysql.version>
</properties>
<!-- 公共依赖-->
<dependencies>
<!-- 1. 添加spring/springmvc的依赖 start =======================-->
<!-- aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- expression -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 添加mybatis-spring的整合依赖-->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- 数据连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<!-- start..............dubbo.................-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.0</version>
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<!-- end..............dubbo.................-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
一,基本准备
创建一个Model模块
package com.yuxiu.edu.model;
import java.io.Serializable;
public class User implements Serializable{
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
里面有用户信息
使用的依赖:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
创建一个Dao模块
BaseMapper.java
package com.yuxiu.edu.mapper.base;
public interface BaseMapper<T> {
public T findById(Integer id);
public T findByUUID(String uuid);
public void deleteById(Integer id);
public void deleteByUUID(String uuid);
public void update(T t);
public void insert(T t);
}
UserMapper.java
package com.yuxiu.edu.mapper;
import com.yuxiu.edu.mapper.base.BaseMapper;
import com.yuxiu.edu.model.User;
public interface UserMapper extends BaseMapper<User> {
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.yuxiu.edu.mapper.UserMapper" >
<select id="findById" resultType="com.yuxiu.edu.model.User" parameterType="int">
SELECT * FROM t_user WHERE id = #{id}
</select>
</mapper>
需要的依赖
<dependencies>
<!-- 依赖model-->
<dependency>
<artifactId>edu-model</artifactId>
<groupId>com.yuxiu.edu</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 依赖mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
</dependencies>
二,Provider提供商部分
创建一个独立的service接口模块
package com.yuxiu.edu.eb.service;
import com.yuxiu.edu.model.User;
public interface IUserService {
public User findById(Integer id);
public void register(String username,String password);
}
引用了Model模块的依赖
<!--引入edu-model的依赖-->
<dependency>
<groupId>com.yuxiu.edu</groupId>
<artifactId>edu-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
创建一个实现service接口实现类模块
package com.yuxiu.edu.eb.service.impl;
import com.yuxiu.edu.eb.service.IUserService;
import com.yuxiu.edu.mapper.UserMapper;
import com.yuxiu.edu.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
@Transactional
public class UserServiceImpl implements IUserService{
@Autowired
private UserMapper userMapper;
@Override
public User findById(Integer id) {
return userMapper.findById(id);
}
@Override
public void register(String username, String password) {
}
}
所需的依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- User服务接口-->
<dependency>
<groupId>com.yuxiu.edu</groupId>
<artifactId>edu-eb-facade-userservice</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Dao -->
<dependency>
<groupId>com.yuxiu.edu</groupId>
<artifactId>edu-dao</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
这部分完成之后 下面着手准备我们的注册中心
三,注册中心部分
下载zookeeper: http://zookeeper.apache.org/releases.html
选择的是稳定版本的
虽然是以.tar.gz结尾的 但是Windows也可以解压 安装.
不能正确解压的话 是因为解压软件处理不好的缘故
我这里用的是3.4.6版本的
解压后,找到目录conf 下创建 zoo.cfg 文件,默认就是加载这个文件,然后修改些东西。
#zoo.cfg 的内容
# 心跳检查的时间 2秒
tickTime=2000
# 初始化时 连接到服务器端的间隔次数,总时间10*2=20秒
initLimit=10
# ZK Leader 和follower 之间通讯的次数,总时间5*2=10秒
syncLimit=5
# 存储内存中数据库快照的位置,如果不设置参数,更新事务日志将被存储到默认位置。
dataDir=C:\\test\\tmp\\zookeeper
# 错误日志的存放位置
dataLogDir=C:\\test\\log\\zookeeper
# ZK 服务器端的监听端口
clientPort=2181
注意路径的写法!两个\ 一个负责转义
启动bin目录下的zkServer.cmd
成功界面:
下面将服务提供者的服务在注册中心进行注册(所在模块为edu-eb-userservice-impl)
<?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-4.3.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--配置dubbo的应用名称-->
<dubbo:application name="edu-eb-userservice"/>
<!--注册中心-->
<dubbo:registry protocol="zookeeper" address="192.168.1.109:2181"></dubbo:registry>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.yuxiu.edu.eb.service.IUserService" ref="userService" />
<bean id="userService" class="com.yuxiu.edu.eb.service.impl.UserServiceImpl"/>
</beans>
其他配置
db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/edu1
jdbc.username=root
jdbc.password=123456
log4j.properties
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
spring-context. 这里引入了dao dubbo的xml配置 dubbo的依赖在父项目的pom.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<import resource="spring-dao.xml"></import>
<import resource="spring-dubbo.xml"></import>
</beans>
pring-dao.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<context:property-placeholder location="classpath:db.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="2"/>
</bean>
<!-- 配置sessionFactory -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 指定配置文件位置 -->
<!--<property name="configLocation" value="classpath:mybatis.xml"/>-->
<!--配置别名-->
<property name="typeAliasesPackage" value="com.yuxiu.edu.model"></property>
<!--配置加载映射文件 UserMapper.xml-->
<property name="mapperLocations" value="classpath:com/yuxiu/edu/mapper/*Mapper.xml"/>
</bean>
<!-- 自动生成dao,mapper-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.yuxiu.edu.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
</bean>
<!-- 配置事务-->
<!-- 5.配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 6.开启事务注解-->
<tx:annotation-driven></tx:annotation-driven>
</beans>
spring-dubbo.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-4.3.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--配置dubbo的应用名称-->
<dubbo:application name="edu-eb-userservice"/>
<!--注册中心-->
<dubbo:registry protocol="zookeeper" address="192.168.3.56:2181"></dubbo:registry>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.yuxiu.edu.eb.service.IUserService" ref="userService" />
<bean id="userService" class="com.yuxiu.edu.eb.service.impl.UserServiceImpl"/>
</beans>
声明需要暴露的服务接口 的使用要引用实现类
在App.java中设置启动
package com.yuxiu.edu;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args ) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-context.xml");
context.start();
System.in.read();
/* synchronized (App.class) {
while (true) {
try {
App.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}*/
}
}
启动该类即可与zookeeper服务器端进行连接
Consumer部分
创建一个web模块
导入依赖:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.yuxiu.edu</groupId>
<artifactId>edu-eb-facade-userservice</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
UserController.java
package com.yuxiu.edu.eb.web.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yuxiu.edu.eb.service.IUserService;
import com.yuxiu.edu.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Controller
@RequestMapping("user")
public class UserController {
@Autowired
private IUserService userService;
@RequestMapping("find")
@ResponseBody
public void find(Integer id){
User user = userService.findById(id);
System.out.println("dubbo服务返回的数据:" +user);
responseJson(user);
}
public void responseJson(Object obj){
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
response.setHeader("Content-Type","text/json;charset=utf-8");
//ServletContext context = ContextLoader.getCurrentWebApplicationContext().getServletContext();
ObjectMapper mapper = new ObjectMapper();
try {
response.getWriter().write(mapper.writeValueAsString(obj));
} catch (IOException e) {
e.printStackTrace();
}
}
}
相关的配置文件
applicationContext.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.yuxiu.edu.eb"></context:component-scan>
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="edu-eb-web" />
<!-- 使用zookeeper注册中心暴露服务地址 -->
<!-- 注册中心地址 -->
<dubbo:registry protocol="zookeeper" address="192.168.3.56:2181" />
<!-- 用户服务接口 -->
<dubbo:reference interface="com.yuxiu.edu.eb.service.IUserService" id="userService" check="false" />
</beans>
日志
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
springmvc.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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- 1.注解扫描位置-->
<context:component-scan base-package="com.yuxiu.edu.eb.web.controller" />
<!-- 2.配置映射处理和适配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!-- 3.视图的解析器-->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/Modules/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 配置spring-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<!-- 配置springmvc-->
<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:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
index.jsp
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
下面要执行的时候 要这是Tomcat
将默认的进行移除
添加web
首先启动服务提供者 再启动服务消费者 输入url
获取到了数据库中的数据(数据库中的表 字段 值啥的都是为了演示随便建的)
主体的内容已经演示完了
四、Dubbo后台管理和监控中心部署
下面看看看dubbo的后台管理:
jdk1.8
dubbo的版本为 2.6.0
最上面我们使用的dubbo依赖也是这个版本
在github https://github.com/apache/dubbo/tree/dubbo-2.6.0 上下载源码
解压后 命令行进入dubbo-admin文件夹,输入下命令进行编译打包:
mvn package -Dmaven.skip.test=true
打包成功:
下面部署dubbo-admin
zookeeper默认使用的是8080,我的改成了别的了
如果你不想改,可以修改Tomcat的端口
打开本地Tomcat conf目录下的server.xml文件,把启动端口改成其他端口,以免冲突:
其他的应该没什么坑了 可以参考dubbo的后台管理以及监控中心进行搭建