最近由于客户需求的不断挖掘扩展以及分模块部署的需求。我们在原有的SpringBoot+Maven的项目基础上,使用dubbo进行分布式架构的服务管理。现记录详细搭建步骤如下:

首先,通过各方调研,最终采用zookeeper注册中心方式进行服务注册和使用。关于dubbo的API如下:

http://dubbo.io/

http://dubbo.io/books/dubbo-user-book/quick-start.html

关于zookeeper的下载配置,服务监控dubbo-admin的的下载部署,你可以直接使用笔者搭好的项目模型,如果你想自己搭建,也可以从笔者资源库下载,包含配置好的zookeeper以及支持jdk1.8的dubbo-admin.war,开箱即用。地址如下:

http://download.csdn.net/download/qq_21144985/10264778

如果你不关注搭建过程,只是需要启动demo,请阅读下载文件中的readme.txt即可,监控页面的账号密码均为root。需要加新的模块的话,在-master项目上右键new 一个 maven Module即可。公共的pom依赖只需要加入到-master项目的pom中即可。

-master后缀的项目为父项目
-provider后缀的项目为服务实现者
-consumer后缀的项目为服务调用者
-restapi后缀的项目为服务提供者

下面介绍详细搭建过程以及搭建过程中的一些问题

1、搭建分布式模块化应用

1)Eclipse中New Maven project=>选择maven-archetype-site-simple创建父项目。
2)在父项目上右键=>Maven 选择New Maven Module Project =>选择maven-archetype-quickstart创建各模块子项目。
如果创建quickstart项目报错,那就需要手动下载quickstart并配置,下载地址:

http://download.csdn.net/download/qt765765/9952220

创建好的项目目录如下:
这里写图片描述

2、修改配置

1)在父项目-master的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>com.iking.quickresp</groupId>
  <artifactId>quickresp-master</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
  <distributionManagement>
    <site>
      <id>website</id>
      <url>scp://webhost.company.com/www/website</url>
    </site>
  </distributionManagement>
  <parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.4.2.RELEASE</version>
  </parent>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <modules>
    <module>user-provider</module>
    <module>user-consumer</module>
    <module>user-restapi</module>
  </modules>
  <dependencies>
  	<!-- mysql odbc -->
  	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
	</dependency>
  	<!-- 数据库连接池 -->
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>druid</artifactId>
		<version>1.0.26</version>
	</dependency>
  	<!-- json-lib -->
	<dependency>
		<groupId>net.sf.json-lib</groupId>
		<artifactId>json-lib</artifactId>
		<version>2.4</version>
		<classifier>jdk15</classifier>
	</dependency>
	<!-- 集成 Swagger -->
	<dependency>
		<groupId>io.springfox</groupId>
		<artifactId>springfox-swagger-ui</artifactId>
		<version>2.2.2</version>
	</dependency>
	<dependency>
		<groupId>io.springfox</groupId>
		<artifactId>springfox-swagger2</artifactId>
		<version>2.2.2</version>
	</dependency>
	<!-- jwt -->
	<dependency>
		<groupId>io.jsonwebtoken</groupId>
		<artifactId>jjwt</artifactId>
		<version>0.6.0</version>
	</dependency>
  	<!-- spring -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-test</artifactId>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-tomcat</artifactId>
		<scope>provided</scope>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
	</dependency>
	<dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.1.1</version>
	</dependency>
  	<!--junit -->
    <dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
    </dependency>
    <!-- dubbo -->
    <dependency>
	     <groupId>com.alibaba</groupId>
	     <artifactId>dubbo</artifactId>
	     <version>2.5.3</version>
	     <exclusions>
	         <exclusion>
	             <groupId>log4j</groupId>
	            <artifactId>log4j</artifactId>
	         </exclusion>
	        <exclusion>
	             <groupId>commons-logging</groupId>
	             <artifactId>commons-logging</artifactId>
	         </exclusion>
	         <exclusion>
	             <groupId>org.springframework</groupId>
	             <artifactId>spring</artifactId>
	         </exclusion>
	         <exclusion>
	             <groupId>com.alibaba</groupId>
	             <artifactId>fastjson</artifactId>
	         </exclusion>
	     </exclusions>
	 </dependency>
	 <dependency>
	     <groupId>com.github.sgroschupf</groupId>
	     <artifactId>zkclient</artifactId>
	     <version>0.1</version>
	 </dependency>
	 <dependency>
         <groupId>io.dubbo.springboot</groupId>
         <artifactId>spring-boot-starter-dubbo</artifactId>
         <version>1.0.0</version>
     </dependency>
  </dependencies>
</project>

2)在子项目的pom中分别引入打包设置:


