體系架構(gòu)
Dubbo是一個(gè)非常輕量級(jí)的分布式RPC框架脉课,它使用Spring進(jìn)行配置综看,而非注入式的編程方式,深受大家的喜愛苦银。粗淺的研究了一下其應(yīng)用,并使用Web容器(Jetty)實(shí)現(xiàn)了一個(gè)基于Dubbo的分布式系統(tǒng)杂彭,提供多種服務(wù)墓毒,并可以在多個(gè)服務(wù)源中進(jìn)行切換。這個(gè)Demo系統(tǒng)的參與者包括
- 服務(wù)的消費(fèi)者(Consumer)可以是多種形式亲怠,這里采用war包的方式放到Jetty服務(wù)器中所计。后臺(tái)由Spring容器進(jìn)行管理,以獲得服務(wù)的句柄团秽;前臺(tái)為了簡便主胧,使用最基本的Servlet來展現(xiàn)獲取的服務(wù)內(nèi)容叭首;
- 服務(wù)的提供者(Provider)同樣可以采用多種形式,這里也同樣采用war包方式放到Jetty服務(wù)器中踪栋,并由Spring容器進(jìn)行管理焙格。系統(tǒng)可以有多個(gè)Provider,這就需要多個(gè)Jetty環(huán)境夷都,并在注冊(cè)中心注冊(cè)眷唉;
- 服務(wù)注冊(cè)中心(Registry)用于管理所有的服務(wù),Consumer和Provider都需要在配置中指明注冊(cè)中心地址囤官。Registry可以使用Redis和Zookeeper實(shí)現(xiàn)冬阳,本Demo使用后者。
- Dubbo實(shí)現(xiàn)的監(jiān)控中心(Monitor)和服務(wù)治理程序(Admin)用于監(jiān)控系統(tǒng)的使用情況和性能党饮,同時(shí)在多個(gè)提供者的情況下肝陪,提供服務(wù)治理功能,例如權(quán)重刑顺,生效/失效設(shè)置等氯窍。
下圖描述了整個(gè)體系架構(gòu)。
API的定義
API是Java接口定義的約定Consumer和Provider都可以使用的函數(shù)列表蹲堂。Consumer通過API了解Service能夠提供的服務(wù)狼讨;Provider提供服務(wù)的實(shí)現(xiàn)。其中
- Service.java只是一個(gè)空接口贯城,所有的服務(wù)都繼承自這個(gè)接口熊楼。
public interface Service { }
- DateService.java提供一個(gè)關(guān)于日期的服務(wù),調(diào)用后返回一個(gè)當(dāng)前的日期能犯。
public interface DateService extends Service { public DateServiceResult getCurrentDate(); }
- MathService.java提供一個(gè)關(guān)于數(shù)字的服務(wù),調(diào)用后返回一個(gè)排序的數(shù)組(相對(duì)于參數(shù))犬耻。
public interface MathService extends Service { public NumberServiceResult sort(int[] numbers); }
- StringService.java提供一個(gè)關(guān)于字符串的服務(wù)踩晶,調(diào)用后返回一個(gè)翻轉(zhuǎn)的字符串(相對(duì)于參數(shù))。
public interface StringService extends Service { public StringServiceResult reverse(String str); }
API作為一個(gè)獨(dú)立的枕磁,純的Java的jar包發(fā)布給Consumer使用渡蜻。
服務(wù)的消費(fèi)者
為了簡單起見,這里只將服務(wù)的Consumer作為基本的Servlet來處理计济。如果Servlet可以走通茸苇,應(yīng)用到JSP,或是JSF環(huán)境中都水到渠成沦寂。Consumer中最重要的是獲取服務(wù)的句柄学密,因?yàn)橛捎谟蠥PI的存在,在靜態(tài)編程中传藏,是很簡單的腻暮,且沒有技術(shù)難度彤守。獲取句柄的代碼在init方法中,如下所示
@Override public void init() throws ServletException { super.init(); ServletContext servletContext = this.getServletContext(); WebApplicationContext ctx = WebApplicationContextUtils .getWebApplicationContext(servletContext); dateService = (DateService) ctx.getBean("dateService"); }
顯而易見哭靖,我們通過Spring容器獲得真實(shí)的對(duì)象(由Provider實(shí)現(xiàn))具垫,并從對(duì)象的調(diào)用結(jié)果中獲取我們需要的內(nèi)容。
服務(wù)的提供者
服務(wù)的Provider是比較簡單的试幽,只需要實(shí)現(xiàn)API所定義的方法即可筝蚕,這里就不列舉了。但為了將這個(gè)實(shí)現(xiàn)加載到Dubbo的系統(tǒng)中铺坞,也需要Spring容器饰及,并打成War包發(fā)布到Jetty中。
Spring容器的配置
web.xml
web.xml的配置對(duì)于Consumer和Provider都是一樣的康震,即定義Spring容器燎含,如下所示
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/classes/applicationContext*.xml</param-value> </context-param>
作為Consumer,還要定義Servlet的映射腿短,不再贅述屏箍。
Consumer
<dubbo:application name="dubbo-evaluation-consumer" /> <dubbo:registry address="zookeeper://10.16.2.46:2181" /> <dubbo:monitor protocol="registry" /> <dubbo:reference id="stringService" interface="com.synnex.dubboevaluation.service.StringService" /> <dubbo:reference id="mathService" interface="com.synnex.dubboevaluation.service.MathService" /> <dubbo:reference id="dateService" interface="com.synnex.dubboevaluation.service.DateService" />
對(duì)于Consumer,比較重要的是
- 使用 dubbo:registry 聲明注冊(cè)中心橘忱;
- 使用 dubbo:reference 聲明接口赴魁。
Provider
<dubbo:application name="dubbo-evaluation-provider" /> <dubbo:registry address="zookeeper://10.16.2.46:2181" /> <dubbo:protocol name="dubbo" port="20880" /> <dubbo:monitor protocol="registry"/> <dubbo:service interface="com.synnex.dubboevaluation.service.StringService" ref="stringService" /> <bean id="stringService" class="com.synnex.dubboevaluation.service.StringServiceImpl" /> <dubbo:service interface="com.synnex.dubboevaluation.service.MathService" ref="mathService" /> <bean id="mathService" class="com.synnex.dubboevaluation.service.MathServiceImpl" /> <dubbo:service interface="com.synnex.dubboevaluation.service.DateService" ref="dateService" /> <bean id="dateService" class="com.synnex.dubboevaluation.service.DateServiceImpl" />
對(duì)于Provider,比較重要的是
- 使用 dubbo:registry 聲明注冊(cè)中心钝诚;
- 使用 dubbo:service 聲明服務(wù)颖御;
- 使用 bean id="xxxService" 聲明服務(wù)的實(shí)現(xiàn)。