dubbo學習筆記(3):快速搭建
搭建一個簡單的dubbo服務
參考地址:
dubbo官網:http://dubbo.apache.org/zh-cn/docs/user/references/registry/zookeeper.html
博客:http://www.cnblogs.com/lighten/p/6828026.html
以上兩個教程經實踐發現都有部分謬誤,本教程做了一定更正
1.簡介
dubbo是一個分布式服務框架,由阿裏巴巴的工程師開發,致力於提供高性能和透明化的RPC遠程服務調用。可惜的是該項目在2012年之後就沒有再更新了,之後由當當基於dubbo開發了dubbox。這裏對dubbo的入門構建進行簡單的介紹。不涉及dubbo的運行機制,只是搭建過程,方便學習者快速構建項目,運行、熟悉該框架。
dubbo提供了兩種構建項目的方法:
- 通過Spring容器快速構建,其中還有註解的方式;
- 通過直接使用API(不推薦)。以下對其一一說明。
2.spring配置的形式
1.導入maven依賴
<!--如果引入的是2.6.2以下版本,xml文件頭引入的xsd地址會報錯--> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.3</version> <exclusions> <exclusion> <!-- 排除傳遞spring依賴 --> <artifactId>spring</artifactId> <groupId>org.springframework</groupId> </exclusion> </exclusions> </dependency> <!--下面分別是兩種不同的zookeeper客戶端實現,選擇一種就好--> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.4</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.12.0</version> </dependency> <!--後期可能還會用到如下zookeeper客戶端jar包依賴,但是目前這個demo不引入也沒有問題--> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.3.3</version> </dependency> <!--spring配置方式,自然需要spring相關的依賴--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>3.2.17.RELEASE</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <!--打印日誌相關--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.4</version> </dependency>
zkclient和curator
curator和zkclient分別為兩種不同的zookeeper實現,兩者使用的同時都需要開啟先zookeeper註冊中心的服務端。(關於如何下載配置並啟動zookeeper服務端,參考win10環境下搭建zookeeper偽集群)
在本項目中,它默認是使用了curator實現的,要改成zkclient實現,需要在<dubbo:registry address="zookeeper://127.0.0.1:2181/" client="zkclient" />
標簽中加入 client="zkclient"
(在dubbo官網中稱2.5以上的dubbo版本默認使用zookeeper實現,但是實測結果卻相反)
2.定義服務接口(對提供方和調用方都可見)
package dubboXml;
public interface DemoService {
String sayHello(String name);
}
3.服務提供方配置
實現服務接口
package dubboXml; public class DemoServiceImpl implements DemoService{ public String sayHello(String name) { return "Hello " + name; } }
spring配置
<?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://dubbo.apache.org/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <!-- 提供方應用信息,用於計算依賴關系 --> <dubbo:application name="hello-world-app" /> <!-- 使用zookeeper註冊中心暴露服務地址 --> <dubbo:registry address="zookeeper://127.0.0.1:2181" client="zkclient" /> <!-- 用dubbo協議在20880端口暴露服務 --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 聲明需要暴露的服務接口 --> <dubbo:service interface="dubboXml.DemoService" ref="demoService" /> <!-- 和本地bean一樣實現服務 --> <bean id="demoService" class="dubboXml.DemoServiceImpl" /> </beans>
讀取配置,提供服務
package dubboXml; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Provider { public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"provider.xml"}); context.start(); System.in.read(); // 按任意鍵退出 } }
4.服務調用方配置
spring配置
<?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://dubbo.apache.org/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <!-- 消費方應用名,用於計算依賴關系,不是匹配條件,不要與提供方一樣 --> <dubbo:application name="consumer-of-helloworld-app" /> <!-- 使用zookeeper註冊中心暴露發現服務地址 --> <dubbo:registry address="zookeeper://127.0.0.1:2181" /> <!-- 生成遠程服務代理,可以和本地bean一樣使用demoService --> <dubbo:reference id="demoService" interface="dubboXml.DemoService" /> </beans>
讀取配置,調用服務
package dubboXml; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Consumer { public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"consumer.xml"}); context.start(); DemoService demoService = (DemoService)context.getBean("demoService"); // 獲取遠程服務代理 String hello = demoService.sayHello("nihao"); // 執行遠程方法 System.out.println( hello ); // 顯示調用結果 } }
最終結果:
5.其他說明
- 如果涉及傳輸對象,那麽被傳輸的對象類應該實現serializable接口。因為對象遠程傳輸是以二進制的形式進行的,那麽在傳輸之前需要實現序列化。
- 我的demo地址:demoXml
我的目錄結構:
3.註解配置的方式
maven配置同上。
1.服務接口和傳輸對象
服務接口
package com.common.server;
import java.util.List;
public interface DemoService {
public String greet(String name);
public List<User> getUsers();
}
傳輸對象:實現序列化接口
package com.common.server;
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private String sex;
public User(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
}
2.服務提供方
實現接口(註意加上相應註解)
package com.provider; import com.alibaba.dubbo.config.annotation.Service; import com.common.server.DemoService; import com.common.server.User; import java.util.ArrayList; import java.util.List; /** * 實現類上打上service註解:註意,是dubbo的service註解 */ @Service public class DemoServiceImpl implements DemoService { @Override public String greet(String name) { return "Hello " + name; } @Override public List<User> getUsers() { List<User> list = new ArrayList<>(); User user1 = new User("張三",10,"男"); User user2 = new User("李四",11,"女"); User user3 = new User("王五",12,"男"); list.add(user1); list.add(user2); list.add(user3); return list; } }
xml配置
(與全xml配置服務的方式相比,這裏去掉了bean和<dubbo:service>
,使用<dubbo:anotition>
取代了,相當於自動掃描並暴露服務)<?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="provider" /> <!-- 使用zookeeper註冊中心暴露服務地址 --> <dubbo:registry address="zookeeper://127.0.0.1:2181" client="zkclient" /> <!--<dubbo:registry address="N/A"/>--> <!-- 用dubbo協議在20880端口暴露服務 --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 註解實現,指向服務提供者實現類的包掃描--> <dubbo:annotation package="com.provider" /> </beans>
開啟服務提供
package com.provider; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; /** * 服務提供者 */ public class Provider { public static void main(String[] args) throws IOException { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"provider.xml"}); context.start(); System.in.read(); } }
3.服務調用方
類中註入並使用遠程服務代理(為什麽不在加載spring文件的類中註入?因為那是入口)
package com.consumer; import com.alibaba.dubbo.config.annotation.Reference; import com.common.server.DemoService; import org.springframework.stereotype.Component; /** * 服務消費者:service是spring的註解 */ @Component("anotationConsumer") public class AnotationConsumer { /** * 遠程服務代理,可以和本地bean一樣使用demoService */ @Reference(check = false) private DemoService demoService; public void print(){ System.out.println(demoService.greet("張三")); System.out.println(demoService.getUsers()); } }
consumer.xml spring配置文件
<?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" 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-3.0.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <dubbo:application name="consumer"/> <dubbo:registry address="zookeeper://127.0.0.1:2181" client="zkclient" /> <!--指向服務調用者所在的包--> <dubbo:annotation package="com.consumer" /> <!-- 配置spring註解包掃描 --> <context:component-scan base-package="com.consumer"></context:component-scan> </beans>
啟動服務
package com.consumer; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Consumer { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"consumer.xml"}); context.start(); AnotationConsumer anotationConsumer = (AnotationConsumer) context.getBean("anotationConsumer"); anotationConsumer.print(); } }
調用結果:
4.附加信息
- 無論是哪種配置方式,如果使用了註冊中心,那麽註冊和調用的時候必須先開啟註冊中心。
- demo地址:dubboAnotation
- 還有一種api調用的形式,由於不常用所以這裏沒有提供教程。如果有興趣可以查看參考帖。
dubbo學習筆記(3):快速搭建