dubbo+zookeeper+springmvc
一、Dubbo是一個分散式服務框架,解決了上面的所面對的問題,Dubbo的架構如圖所示:
節點角色說明:
Provider: 暴露服務的服務提供方。
Consumer: 呼叫遠端服務的服務消費方。
Registry: 服務註冊與發現的註冊中心。
Monitor: 統計服務的呼叫次調和呼叫時間的監控中心。
Container: 服務執行容器。
二、呼叫關係說明:
0. 服務容器負責啟動,載入,執行服務提供者。
1. 服務提供者在啟動時,向註冊中心註冊自己提供的服務。
2. 服務消費者在啟動時,向註冊中心訂閱自己所需的服務。
3. 註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連線推送變更資料給消費者。
4. 服務消費者,從提供者地址列表中,基於軟負載均衡演算法,選一臺提供者進行呼叫,如果呼叫失敗,再選另一臺呼叫。
5. 服務消費者和提供者,在記憶體中累計呼叫次數和呼叫時間,定時每分鐘傳送一次統計資料到監控中心。
三、Dubbo與Zookeeper、SpringMVC整合使用
第一步:在Linux上安裝Zookeeper
Zookeeper作為Dubbo服務的註冊中心,Dubbo原先基於資料庫的註冊中心,沒采用Zookeeper,Zookeeper一個分散式的服務框架,是樹型的目錄服務的資料儲存,能做到叢集管理資料 ,這裡能很好的作為Dubbo服務的註冊中心,Dubbo能與Zookeeper做到叢集部署,當提供者出現斷電等異常停機時,Zookeeper註冊中心能自動刪除提供者資訊,當提供者重啟時,能自動恢復註冊資料,以及訂閱請求。
1)下載Zookeeper-3.4.6.tar.gz 地址http://www.apache.org/dist/zookeeper/
(2)我們放到Linux下的一個資料夾,然後解壓:
#tar zxvf zookeeper-3.4.6.tar.gz
(3)然後在對應的zookeeper-3.4.6/conf 下有一個檔案zoo_sample.cfg的這個檔案裡面配置了監聽客戶端連線的埠等一些資訊,Zookeeper 在啟動時會找zoo.cfg這個檔案作為預設配置檔案,所以我們複製一個名稱為zoo.cfg的檔案,如圖所示:
說明:
clientPort:監聽客戶端連線的埠。
tickTime:基本事件單元,以毫秒為單位。它用來控制心跳和超時,預設情況下最小的會話超時時間為兩倍的 tickTime。
我們可以對配置檔案的埠等或者進行高階配置和叢集配置例如:maxClientCnxns:限制連線到 ZooKeeper 的客戶端的數量等
(4)啟動Zookeeper 的服務
Zookeeper的安裝和配置完成
第二步:配置dubbo-admin的管理頁面,方便我們管理頁面
(1)下載dubbo-admin-2.4.1.war包,在Linux的tomcat部署,先把dubbo-admin-2.4.1放在tomcat的webapps/ROOT下,然後進行解壓:
#jar -xvf dubbo-admin-2.4.1.war
(2)然後到webapps/ROOT/WEB-INF下,有一個dubbo.properties檔案,裡面指向Zookeeper ,使用的是Zookeeper 的註冊中心
(3)然後啟動tomcat服務,使用者名稱和密碼:root,並訪問服務,顯示登陸頁面,說明dubbo-admin部署成功,如圖所示:
第三步、建立提供者provider工程(使用maven構建)
dubbo.provider專案結構如下圖:
匯入依賴,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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.soecode</groupId>
<artifactId>dubbo.provider</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>dubbo.provider Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<!-- Logger日誌 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.4.10</version>
</dependency>
<!-- zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.3.4</version>
</dependency>
<!-- zkclient 用於訪問zookeeper -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.3</version>
</dependency>
</dependencies>
<build>
<finalName>dubbo.provider</finalName>
</build>
</project>
在service包下建立介面HelloService.java
public interface HelloService {
/**
* say hello
* @param name
* @return
*/
public String sayHello(String name);
}
在Service.impl下實現介面HelloServiceImpl.java
@Service("helloServiceImpl")
public class HelloServiceImpl implements HelloService {
public String sayHello(String name) {
return "hello,"+name+"!";
}
}
接下來填寫dubbo-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: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.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 註解包掃描位置: 因為這裡的實現類使用註解的方式 -->
<context:component-scan base-package="com.soecode.dubbo.*" />
<!-- 接入dubbo的應用程式名稱 -->
<dubbo:application name="demo-provider" />
<!-- 註冊倉庫地址:zookeeper元件,192.168.61.128:2181 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 用dubbo協議在20880埠暴露服務 -->
<dubbo:protocol name="dubbo" port="20880" />
<!--
宣告需要暴露的服務介面,
請注意ref屬性中指定的HelloService介面實現類,它並沒有在xml檔案中定義,而是使用註解的方式在class中定義
-->
<dubbo:service interface="com.soecode.dubbo.service.HelloService" ref="helloServiceImpl"/>
</beans>
到此服務介面已經定義好,接下來要通過main方法讀取配置檔案,來達到zookeeper服務註冊的效果。
建立ProviderApp.java
package com.soecode.dubbo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 服務提供者示例
* @author antgan
* @date 2017/1/12
*
*/
public class ProviderApp {
public static void main(String[] args) throws Exception {
//讀取配置檔案
new ClassPathXmlApplicationContext(new String[]{"dubbo-provider.xml"});
System.out.println("provider服務已註冊");
//使執行緒阻塞
System.in.read();
}
}
執行ProviderApp,即可。
如何校驗是否成功註冊?進入dubbo-admin,點選單欄上的提供者,如下圖就註冊成功了,成功暴露介面。
第四步、
建立消費者consumer專案
dubbo.consumer專案結構
引入依賴,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.soecode</groupId>
<artifactId>dubbo.consumer</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>dubbo.consumer Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<!-- log4j日誌 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.4.10</version>
</dependency>
<!-- zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.3.4</version>
</dependency>
<!-- zkclient -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.3</version>
</dependency>
<!-- 引用dubbo.provider -->
<dependency>
<groupId>com.soecode</groupId>
<artifactId>dubbo.provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- SpringMVC -->
<!-- spring web依賴 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<!--3: Servlet web 相關依賴 -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.4</version>
</dependency>
</dependencies>
<build>
<finalName>dubbo.consumer</finalName>
</build>
</project>
配置dubbo-consumer.xml,向zookeeper註冊介面
<?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="demo-consumer" />
<!-- 註冊倉庫地址:zookeeper元件,192.168.61.128:2181 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 引用的服務,那個interface一定是一個被引入到DUBBO倉庫的介面定義 -->
<dubbo:reference id="helloService" interface="com.soecode.dubbo.service.HelloService"/>
</beans>
建立ConsumerApp.java,執行測試
package com.soecode.dubbo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.soecode.dubbo.service.HelloService;
/**
* 消費者示例
* @author antgan
* @date 2017/1/12
*
*/
public class ConsumerApp {
public static void main(String[] args) throws Exception {
//讀取配置檔案
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"dubbo-consumer.xml"});
//獲取在zookeeper註冊的服務介面
HelloService helloService = (HelloService)context.getBean("helloService");
//呼叫介面
System.out.println("HelloService = " + helloService.sayHello("ant"));
//不讓控制檯消失,按任意鍵結束
System.in.read();
}
}
執行結果:
我們也可以在dubbo-admin上看一下,如下
至此,已經完成了第一部分,在main方法模擬呼叫遠端介面。
第五步、
consumer引入SpringMVC
在dubbo.consumer引入springMVC,pom.xml 新增以下jar包:
<!-- SpringMVC -->
<!-- spring web依賴 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<!--3: Servlet web 相關依賴 -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.4</version>
</dependency>
在resource資料夾下建立spring-web.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"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 配置SpringMVC -->
<!-- 1:開啟SpringMVC註解模式 -->
<!-- 簡化配置:
1)自動註冊DefaultAnnotationHandlerMapping,AnnotationMethodHandlerAdapter
2) 提供一系列:資料繫結,數字和日期的format等功能,支援xml,json讀寫-->
<mvc:annotation-driven/>
<!--2: 靜態資源配置
1) 加入靜態資源的處理,如js,gif,png
2)允許使用"/"處理
-->
<mvc:default-servlet-handler/>
<!-- 3: 配置jsp 顯示ViewResolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" /> <!-- 字首 -->
<property name="suffix" value=".jsp" /> <!-- 字尾 -->
</bean>
<!-- 4: 掃描web相關的bean -->
<context:component-scan base-package="com.soecode.dubbo.web"/>
</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>dubbo.consumer</display-name>
<!-- 載入dubbo-consumer.xml -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/dubbo-consumer.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置DispatcherServlet -->
<servlet>
<servlet-name>dubbo.consumer-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 載入spring-web.xml -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-web.xml</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dubbo.consumer-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
在dubbo.web包下建立HelloController.java
package com.soecode.dubbo.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.soecode.dubbo.service.HelloService;
@Controller
@RequestMapping("hello")
public class HelloController {
/**
* 注入遠端介面
*/
@Autowired
private HelloService helloService;
/**
* 呼叫遠端介面,返回index.jsp頁面
* @param model
* @return
*/
@RequestMapping("index")
public String index(Model model){
model.addAttribute("str", helloService.sayHello("ant"));
return "index";
}
}
執行,位址列輸入:http://localhost:8080/dubbo.consumer/hello/index