Dubbo是:
- 一个分布式、高性能、透明化的RPC服务框架。
- 提供服务的自动注册、自动发现等高效服务自理方案。
- 主要功能包括:高性能NIO通讯及多协议集成,服务动态寻址与路由,软负载均衡与容错,依赖分析与降级等。
Dubbo结构与功能:
- container负责启动、加载、运行provider
- provider启动时,向registry注册自己的服务
- cousumer启动时,向registry订阅自己的服务
- registry提供provider列表给consumer,实时推送变动情况
- consumer根据provider列表,按负载算法选一台provider调用
- monitor统计rpc的调用频次
项目中部署的dubbo:
-
一台应用服务(application)内,既有对外提供服务(provider),也有依赖外部服务(consumer)。
-
provider涉及:registry/protocol/service/method/provider
-
consumer涉及:registry/reference/method/consumer
-
每台服务接口的信息,都会反映到monitor。以application的名称标识属于哪个应用。
简单搭建一个分布式项目,服务用dubbo来管理:
环境依赖:zookeeper,jdk1.8,tomcat7,dubbo-admin(控制台)
dubbo-admin安装:
- 下载地址:https://github.com/apache/incubator-dubbo/archive/dubbo-2.6.0.zip
- 解压进入dubbo-admin目录下,打开命令窗口,输入命令 mvn clean package
- 将war包解压,找到dubbo配置文件dubbo.properties修改zk连接地址
- 将这个文件夹放到tomcat的webapps目录下,启动tomcat
- 输入localhost:8080/文件名,用户名/密码 root/root
一、新建一个简单的mvc项目 storePortal
pom文件除了引入mvc必备的依赖,还需要引入dubbo相关依赖
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.3</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.0</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
这个模块需要被外界访问,添加一个tomcat插件,或者打包后放到tomcat中
<build>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<port>8080</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>storePortal</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- Spring MVC servlet -->
<servlet>
<servlet-name>SpringMVC</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>SpringMVC</servlet-name>
<!-- 此处可以可以配置成*.do,对应struts的后缀习惯 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>
</web-app>
dubbo配置方式有XML、peoperties、注解和api方式:
xml方式:
服务提供方:xml配置是将服务类交给spring的ioc容器,在由dubbo将服务开放成rpc服务,对外提供服务,所以在服务类上不需要加@Service注解
<?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://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<context:component-scan base-package="com.enjoy.dao"/>
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="storeServer"/>
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://192.168.244.2:2181"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:protocol name="rmi" port="21880"/>
<!--
声明需要暴露的服务接口
dubbo把ioc容器内的service开放成rpc服务
-->
<dubbo:service interface="com.enjoy.service.OrderService" ref="orderService" >
<!-- <dubbo:method name="getDetail" cache="lru" /> -->
</dubbo:service>
<dubbo:service interface="com.enjoy.service.UserService" ref="userService" />
<dubbo:service interface="com.enjoy.service.VipUserService" ref="vipUserService" />
<!--
和本地bean一样实现服务
把服务交给ioc容器管理
-->
<bean id="orderService" class="com.enjoy.service.impl.OrderServiceImpl"/>
<bean id="userService" class="com.enjoy.service.impl.UserServiceImpl"/>
<bean id="vipUserService" class="com.enjoy.service.impl.VipUserServiceImpl"/>
服务消费方:xml方式是将引用的服务交给spring的ioc容器,如果从容器中取得这个服务,需要用@Autowired注解
<?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="enjoyStore"/>
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://192.168.244.2:2181"/>
<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:reference id="orderService" interface="com.enjoy.service.OrderService" >
</dubbo:reference>
<dubbo:reference id="userService" interface="com.enjoy.service.UserService" />
<dubbo:reference id="vipUserService" interface="com.enjoy.service.VipUserService" />
</beans>
@Controller
public class IndexController implements ApplicationContextAware{
private ApplicationContext context;
@Autowired
private UserService userService;
@Autowired
private OrderService orderService;
}
这样就可以使用这个服务。
properties方式:是对xml方式的补充,如果xml配置里没有定义的配置信息,dubbo会从dubbo.properties这个文件中读取,如果xml中定义了相关信息,则peoperties的相关配置不会生效,properties文件的级别最低,一般将连接信息配置到properties文件,并且这个文件放在Resources文件夹下,起名dubbo.properties,dubbo会自动加载这个文件
# 应用名
dubbo.application.name=enjoyStore_properties
# 注册中心地址
dubbo.registry.address=zookeeper://192.168.244.2:2181
# 调用协议地址
dubbo.protocol.name=dubbo
dubbo.protocol.port=28080
注解方式配置dubbo
服务提供方:注解方式是在xml里加一个扫描包,扫描指定包下的类,如果发现类上加了@Service(这个注解是dubbo的注解)这个注解,那么就会将这个类交给spring的ioc容器管理,并将这个类开放成rpc服务,对外提供服务
<?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://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<context:component-scan base-package="com.enjoy.dao"/>
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="storeServer_annotation"/>
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://192.168.244.2:2181"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="rmi" port="20880"/>
<dubbo:annotation package="com.enjoy.service" />
</beans>
服务消费方:注解方式是指定扫描包,扫描指定包下的类,发现哪个类的成员变量上加了@Reference注解(dubbo注解),就会将这个代理服务对象注入到这个类上,完成调用。这里不能用spring的注解,必须用dubbo的注解才能完成引用
@Controller
public class IndexController implements ApplicationContextAware{
private ApplicationContext context;
@Reference
private UserService userService;
@Reference
private OrderService orderService;
}
API方式:这种方式开发时不会使用,但是这种方式结构看起来会清晰一些,方便学习使用
服务提供方:
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.ServiceConfig;
import com.enjoy.service.VipUserService;
import com.enjoy.service.impl.VipUserServiceImpl;
import java.io.IOException;
public class StoreProvider {
public static void main(String[] args) throws IOException {
initDubbo();
}
public static void initDubbo() throws IOException {
// 当前应用配置
ApplicationConfig application = new ApplicationConfig();
application.setName("StoreServerApi");
// 连接注册中心配置
RegistryConfig registry = new RegistryConfig();
registry.setProtocol("zookeeper");
registry.setAddress("192.168.244.2:2181");
// 服务提供者协议配置
ProtocolConfig protocol = new ProtocolConfig();
protocol.setName("rmi");
protocol.setPort(21880);
protocol.setThreads(100);
// 注意:ServiceConfig为重对象,内部封装了与注册中心的连接,以及开启服务端口
// 服务提供者暴露服务配置
// 此实例很重,封装了与注册中心的连接,请自行缓存,否则可能造成内存和连接泄漏
ServiceConfig<VipUserService> service = new ServiceConfig<>();
service.setApplication(application);
service.setRegistry(registry); // 多个注册中心可以用setRegistries()
service.setProtocol(protocol); // 多个协议可以用setProtocols()
service.setInterface(VipUserService.class);
service.setRef(new VipUserServiceImpl());
// 暴露及注册服务
service.export();
System.out.println("dubbo服务开启。。。。。。。。");
System.in.read();
}
}
服务消费方:
import com.alibaba.dubbo.config.*;
import com.enjoy.service.VipUserService;
import java.io.IOException;
public class StoreConsumer {
public static void main(String[] args) throws IOException {
// 当前应用配置
ApplicationConfig application = new ApplicationConfig();
application.setName("StoreServerClientApi");
// 连接注册中心配置
RegistryConfig registry = new RegistryConfig();
registry.setProtocol("zookeeper");
registry.setAddress("192.168.244.2:2181");
// 服务提供者协议配置
ProtocolConfig protocol = new ProtocolConfig();
protocol.setName("dubbo");
protocol.setPort(20882);
protocol.setThreads(100);
// 注意:ReferenceConfig为重对象,内部封装了与注册中心的连接,以及与服务提供方的连接
// 引用远程服务
ReferenceConfig<VipUserService> reference = new ReferenceConfig<>(); // 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
reference.setApplication(application);
reference.setRegistry(registry); // 多个注册中心可以用setRegistries()
reference.setInterface(VipUserService.class);
// 和本地bean一样使用xxxService
VipUserService vipUserService = reference.get(); // 注意:此代理对象内部封装了所有通讯细节,对象较重,请缓存复用
String ret = vipUserService.getVipDetail("123");
reference.destroy();
System.out.println(ret);
System.in.read();
}
}