Dubbo和Spring整合

本文介绍微服务架构的特点及其实现方式,重点讲解Dubbo框架如何助力微服务间的通信,包括服务提供者与消费者的配置流程,以及注册中心的集成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

微服务(英语:Micservices)是一种软件实现风格

它的代码与两个特点:代码专注于单一功能;能独立部署到服务器上对外提供服

微服务的功能使用与语言无关(微服务会把实现功能后的结果封装到某个公用协议报文里,这样只要接收方能解析这个协议就能使用微服务的功能),例如微服务A(部署在a主机)是用Java编写功能代码,微服务B(部署在b主机)是用GoLang编写功能代码,B要调用A的函数,可以通过Http发请求,响应结果再封装在Http报文中,这样只要双方语言有解析Http报文的功能就能使用这个微服务

微服务API集告知外界他能提供的功能

 

在微服务里,会出现A主机调用B主机的方法,这属于跨进程调度,自己实现复杂,可以用Dubbo框架辅助实现

Dubbo是阿里集团开源的一个极为出名的RPC(Remote process call)框架,RPC是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一个地址空间(通常为一个开放网络的一台计算机)的子程序,而程序员就像调用本地程序一样,无需额外地为这个交互作用编程(无需关注细节)。如果涉及的软件采用面向对象编程,那么远程过程调用亦可称作远程调用或远程方法调用

实现过程

新建maven工程,新建三个module(服务提供者/微服务,调用微服务的使用者,API集)

PS:代码不要直接放在java文件夹下,会有问题

a、服务的API集:这里说明了服务提供者会提供什么服务

public interface ServiceAPI {
    public String sayHello(String name);//这是服务会提供的方法
}

 

b、提供服务的叫服务提供者

服务要实现API集的接口,避免自己额外提供的函数外界不知道

在provider的pom.xml里导入API集所在的依赖,才能使用接口

还要引入Dubbo框架所需依赖,provider才能保证自己提供的功能,能被外界获取、使用

 <!--注册中心相关,暂时用不到,先注释掉-->
        <!--<dependency>-->
            <!--<groupId>com.101tec</groupId>-->
            <!--<artifactId>zkclient</artifactId>-->
            <!--<version>0.9</version>-->
        <!--</dependency>-->
        <!--<dependency>-->
            <!--<groupId>org.apache.zookeeper</groupId>-->
            <!--<artifactId>zookeeper</artifactId>-->
            <!--<version>3.4.9</version>-->
            <!--<type>pom</type>-->
        <!--</dependency>-->

        <!--dubbo,下面是dubbo本身的依赖,和dubbo底层实现网络通信所需的其它框架netty-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.3</version>
        </dependency>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.6.Final</version>
        </dependency>

        <!--日志-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!--字节码增强,dubbo要生成代理对象,在字节码层面实现增强-->
        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.21.0-GA</version>
        </dependency>


        <!-- spring相关jar ,现在是实现spring和dubbo整合-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

 

微服务提供的方法
public class Provider implements ServiceAPI{
    public String sayHello(String name){//提供给外界使用的方法
        return "你好:"+name;
    }
}

因为实现远程通信的对象通过spring容器管理,创建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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
		http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
		"
>

    <!--定义服务提供者的应用名称(因为微服务是可以单独部署在服务器的,所以称为一个应用)-->
    <dubbo:application name="test-provider"/>

    <!--将真正实现了接口方法的对象(提供功能的对象)注入Spring容器,让spring管理-->
    <bean class="Provider" id="serviceAPI"/>

    <!--定义是哪个接口帮provider提供服务给外界,ref是这个接口的实例对象,暂时不涉及服务注册中心让registry="N/A"-->
    <dubbo:service interface="ServiceAPI" ref="serviceAPI" registry="N/A"/>

    <!--暴露服务(在port(一般默认dubbo的端口是20880)监听谁需要服务,name是协议名字,通过某个公有协议(基于dubbo协议)把服务提供的功能传递出去)-->
    <dubbo:protocol name="dubbo" port="20880"/>

</beans>

加载spring配置文件,让容器里的组件生

在provider的src/main/java里加载

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext springContext = new ClassPathXmlApplicationContext("application-dubbo.xml");
        springContext.start();//启动容器
        //为了不让进程结束,用read阻塞进程,这样spring容器就一直处于生效状态
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

c、调用服务的叫服务消费者

服务消费者实际只知道接口里提供的方法,现在要通过拿到接口引用(指针),调用服务提供的方法

导入接口所在依赖

<?xml version="1.0" encoding="UTF-8"?>
<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</groupId>
    <artifactId>consumer</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
        <!--接口所在依赖-->
            <groupId>com</groupId>
            <artifactId>common-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

服务消费者希望获取到已经实现了ServiceAPI接口的对象的引用,直接通过这个引用调用函数

ServiceAPI serviceAPI = null;
//通过这个引用调用函数
serviceAPI.sayHello("张三");

但是实现类在其它主机中,Dubbo框架可以帮我们拿到其它主机的实例对象

