Dubbo
一,概念
1.概述:Apache Dubbo是一款高性能的Java RPC框架。
2.RPC:全称为remote procedure call,即远程过程调用。比如两台服务器A和B,A服务器上部署一个应用,B服务器上部署一个应用,A服务器上的应用想调用B服务器上的应用提供的方法,由于两个应用不在一个内存空间,不能直接调用,所以需要通过网络来传输数据。
注意:RPC并不是一个具体的技术,而是指整个网络远程调用过程。
3.架构图:(详见官网)
4.调用关系说明:
0-服务容器负责启动,加载,运行服务提供者。
1-服务提供者在启动时,向注册中心注册自己提供的服务。
2-服务消费者在启动时,向注册中心订阅自己所需的服务。
3-注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4-服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5-服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
5.Dubbo 架构的特点:
- 连通性
- 健壮性
- 伸缩性
- 向未来架构的升级性。
6.dubbo解决事务问题
原因:在使用dubbo时,会通过扫描dubbo的@Service注解来创建这个接口的实现类对象,若加入@Transactional注解后,默认也是通过jdk(基于接口)的方式来创建代理对象,这时创建的代理对象为com.sun包下的,在找这个实现类时就找不到了。
因此为了解决这个问题,需要添加:
1.在事务注解驱动,加上proxy-target-class=“true”,就是使用cglib方式来代理的(基于类的,相当于继承):
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
2.@Service注解的源码,类上有@Inherited,这样代理类就会继承了这个注解。
3.但是现在发布的服务还不是我们想要的,是spring的代理SpringProxy,需将@Service注解修改为@Service(interfaceName=“我们自己的接口名称”)。
二,快速入门
1.在虚拟机上开启Zookeeper,作为 Dubbo 服务的注册中心。(注意:需要关闭防火墙)
2.启动Dubbo管理控制台。(启动tomcat)
访问地址,出现如下页面,就说明进去了管理控制台。
3.编写代码
1.功能需求:
1.provider: 提供一个service实现类的方法。
2.consumer: 在web层注入service的接口,dubbo通过创建的代理对象来调用实现类中的方法。
3.公共的接口提取出来,这样方便后期维护。
2.模块目录:
1)消费者模块
代码实现:
控制层代码:
package com.br.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.br.service.HelloService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/hello")
public class HelloController {
@Reference /*注意此处的注解*/
private HelloService helloService;
@RequestMapping("/sayHello")
@ResponseBody
public String sayHello(String name){
return helloService.sayHello(name);
}
}
在applicationContext-web.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:application name="dubbo_consumer"></dubbo:application>
<!-- 连接服务注册中心zookeeper ip为zookeeper所在服务器的ip地址-->
<dubbo:registry address="zookeeper://192.168.204.128:2181"/>
<!--扫描包,主要扫描到@Reference-->
<dubbo:annotation package="com.br.controller"></dubbo:annotation>
<!--在未配置之前,默认值为true;我们必须先启动提供者一方;配置这个是将启动时检查关闭,这样就不需要注意先启动哪一方。-->
<dubbo:consumer check="false"></dubbo:consumer>
</beans>
在web.xml中
<!--配置前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-web.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
2)公共接口模块
代码实现:
接口:
package com.br.service;
public interface HelloService {
String sayHello(String name);
}
3)提供者模块(相当于service层)
代码实现:
实现类:(注意@Service注解的包是dubbo的)
package com.br.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.br.service.HelloService;
@Service
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return "hello," + name;
}
}
在applicationContext-service.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:application name="dubbo_provider"></dubbo:application>
<!-- 连接服务注册中心zookeeper, ip为zookeeper所在服务器的ip地址 192.168.204.128是我的注册中心的ip ,端口号都为2181-->
<dubbo:registry address="zookeeper://192.168.204.128:2181"></dubbo:registry>
<!--提供方进行注册-->
<dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
<!-- 扫描指定包,加入@Service注解的类会被发布为服务 -->
<dubbo:annotation package="com.br.service.impl"></dubbo:annotation>
</beans>
在web.xml配置文件中
<!--配置监听器,加载配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
引入公共接口的坐标:
3.测试:
1.分别启动提供者和消费者的服务器:
2.查看Dubbo管理控制台
3.在地址栏输入访问路径:(访问成功)