基於Dubbo框架構建分佈式服務【續】

上面調用了DubboServer類的靜態方法startServer,如下所示:

01 public static void startServer(String config) {
02      ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config);
03      try {
04           context.start();
05           System.in.read();
06      catch (IOException e) {
07           e.printStackTrace();
08      finally {
09           context.close();
10      }
11 }

方法中主要是初始化Spring IoC容器,全部對象都交由容器來管理。

  • 服務消費方

服務消費方就容易了,只需要知道註冊中心地址,並引用服務提供方提供的接口,消費方調用服務實現如下所示:

01 package org.shirdrn.dubbo.consumer;
02  
03 import java.util.Arrays;
04 import java.util.List;
05  
06 import org.apache.commons.logging.Log;
07 import org.apache.commons.logging.LogFactory;
08 import org.shirdrn.dubbo.api.ChatRoomOnlineUserCounterService;
09 import org.springframework.context.support.AbstractXmlApplicationContext;
10 import org.springframework.context.support.ClassPathXmlApplicationContext;
11  
12 public class ChatRoomDubboConsumer {
13  
14      private static final Log LOG = LogFactory.getLog(ChatRoomDubboConsumer.class);
15      
16      public static void main(String[] args) throws Exception {
17           AbstractXmlApplicationContext context = newClassPathXmlApplicationContext("classpath:consumer.xml");
18           try {
19                context.start();
20                ChatRoomOnlineUserCounterService chatRoomOnlineUserCounterService = (ChatRoomOnlineUserCounterService) context.getBean("chatRoomOnlineUserCounterService");        
21                getMaxOnlineUserCount(chatRoomOnlineUserCounterService);             
22                getRealtimeOnlineUserCount(chatRoomOnlineUserCounterService);             
23                System.in.read();
24           finally {
25                context.close();
26           }
27           
28      }
29  
30      private static void getMaxOnlineUserCount(ChatRoomOnlineUserCounterService liveRoomOnlineUserCountService) {
31           List<String> maxUserCounts = liveRoomOnlineUserCountService.getMaxOnlineUserCount(
32                     Arrays.asList(new String[] {"1482178010" "1408492761""1430546839","1412517075""1435861734"}), "20150327""yyyyMMdd");
33           LOG.info("After getMaxOnlineUserCount invoked: maxUserCounts= " + maxUserCounts);
34      }
35  
36      private static void getRealtimeOnlineUserCount(ChatRoomOnlineUserCounterService liveRoomOnlineUserCountService)
37                throws InterruptedException {
38           String rooms = "1482178010,1408492761,1430546839,1412517075,1435861734";
39           String onlineUserCounts = liveRoomOnlineUserCountService.queryRoomUserCount(rooms);
40           LOG.info("After queryRoomUserCount invoked: onlineUserCounts= " + onlineUserCounts);
41      }
42 }

對應的配置文件爲consumer.xml,內容如下所示:

01 <?xml version="1.0" encoding="UTF-8"?>
02  
07  
08      <dubbo:application name="chatroom-consumer" />
09      <dubbo:registry address="zookeeper://zk1:2181?backup=zk2:2181,zk3:2181" />
10      
11      <dubbo:reference id="chatRoomOnlineUserCounterService"interface="org.shirdrn.dubbo.api.ChatRoomOnlineUserCounterService" version="1.0.0">
12           <dubbo:method name="queryRoomUserCount" retries="2" />
13      </dubbo:reference>
14  
15 </beans>

也可以根據需要配置dubbo:reference相關的屬性值,也可以配置dubbo:method指定調用的方法的配置信息,詳細配置屬性可以參考Dubbo官方文檔。

  • 部署與驗證

開發完成提供方服務後,在本地開發調試的時候可以怎麼簡單怎麼做,如果是要部署到生產環境,則需要打包後進行部署,可以參考下面的Maven POM配置:

01 <build>
02      <plugins>
03           <plugin>
04                <groupId>org.apache.maven.plugins</groupId>
05                <artifactId>maven-shade-plugin</artifactId>
06                <version>1.4</version>
07                <configuration>
08                     <createDependencyReducedPom>true</createDependencyReducedPom>
09                </configuration>
10                <executions>
11                     <execution>
12                          <phase>package</phase>
13                          <goals>
14                               <goal>shade</goal>
15                          </goals>
16                          <configuration>
17                               <transformers>
18                                    <transformerimplementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
19                                    <transformerimplementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
20                                         <mainClass>org.shirdrn.dubbo.provider.ChatRoomClusterServer</mainClass>
21                                    </transformer>
22                               </transformers>
23                          </configuration>
24                     </execution>
25                </executions>
26           </plugin>
27      </plugins>
28 </build>

這裏也給出Maven POM依賴的簡單配置:

1 <dependencies>
2      <dependency>
3           <groupId>org.shirdrn.dubbo</groupId>
4           <artifactId>dubbo-api</artifactId>
5           <version>0.0.1-SNAPSHOT</version>
6      </dependency>
7 </dependencies>

我們開發的服務應該是分佈式的,首先是通過配置內容來決定,例如設置集羣模式、設置負載均衡模式等,然後在部署的時候,可以在多個節點上同一個服務,這樣多個服務都會註冊到Dubbo註冊中心,如果某個節點上的服務不可用了,可以根據我們配置的策略來選擇其他節點上的可用服務,後面通過Dubbo服務管理中心和監控中心就能更加清楚明瞭。

Dubbo服務管理與監控

我們需要在安裝好管理中心和監控中心以後,再將上面的開發的提供方服務部署到物理節點上,然後就能夠通過管理中心和監控中心來查看對應的詳細情況。

  • Dubbo服務管理中心

安裝Dubbo服務管理中心,需要選擇一個Web容器,我們使用Tomcat服務器。首先下載Dubbo管理中心安裝文件dubbo-admin-2.5.3.war,或者直接從源碼構建得到該WAR文件。這裏,我們已經構建好對應的WAR文件,然後進行安裝,執行如下命令:

1 cd apache-tomcat-6.0.35
2 rm -rf webapps/ROOT
3 unzip ~/dubbo-admin-2.5.3.war -d webapps/ROOT

修改配置文件~/apache-tomcat-6.0.35/webapps/ROOT/WEB-INF/dubbo.properties,指定我們的註冊中心地址以及登錄密碼,內容如下所示:

1 dubbo.registry.address=zookeeper://zk1:2181?backup=zk2:2181,zk3:2181
2 dubbo.admin.root.password=root
3 dubbo.admin.guest.password=guest

然後,根據需要修改~/apache-tomcat-6.0.35/conf/server.xml配置文件,主要是Tomcat HTTP 端口號(我這裏使用8083端口),完成後可以直接啓動Tomcat服務器:

1 cd ~/apache-tomcat-6.0.35/
2 bin/catalina.sh start

然後訪問地址http://10.10.4.130:8083/即可,根據配置文件指定的root用戶密碼,就可以登錄Dubbo管理控制檯。
我們將上面開發的服務提供方服務,部署到2個獨立的節點上(192.168.14.1和10.10.4.125),然後可以通過Dubbo管理中心查看對應服務的狀況,如圖所示:
dubbo-admin-providers
上圖中可以看出,該服務有兩個獨立的節點可以提供,因爲配置的集羣模式爲failover,如果某個節點的服務發生故障無法使用,則會自動透明地重試另一個節點上的服務,這樣就不至於出現拒絕服務的情況。如果想要查看提供方某個節點上的服務詳情,可以點擊對應的IP:Port鏈接,示例如圖所示:
dubbo-admin-providers-detail
上圖可以看到服務地址:

1 dubbo://10.10.4.125:20880/org.shirdrn.dubbo.api.ChatRoomOnlineUserCounterService?actives=100&anyhost=true&application=chatroom-cluster-provider&cluster=failover&dubbo=0.0.1-SNAPSHOT&executes=200&interface=org.shirdrn.dubbo.api.ChatRoomOnlineUserCounterService&loadbalance=random&methods=getMaxOnlineUserCount,queryRoomUserCount&pid=30942&queryRoomUserCount.actives=50&queryRoomUserCount.loadbalance=leastactive&queryRoomUserCount.retries=2&queryRoomUserCount.timeout=500&retries=2&revision=0.0.1-SNAPSHOT&side=provider&timeout=1000×tamp=1427793652814&version=1.0.0

如果我們直接暴露該地址也是可以的,不過這種直連的方式對服務消費方不是透明的,如果以後IP地址更換,也會影響調用方,所以最好是通過註冊中心來隱蔽服務地址。同一個服務所部署在的多個節點上,也就對應對應着多個服務地址。另外,也可以對已經發布的服務進行控制,如修改訪問控制、負載均衡相關配置內容等,可以通過上圖中“消費者”查看服務消費方調用服務的情況,如圖所示:
dubbo-admin-consumers
也在管理控制檯可以對消費方進行管理控制。

  • Dubbo監控中心

Dubbo監控中心是以Dubbo服務的形式發佈到註冊中心,和普通的服務時一樣的。例如,我這裏下載了Dubbo自帶的簡易監控中心文件dubbo-monitor-simple-2.5.3-assembly.tar.gz,可以解壓縮以後,修改配置文件~/dubbo-monitor-simple-2.5.3/conf/dubbo.properties的內容,如下所示:

01 dubbo.container=log4j,spring,registry,jetty
02 dubbo.application.name=simple-monitor
03 dubbo.application.owner=
04 dubbo.registry.address=zookeeper://zk1:2181?backup=zk2:2181,zk3:2181
05 dubbo.protocol.port=7070
06 dubbo.jetty.port=8087
07 dubbo.jetty.directory=${user.home}/monitor
08 dubbo.charts.directory=${dubbo.jetty.directory}/charts
09 dubbo.statistics.directory=${user.home}/monitor/statistics
10 dubbo.log4j.file=logs/dubbo-monitor-simple.log
11 dubbo.log4j.level=WARN

然後啓動簡易監控中心,執行如下命令:

1 cd ~/dubbo-monitor-simple-2.5.3
2 bin/start.sh

這裏使用了Jetty Web容器,訪問地址http://10.10.4.130:8087/就可以查看監控中心,Applications選項卡頁面包含了服務提供方和消費方的基本信息,如圖所示:
dubbo-monitor-applications
上圖主要列出了所有提供方發佈的服務、消費方調用、服務依賴關係等內容。
接着,查看Services選項卡頁面,包含了服務提供方提供的服務列表,如圖所示:
dubbo-monitor-services
點擊上圖中Providers鏈接就能看到服務提供方的基本信息,包括服務地址等,如圖所示:
dubbo-monitor-providers
點擊上圖中Consumers鏈接就能看到服務消費方的基本信息,包括服務地址等,如圖所示:
dubbo-monitor-consumers
由於上面是Dubbo自帶的一個簡易監控中心,可能所展現的內容並不能滿足我們的需要,所以可以根據需要開發自己的監控中心。Dubbo也提供了監控中心的擴展接口,如果想要實現自己的監控中心,可以實現接口com.alibaba.dubbo.monitor.MonitorFactory和com.alibaba.dubbo.monitor.Monitor,其中MonitorFactory接口定義如下所示:

01 /**
02 * MonitorFactory. (SPI, Singleton, ThreadSafe)
03 *
04 * @author william.liangf
05 */
06 @SPI("dubbo")
07 public interface MonitorFactory {
08     
09     /**
10      * Create monitor.
11      * @param url
12      * @return monitor
13      */
14     @Adaptive("protocol")
15     Monitor getMonitor(URL url);
16  
17 }

Monitor接口定義如下所示:

1 /**
2 * Monitor. (SPI, Prototype, ThreadSafe)
3 *
4 * @see com.alibaba.dubbo.monitor.MonitorFactory#getMonitor(com.alibaba.dubbo.common.URL)
5 * @author william.liangf
6 */
7 public interface Monitor extends Node, MonitorService {
8  
9 }

具體定義內容可以查看MonitorService接口,不再累述。

總結

Dubbo還提供了其他很多高級特性,如路由規則、參數回調、服務分組、服務降級等等,而且很多特性在給出內置實現的基礎上,還給出了擴展的接口,我們可以給出自定義的實現,非常方便而且強大。更多可以參考Dubbo官網用戶手冊和開發手冊。

附錄:Dubbo使用Maven構建依賴配置

01 <properties>
02     <spring.version>3.2.8.RELEASE</spring.version>
03     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
04 </properties>
05  
06 <dependencies>
07     <dependency>
08         <groupId>com.alibaba</groupId>
09         <artifactId>dubbo</artifactId>
10         <version>2.5.3</version>
11         <exclusions>
12             <exclusion>
13                 <groupId>org.springframework</groupId>
14                 <artifactId>spring</artifactId>
15             </exclusion>
16             <exclusion>
17                 <groupId>org.apache.zookeeper</groupId>
18                 <artifactId>zookeeper</artifactId>
19             </exclusion>
20             <exclusion>
21                 <groupId>org.jboss.netty</groupId>
22                 <artifactId>netty</artifactId>
23             </exclusion>
24         </exclusions>
25     </dependency>
26     <dependency>
27         <groupId>org.springframework</groupId>
28         <artifactId>spring-core</artifactId>
29         <version>${spring.version}</version>
30     </dependency>
31     <dependency>
32         <groupId>org.springframework</groupId>
33         <artifactId>spring-beans</artifactId>
34         <version>${spring.version}</version>
35     </dependency>
36     <dependency>
37         <groupId>org.springframework</groupId>
38         <artifactId>spring-context</artifactId>
39         <version>${spring.version}</version>
40     </dependency>
41     <dependency>
42         <groupId>org.springframework</groupId>
43         <artifactId>spring-context-support</artifactId>
44         <version>${spring.version}</version>
45     </dependency>
46     <dependency>
47         <groupId>org.springframework</groupId>
48         <artifactId>spring-web</artifactId>
49         <version>${spring.version}</version>
50     </dependency>
51  
52     <dependency>
53         <groupId>org.slf4j</groupId>
54         <artifactId>slf4j-api</artifactId>
55         <version>1.6.2</version>
56     </dependency>
57     <dependency>
58         <groupId>log4j</groupId>
59         <artifactId>log4j</artifactId>
60         <version>1.2.16</version>
61     </dependency>
62     <dependency>
63         <groupId>org.javassist</groupId>
64         <artifactId>javassist</artifactId>
65         <version>3.15.0-GA</version>
66     </dependency>
67     <dependency>
68         <groupId>com.alibaba</groupId>
69         <artifactId>hessian-lite</artifactId>
70         <version>3.2.1-fixed-2</version>
71     </dependency>
72     <dependency>
73         <groupId>com.alibaba</groupId>
74         <artifactId>fastjson</artifactId>
75         <version>1.1.8</version>
76     </dependency>
77     <dependency>
78         <groupId>org.jvnet.sorcerer</groupId>
79         <artifactId>sorcerer-javac</artifactId>
80         <version>0.8</version>
81     </dependency>
82     <dependency>
83         <groupId>org.apache.zookeeper</groupId>
84         <artifactId>zookeeper</artifactId>
85         <version>3.4.5</version>
86     </dependency>
87     <dependency>
88         <groupId>com.github.sgroschupf</groupId>
89         <artifactId>zkclient</artifactId>
90         <version>0.1</version>
91     </dependency>
92     <dependency>
93         <groupId>org.jboss.netty</groupId>
94         <artifactId>netty</artifactId>
95         <version>3.2.7.Final</version>
96     </dependency>
97 </dependencies>

參考鏈接

Creative Commons License

本文基於署名-非商業性使用-相同方式共享 4.0許可協議發佈,歡迎轉載、使用、重新發布,但務必保留文章署名時延軍(包含鏈接:http://shiyanjun.cn),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請與我聯繫

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章