Dubbo
课程内容的介绍
一、Dubbo概述
1、Dubbo及架构变化
1.1 Dubbo 介绍
现在出去找工作如果不会点分布式和微服务相关的内容,都不太好更面试官扯蛋。但这些架构也不是突然就出现的,而是经过不但演变才出现及流行起来的,本文就给大家来梳理下java项目架构的演变历程。
系统架构演化历程
单体架构
大型网站都是从小型网站发展而来的,网站架构也是一样,是从小型网站架构逐步演化而来的,小型网站最开始没有太多人访问,只需要一台服务器就绰绰有余了,这时的架构如下:应用程序、数据库、文件等所有的资源都在一台服务器上,通常服务器操作系统使用Linux、应用程序使用java或者其他语句,然后部署在Apache或者Nginx上。数据库使用MySQL,使用开源的技术实现,然后部署在一台廉价的服务器上就开始了网站的发展之路。
应用服务和数据服务分离
好景不长,随着公司业务的发展,一台服务逐渐满足不了需求,越来越多的用户访问导致性能越来越差,数据存储空间开始不足,这时我们需要将应用和数据分离,分离后开始使用三台服务器:应用服务器、文件服务器、数据库服务器。如图:
应用和数据分离后,不同特性的服务器承担着不同的服务角色,网站的并发处理能力和数据存储空间都得到了很大的改善,支持网站业务进一步发展,但是随着用户逐渐增多,数据库压力越来越大,访问延迟,进而影响整个网站的性能,此时需要进一步优化。
缓存的使用
网站访问有个著名的二八定律,即80%的业务集中访问在20%的数据上,如果我们将这一小部分的数据缓存在内存中,能够很好的减少数据库的访问压力,提高整个网站的数据访问速度。
缓存常用的组件可以是Redis,ehcache等。
集群的使用
缓存解决了数据库访问量比较大的问题,但是并不能解决随着业务增多造成的服务器并发压力大的问题,这时我们需要增加一台应用服务器来分担原来服务器的访问压力和存储压力。如图:
通过负载均衡调度服务器,可将来自用户的访问请求分发到应用服务器中的任何一台服务器中,这样多台服务器就分担了原来一台服务器的压力,我们只需要注意会话的一致性就可以了。
数据库读写分离
系统正常运行了一段时间后,虽然加的有缓存,使绝大多数的数据库操作可以不通过数据库就能完成,但是任然有一部分的操作(缓存访问不命中,缓存过期)和全部的写操作需要访问数据库,当用户达到一定规模后,数据库因为负载压力过大还是会成为系统的瓶颈,
这时主流的数据库都提供的有主从热备份功能,通过配置两台数据库实现主从关系,可以将一台数据库服务器的数据更新同步到另一台服务器上。可以利用这一功能来实现数据库读写分离。从而改善数据库的负载压力,如图:
mysql的读写分离可以通过自身自带的从主复制实现,Oracle的话可以通过阿里巴巴的mycat组件来实现。
反向代理和CDN加速
为了应付复杂的网络环境和不同地区用户的访问,通过CDN和反向代理加快用户访问的速度,同时减轻后端服务器的负载压力。CDN与反向代理的基本原理都是缓存。CDN部署在网络提供商的机房。用户请求到来的时候从距离自己最近的网络提供商机房获取数据,而反向代理则部署在网站的中心机房中,请求带来的时候先去反向代理服务器中查看请求资源,如果有则直接返回。如图:
使用CDN和反向代理的目的都是尽早返回数据给用户,一方面加快用户的访问速度,另一方面也减轻后端服务器的负载压力。
分布式文件和分布式数据库
任何强大的单一服务器都满足不了大型网站持续增长的业务需求。数据库经过读写分离后,从一台服务器拆分成两天服务器,但是随着业务的增长后面依然不能满足需求,这时我们需要使用分布式数据库,同时文件系统也一样,需要使用分布式文件系统。
分布式数据库是数据库拆分的最后的手段,只有在表单数据规模非常庞大的时候才使用,不到不得已时,我们更常用的手段是业务分库,将不同的业务数据部署在不同的物理服务器上。
NoSql和搜索引擎
随着业务越来越复杂,对数据存储和检索的需求也越来越复杂,这时一些NoSQL(Reids,HBase,mongodb)数据库技术和搜索引擎(Solr,Elasticsearch)的时候就显得很有必要。如下图:
NoSQL和搜索引擎对可伸缩的分布式特性具有更好的支持,应用服务器通过一个统一的数据访问模块访问各种数据,减轻应用程序管理诸多数据源的麻烦。
业务拆分
当访问量达到一定规模的时候我们可以通过分而治之的手段将整个系统的业务分成不同的产品线,例如我们将系统的首页,商铺,订单,买家,卖家,支付,订单等拆分成不同的产品线。
具体到技术实现上,也可以根据产品线划分,将一个网站拆分成许多不同的应用,每个应用独立部署维护,应用之间通过RPC框架(dubbo,webService,httpClient…)建立连接,也可以通过消息队列实现异步分发处理。来构成一个完整的系统,如下图:
分布式服务
随着业务拆分越来越小,存储系统越来越庞大,应用系统的整体复杂度呈指数级增加,部署维护越来越困难,由于所有应用要和所有数据库系统连接,最终导致数据库连接资源不足,拒绝服务。1.当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。
2.当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。
3.接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?
4.服务多了,沟通成本也开始上升,调某个服务失败该找谁?服务的参数都有什么约定?
5.一个服务有多个业务消费者,如何确保服务质量?
6.随着服务的不停升级,总有些意想不到的事发生,比如cache写错了导致内存溢出,故障不可避免,每次核心服务一挂,影响一大片,人心慌慌,如何控制故障的影响面?服务是否可以功能降级?或者资源劣化?
解决方案:公共的应用模块被提取出来,部署在分布式服务器上供应用服务器调用。也就是我们将的分布式服务或者微服务。
1.2 单体架构
1.3 SOA 架构:
1.4 RPC 远程过程调用
2、Dubbo 框架结构图
2.1 Dubbo 角色介绍
2.2 Dubbo 执行流程
3.Dubbo 支持的协议
3.1Dubbo 协议(官方推荐协议)
3.2RMI(Remote Method Invocation)协议
3.3Hessian 协议
4.Dubbo 支持的注册中心
4.1Zookeeper(官方推荐)
4.2 Multicast
4.3Redis
4.4Simple
二、Dubbo基本应用
1. Dubbo基本案例
1.1 项目结构
1.2 公共模块
package com.bobo;
public interface UserService {
String sayHello(String name);
}
1.3 provider
<dependencies>
<!-- 添加commons模块 -->
<dependency>
<groupId>com.bobo</groupId>
<artifactId>dubbo-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--- 添加Spring依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<!-- dubbo的依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<groupId>spring</groupId>
<artifactId>org.springframework</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Zookeeper的客户端 -->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
package com.bobo.service;
import com.bobo.service.UserService;
public class UserServiceImpl implements UserService {
@Override
public String sayHello(String name) {
System.out.println("服务端执行了: " + name);
return "HELLO:" + name + "[msg]";
}
}
<?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: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://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息 -->
<dubbo:application name="dubboProvider" />
<!-- 配置Zookeeper注册中心 -->
<dubbo:registry protocol="zookeeper"
address="192.168.100.120:2181,192.168.100.121:2181,192.168.100.122:2181"/>
<!-- 开启监控 -->
<dubbo:monitor protocol="registry" />
<!-- 设置Dubbo使用的协议 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 注入UserServiceImpl -->
<bean class="com.bobo.service.UserServiceImpl" id="userService"/>
<!-- 声明需要对外暴露的服务 -->
<dubbo:service interface="com.bobo.service.UserService" ref="userService"
group="dubbo" version="1.0.0" timeout="5000"
/>
</beans>
log4j.rootLogger=INFO,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
package com.bobo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppStart {
public static void main(String[] args) throws Exception{
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
// 挂起当前线程
Thread.currentThread().join();
}
}
1.4 consumer
<dependencies>
<!-- 添加commons模块 -->
<dependency>
<groupId>com.bobo</groupId>
<artifactId>dubbo-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--- 添加Spring依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<!-- dubbo的依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<groupId>spring</groupId>
<artifactId>org.springframework</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Zookeeper的客户端 -->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
<?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: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://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 消费者应用信息 -->
<dubbo:application name="dubboConsumer" />
<!-- 配置和Provide相同的注册中心 -->
<dubbo:registry protocol="zookeeper"
address="192.168.100.120:2181,192.168.100.121:2181,192.168.100.122:2181" />
<!-- 开启监控 -->
<dubbo:monitor protocol="registry" />
<!-- 生成远程连接的服务代理 -->
<dubbo:reference interface="com.bobo.service.UserService" id="userService"
group="dubbo" version="1.0.0" timeout="5000"
/>
</beans>
package com.bobo;
import com.bobo.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppStart {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取接口的代理对象
UserService userService = (UserService) ac.getBean("userService");
System.out.println(userService.sayHello("aaa"));
}
}
1.5 测试
2. Dubbo源码下载和编译
3. 管理控制台
dubbo.registry.address=zookeeper://192.168.100.120:2181?
backup=192.168.100.121:2181,192.168.100.122:2181
dubbo.admin.root.password=root
dubbo.admin.guest.password=guest
4. 监控平台
4.1 开启monitor服务
<!-- 开启监控 -->
<dubbo:monitor protocol="registry" />
4.2 修改配置
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
dubbo.container=log4j,spring,registry,jetty
dubbo.application.name=simple-monitor
dubbo.application.owner=
# zookeeper的配置信息
dubbo.registry.address=zookeeper://192.168.100.120:2181?
backup=192.168.100.121:2181,192.168.100.122:2181
#dubbo.registry.address=zookeeper://127.0.0.1:2181
#dubbo.registry.address=redis://127.0.0.1:6379
#dubbo.registry.address=dubbo://127.0.0.1:9090
dubbo.protocol.port=7070
dubbo.jetty.port=8080
dubbo.jetty.directory=${user.home}/monitor
dubbo.charts.directory=${dubbo.jetty.directory}/charts
dubbo.statistics.directory=${user.home}/monitor/statistics
dubbo.log4j.file=logs/dubbo-monitor-simple.log
dubbo.log4j.level=WARN
4.3 启动监控服务
4.4 访问服务
三、Dubbo实战案例
1、案例介绍
1.1 案例结构图
1.2 需求
1.3 技术选型
1.4 表结构
CREATE TABLE `users` (
`userid` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(30) DEFAULT NULL,
`userage` int(11) DEFAULT NULL,
PRIMARY KEY (`userid`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
2、项目创建
2.1 项目设计
dubbo-parent(POM)
|-- dubbo-pojo(jar)
|-- dubbo-mapper(jar)
|-- dubbo-user-provider(POM)
|-- dubbo-user-provider-interface(jar)
|-- dubbo-user-provider-service(jar)
|-- dubbo-user-consumer(POM)
|-- dubbo-user-consumer-web-service(jar)
|-- dubbo-user-consumer-web(war)
2.2 创建dubbo-parent
<!-- jar包的依赖注入 ,由于该工程是一个父工程,所以jar包在该pom文件中只是声明 -->
<dependencyManagement>
<dependencies>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!-- 日志处理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis.spring.version}</version>
</dependency>
<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- JSP相关 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp-api.version}</version>
<scope>provided</scope>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo-version}</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>${zkClient-version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
<!-- tomcat插件,由于子项目不一定每个都是web项目,所以该插件只是声明,并未开启 -->
<pluginManagement>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>${tomcat.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
2.2 创建dubbo-pojo
package com.bobo.pojo;
import java.io.Serializable;
public class User implements Serializable {
private Integer userid;
private String username;
private Integer userage;
public Integer getUserid() {
return userid;
}
public void setUserid(Integer userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getUserage() {
return userage;
}
public void setUserage(Integer userage) {
this.userage = userage;
}
public User() {
}
public User(Integer userid, String username, Integer userage) {
this.userid = userid;
this.username = username;
this.userage = userage;
}
@Override
public String toString() {
return "User{" +
"userid=" + userid +
", username='" + username + '\'' +
", userage=" + userage +
'}';
}
}
2.3 创建dubbo-mapper
/**
* UserMapper接口
*/
public interface UserMapper {
}
<?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.bobo.mapper.UserMapper">
</mapper>
<dependencies>
<dependency>
<groupId>com.bobo</groupId>
<artifactId>dubbo-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</dependency>
<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
2.4 创建服务提供者
2.4.1 创建dubbo-user-provider
2.4.2 创建dubbo-user-provider-interface
<dependencies>
<dependency>
<groupId>com.bobo</groupId>
<artifactId>dubbo-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependencies>
2.4.3 创建dubbo-user-provider-service
<dependencies>
<dependency>
<groupId>com.bobo</groupId>
<artifactId>dubbo-user-provider-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.bobo</groupId>
<artifactId>dubbo-mapper</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<!-- dubbo的依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<groupId>spring</groupId>
<artifactId>org.springframework</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Zookeeper的客户端 -->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
</dependencies>
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/shop?characterEncoding=utf-8&serverTimezone=UTC
jdbc.username=root
jdbc.password=123456
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
<?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:p="http://www.springframework.org/schema/p"
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.xsd">
<!-- 扫描bean对象 -->
<context:component-scan base-package="com.bobo.dubbo.service.impl"/>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 配置事物管理器的切面 -->
<bean id="transactionMananger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事物传播行为 :其实就是那些方法应该受什么样的事物控制-->
<tx:advice id="advice" transaction-manager="transactionMananger">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="modify*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="dorp*" propagation="REQUIRED"/>
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="find*" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 那些类下的方法需要参与到当前的事物管理中 。配置切点 -->
<aop:config>
<aop:advisor advice-ref="advice" pointcut="execution(* com.bobo.dubbo.service.impl*.*(..))"/>
</aop:config>
</beans>
<?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:p="http://www.springframework.org/schema/p"
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.xsd">
<!-- 配置解析properties文件的工具类 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 配置数据源 dataSource -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="driverClassName" value="${jdbc.driver}" />
<property name="maxActive" value="10" />
<property name="minIdle" value="5" />
</bean>
<!-- 创建mybatis的上下文对象 -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="configLocation">
<value>classpath:SqlMapperClient.xml</value>
</property>
</bean>
<!-- 扫描mybatis的接口与映射配置文件 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.bobo.mapper"/>
</bean>
</beans>
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
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://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 导入Spring相关的配置文件 -->
<import resource="../../applicationContext-dao.xml" />
<import resource="../../applicationContext-service.xml" />
<import resource="../../applicationContext-trans.xml" />
<dubbo:application name="user-provider" />
<dubbo:registry protocol="zookeeper"
address="192.168.100.120:2181,192.168.100.121:2181,192.168.100.122:2181"/>
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 添加向Zookeeper注册的服务 -->
<dubbo:service interface="com.bobo.dubbo.service.AddUserDubboService"
ref="addUserDubboServiceImpl" group="dubbo" version="1.0.0" timeout="5000"/>
<dubbo:service interface="com.bobo.dubbo.service.SelectUserDubboService"
ref="selectUserDubboServiceImpl" group="dubbo" version="1.0.0" timeout="5000"/>
<dubbo:service interface="com.bobo.dubbo.service.DeleteUserDubboService"
ref="deleteUserDubboServiceImpl" group="dubbo" version="1.0.0" timeout="5000"/>
</beans>
package com.bobo.dubbo;
import com.alibaba.dubbo.container.Main;
public class Start {
public static void main(String[] args) throws Exception{
// Dubbo提供的启动方法,默认会去classpath:/META-INF/spring/*.xml 加载
Main.main(args);
}
}
2.5 创建消费者
2.5.1 创建dubbo-user-consumer
2.5.2 创建service服务
<dependencies>
<!-- 添加对provide中的interface服务的依赖 -->
<dependency>
<groupId>com.bobo</groupId>
<artifactId>dubbo-user-provider-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
</dependencies>
2.5.3 创建web服务
<?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">
<parent>
<artifactId>dubbo-user-consumer</artifactId>
<groupId>com.bobo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-user-consumer-web</artifactId>
<packaging>war</packaging>
<name>dubbo-user-consumer-web Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.bobo</groupId>
<artifactId>dubbo-user-consumer-web-service</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- dubbo的依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<groupId>spring</groupId>
<artifactId>org.springframework</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Zookeeper的客户端 -->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path>
<port>8082</port>
</configuration>
</plugin>
</plugins>
<finalName>dubbo-user-consumer-web</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
<?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: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://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 消费者应用信息 -->
<dubbo:application name="dubboConsumer" />
<!-- 配置和Provide相同的注册中心 -->
<dubbo:registry protocol="zookeeper"
address="192.168.100.120:2181,192.168.100.121:2181,192.168.100.122:2181" />
<!-- 订阅Dubbo中的服务 -->
<dubbo:reference interface="com.bobo.dubbo.service.AddUserDubboService"
id="addUserDubboService" group="dubbo" version="1.0.0" timeout="5000"/>
<dubbo:reference interface="com.bobo.dubbo.service.SelectUserDubboService"
id="selectUserDubboService" group="dubbo" version="1.0.0" timeout="5000"/>
<dubbo:reference interface="com.bobo.dubbo.service.DeleteUserDubboService"
id="deleteUserDubboService" group="dubbo" version="1.0.0" timeout="5000"/>
</beans>
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描bean对象 -->
<context:component-scan base-package="com.bobo.service.impl"/>
</beans>
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 包的扫描器主要是扫描@controller -->
<context:component-scan base-package="com.bobo.controller" />
<!-- 注册两个新对象 主要是为了来处理springmvc中的其他anntation 如:@requestmapping -->
<mvc:annotation-driven />
<!-- 视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- jsp所在的前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 配置静态资源映射 -->
<mvc:resources location="/WEB-INF/css/" mapping="/css/**" />
<mvc:resources location="/WEB-INF/js/" mapping="/js/**" />
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<!-- 上下文参数,告诉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>
<!-- 配置springmvc -->
<servlet>
<servlet-name>springmvc</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>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
3. 业务实现
3.1 添加用户信息
3.1.1 dubbo-mapper
package com.bobo.mapper;
import com.bobo.pojo.User;
/**
* UserMapper接口
*/
public interface UserMapper {
int insertUser(User user);
}
<?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.bobo.mapper.UserMapper">
<insert id="insertUser" parameterType="com.bobo.pojo.User">
insert into users(username,userage)values(#{username},#{userage})
</insert>
</mapper>
3.1.2 dubbo-user-service-interface
package com.bobo.dubbo.service;
import com.bobo.pojo.User;
public interface AddUserDubboService {
void addUser(User user);
}
3.1.3 dubbo-user-service
<dependencies>
<dependency>
<groupId>com.bobo</groupId>
<artifactId>dubbo-user-provider-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.bobo</groupId>
<artifactId>dubbo-mapper</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<!-- dubbo的依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<groupId>spring</groupId>
<artifactId>org.springframework</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Zookeeper的客户端 -->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
</dependencies>
package com.bobo.dubbo.service.impl;
import com.bobo.dubbo.service.AddUserDubboService;
import com.bobo.mapper.UserMapper;
import com.bobo.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AddUserDubboServiceImpl implements AddUserDubboService {
@Autowired
private UserMapper userMapper;
@Override
public void addUser(User user) {
userMapper.insertUser(user);
}
}
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 导入Spring相关的配置文件 -->
<import resource="../../applicationContext-dao.xml" />
<import resource="../../applicationContext-service.xml" />
<import resource="../../applicationContext-trans.xml" />
<dubbo:application name="user-provider" />
<dubbo:registry protocol="zookeeper"address="192.168.100.120:2181,192.168.100.121:2181,192.168.100.122:2181"/>
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 添加向Zookeeper注册的服务 -->
<dubbo:service interface="com.bobo.dubbo.service.AddUserDubboService"ref="addUserDubboServiceImpl"group="dubbo" version="1.0.0"timeout="5000"/>
</beans>
3.1.4 dubbo-user-web-service
public interface UserService {
int addUser(User user);
}
package com.bobo.service.impl;
import com.bobo.dubbo.service.AddUserDubboService;
import com.bobo.pojo.User;
import com.bobo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService{
/**
* 从Spring容器中获取 provider中的接口的代理对象
*/
@Autowired
public AddUserDubboService addUserDubboService;
@Override
public int addUser(User user) {
addUserDubboService.addUser(user);
return 1;
}
}
3.1.5 dubbo-user-web
<!-- 订阅Dubbo中的服务 -->
<dubbo:reference interface="com.bobo.dubbo.service.AddUserDubboService"
id="addUserDubboService"
group="dubbo" version="1.0.0" timeout="5000"
/>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/user/addUser" method="post">
用户名:<input type="text" name="username" /><br />
用户年龄:<input type="text" name="userage" /><br />
<input type="submit" value="提交" />
</form>
</body>
</html>