-
內(nèi)容簡(jiǎn)介
此篇文章是介紹Dubbo以及它的簡(jiǎn)單使用,會(huì)列舉運(yùn)用spring boot + dubbo搭建項(xiàng)目運(yùn)用dubbo的步驟,主要是介紹一下dubbo的作用以及簡(jiǎn)單的配置,若有興趣的朋友可以繼續(xù)關(guān)注后續(xù)的dubbo系列文章,也可以參考官方文檔進(jìn)行學(xué)習(xí).個(gè)人的一點(diǎn)心得和想法,有錯(cuò)誤還請(qǐng)指正。
-
Dubbo介紹
1.什么是Dubbo
一個(gè)分布式服務(wù)治理框架
2.為什么用Dubbo
- 官方介紹
當(dāng)垂直應(yīng)用越來越多,應(yīng)用之間交互不可避免,將核心業(yè)務(wù)抽取出來,作為獨(dú)立的服務(wù),逐漸形成穩(wěn)定的服務(wù)中心,使前端應(yīng)用能更快速的響應(yīng)多變的市場(chǎng)需求。 此時(shí),用于提高業(yè)務(wù)復(fù)用及整合的分布式服務(wù)框架(RPC)是關(guān)鍵。
- 自我心得
小項(xiàng)目中dubbo作用不明顯,因?yàn)轫?xiàng)目中的Api都是通過直接依賴調(diào)用,當(dāng)項(xiàng)目龐大比并且服務(wù)需要多次重復(fù)性的調(diào)用時(shí),就需要一個(gè)框架來治理,dubbo可以做到的效果就是通多xml文件配置,達(dá)到一次提供,到處調(diào)用的效果,并且和可以對(duì)服務(wù)的提供者和消費(fèi)者進(jìn)行管理;就是將提供服務(wù)的Api打包到服務(wù)器,同時(shí)注冊(cè)到注冊(cè)中心(zookeeper),需要調(diào)用此服務(wù)的只需依賴服務(wù)器上的jar包,配置消費(fèi)者服務(wù)即可調(diào)用Api。
3.基本概念
- 節(jié)點(diǎn)角色說明
dubbo-node> - provider 服務(wù)的提供方 - consumer 服用的消費(fèi)方 - registry 注冊(cè)中心(可以對(duì)提供方和消費(fèi)方統(tǒng)一管理) - monitor 統(tǒng)計(jì)中心 - container 運(yùn)行容器
-
調(diào)用關(guān)系說明:
- 服務(wù)容器負(fù)責(zé)啟動(dòng),加載,運(yùn)行服務(wù)提供者。
- 服務(wù)提供者在啟動(dòng)時(shí),向注冊(cè)中心注冊(cè)自己提供的服務(wù)。
- 服務(wù)消費(fèi)者在啟動(dòng)時(shí),向注冊(cè)中心訂閱自己所需的服務(wù)。
- 注冊(cè)中心返回服務(wù)提供者地址列表給消費(fèi)者,如果有變更,注冊(cè)中心將基于長(zhǎng)連接推送變更數(shù)據(jù)給消費(fèi)者。
- 服務(wù)消費(fèi)者,從提供者地址列表中,基于軟負(fù)載均衡算法,選一臺(tái)提供者進(jìn)行調(diào)用,如果調(diào)用失敗,再選另一臺(tái)調(diào)用。
- 服務(wù)消費(fèi)者和提供者,在內(nèi)存中累計(jì)調(diào)用次數(shù)和調(diào)用時(shí)間,定時(shí)每分鐘發(fā)送一次統(tǒng)計(jì)數(shù)據(jù)到監(jiān)控中心。
-
dubbo-provider搭建(Simple)
1.準(zhǔn)備工作
為了更加直觀的體現(xiàn)dubbo的作用,在此我會(huì)搭建一個(gè)簡(jiǎn)單的maven項(xiàng)目,通過項(xiàng)目的搭建流程和dubbo的相關(guān)簡(jiǎn)單配置,介紹dubbo的使用,所以,需要做好以下最基本的準(zhǔn)備工作:
- JDK(1.8)
- 開發(fā)工具(IDEA)
- maven(3.3.9)
- zookepper(注冊(cè)中心)
2.項(xiàng)目結(jié)構(gòu)
為了后續(xù)代碼更好的演示,將兩個(gè)項(xiàng)目建立在一個(gè)工作空間下(IDEA),創(chuàng)建簡(jiǎn)單的接口和實(shí)現(xiàn)類,簡(jiǎn)單的測(cè)試方法,基本結(jié)構(gòu)為:
dubbo-project- 接口基本實(shí)現(xiàn)為:
public interface ISimpleService { public String sayHello(String name); } @Service public class SimpleServiceImpl implements ISimpleService { public String sayHello(String name) { return "Hello" + name; } }
3.spring boot配置
- 配置項(xiàng)目的pom文件,搭建spring boot運(yùn)行環(huán)境,這里給出一個(gè)基本的模板,其中包含mysql的依賴,以及使用基本dubbo的依賴,還有注冊(cè)中心zookeeper的相關(guān)依賴,可以根據(jù)實(shí)際情況修改:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.2.8.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <artifactId>logback-classic</artifactId> <groupId>ch.qos.logback</groupId> </exclusion> <exclusion> <artifactId>log4j-over-slf4j</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--dubbo--> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.8.4</version> </dependency> <!--zookeeper 相關(guān)--> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.8</version> </dependency> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <!-- Import dependency management from Spring Boot --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>1.2.8.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <repositories> <repository> <id>public</id> <name>nexus-repository</name> <url>http://192.168.1.169:8080/nexus/content/groups/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>release</id> <name>nexus-repository</name> <url>http://192.168.1.169:8080/nexus/content/repositories/releases</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>nexus</id> <name>nexus-repository</name> <url>http://192.168.1.169:8080/nexus/content/groups/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
- 配置完pom文件后還需要配置application.xml(spring默認(rèn)加載的配置文件,根目錄下即可,也可以自己修改配置文件制定),由于spring boot默認(rèn)會(huì)配置jdbcTemplate,所以需要指定一個(gè)dataSourcec(也可通過配置修改,不多說):
# 制定spring boot運(yùn)行的端口 server.port=8899 #db properties 需要指定一個(gè)datasource spring.datasource.url=xxx spring.datasource.username=xxx spring.datasource.password=xxx spring.datasource.driver-class-name=com.mysql.jdbc.Driver
4.dubbo配置
- 隨后配置simple-dubbo-provider.xml,此處我們做最簡(jiǎn)單的配置:
<?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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!--提供的服務(wù)名稱 自己指定即可 代表你提供的這個(gè)服務(wù)--> <dubbo:application name="simpleprovider"></dubbo:application> <!--注冊(cè)中心 本地啟動(dòng)zookeeper后默認(rèn)的ip+port--> <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> <!--協(xié)議 port自己指定--> <dubbo:protocol name="dubbo" port="8899"></dubbo:protocol> <!--提供的接口服務(wù)--> <dubbo:service ref="simpleServiceImpl" interface="cn.littledragon.dubbo.service.ISimpleService"></dubbo:service>
5.運(yùn)行函數(shù)
- 最后可以配置日志文件進(jìn)行,進(jìn)行日志記錄,隨后編寫main函數(shù)運(yùn)行項(xiàng)目,運(yùn)用spring boot中寫好的main方法,加以修改:
@SpringBootApplication @ComponentScan("cn.littledragon") // @MapperScan(basePackages = "com.tdh.swaptrailer.comm.dal.mapper") @ImportResource("simple-dubbo-spring.xml") public class Application { public static final String CONTAINER_KEY = "dubbo.container"; public static final String SHUTDOWN_HOOK_KEY = "dubbo.shutdown.hook"; private static final Logger LOGGER = LoggerFactory.getLogger(Application.class); private static final ExtensionLoader<Container> LOADER = ExtensionLoader.getExtensionLoader(Container.class); private static volatile boolean running = true; protected static void keepRunning(String[] args) { try { if (args == null || args.length == 0) { String config = ConfigUtils.getProperty(CONTAINER_KEY, LOADER.getDefaultExtensionName()); args = Constants.COMMA_SPLIT_PATTERN.split(config); } final List<Container> containers = new ArrayList<Container>(); for (int i = 0; i < args.length; i++) { containers.add(LOADER.getExtension(args[i])); } LOGGER.info("Use container type(" + Arrays.toString(args) + ") to run dubbo serivce."); if ("true".equals(System.getProperty(SHUTDOWN_HOOK_KEY))) { Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { for (Container container : containers) { try { container.stop(); LOGGER.info("Dubbo " + container.getClass().getSimpleName() + " stopped!"); } catch (Exception t) { LOGGER.error(t.getMessage(), t); } synchronized (Application.class) { running = false; Application.class.notify(); } } } }); } for (Container container : containers) { container.start(); LOGGER.info("Dubbo " + container.getClass().getSimpleName() + " started!"); } LOGGER.info(new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]").format(new Date()) + " Dubbo service server started!"); } catch (RuntimeException e) { LOGGER.error(e.getMessage(), e); } synchronized (Application.class) { while (running) { try { Application.class.wait(); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } } } } public static void main(String[] args) throws Exception { // SpringApplication.run(Application.class, args); SpringApplication app = new SpringApplication(Application.class); app.setWebEnvironment(false); app.run(args); keepRunning(args); } }
-
dubbo-consumer搭建
-
準(zhǔn)備工作
在dubbo-provider相同目錄下創(chuàng)建dubbo-consumer項(xiàng)目,二者處于同一目錄下同一等級(jí)
-
spring boot配置
步驟與dubbo-provider相同,此處多一個(gè)步驟就是需要將別人提供的服務(wù)(也就是需要使用、消費(fèi)的服務(wù))引入進(jìn)來:
<dependency> <groupId>cn.littledragon</groupId> <artifactId>dubbo.provider</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
-
dubbo配置
隨后配置simple-dubbo-provider.xml,此處我們做最簡(jiǎn)單的配置:
<dubbo:application name="simpleprovider"></dubbo:application> <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> <dubbo:reference interface="cn.littledragon.dubbo.service.ISimpleService" id="simpleService"/>
-
運(yùn)行函數(shù)
Application.java也與dubbo-provider相同即可
-
測(cè)試函數(shù)
編寫測(cè)試類,測(cè)試服務(wù)使用情況
public class ConsumerTest { public static void main(String[] args){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"simple-dubbo-spring.xml"}); context.start(); ISimpleService simpleService = (ISimpleService)context.getBean("simpleService"); System.out.println(simpleService.sayHello(" littledragon ...")); }}
-
-
運(yùn)行效果
- 首先本地運(yùn)行zookepper
- 運(yùn)行dubbo-provider項(xiàng)目的Application.main(),打印dubbo started即可
- 運(yùn)行dubbo-consumer項(xiàng)目的Application.main(),打印dubbo started即可
- 運(yùn)行測(cè)試函數(shù).main(),可以看到輸出結(jié)果:
hello littledragon ...
-
結(jié)語
通過這個(gè)例子可以看出,我們?cè)谕ㄟ^提供方提供服務(wù)到注冊(cè)中心,消費(fèi)方通過配置到注冊(cè)中心上取到該服務(wù),再進(jìn)行消費(fèi)(調(diào)用),即可達(dá)到不同項(xiàng)目之間的相互調(diào)用,也驗(yàn)證了分布式管理的意義,此處只是一個(gè)簡(jiǎn)單的小例子,在實(shí)際項(xiàng)目運(yùn)用中,這種模式加上這個(gè)框架的好處會(huì)更加明顯,后續(xù)也會(huì)給出關(guān)于dubbo其他更深入的運(yùn)用。
本文作者: little-dragon
個(gè)人博客: http://littledragon.cn
版權(quán)聲明: 原創(chuàng)文章,有問題請(qǐng)?jiān)u論中留言。非商業(yè)轉(zhuǎn)載請(qǐng)注明作者及出處。