基于Dubbo的分布式系统架构(二):搭建一个简单的分布式架构

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wx5040257/article/details/78080921

一、Dubbo简介

        Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。
从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。关于注册中心、协议支持、服务监控等内容如下图所示:

调用关系说明:

0. 服务容器(spring)负责启动,加载,运行服务提供者。

1. 服务提供者在启动时,向注册中心注册自己提供的服务(以接口的方式提供,包括服务提供者的ip及端口号)。

2. 服务消费者在启动时,向注册中心订阅自己所需的服务(仍然以接口的形式)。

3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。


二、搭建分布式开发架构

      下面以开发一个用户模块为例说明架构的搭建过程,功能包括用户登录、注册、用户信息展示、删除、修改等等。整个系统可以划分为4个maven工程,分别是dubbo1-common(公共模块)、dubbo1-user-facade(服务接口模块:对外提供服务接口_服务提供者和消费者都需要用到)、dubbo1-user-service(服务提供者模块)、dubbo1-web(服务消费者模块)。

      环境:

      jdk1.7+myeclipse8.6.1+maven3.3.9+mysql5.6+dubbo2.5.3+zookeeper-3.4.6+spring3.2.2+springmvc+mybatis3.2.2

      1. 搭建dubbo1-common(公共模块)

        公共模块:我们可以把服务提供者和消费者都可能用到的东西都放到这里来,到时候让服务提供者和消费者来依赖它即可。例如我们这里把公共的dao层代码BaseDao,工具类MD5加密类,公共的配置文件(连接池及注册中心地址配置),以及服务提供者和消费者全部的依赖的jar包都配置公共模块里面,如图所示:


dubbo1-common搭建完毕后,需要以jar包的形式发布到maven本地库中,如图所示操作:


2. 搭建dubbo1-user-facade(服务接口模块)

   服务接口模块非常简单,只需写对外发布的接口以及依赖的实体类。但是我们必须把它单独划分成一个工程,因为服务提供者和消费者都要用到它。如图所示:


同理,搭建完毕后,需要以jar包的形式发布到maven本地库中,跟第一个工程操作类似,这里就不截图了。

3. 搭建dubbo1-user-service(服务提供者模块)

    

添加依赖,如图:


这时候的pom.xml文件如下所示:

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.wx</groupId>
  <artifactId>dubbo1-user-service</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <!-- 项目jdk版本配置 -->
  <build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
					<encoding>utf-8</encoding>
				</configuration>
			</plugin>
		</plugins>
  </build>
  <dependencies>
  	<dependency>
  		<groupId>com.wx</groupId>
  		<artifactId>dubbo1-common</artifactId>
  		<version>0.0.1-SNAPSHOT</version>
  		<type>jar</type>
  		<scope>compile</scope>
  	</dependency>
  	<dependency>
  		<groupId>com.wx</groupId>
  		<artifactId>dubbo1-user-facade</artifactId>
  		<version>0.0.1-SNAPSHOT</version>
  		<type>jar</type>
  		<scope>compile</scope>
  	</dependency>
  </dependencies>
</project>
================================

服务提供者的配置文件dubbo-provider.xml如下:

<?xml version="1.0" encoding="UTF8"?>
<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://code.alibabatech.com/schema/dubbo  
            http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

	<!-- 服务提方的服务名,注意不要和其它服务重名 -->
	<dubbo:application name="dubbo1-service-user" />

	<!-- 使用zookeeper注册中心暴露服务地址 -->
	<dubbo:registry protocol="zookeeper" address="${dubbo.register.address}" />

	<!-- 用dubbo协议在19880端口暴露服务 -->
	<dubbo:protocol name="dubbo" port="19880" />
		
	<!-- 用户服务接口 -->
	<dubbo:service interface="com.wx.service.IUserBiz" ref="userBiz" />
	
</beans>  
当spring容器启动后,会生成userBiz的实例,<dubbo:service interface="com.wx.service.IUserBiz" ref="userBiz" />表示以接口名com.wx.service.IUserBiz向注册中心注册服务,提供的对象是userBiz,这个对象里面就包含的提供服务的数据。

============================

spring核心配置文件applicationContext.xml如下所示:

