1. 程式人生 > >分散式系統架構實戰demo:SSM+Dubbo

分散式系統架構實戰demo:SSM+Dubbo

對於傳統的單一構架,也就是打成的war或者ear包部署在同一個Web容器裡的構架,它雖然開發、測試、部署簡單,但隨著業務的不斷髮展,維護成本增加,可擴充套件性差,而且一臺Tomcat的併發數在500左右,系統性能存在瓶頸。雖然網際網路應用的系統性能瓶頸存在於每一個地方(資料庫,網路等),先不考慮其他系統瓶頸,本文采用多Tomcat來解決一個Tomcat帶來的瓶頸問題,那麼多個Tomcat之間如何通訊?答案是Dubbo。

        為什麼要使用Dubbo?兩臺伺服器A、B,分別部署不同的應用a,b。當A伺服器想要呼叫B伺服器上應用b提供的函式或方法的時候,由於不在一個記憶體空間,不能直接呼叫,需要通過網路來表達呼叫的語義傳達呼叫的資料。--

RPC。 Dubbo是基於RPC的高效能和透明化的RPC遠端服務呼叫方案。

       Dubbo也是一個被國內網際網路公司廣泛使用的SOA(核心理念:對外提供服務)基礎框架,說的直白點就是:一次開發出來的服務介面,相關服務都能呼叫。很像Java經典的特性:一次編譯,到處執行。

開發環境:

Window 7 64;Eclipse-Jee-mars-2-win32-x86_64 ;Apache-Maven-3.3.9;Spring 4.1.3;Mybatis 3.2.7;Springmvc 4.1.3;Dubbo 2.5.3,開發工具和原始碼:http://pan.baidu.com/s/1pLdoe0r

系統構架如下:

                  

1.配置環境,建立專案工程

需要注意的是本文所用JDK是1.7,Tomcat是7.0。

      1.1  mysql安裝

        資料庫環境搭建吐血推薦,博主在踩了很多坑之後總結的高效安裝方法。一分鐘快速安裝MySQL,超簡單。

       Mysql連結工具Navicat安裝後,開啟Navicat,新建連線-->新建資料庫Mysql-->雙擊進入資料庫-->查詢-->新建查詢:

SET FOREIGN_KEY_CHECKS=0;