<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.iking.quickresp</groupId>
    <artifactId>quickresp-master</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <groupId>com.iking.quickresp</groupId>
  <artifactId>user-customer</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>user-customer</name>
  <url>http://maven.apache.org</url>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
  </dependencies>
  <build>
		<resources>
			<resource>
				<directory>src/main/resource</directory>
				<filtering>false</filtering>
				<includes>
					<include>**/*</include>
				</includes>
			</resource>
			<resource>
				<directory>src/main/java</directory>
				<includes>
					<include>**/*.xml</include>
				</includes>
			</resource>
			<resource>
				<directory>src/test/java</directory>
				<includes>
					<include>**/*</include>
				</includes>
			</resource>
			<resource>
				<directory>src/main/resource</directory>
				<filtering>true</filtering>
				<excludes>  
                    <exclude>**/*</exclude>  
                </excludes> 
			</resource>
		</resources>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<mainClass>com.iking.customer.Run</mainClass>
				</configuration>
				<executions>
					<execution>
						<goals>
							<goal>repackage</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<!-- 打包时跳过测试项 -->
					<skip>true</skip>
					<!-- jdk版本 -->
					<source>1.7</source>
					<target>1.7</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.tomcat.maven</groupId>
				<artifactId>tomcat7-maven-plugin</artifactId>
				<version>2.2</version>
				<configuration>
					<url>http://localhost:8080/manager/text</url>
					<server>TomcatServer</server>
					<path>/customer</path>
					<ignorePackaging>true</ignorePackaging>
					<contextReloadable>true</contextReloadable>
					<!-- tomcat管理权限认证 需要与%TOMCAT7_PATH%/conf/tomcat-users.xml %MAVEN_PATH%/conf/settings.xml 
						保持一致 -->
					<id>tomcat</id>
					<username>admin</username>
					<password>admin</password>
				</configuration>
			</plugin>
			<!-- 发布到tomcat下跳过测试项 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<configuration>
					<testFailureIgnore>true</testFailureIgnore>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<packaging>war</packaging>
</project>

3)创建资源目录和测试目录。
如果子项目中没有src/main/resource资源目录,在此项目上右键build path => Configure Build Path => Source => Add Folder => 选中main => 点击Create New Folder 创建 resource目录。创建完成后在Source目录下,选中刚添加的resource目录中的Output folder => Edit => Browse… => 选择项目下的target => classes。点击Ok即可。

如果项目中没有src/test/java测试目录,则创建方法同上,最后Output folder 指向 target => test-classes即可。

3、创建全局配置文件application.properties

在服务实现者-provider和服务调用者-consumer中的src/main/resource目录下面分别创建application.properties文件

文件内容如下:

服务实现者:


# PROFILES
## dev | prod | test
spring.profiles.active=dev

# EMBEDDED SERVER CON FIGURATION (ServerProperties)
server.port=8091
server.session-timeout=30
server.context-path=
server.tomcat.max-threads=100
server.tomcat.uri-encoding=UTF-8
 
# DATASOURCE
spring.datasource.platform=mysql
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://192.168.1.222:3306/fault?characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.max-active=100
spring.datasource.max-idle=2
spring.datasource.min-idle=1
spring.datasource.initial-size=15