<?xml version="1.0" encoding="UTF8"?>
<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:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	 http://www.springframework.org/schema/aop 
	 http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
	 http://www.springframework.org/schema/tx
	 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
	 http://www.springframework.org/schema/context
	 http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	 
	<!-- 导入dubble配置 -->
	<import resource="classpath:configs/dubbo-provider.xml"/>
	<!-- 扫描包含注解类所在的包 -->
	<context:component-scan base-package="com.wx.dao.*"></context:component-scan>
	<context:component-scan base-package="com.wx.biz"></context:component-scan>
	
	<bean id="config" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
		<property name="locations">
			<list>
			  <value>classpath:service.properties</value>
			  <value>classpath:druidConfig_6.properties</value>
			</list>
		</property>
	</bean>
	<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
		<property name="driverClassName" value="${driverClassName}" />
		<property name="url" value="${url}" />
		<property name="username" value="${username}" />
		<property name="password" value="${password}" />
		<property name="filters" value="${filters}" />
		<property name="initialSize" value="${initialSize}" />
		<property name="maxActive" value="${maxActive}" />
		<property name="minIdle" value="${minIdle}" />
		<property name="maxWait" value="${maxWait}" />
		<property name="validationQuery" value="${validationQuery}" />
		<property name="testWhileIdle" value="${testWhileIdle}" />
		<property name="testOnBorrow" value="${testOnBorrow}" />
		<property name="testOnReturn" value="${testOnReturn}" />
		<property name="maxPoolPreparedStatementPerConnectionSize" value="${maxPoolPreparedStatementPerConnectionSize}" />
		<property name="removeAbandoned" value="${removeAbandoned}" />
		<property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" />
		<property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" />
		<property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" />
	</bean>
	<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="druidDataSource"></property>
		<property name="configLocation">
			<value>classpath:configs/mybatis-config.xml</value>
		</property>
		<property name="mapperLocations">
			<list>
				<value>classpath:configs/mappers/*.xml</value>
			</list>
		</property>
	</bean>
	<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg name="sqlSessionFactory" ref="sessionFactory"></constructor-arg>
	</bean>
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="druidDataSource"></property>
	</bean>
	<tx:advice id="txAdvise" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="find*" read-only="true"/>
			<tx:method name="search*" read-only="true"/>
			<tx:method name="query*" read-only="true"/>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="add*" propagation="REQUIRED"/>
			<tx:method name="save*" propagation="REQUIRED"/>
			<tx:method name="do*" propagation="REQUIRED"/>
			<tx:method name="update*" propagation="REQUIRED"/>
			<tx:method name="del*" propagation="REQUIRED"/>
		</tx:attributes>
	</tx:advice>
	<aop:config>
		<aop:pointcut expression="execution(* com.wx.biz.*.*(..))" id="myCut"/>
		<aop:advisor advice-ref="txAdvise" pointcut-ref="myCut"/>
	</aop:config>
</beans>
==============================

接下来创建测试类启动服务:

package dubbo.test;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 
 * @描述: 启动Dubbo服务用的MainClass.
 * @作者: wx
 * @创建时间: 2015-11-5,下午9:47:55 .
 * @版本: 1.0
 */
public class DubboProvider {
	
	private static final Log log = LogFactory.getLog(DubboProvider.class);

	public static void main(String[] args) {
		try {
			ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:configs/applicationContext.xml");
			context.start();
		} catch (Exception e) {
			log.error("== DubboProvider context start error:",e);
		}
		synchronized (DubboProvider.class) {
			while (true) {
				try {
					DubboProvider.class.wait();
				} catch (InterruptedException e) {
					log.error("== synchronized error:",e);
				}
			}
		}
	}
    
}
单击右键运行,没报错,服务就正常启动了,这时候可以在监控中心看到如下结果:


4.  搭建dubbo1-web(服务消费者模块)
     这时候服务消费者完全可以在不同的地方,不同的项目组开发,体现分布式。消费者模块搭建的是一个maven   web工程,如下图所示:



---------------------------------------------


如图所示:消费者工程需要依赖dubbo1-common和dubbo1-user-facade。

消费者核心配置文件dubbo-consumer.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://code.alibabatech.com/schema/dubbo  
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

	<!-- 消费方应用名,不要与提供方一样 -->
	<dubbo:application name="dubbo1-user-web" />

	<!-- 使用zookeeper注册中心暴露服务地址 -->
	<!-- 注册中心地址 -->
	<dubbo:registry protocol="zookeeper" address="${dubbo.register.address}" />
	
	<!-- 用户服务接口 id=userBiz表示服务以名称userBiz向消费者的控制器注入对象  check=false表示不检查服务端是否正常 -->
	<dubbo:reference interface="com.wx.service.IUserBiz" id="userBiz" check="false" />
    
</beans>
启动消费者,即发布到tomcat启动。然后运行,监控界面如下所示:

运行效果如图:

ok,到此为止,分布式开发框架搭建完毕!










阅读更多

没有更多推荐了,返回首页