1. Dubbo介紹
示例代碼:Github
1.1 RPC
Remote Procedure Call:遠程過程調用
1.2 Dubbo架構
Subscribe 訂閱;簽署;贊成
Monitor 監聽器;監控器
1.3 Dubbo在Zookeeper中注冊信息的結構
2. Dubbo使用
2.1 創建Common工程
group id:com.joker.dubbo
artifact id:dubbo-common
package:jar
創建實體類
com.joker.dubbo.entity.Employee.java
package com.joker.dubbo.entity;
import java.io.Serializable;
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Integer empId;
private String empName;
private Double salary;
public Employee() {
}
public Employee(Integer empId, String empName, Double salary) {
this.empId = empId;
this.empName = empName;
this.salary = salary;
}
// getter、setter略
}
創建遠程調用的接口
package com.joker.dubbo.service.EmployeeRemoteService.java
package com.joker.dubbo.service;
import com.joker.dubbo.entity.Employee;
import java.util.List;
public interface EmployeeRemoteService {
List<Employee> getEmployeeByConditionRemote(Employee employee);
}
2.2 創建Provider工程
group id:com.joker.dubbo
artifact id:dubbo-provider
package:war
依賴於:Common工程,使用其中的實體類和接口
依賴信息
pom.xml
<dependencies>
<!-- 依賴於dubbo-common -->
<dependency>
<groupId>com.joker.dubbo</groupId>
<artifactId>dubbo-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.5</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
配置log4j日志文件
log4j.properties
log4j.rootLogger=DEBUG,myConsole
log4j.appender.myConsole=org.apache.log4j.ConsoleAppender
log4j.appender.myConsole.Target=System.out
log4j.appender.myConsole.layout=org.apache.log4j.PatternLayout
log4j.appender.myConsole.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
配置web.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-dubbo.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
Spring配置文件中Dubbo的配置
spring-dubbo.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: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配置:指定當前Web應用名稱,便於在注冊中心中注冊 -->
<dubbo:application name="dubbo-provider"/>
<!-- Dubbo配置:指定注冊中心的種類以及位置 -->
<dubbo:registry protocol="zookeeper" address="192.168.252.128" port="2181"/>
<!-- Dubbo配置:指定Dubbo的Provider本身監聽的端口號 consumer訪問時要使用這個端口號-->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 配置接口實現類的bean -->
<bean id="employeeRemoteServiceImpl" class="com.joker.dubbo.service.impl.EmployeeRemoteServiceImpl"/>
<!-- Dubbo配置:給遠程方法接口指定實現類 -->
<dubbo:service interface="com.joker.dubbo.service.EmployeeRemoteService" ref="employeeRemoteServiceImpl"/>
</beans>
創建遠程調用接口的實現類
com.joker.dubbo.service.impl.EmployeeRemoteServiceImpl.java
package com.joker.dubbo.service.impl;
import com.joker.dubbo.entity.Employee;
import com.joker.dubbo.service.EmployeeRemoteService;
import java.util.ArrayList;
import java.util.List;
/** * @PackageName:com.joker.dubbo.service.impl * @Date:2019/10/18 14:02 * @Author: zsy */
public class EmployeeRemoteServiceImpl implements EmployeeRemoteService {
@Override
public List<Employee> getEmployeeByConditionRemote(Employee employee) {
System.out.println("***provider***:" + employee);
// 假數據用於數據測試
List<Employee> empList = new ArrayList<>();
empList.add(new Employee(111, "empName111", 111.11));
empList.add(new Employee(222, "empName222", 222.22));
empList.add(new Employee(333, "empName333", 333.33));
return empList;
}
}
注冊簡單測試
運行web項目,啟動tomcat服務器,嘗試連接Zookeeper,此時要確保服務器Zookeeper已啟動
啟動成功可以看到控制台日志打印心跳檢查信息:
[2019-10-18 02:19:51,355] Artifact dubbo-provider:war exploded: Artifact is deployed successfully
[2019-10-18 02:19:51,355] Artifact dubbo-provider:war exploded: Deploy took 24,538 milliseconds
[DEBUG] 2019-10-18 14:20:01,235(31554) --> [RMI TCP Connection(192.168.252.128:2181)] org.apache.zookeeper.ClientCnxn$SendThread.readResponse(ClientCnxn.java:758): Got ping response for sessionid: 0x16ddd844d9a0000 after 2ms
[DEBUG] 2019-10-18 14:20:11,241(41560) --> [RMI TCP Connection(192.168.252.128:2181)] org.apache.zookeeper.ClientCnxn$SendThread.readResponse(ClientCnxn.java:758): Got ping response for sessionid: 0x16ddd844d9a0000 after 2ms
此時到服務器端啟動Zookeeper客戶端:
/opt/zookeeper3.4.9/bin/zkCli.sh
#啟動后查看是否已經注冊上provider的信息
[zk: localhost:2181(CONNECTED) 0] ls /
[animal, dubbo, zookeeper, fruits]
[zk: localhost:2181(CONNECTED) 1] ls /dubbo
[com.joker.dubbo.service.EmployeeRemoteService]
[zk: localhost:2181(CONNECTED) 2] ls /dubbo/com.joker.dubbo.service.EmployeeRemoteService
[configurators, providers]
[zk: localhost:2181(CONNECTED) 3] ls /dubbo/com.joker.dubbo.service.EmployeeRemoteService/providers
[dubbo%3A%2F%2F192.168.252.1%3A20880%2Fcom.joker.dubbo.service.EmployeeRemoteService%3Fanyhost%3Dtrue%26application%3Ddubbo-provider%26dubbo%3D2.5.5%26generic%3Dfalse%26interface%3Dcom.joker.dubbo.service.EmployeeRemoteService%26methods%3DgetEmployeeByConditionRemote%26pid%3D6364%26revision%3D1.0-SNAPSHOT%26side%3Dprovider%26timestamp%3D1571379571726]
[zk: localhost:2181(CONNECTED) 4]
通過ls /dubbo/com.joker.dubbo.service.EmployeeRemoteService/providers
我們看到下面注冊的provider,通過Url解碼得到內容:
dubbo://192.168.252.1:20880/com.joker.dubbo.service.EmployeeRemoteService?anyhost=true&application=dubbo-provider&dubbo=2.5.5&generic=false&interface=com.joker.dubbo.service.EmployeeRemoteService&methods=getEmployeeByConditionRemote&pid=6364&revision=1.0-SNAPSHOT&side=provider×tamp=1571379571726
至此,證明Provider配置成功!
2.3 創建Consumer工程
group id:com.joker.dubbo
artifact id:dubbo-consumer
package:war
依賴信息
pom.xml
<dependencies>
<!-- 依賴於dubbo-common -->
<dependency>
<groupId>com.joker.dubbo</groupId>
<artifactId>dubbo-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.5</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<!-- spring-mvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<!-- jsp -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1.3-b06</version>
<scope>provided</scope>
</dependency>
</dependencies>
配置log4j日志配置文件
log4j.properties
log4j.rootLogger=DEBUG,myConsole
log4j.appender.myConsole=org.apache.log4j.ConsoleAppender
log4j.appender.myConsole.Target=System.out
log4j.appender.myConsole.layout=org.apache.log4j.PatternLayout
log4j.appender.myConsole.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
配置web.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
配置SpringMVC
spring-mvc.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:dubbo="http://code.alibabatech.com/schema/dubbo" 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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- SpringMVC相關配置 -->
<context:component-scan base-package="com.joker.dubbo.handler"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
<!-- Dubbo配置:當前應用名稱 -->
<dubbo:application name="dubbo-consumer"/>
<!-- Dubbo配置:指定Dubbo注冊中心類型和位置 -->
<dubbo:registry protocol="zookeeper" address="192.168.252.128" port="2181"/>
<!-- Dubbo配置:引用Provider提供的可以遠程調用的服務 -->
<dubbo:reference id="employeeRemoteService" interface="com.joker.dubbo.service.EmployeeRemoteService"/>
</beans>
創建Handler類映射遠程接口請求
com.joker.dubbo.handler.EmployeeHandler.java
package com.joker.dubbo.handler;
import com.joker.dubbo.entity.Employee;
import com.joker.dubbo.service.EmployeeRemoteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
/** * @PackageName:com.joker.dubbo.handler * @Date:2019/10/18 14:51 * @Author: zsy */
@Controller
public class EmployeeHandler {
@Autowired
EmployeeRemoteService employeeRemoteService;
@RequestMapping("/get/emp/list")
public String getEmpList() {
Employee employee = new Employee(666, "empName666", 666.66);
List<Employee> empList = employeeRemoteService.getEmployeeByConditionRemote(employee);
for (Employee emp : empList) {
System.out.println(emp);
}
return "success";
}
}
創建返回成功頁面
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1> Success !</h1>
</body>
</html>
注冊簡單測試
運行consumer的web項目,啟動一個新的tomcat服務器,並設置不同的端口號;
同provider,啟動完成后可以看到控制台日志打印心跳檢查信息:
[DEBUG] 2019-10-18 16:21:14,947(31499) --> [RMI TCP Connection(192.168.252.128:2181)] org.apache.zookeeper.ClientCnxn$SendThread.readResponse(ClientCnxn.java:758): Got ping response for sessionid: 0x16ddd844d9a000b after 3ms
[DEBUG] 2019-10-18 16:21:24,947(41499) --> [RMI TCP Connection(192.168.252.128:2181)] org.apache.zookeeper.ClientCnxn$SendThread.readResponse(ClientCnxn.java:758): Got ping response for sessionid: 0x16ddd844d9a000b after 1ms
[DEBUG] 2019-10-18 16:21:34,949(51501) --> [RMI TCP Connection(192.168.252.128:2181)] org.apache.zookeeper.ClientCnxn$SendThread.readResponse(ClientCnxn.java:758): Got ping response for sessionid: 0x16ddd844d9a000b after 1ms
此時到Zookeeper服務端查看服務注冊信息:
[zk: localhost:2181(CONNECTED) 21] ls /dubbo/com.joker.dubbo.service.EmployeeRemoteService
[consumers, configurators, routers, providers]
[zk: localhost:2181(CONNECTED) 22]
這是可以看到Zookeeper注冊中心不僅有providers,還有了新注冊的consumers;
這時執行命令:ls /dubbo/com.joker.dubbo.service.EmployeeRemoteService/consumers
可以看到我們注冊的consumer信息
[consumer%3A%2F%2F192.168.252.1%2Fcom.joker.dubbo.service.EmployeeRemoteService%3Fapplication%3Ddubbo-consumer%26category%3Dconsumers%26check%3Dfalse%26dubbo%3D2.5.5%26interface%3Dcom.joker.dubbo.service.EmployeeRemoteService%26methods%3DgetEmployeeByConditionRemote%26pid%3D13468%26revision%3D1.0-SNAPSHOT%26side%3Dconsumer%26timestamp%3D1571386846115]
通過URL解碼可以看到:
consumer://192.168.252.1/com.joker.dubbo.service.EmployeeRemoteService?application=dubbo-consumer&category=consumers&check=false&dubbo=2.5.5&interface=com.joker.dubbo.service.EmployeeRemoteService&methods=getEmployeeByConditionRemote&pid=13468&revision=1.0-SNAPSHOT&side=consumer×tamp=1571386846115
這里顯示的是調用接口的消費者信息。
這時打開瀏覽器輸出http://localhost:8081/consumer/get/emp/list
注意:本項目中配置consumer的tomcat端口號為8081
可以看到成功頁面返回!
同時看到tomcat運行控制台打印信息:
consumer端:
Employee{empId=111, empName='empName111', salary=111.11}
Employee{empId=222, empName='empName222', salary=222.22}
Employee{empId=333, empName='empName333', salary=333.33}
provider端
***provider***:Employee{empId=666, empName='empName666', salary=666.66}
證明遠程方法調用成功,consumer調用了遠程方法,並傳遞給provider一個Employee對象。
provider成功接收,並執行getEmployeeByConditionRemote()方法,返回一個Employee的List。
至此,consumer配置成功!
Dubbo+Zookeeper實現遠程調用成功!
返回!
同時看到tomcat運行控制台打印信息:
consumer端:
Employee{empId=111, empName='empName111', salary=111.11}
Employee{empId=222, empName='empName222', salary=222.22}
Employee{empId=333, empName='empName333', salary=333.33}
provider端
***provider***:Employee{empId=666, empName='empName666', salary=666.66}
證明遠程方法調用成功,consumer調用了遠程方法,並傳遞給provider一個Employee對象。
provider成功接收,並執行getEmployeeByConditionRemote()方法,返回一個Employee的List。
至此,consumer配置成功!
Dubbo+Zookeeper實現遠程調用成功!