1、导入dubbo框架所需要的依赖

 <!--注册中心相关,暂时用不到,先注释掉-->
        <!--<dependency>-->
            <!--<groupId>com.101tec</groupId>-->
            <!--<artifactId>zkclient</artifactId>-->
            <!--<version>0.9</version>-->
        <!--</dependency>-->
        <!--<dependency>-->
            <!--<groupId>org.apache.zookeeper</groupId>-->
            <!--<artifactId>zookeeper</artifactId>-->
            <!--<version>3.4.9</version>-->
            <!--<type>pom</type>-->
        <!--</dependency>-->

        <!--dubbo,下面是dubbo本身的依赖,和dubbo底层实现网络通信所需的其它框架netty-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.3</version>
        </dependency>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.6.Final</version>
        </dependency>

        <!--日志-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!--字节码增强,dubbo要生成代理对象,在字节码层面实现增强-->
        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.21.0-GA</version>
        </dependency>


        <!-- spring相关jar ,现在是实现spring和dubbo整合-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

2、配置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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
		http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
		"
>

    <!--定义服务消费者的名字-->
    <dubbo:application name="test-consumer"/>


在启动消费者程序后,Dubbo会自动生成ServiceAPI接口的代理对象,这个代理对象的id就是serviceAPI
    <!--定义获得服务的接口引用(指针),id是这个引用对象组件id,url是告诉服务引用向哪个地方发起请求-->
    <dubbo:reference interface="com.ServiceAPI" id="serviceAPI" url="dubbo://localhost:20880"/>

</beans>

3、消费者调用服务提供的方法

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Consumer {
    public static void main(String[] args) {
        // 服务消费者希望获取到已经实现了ServiceAPI接口的对象的引用
        //ServiceAPI serviceAPI = null;

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application-dubbo.xml");
        ServiceAPI serviceAPI = (ServiceAPI) context.getBean("serviceAPI");
        //通过这个引用调用函数
        serviceAPI.sayHello("张三");
    }
}

目录结构

打印结果

 

上面的整合存在不足

在消费者的spring配置文件中发送请求时,url的地址写死了
 

<dubbo:reference interface="ServiceAPI" id="demoService" url="dubbo://localhost:20880"/>

这样当很多消费者想使用provider的方法时,会导致服务器负载过大,这时候引入集群(多个实现功能完全一样的服务器组合成一个集合),分散服务器压力,但这是会有很多不同IP地址和端口号,可是消费者固定死了只能请求一个ip+端口,不能使用集群里的其它服务器

所以引入注册中心,他能管理提供服务的所有服务器信息:提供服务的对应接口、服务器ip,服务暴露的协议+端口号

有了注册中心后,dubbo在服务提供者启动的时候会做3件事:生成服务的代理对象;按照服务暴露协议在指定端口暴露服务;去注册中心注册自己的信息

dubbo在服务消费者启动后会做:生成服务引用对象(代理对象);把自己的信息提交给注册中心;从注册中心拉取已有的服务提供者信息

这样消费者就可以动态的知道集群里所有服务提供者的信息,就可以去请求不同的服务提供者获取功能

 

有了注册中心,可以实现服务的注册和自动发现

 

dubbo默认的注册中心是zookeeper框架

实现过程,要在上面的项目中修改

1、先把provider和consumer的pom.xml里注册中心的依赖导入

<!--注册中心相关-->
        <dependency>
        <groupId>com.101tec</groupId>
        <artifactId>zkclient</artifactId><!--zookeeper的客户端,通过它向zookeeper发送消息-->
        <version>0.9</version>
        </dependency>
        <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.4.9</version>
        <type>pom</type>
        </dependency>

2、修改provider的spring配置文件

<!--定义服务注册中心,当服务启动时会dubbo自动访问2181端口,把服务的元数据上传到注册中心,完成注册-->
    <dubbo:registry address="zookeeper://localhost:2181"/>

    <!--定义是哪个接口帮provider提供服务给外界,ref是这个接口的实例对象,把registry="N/A"删掉-->
    <dubbo:service interface="com.ServiceAPI" ref="serviceAPI"/>

3、修改consumer的spring配置文件

<!--定义服务注册中心,当消费者启动时会dubbo自动访问2181端口,把消费者的元数据上传到注册中心,完成消费者注册,并拉取所有的服务提供者信息给消费者-->
    <dubbo:registry address="zookeeper://localhost:2181"/>
    <!--定义获得服务的接口引用(指针),id是这个引用对象组件id,url是告诉服务引用向哪个地方发起请求-->
    <dubbo:reference interface="com.ServiceAPI" id="serviceAPI"/>

4、启动zookeeper服务器,让它监听2181端口

启动zookeeper后就可以启动Java程序

用ZooInspector(它是一个可以连接zookeeper的客户端,可以把zookeeper的信息读取到并显示到界面上)查看的注册中心里的数据

zooInspector启动方法,进入zooInspector的build目录的cmd路径

执行 java -jar zookeeper-dev-ZooInspector.jar命令

连接zookeeper

输入zookeeper所在主机+端口号

可以看到上面启动的provider和consumer已经注册到注册中心,providers里是实现ServiceAPI接口的所有服务提供者的注册信息,consumers是所有使用了ServiceAPI接口的消费者注册信息

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值