spring boot2整合dubbox全注解


前題

    dubbox是dubbo的一個升級版,簡單說就是本來dubbo是阿里開發的,現在阿里不維護了,當當網拿過去繼續開發。本來阿里的dubbo維護到2.6版本,而再高版本的都是當當網維護的就叫成dubbox了。

    dubbo的機制是這樣的,首先有一個數據中心zookeeper,這里zookeeper的搭建可以參考 zookeeper集群搭建 這篇博客,數據中心的職能只有一個,就是數據的存儲。

如圖,提供者將自己的服務信息注冊到zookeeper中,消費者從zookeeper中取得提供者的服務信息,包括提供者的ip,端口,服務類名參數,這樣就可以直接請求提供者所在的服務器,完成調用。

 

 一、dubbox maven導包

1、編譯安裝

  因為dubbox沒有編譯發布,所以不能夠通過maven拉取遠程jar包,需要自己編譯安裝到自己的本地Maven倉庫中。從 dubbox github地址 下載項目,在項目根目錄下運行

 mvn install -Dmaven.test.skip=true 或者在powershell中運行  mvn clean install package '-Dmaven.test.skip=true'

 2、項目構建

創建一個maven項目,項目下創建三個module,如圖 (這個dubbox是我自己的項目命名,不是官方的dubbox)

 

 這里需要注意,因為是模塊項目,所以在dubboapi等module中的pom的parent是dubbox,但是我們的springboot也需要用spring-boot-starter-parent控制版本,所以spring-boot-starter-parent需要定義在dubbox的pom中,繼承下去,但是我在dubbox中控制子模塊的jar包版本,這會導致一個問題,就是我在dubbox中的版本控制把spring-boot-starter-parent中的版本給沖突掉了。具體情況下面會說。

dubbox的pom

<?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>xin.shaozeming</groupId>
    <artifactId>dubbox</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>dubboxserver</module>
        <module>dubboxclient</module>
        <module>dubboxapi</module>
    </modules>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.BUILD-SNAPSHOT</version>
    </parent>

    <dependencyManagement>
        <dependencies>
            <!-- dubbo  -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>dubbo</artifactId>
                <version>2.8.4</version>
            </dependency>

            <!--zookeeper -->
            <dependency>
                <groupId>com.github.sgroschupf</groupId>
                <artifactId>zkclient</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                    </exclusion>
                </exclusions>
                <version>0.1</version>
            </dependency>
            <dependency>
                <groupId>net.dubboclub</groupId>
                <artifactId>netty4</artifactId>
                <version>0.0.6</version>
            </dependency>
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>3.4.9</version>
                <exclusions>
                    <exclusion>
                        <groupId>io.netty</groupId>
                        <artifactId>netty</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>


            <!--rest api-->
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-jaxrs</artifactId>
                <version>3.0.7.Final</version>
            </dependency>
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-client</artifactId>
                <version>3.0.7.Final</version>
            </dependency>

            <!-- 如果要使用json序列化 -->
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-jackson-provider</artifactId>
                <version>3.0.7.Final</version>
            </dependency>

            <!-- 如果要使用xml序列化 -->
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-jaxb-provider</artifactId>
                <version>3.0.7.Final</version>
            </dependency>

            <!--kryo序列化-->
            <dependency>
                <groupId>com.esotericsoftware.kryo</groupId>
                <artifactId>kryo</artifactId>
                <version>2.24.0</version>
            </dependency>
            <dependency>
                <groupId>de.javakaffee</groupId>
                <artifactId>kryo-serializers</artifactId>
                <version>0.26</version>
            </dependency>

            <!-- 如果要使用tomcat server -->
            <dependency>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-logging-juli</artifactId>
                <version>8.0.11</version>
            </dependency>

            <!-- 如果要使用netty server -->
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-netty</artifactId>
                <version>3.0.7.Final</version>
                <exclusions>
                    <exclusion>
                        <groupId>io.netty</groupId>
                        <artifactId>netty</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>

        </dependencies>
    </dependencyManagement>

    <!--&lt;!&ndash; Package as an executable jar &ndash;&gt;-->
    <build>
        <finalName>dubbox</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <!-- Add Spring repositories -->
    <!-- (you don't need this if you are using a .RELEASE version) -->
    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <url>https://repo.spring.io/snapshot</url>
        </pluginRepository>
        <pluginRepository>
            <id>spring-milestones</id>
            <url>https://repo.spring.io/milestone</url>
        </pluginRepository>
    </pluginRepositories>

</project>

dubboxapi的pom

<?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">
    <parent>
        <artifactId>dubbox</artifactId>
        <groupId>xin.shaozeming</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>dubbox.api</artifactId>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
            <scope>test</scope>
        </dependency>
        
        <!--zookeeper -->
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
        </dependency>
        <dependency>
            <groupId>net.dubboclub</groupId>
            <artifactId>netty4</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </dependency>


        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-logging-juli</artifactId>
        </dependency>

        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-netty</artifactId>
        </dependency>


        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jaxrs</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-client</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
        </dependency>
        <!--&lt;!&ndash; dubbo  &ndash;&gt;-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>

        <!-- 如果要使用json序列化 -->
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jackson-provider</artifactId>
        </dependency>

        <!-- 如果要使用xml序列化 -->
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jaxb-provider</artifactId>
        </dependency>
        <dependency>
            <groupId>com.esotericsoftware.kryo</groupId>
            <artifactId>kryo</artifactId>
        </dependency>
        <dependency>
            <groupId>de.javakaffee</groupId>
            <artifactId>kryo-serializers</artifactId>
        </dependency>
    </dependencies>

</project>

dubboxserver和dubboxclient的pom

   <dependencies>
        <dependency>
            <groupId>xin.shaozeming</groupId>
            <artifactId>dubbox.api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

仔細看dubbox和dubboxapi中的jar包,dubboxapi中有 tomcat-embed-core 和 validation-api兩個jar包,而dubbox的dependencyManagem中並沒有控制版本,這是因為這兩個包的版本是spring boot parent里面版本控制繼承的tomcat-embed-core springboot2默認的是版本是9,如果這里改成8版本。會出現這樣的錯

org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:155) ~[spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:540) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) [spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT]
    at xin.shaozeming.dubboxclient.ClientStart.main(ClientStart.java:17) [classes/:?]
Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:204) ~[spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:178) ~[spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:152) ~[spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT]
    ... 8 more

