dubbo的入门使用总结

1.在企业开发过程中我们发现url越来越多,各个节点之间维护起来很困难,依赖关系很模糊,并且每个节点的性能、访问量、响应时间我们无法评估,这个时候就可以引入dubbo来治理。

在项目中新建一个新建一个名为sumei-order 的pom父工程,

然后在父工程上新建两个子工程 一 sumei-order-api 用于向外部暴露接口、sumei-order-provider 用于提供api中接口实现,

工程结构如下

sumei-order-api pom文件

<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">
    <parent>
        <artifactId>sumei-order</artifactId>
        <groupId>com.sumei</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>sumei-order-api</artifactId>
    <packaging>jar</packaging>

    <name>sumei-order-api</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
        </dependency>
    </dependencies>
</project>

suimei-order-provdier 

<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">
    <parent>
        <artifactId>sumei-order</artifactId>
        <groupId>com.sumei</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>sumei-order-provider</artifactId>
    <packaging>jar</packaging>

    <name>sumei-order-provider</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.sumei</groupId>
            <artifactId>sumei-order-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.3</version>
        </dependency>
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>

        <dependency>
            <groupId>com.caucho</groupId>
            <artifactId>hessian</artifactId>
            <version>4.0.38</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>org.mortbay.jetty</groupId>
            <artifactId>jetty</artifactId>
            <version>6.1.26</version>
        </dependency>


    </dependencies>
</project>

在sumei-api-order 新建两个实体类

一个为入参(DoRequest) 一个为出参(DoResponse)

package com.sumei.order.request;

import java.io.Serializable;

public class DoRequest implements Serializable {
    private static final long serialVersionUID = -101933701419873281L;

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
package com.sumei.order.reponse;

import java.io.Serializable;

public class DoResponse implements Serializable {
    private static final long serialVersionUID = 1048196133759063700L;
    private String code;
    private Object data;
    private String msg;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

定义个接口

package com.sumei.order;

import com.sumei.order.reponse.DoResponse;
import com.sumei.order.request.DoRequest;

public interface OrderService {
    DoResponse doOrder(DoRequest doRequest);
}

在sumei-order-provider 中提供接口实现

package com.sumei.order.impl;

import com.sumei.order.OrderService;
import com.sumei.order.reponse.DoResponse;
import com.sumei.order.request.DoRequest;

public class OrderServiceImpl implements OrderService {
    public DoResponse doOrder(DoRequest doRequest) {
        System.out.println("有人进来了");
        DoResponse doResponse=new DoResponse();
        doResponse.setCode("200");
        doResponse.setData("00000000000000000");
        doResponse.setMsg(doRequest.getName());
        return doResponse;
    }
}

在sumei-order-provider src目录下面 新建一个

resources 文件夹,在resources下建一个META-INF文件夹,再在META-INF 新建一个spring 文件夹

在spring文件夹中新建一个 xml文件

在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">
    <!-- name为分布式中唯一的应用名称,owner 为服务的管理者-->
    <dubbo:application name="order-provider" owner="piaomj" />
 <!--   <dubbo:registry protocol="zookeeper" address="192.168.31.100,192.168.31.101,192.168.31.102" />-->
    <!-- address 为服务的注册地址-->
    <dubbo:registry address="N/A" />
    <!--服务默认使用的协议-->
    <dubbo:protocol port="20880" name="dubbo"/>
    <!--<dubbo:protocol name="hessian" port="8090" server="jetty" />-->
    <!-- 声明一个bean-->
    <bean class="com.sumei.order.impl.OrderServiceImpl" id="orderService" />
    <!--对外部暴露的接口-->
    <dubbo:service interface="com.sumei.order.OrderService" ref="orderService"  />
</beans>

在resources 中加入 log4j.properties 配置文件如下

log4j.rootLogger=info, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

这个时候用main方法启动dubbo

package com.sumei.order;


import com.alibaba.dubbo.container.Main;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ){
        Main.main(args);

    }
}

会看到 

日志中有Export dubbo service com.sumei.order.OrderService to url dubbo://192.168.31.134:20880/com.sumei.order.OrderService?

其中dubbo://192.168.31.134:20880/com.sumei.order.OrderService 是消费端的直连地址

新建一个名为suemi-user消费者

pom文件

<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.sumei</groupId>
  <artifactId>sumei-user</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>sumei-user</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>dubbo</artifactId>
      <version>2.5.3</version>
    </dependency>

    <dependency>
      <groupId>com.caucho</groupId>
      <artifactId>hessian</artifactId>
      <version>4.0.38</version>
    </dependency>

    <dependency>
      <groupId>com.github.sgroschupf</groupId>
      <artifactId>zkclient</artifactId>
      <version>0.1</version>
    </dependency>

  </dependencies>
</project>

user项目要填入api的依赖,为了途方便直接把api打成jar包直接加入到user依赖

order-consumer.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="order-provider" owner="piaomj"/>

    <dubbo:registry  address="N/A" />
    <!--<dubbo:protocol name="hessian" port="8090" />-->

    <dubbo:reference id="orderService" interface="com.sumei.order.OrderService" url="dubbo://192.168.31.134:20880/com.sumei.order.OrderService"/>

</beans>

用dubbo调用远程服务

package com.sumei;


import com.sumei.order.OrderService;
import com.sumei.order.reponse.DoResponse;
import com.sumei.order.request.DoRequest;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ) throws IOException {
        ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("classpath:order-consumer.xml");
        OrderService orderService = (OrderService) classPathXmlApplicationContext.getBean("orderService");
        DoRequest doRequest=new DoRequest();
        doRequest.setName("ppp" );
        DoResponse doResponse = orderService.doOrder(doRequest);
        System.out.println("状态码:"+doResponse.getCode());
        System.out.println("状态数据:"+doResponse.getData());
        System.in.read();
    }
}

输出结果:

调用端输出结果:

服务端输出结果:

dubbo 不采用zk的搭建成功

二、使用中的问题

1.注册中心

在配置中将

address="N/A" 不采用注册中心地址 

<dubbo:registry  address="N/A" />

改为

<dubbo:registry protocol="zookeeper" address="192.168.31.100,192.168.31.101,192.168.31.102" />

protocol="zookeeper" 采用的注册中心为zookeeper,

address="192.168.31.100,192.168.31.101,192.168.31.102", 表示注册中心的的地址

2.多个注册中心

<dubbo:registry id="zk1" protocol="zookeeper" version="1.0" address="192.168.31.100,192.168.31.101,192.168.31.102" />

<dubbo:registry id="zk2" protocol="zookeeper" version="1.0" address="192.168.31.100,192.168.31.101,192.168.31.102" />

比如 一个可以用于测试版本、一个可以用于开发版本

<dubbo:registry id="zk1" protocol="zookeeper" version="1.0" address="192.168.31.100,192.168.31.101,192.168.31.102" />

3.多个版本

原因由于业务更新,我们需要重新对业务进行梳理,但是还不能影响老的用户,这个时候我们需要进行多个版本的实现

我们可以对api中的接口 新加入一个实现类

package com.sumei.order.impl;

import com.sumei.order.OrderService;
import com.sumei.order.reponse.DoResponse;
import com.sumei.order.request.DoRequest;

public class Order2ServiceImpl implements OrderService {
    public DoResponse doOrder(DoRequest doRequest) {
        System.out.println("有人进来了");
        DoResponse doResponse=new DoResponse();
        doResponse.setCode("200");
        doResponse.setData("11111111111111");
        doResponse.setMsg(doRequest.getName());
        return doResponse;
    }
}

在消费端调用:

<?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="order-consumer" owner="piaomj"/>

   <dubbo:registry protocol="zookeeper" address="192.168.31.100,192.168.31.101,192.168.31.102" />
    <!--<dubbo:registry  address="N/A" />-->
    <!--<dubbo:protocol name="hessian" port="8090" />-->

    <dubbo:reference id="orderService" interface="com.sumei.order.OrderService"  version="0.0.1"/>

</beans>
package com.sumei;


import com.sumei.order.OrderService;
import com.sumei.order.reponse.DoResponse;
import com.sumei.order.request.DoRequest;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ) throws IOException {
        ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("classpath:order-consumer.xml");
        OrderService orderService = (OrderService) classPathXmlApplicationContext.getBean("orderService");
        DoRequest doRequest=new DoRequest();
        doRequest.setName("ppp" );
        DoResponse doResponse = orderService.doOrder(doRequest);
        System.out.println("状态码:"+doResponse.getCode());
        System.out.println("状态数据:"+doResponse.getData());
        System.in.read();
    }
}

配置

<dubbo:reference id="orderService" interface="com.sumei.order.OrderService"  version="0.0.1"/>

输出:
状态码:200
状态数据:00000000000000000

配置:

<dubbo:reference id="orderService" interface="com.sumei.order.OrderService"  version="0.0.2"/>

输出

状态码:200
状态数据:11111111111111

4.多协议

dubbo支持 dubbo、RMI、hessian、webservice、http、Thrift 协议

dubbo、RMI 底层为tcp

hessian、webservice、http、Thrift 底层为http

默认是dubbo协议,我们还可以添加个hessian协议

服务提供者配置如下

<?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">
    <!-- name为分布式中唯一的应用名称,owner 为服务的管理者-->
   <!-- -->
    <dubbo:application name="order-provider" owner="piaomj" />
 <!--   <dubbo:registry protocol="zookeeper" address="192.168.31.100,192.168.31.101,192.168.31.102" />-->
    <dubbo:registry id="zk1" protocol="zookeeper" version="1.0" address="192.168.31.100,192.168.31.101,192.168.31.102" />

    <dubbo:registry id="zk2" protocol="zookeeper" version="1.0" address="192.168.31.100,192.168.31.101,192.168.31.102" />
    <!-- address 为服务的注册地址-->
    <!--<dubbo:registry address="N/A" />-->
    <!--服务默认使用的协议-->
    <dubbo:protocol port="20880" name="dubbo"/>
    <dubbo:protocol name="hessian" port="8090" server="jetty" />
    <!-- 声明一个bean-->
    <bean class="com.sumei.order.impl.OrderServiceImpl" id="orderService" />
    <bean class="com.sumei.order.impl.Order2ServiceImpl" id="order2Service" />
    <!--对外部暴露的接口-->

 <dubbo:service interface="com.sumei.order.OrderService" ref="orderService" registry="zk1" protocol="hessian" version="0.0.1" />     <dubbo:service interface="com.sumei.order.OrderService" ref="order2Service" registry="zk1"  version="0.0.2" />

</beans>

我们制定 id=“orderService” 为hessian协议

启动的时候我们会看见

hessian://192.168.31.134:8090/com.sumei.order.OrderService2?anyhost=true&application=order-provider&dubbo=2.5.

我们在调用的的时候可以制定协议

<dubbo:reference id="orderService" interface="com.sumei.order.OrderService" protocol="hessian" version="0.0.1"/>

5.解决循环依赖

    场景 

     这个场景服务怎么也起不来,原因是消费者在启动的过程中要检查服务提供者有没有用启动

A 启动的时候,去检车b有没有启动,b启动的时候去检查A有没有启动,这样服务就会起不来了,要起来还需要一个配置

这个是在消费端的配置

<dubbo:reference check="false" id="orderService" interface="com.sumei.order.OrderService" protocol="hessian" version="0.0.1"/>

    check="false" 表示启动的时候不进行检查

  

6.只订阅不注册

<dubbo:registry id="zk1" protocol="zookeeper" version="1.0" address="192.168.31.100,192.168.31.101,192.168.31.102" register="false" />

表示当前服务只调用其他服务并不会将本地的服务祖册到其注册中心上

7.只注册不订阅

表示当前只提供服务

<dubbo:registry subscribe="false"/>

8.负载均衡

将sumei-order 项目复制一份,然后在用idea开个新窗口打开

然后改下dubbo协议的端口

<!--服务默认使用的协议-->
<dubbo:protocol port="20881" name="dubbo"/>

然后我们用user调用

package com.sumei.order;


import com.alibaba.dubbo.container.Main;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ){
        Main.main(args);

    }
}

dubbo 可自行进行负载均衡,默认的采用。可以自行扩展负载均衡策略。

默认采用,Random LoadBalance 随机、按权重设置随机概率。

9.异步调用

消费端

<dubbo:reference  async="true" id="orderService" interface="com.sumei.order.OrderService"  version="0.0.1"/>

调用

*/
public class App 
{
    public static void main( String[] args ) throws IOException {
        ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("classpath:order-consumer.xml");
        OrderService orderService = (OrderService) classPathXmlApplicationContext.getBean("orderService");
        DoRequest doRequest=new DoRequest();
        DoResponse doResponse = orderService.doOrder(doRequest);
        Future<DoResponse> future = RpcContext.getContext().getFuture();
        doRequest.setName("aaa" );
        try {
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }


    }
}

猜你喜欢

转载自my.oschina.net/u/2474435/blog/1634482