#mybatis
mybatis.mapperLocations=classpath*:com/iking/provider/*/mapping/*.xml
mybatis.typeAliasesPackage=com.iking.provider.*.model.*
 
#multipart file
spring.http.multipart.maxFileSize=100Mb
spring.http.multipart.maxRequestSize=1000Mb

#dubbo
spring.dubbo.application.name=user-provider
spring.dubbo.registry.address=zookeeper://192.168.1.200:2181
spring.dubbo.protocol.name=dubbo
spring.dubbo.protocol.port=20880
spring.dubbo.scan=com.iking.provider.service
spring.dubbo.application.registries.timeout=10000
spring.dubbo.application.registries.session=100000

服务调用者:
将上面配置copy下来,修改项目端口号


server.port=8092

修改dubbo配置中的应用名称和服务扫描路径


spring.dubbo.application.name=user-consumer
spring.dubbo.scan=com.iking.consumer.service


配置文件创建完成后可以将数据库相关配置注释掉,也可以将地址随便指向一个已存在的数据库。之后 修改zookeeper的地址为127.0.0.1


spring.dubbo.registry.address=zookeeper://127.0.0.1:2181

然后分别创建SpringBoot启动类


package com.iking.provider;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.support.SpringBootServletInitializer;

@SpringBootApplication
public class Run extends SpringBootServletInitializer {

	public static void main(String[] args) throws Exception {
		SpringApplication.run(Run.class, args);
		
	}
}

至此,项目搭建已全部完成。

这里解释一下dubbo的几个配置:

spring.dubbo.application.name 提供服务的项目名称
spring.dubbo.registry.address 注册中心的地址
spring.dubbo.protocol.name dubbo的进程名称
spring.dubbo.protocol.port dubbo的端口号
spring.dubbo.scan 服务扫描路径,即需要暴露的service所在包路径
spring.dubbo.application.registries.timeout 连接注册中心的超时时间
spring.dubbo.application.registries.session 注册中心的会话超时时间

更详细的配置请参考下面地址:

http://blog.csdn.net/jeffli1993/article/details/71480627

4、编写测试代码

1)首先在restapi项目中创建服务接口DemoService。


package com.iking.restapi.service;

public interface DemoService {
	
	String sayHello(String name);
}

2)然后在provider项目中引入restapi项目。
在provider项目上右键=> build path => Configure Build Path => Projects => add => 勾选restapi项目 确认即可引入。检测不到的话继续进入 Projects这个页面,选中Native library location ,点击Edit ,点workspace 在此选中restapi 确认即可引入。

引入后创建DemoServiceImpl.java 实现服务接口


package com.iking.provider.service;

import com.alibaba.dubbo.config.annotation.Service;
import com.iking.restapi.service.DemoService;

@Service(version="1.0.0")
public class DemoServiceImpl implements DemoService {

	@Override
	public String sayHello(String name) {
		System.out.println("服务端调用 -------------------------------------------------------------------------");
		return "Hello " + name;
	}

}

此处需要注意的是:所有需要暴露的接口都需要通过com.alibaba.dubbo.config.annotation.Service包下的@Service注解。

3)在consumer项目中调用服务。
在consumer项目中引入restapi项目。

引入后创建InvorkService.java进行调用。


package com.iking.consumer.service;

import org.springframework.stereotype.Service;

import com.alibaba.dubbo.config.annotation.Reference;
import com.iking.restapi.service.DemoService;

@Service
public class InvorkService {
	
	@Reference(version="1.0.0",timeout=100000)
	private DemoService demoServices;
	
	public void sayHello(String name) {
		System.out.println("消费端调用----------------------------------------------------------------");
		String result = demoServices.sayHello(name);
		System.out.println("result ====================================================  " + result);
	}

}

调用时的Service注解用普通的Service注解即可:org.springframework.stereotype.Service包。

在引入服务时需要通过com.alibaba.dubbo.config.annotation.Reference包下的@Reference注解引入,且版本号要和暴露接口时的版本号一致,超时时间也必须设置一个比较长的时间,否则会因为调用超时而报错。

项目结构图如下:



4)junit测试。
在服务调用者consumer项目中,选中InvorkService右键=>new => Others => 输入junit => 选择JUnit Test Case =>next => 将Source folder 的目录选到src/test/java。确认完成即可生成测试用例。

在src/test/java中创建BaseTest.java作为默认测试类。


package com.iking.consumer;

import org.junit.runner.RunWith;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import com.iking.consumer.Run;

@SuppressWarnings("deprecation")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Run.class)
@WebAppConfiguration
public class BaseTest {

}

找到InvorkServiceTest.java。打开后编辑如下:


package com.iking.consumer.service;


import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import com.iking.consumer.BaseTest;
import com.iking.consumer.service.InvorkService;

public class InvorkServiceTest extends BaseTest{
	
	@Autowired
	private InvorkService invorkService;
	
	@Test
	public void testSayHello() {
		invorkService.sayHello("张三");
	}

}

此时测试的所有代码均已完成。

5、搭建全局环境

1)找到zookeeper-3.4.9文件夹=>bin=>双击运行zkServer.cmd即可开启zookeeper注册中心。也可以在网上下载zookeeper并配置后启动服务。
2)找到dubbo-admin-2.5.5.war,将其放置在tomcat中,启动tomcat,访问http://localhost:8080/dubbo-admin-2.5.5/即可监控服务。账号密码均为root。
6、测试

1)在provider中选中Run.java启动SpringBoot项目即可。
2)在consumer中的InvorkServiceTest.java中,选中testSayHello方法右键=> Run As=> 点击JUnit Test启动即可。如果没看到打印结果就切换控制台。

打印出结果即说明调用成功,后续如需要在扩展模块,则只需要一直new maven module 创建provider和consumer即可,所有的暴露的服务api全部加如进restapi即可。

7、搭建过程中的一些问题

1)暴露的服务接口中需要传输***对象***参数时,上述代码会因为对象没有进行序列化而导致消费者调用不到服务实现者,解决方案如下:

首先,分别在消费者-consumer和服务实现者-provider中的application.properties中启用dubbo的序列化配置


spring.dubbo.application.protocol.serialization=kryo

其次,将每个参数对象实现Serializable序列化标识接口

这里写图片描述

设置完成后即可进行对象参数传输。

注:使用spring-boot-devtools热部署功能时可能会报错,如果报错,将这个依赖注释掉即可。

至此所有步骤已全部完成,如有疑问烦请@ 笔者:Q:980420579 Q群:697819474

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