這里說這個是希望讀者對這個問題注意一下,實際上這里沒辦法用tomcat,因為如果把這個包改成9版本的,dubbox里面啟動tomcat使用的api又有問題了,不過這里服務器可以用netty,這個服務器是消費者和提供者之間通訊的服務器,tomcat和netty的性能沒什么差距。所以以上關於tomcat服務器的jar包都可以刪掉了,當然不刪也沒影響。

 

 三、代碼實現

provider提供者方面

先看看xml的實現

    <dubbo:application name="provider"/>

    <dubbo:registry address="zookeeper://47.105.202.148:2181"/>

<dubbo:annotation package="xin.shaozeming.dubboxserver.api" />

<dubbo:protocol name="rest" port="8888" threads="500" contextpath="services" server="netty" accepts="500"/>

<dubbo:service interface="xin.shaozeming.dubboxapi.service.UserService" ref="userService" protocol="rest"/>

javaconfig的實現

/**
 * @author: 邵澤銘
 * @date: 2018/12/21
 * @description:
 **/
@Configuration
public class config {

    private static final String APPLICATION_NAME = "provider";

    private static final String REGISTRY_ADDRESS = "zookeeper://47.105.202.148:2181";

    private static final String ANNOTATION_PACKAGE = "xin.shaozeming.dubboxserver.api";


    @Bean
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName(APPLICATION_NAME);
        return applicationConfig;
    }

    @Bean
    public RegistryConfig registryConfig() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress(REGISTRY_ADDRESS);
        return registryConfig;
    }

    @Bean
    public ProtocolConfig protocolConfig(){
        ProtocolConfig protocolConfig=new ProtocolConfig();
        protocolConfig.setName("rest");
        protocolConfig.setPort(8887);
        protocolConfig.setSerialization("kryo");
        protocolConfig.setOptimizer(SerializationOptimizerImpl.class.getName());
//        protocolConfig.setHost("192.168.0.244");
        protocolConfig.setServer("netty");
        protocolConfig.setThreads(500);
        protocolConfig.setAccepts(500);
        protocolConfig.setExtension(
                "com.alibaba.dubbo.rpc.protocol.rest.support.LoggingFilter"
        );
        return protocolConfig;
    }


    @Bean
    public AnnotationBean annotationBean() {
        AnnotationBean annotationBean = new AnnotationBean();
        annotationBean.setPackage(ANNOTATION_PACKAGE);
        return annotationBean;
    }

}

