一、Dubbo
DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架,并被广泛应用于阿里巴巴集团的各成员站点。
Dubbo最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。关于注册中心、协议支持、服务监控等内容,详见后面描述。
二、Dubbo除了RPC之外的应用
1. 访问权限:在整个系统生态环境中,不是任何用户都可以随意访问任何的接口。那么除了访问接口的用户组、用户和密码管理以外(或者是公私钥文件),还需要限制用户的访问权限。例如规定用户组A下所有的用户才能够访问接口X。
2. 版本控制:就像上篇文中描述的问题一样。在比较大的系统中,某一个子系统一般都是使用集群环境运行(有多个工作节点),且必须24小时连续工作不允许中断。那么要进行服务接口升级,一般是先升级一部分服务节点,其间让另一部分服务节点继续提供服务,造成了在一个时间段同一个子系统提供的某一个服务可能出现服务接口版本的不兼容。为了子系统能够保证24小时连续提供服务,就需要标注服务接口的版本号,让之前没有完成升级的服务节点提供/访问老版本的服务接口;已经完成升级的服务节点提供/访问新版本的服务接口。
3. 服务时效控制、次数控制:各个子系统提供的服务本身也是具有时效性的。比如某一个服务Y只在每天早上10:00——11:00才能提供访问服务,且对于某个用户来说每天只能调用100次。
4. 性能措施:性能是评价一款服务治理框架是否优秀的重要标准。在服务治理框架的各层都应该有足够的性能优化措施。例如在服务注册层/服务仓库层,注册通知是如何实现的、“能够提供的”服务列表是否进行本地缓存、缓存何时更新、访问令牌如何实现、如何确定访问节点等等问题都直接影响性能;在RPC层/服务实现层,如何支持非阻塞异步网络IO、是采用现成的网络通信框架(Netty、MINA、Grizzly等等)还是自行编写网络通信框架、如何进行信息的序列化等等问题也会直接影响性能。
5. 其他细节问题:能够应用到生产环境的服务治理框架还需要关注很多细节问题,例如多个子系统所注册服务可能出现的服务名称重复的问题,类似的这种问题如何解决、服务治理框架本身的稳定性如何进行保证、是否需要支持跨语言通信的问题等等。
三、Dubbo的使用方式
1. Maven配置
在工程中引入maven的支持。并且导入相关的依赖:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.xp</groupId> <artifactId>xp</artifactId> <version>0.0.1</version> <packaging>pom</packaging> <url>http://maven.apache.org</url> <properties> <version.log4j>1.2.14</version.log4j> <version.slf4j.api>1.7.5</version.slf4j.api> <version.slf4j.log4j12>1.7.5</version.slf4j.log4j12> <version.slf4j.jcl.over.slf4j>1.7.5</version.slf4j.jcl.over.slf4j> <!-- jackson --> <jackson.version>1.9.13</jackson.version> </properties> <dependencies> <!-- apache commons --> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.5</version> </dependency> <!-- Logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${version.slf4j.api}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${version.slf4j.jcl.over.slf4j}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${version.slf4j.log4j12}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${version.log4j}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.7.4</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.7.4</version> </dependency> <!-- dubbo --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.4.10</version> </dependency> <!-- zookeeper --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.3.4</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.3</version> </dependency> </dependencies> </project>
zookeeper可以作为DUBBO服务管理仓库使用,但是并非只有Zookeeper才可以作为服务管理仓库使用,Redis也可以作为服务管理仓库使用。
2. Spring配置(提供者和消费者都需要)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.xp</groupId> <artifactId>dubbo-provider</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>dubboService</name> <url>http://maven.apache.org</url> <properties> <version.log4j>1.2.14</version.log4j> <version.slf4j.api>1.7.5</version.slf4j.api> <version.slf4j.log4j12>1.7.5</version.slf4j.log4j12> <version.slf4j.jcl.over.slf4j>1.7.5</version.slf4j.jcl.over.slf4j> <!-- jackson --> <jackson.version>1.9.13</jackson.version> </properties> <dependencies> <!-- apache commons --> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.5</version> </dependency> <!-- Logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${version.slf4j.api}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${version.slf4j.jcl.over.slf4j}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${version.slf4j.log4j12}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${version.log4j}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.7.4</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.7.4</version> </dependency> <!-- dubbo --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.4.10</version> </dependency> <!-- zookeeper --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.3.4</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.3</version> </dependency> </dependencies> </project>
3. 编写服务接口和实现
接口xp-dubbo:
UserService:
package com.xp.service; public interface UserService { /** * dubbo接口 * * @param name * @return */ String sayHello(String name); }
服务提供者:
UserServiceImpl:
package com.xp.service.impl; import org.springframework.stereotype.Service; import com.xp.service.UserService; @Service("userService") public class UserServiceImpl implements UserService{ @Override public String sayHello(String name) { System.out.println("xp-dubbo-provider,UserServiceImpl.sayUSer:"+name); return "我是"+name; } }
配置文件ServiceConfig:
spring-provider.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" default-autowire="byName"> <!-- dubbo运用名 --> <dubbo:application name="xp-dubbo-provider" /> <!-- 向zookeeper注册中心注册服务 --> <dubbo:registry address="zookeeper://192.168.2.117:2181" /> <!-- 申明dubbo的协议和暴露端口 --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 申明需要暴露的服务接口 --> <bean id="userService" class="com.xp.service.impl.UserServiceImpl" /> <dubbo:server interface="com.xp.service.UserService" ref="userService" /> </beans>
服务生产者发布服务(也可以使用容器加载,这里只做一下测试,所以就直接写Main方法):
Main
package com.xp.service.impl; import java.io.IOException; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring-provider.xml"); context.start(); System.out.println("xp-dubbo-provider starting..."); try { System.in.read(); } catch (IOException e) { } } }
服务消费者:
UserCustomer:
package com.xp.customer; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.xp.service.UserService; public class UserCustomer { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring-dubbo.xml"}); context.start(); UserService demoService = (UserService) context.getBean("userService"); // 获取远程服务代理 String hello = demoService.sayHello("ricky"); // 执行远程方法 System.out.println(hello); // 显示调用结果 } }
服务消费者的ServiceConfig
spring-customer.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"
default-autowire="byName">
<!-- dubbo运用名 -->
<dubbo:application name="xp-dubbo-customer" />
<!-- 使用zk注册中心暴露的服务地址 -->
<dubbo:registry address="multicast://192.168.2.117:2181" />
<!-- 引用需要暴露的服务接口 -->
<dubbo:reference interface="com.xp.service.UserService"
id="userService" />
</beans>
dubbo:protocol是指定dubbo的协议,除了dubbo协议还有其他:
dubbo,webService,redis,rmi,http,Hessian、Thrift、memcached