DROP TABLE IF EXISTS `book`;
CREATE TABLE `book` (
  `book_id`
varchar(100) NOT NULL COMMENT '圖書ID', `book_name` varchar(100) DEFAULT NULL COMMENT '圖書名稱', `number` int(11) DEFAULT NULL COMMENT '館藏數量', PRIMARY KEY (`book_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='圖書表'; INSERT INTO `book` VALUES ('1000', 'Java程式設計', '10'); INSERT INTO `book` VALUES ('1001', '資料結構', '10'); INSERT INTO `book` VALUES ('1002', '設計模式', '10'); INSERT INTO `book` VALUES ('1003', '編譯原理', '10');

      1.3  建立父工程和子工程,目錄結構如下:

                                            

    其中,parent是pom檔案的父工程,common是jar包,裡面存放interface,bean,dao等公用內容。

controller控制層和service業務層是war包,也就是各分為一個Tomcat。

建立父工程:

                 

                      

建立common工程,在Packaging時選擇jar:

                

建立controller和service的步驟和common一樣,不過Packaging選擇war,完成後會出現以下報錯:

                      

原因是webapp下沒有WEB_INF資料夾和web.xml檔案,自己建立web.xml,它內容在下文2.1中,複製貼上即可。注意,此時的執行環境是jdk1.5,需要永久切換成jdk1.7(點buildPath切換1.7的執行環境,下回開啟還是jdk1.5).所以在所有的pom檔案中加入

<!-- jdk1.7 -->
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.2</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>

加入後會有以下報錯,根據如下圖片中步驟處理即可:

           

      1.4  匯入jar包。

parent專案pom.xml匯入所有jar包的座標,service和controller會依賴common,所以在common的pom檔案中加入要引入的jar包。因為太長,此處省略原始碼,讀者可以下載原始碼檢視。

因為公用jar放在了common裡,所以在controller和service的pom,xml檔案中都加入common的依賴:

 <!-- 依賴管理 -->
  <dependencies>
  	<dependency>
  		 <groupId>com.test</groupId>
    	<artifactId>test-common</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
  	</dependency>
  </dependencies>

2.整合Spring+Mybatis

      2.1  配置Spring監聽器

       一般會整合Spring+Mybatis放在業務邏輯層service。在service的web.xml中加入:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	<!-- 上下文配置檔案 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring-context.xml</param-value>
	</context-param>
	
	<!-- 監聽器 載入配置上下文配置檔案-->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
</web-app>

      2.2  建立上下文配置檔案: spring-context.xml

<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"
	xmlns:task="http://www.springframework.org/schema/task"
	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.0.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-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/task
   		http://www.springframework.org/schema/task/spring-task-4.0.xsd
		http://code.alibabatech.com/schema/dubbo        
		http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
		
       <!-- 資料來源  、事務 、掃描、MYbatis、ActiveMQ、Freemarker、Redis、Solr。。。。。 -->		
		<import resource="classpath:config/*.xml"/>

</beans>

      2.3建立資料來源和配置檔案jdbc.xml:

      

jdbc.xml中加入讀取配置檔案-->資料來源-->事務管理-->Spring宣告式事務管理配置:

<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"
	xmlns:task="http://www.springframework.org/schema/task"
	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.0.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-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/task
   		http://www.springframework.org/schema/task/spring-task-4.0.xsd
		http://code.alibabatech.com/schema/dubbo        
		http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
	
	<!-- 讀取配置檔案,可以讀取多個 -->
	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:jdbc.properties</value>
			</list>
		</property>
	</bean>
		
	  <!-- 資料來源  阿里巴巴出品  druid   -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
		<property name="initialSize" value="${jdbc.initialSize}"></property>
		<property name="maxActive" value="${jdbc.maxActive}"></property>
		<property name="minIdle" value="1"></property>
		<property name="maxWait" value="30000"></property>
		<property name="timeBetweenEvictionRunsMillis" value="60000"></property>
		<property name="minEvictableIdleTimeMillis" value="300000"></property>
		<property name="validationQuery" value="SELECT 1 "></property>
		<property name="testWhileIdle" value="true"></property>
		<property name="poolPreparedStatements" value="true"></property>
		<property name="maxPoolPreparedStatementPerConnectionSize" value="20"></property>
		<property name="filters" value="stat,slf4j" />
		<property name="proxyFilters">
			<list>
				<ref bean="stat-filter" />
				<ref bean="log-filter" />
			</list>
		</property>
	</bean>
	
	<bean id="log-filter" class="com.alibaba.druid.filter.logging.Slf4jLogFilter">
		<property name="resultSetLogEnabled" value="true" />
		<property name="statementExecutableSqlLogEnable" value="true" />
	</bean>

	<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter">
		<property name="slowSqlMillis" value="30000" />
		<property name="logSlowSql" value="true" />
		<property name="mergeSql" value="true" />
	</bean>
	<!-- 事務管理-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	 <!-- 攔截器方式配置事物,方法命名記得要規範 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="select*" read-only="true" propagation="REQUIRED"/>
			<tx:method name="find*" read-only="true" propagation="REQUIRED"/>
			<tx:method name="query*" read-only="true" propagation="REQUIRED"/>
			<tx:method name="get*" read-only="true" propagation="REQUIRED"/>
			<tx:method name="search*" read-only="true" propagation="REQUIRED"/>
			<tx:method name="is*" read-only="true" propagation="REQUIRED"/>
			<tx:method name="save*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="create*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="update*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="execute*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="remove*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="put*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="import*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="submit*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="cancel*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="send*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="edit*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="handle*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="close*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
			<tx:method name="export*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
		</tx:attributes>
	</tx:advice>
	
	<aop:config>
		<aop:pointcut id="transactionPointcut"
			expression="execution(* com.test..*ServiceImpl.*(..))" />
		<aop:advisor pointcut-ref="transactionPointcut" advice-ref="txAdvice" />
	</aop:config>
</beans>

        此處的Spring宣告式事務管理配置是上一篇具體應用,有興趣的可以深入理解下AOP: Spring AOP是什麼?你都拿它做什麼?

      2.4  建立spring-common-context.xml自動掃描