以下是提供者的接口注解,這里這個service不是spring的service,是dubbox里提供的注解

@Service(interfaceClass = UserService.class)
public class UserServiceProvider implements UserService {
   @Override
    public User getUser() {
       User user=new User();
       user.setUserName("szm");
       user.setPassword("123456");
       return user;
    }
}

而rest的注解是需要配置在 UserService 上的,因為 rest的注解不僅僅是提供者接收請求的時候需要,消費者發起請求的時候也需要,之前就是因為這個問題,加上消費者端上沒開日志,找了好久的bug。

UserService接口我是定義在dubboxapi里面的 

package xin.shaozeming.dubboxapi.service;

import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType;
import xin.shaozeming.dubboxapi.po.User;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/**
 * \* Created with IntelliJ IDEA.
 * \* User: 邵澤銘
 * \* Date: 2018/12/21
 * \* Time: 9:50
 * \* Description:
 * \
 */

@Path("user")
public interface UserService {

    @GET
    @Path("getUser")
    @Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
    @Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})
    public User  getUser();

}

到這里提供者就配置好了,再看消費者端

xml版本

<dubbo:application name="consumer"  />

    <dubbo:registry address="zookeeper://47.105.202.148:2181" check="false" />

    <!--uncomment this if you want to test dubbo's monitor-->
    <!--<dubbo:monitor protocol="registry"/>-->

    <dubbo:reference id="userService" interface="xin.shaozeming.dubboxapi.service.UserService"   />

javaconfig

@Configuration
public class config {
    private static final String APPLICATION_NAME = "consumer";

    private static final String REGISTRY_ADDRESS = "zookeeper://47.105.202.148:2181";

    private static final String ANNOTATION_PACKAGE = "xin.shaozeming.dubboxclient.controller";


    @Bean
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName(APPLICATION_NAME);
        return applicationConfig;
    }

    @Bean
    public RegistryConfig registryConfig() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress(REGISTRY_ADDRESS);
        return registryConfig;
    }


    @Bean
    public AnnotationBean annotationBean() {
        AnnotationBean annotationBean = new AnnotationBean();
        annotationBean.setPackage(ANNOTATION_PACKAGE);
        return annotationBean;
    }

}

 

@RestController
public class UserController  {

    @Reference(interfaceClass=UserService.class)
    private UserService userService;


    @GetMapping("/user")
    public User getUser(){
        return userService.getUser();
    }
    

}

  到此消費者端就也配置好了

 關於duubox的日志,不知道為什么log4j配置了也實現不了,不過后來翻了翻代碼,發現可以通過系統屬性選擇日志實現,start類里面加入以下代碼,spring boot整合log4j2可以看這篇文章 sprintboot2整合log4j2

System.setProperty("dubbo.application.logger","slf4j");

 還有一個問題,就是對於provider提供者來說,只需要一個netty服務器端口提供服務就可以了,而用springboot啟動的時候,springboot會啟動一個web,加上netty就是兩個服務器,這顯然沒什么必要,所以可以將spring boot設置成不以web啟動方式啟動

/**
 * @author: 邵澤銘
 * @date: 2018/12/21
 * @description:
 **/

@SpringBootApplication
//@ImportResource("classpath:dubbo-provider.xml")
public class ServerStart {
   public static void main(String[] args) throws Exception{

       System.setProperty("org.springframework.boot.logging.LoggingSystem","org.springframework.boot.logging.log4j2.Log4J2LoggingSystem");
       System.setProperty("dubbo.application.logger","slf4j");
       new SpringApplicationBuilder(ServerStart.class)
               .web(WebApplicationType.NONE)
               .run(args);
   }


}

 

一切准備完成之后,啟動運行

大功告成!!!

demo項目github地址    https://github.com/1160809039/springboot2-dubbox


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM