7-项目开发基础
Dubbo 项目搭建要点说明
1、ZooKeeper 准备
Dubbo 项目的开发需要注册中心,有多种技术可以作为注册中心。现阶段而言,ZooKeeper 是比较合适作为注册中心的组件。所以,Dubbo 项目会将远程接口的服务注册到 ZooKeeper 目录之中。
2、构建 Maven 项目
Java 项目运行于 Linux 系统之上,并且由于 Dubbo 项目之间程序类的互相调用,故采用 Maven 进行项目的搭建最为合适。可利用 Maven 将项目打包为*.tar.gz、*.zip、目录等文件。
课程使用四个项目进行说明。
parent 项目:定义公共的父项目,包括全局属性、全局引用、开发包版本、插件的配置等等。
api 项目:定义远程接口,不包含实现实现子类。
service 项目:定义远程接口的实现子类,编写具体的业务逻辑实现,远程接口的实现子类被自动的注册到指定主机的注册中心 ZooKeeper 的相应目录中。
客户端项目:基于 WEB 和 JUNIT,对远程接口进行调用。
问题:
整个 Dubbo 项目结构,建立了 parent、api、service 项目,parent 项目可以省略,但是,为什么 api 项目和 service 项目分开定义?
搭建 ZooKeeper 服务
为了便于代码开发,ZooKeeper 采用单节点模式(standalone),暂不使用集群方式。
1、下载 ZooKeeper 组件,解压至指定目录下
tar zxvf /src/zookeeper-3.4.10.tar.gz -C /app/
2、更名解压文件目录名称,以方便访问
mv /app/zookeeper-3.4.10 /app/zookeeperStandalone
3、建立 ZooKeeper 的数据保存目录
mkdir /data/zookeeperStandalone
4、复制一份配置文件模板,将其作为 ZooKeeper 运行的配置文件
cp -a /app/zookeeperStandalone/conf/zoo_sample.cfg /app/zookeeperStandalone/conf/zoo.cfg
5、修改配置文件 zoo.cfg
dataDir=/data/zookeeperStandalone
clientPort=2181
6、为了方便 Dubbo 项目能够正常访问使用 ZooKeeper 服务,故修改 hosts 文件,增加主机名和 ip 地址映射关系。
vim /etc/hosts
192.168.6.128 zk-server-01
7、ZooKeeper 启动和查看服务状态
/app/zookeeperStandalone/bin/zkServer.sh start
/app/zookeeperStandalone/bin/zkServer.sh status
8、进入 ZooKeeper 客户端
/app/zookeeperStandalone/bin/zkCli.sh -server 192.168.6.128
定义父项规则
为了统一 Dubbo 项目的开发风格,因此,建立一个父项,这个父项定义统一的全局属性、全局引用、插件和开发版本信息,该父项作为公共的项目约束出现,其他的项目继承该父项目,尤其是远程接口项目和业务中心项目。使用 maven 项目,确定好 settings.xml 文件信息。
1、创建 parent 项目,因为该项目作为公共项目约束,因此选择 quickstart 模式。
2、修改 pom.xml 文件,追加插件信息
<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>own.fuys</groupId>
<artifactId>ownbp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- This file,which is set as pom.xml of parent project,should change that
packaging is pom -->
<packaging>pom</packaging>
<name>ownbp</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Define jdk version -->
<jdk.version>1.8</jdk.version>
<!-- Define maven compiler plugin version -->
<maven.compiler.plugin.version>3.7.0</maven.compiler.plugin.version>
<!-- Define maven source plugin version -->
<maven.source.plugin.version>3.0.1</maven.source.plugin.version>
</properties>
<!-- Configure build -->
<build>
<finalName>ownbp</finalName>
<!-- Configure plugins -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven.source.plugin.version}</version>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
复制代码
定义远程服务接口
远程服务接口也即业务接口。为了统一管理项目的开发插件和版本属性,该远程服务接口继承 parent 父项,遵守 parent 设置的约定。远程业务接口的实现项目和调用远程接口的客户端项目都需要引用该远程接口项目,这也是为什么要使用 Maven,便于依赖的引用传递。
1、创建远程服务接口项目,使用快速启动模式(quickstart)
2、修改 pom.xml 文件,modelVersion 同一级节点下追加以下内容,使其继承父项目配置文件
<parent>
<groupId>org.fuys</groupId>
<artifactId>owndbparent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../owndbparent/pom.xml</relativePath>
</parent>
复制代码
3、更新 Maven 项目
4、为了业务中心项目,定义远程接口,具体实现由业务中心项目完成
package org.fuys.ownrapi.service;
public interface MessageService {
/**
* Define message echo
* @param message
* @return
*/
public String echo(String message);
}
8-定义业务中心
业务中心是 Dubbo 项目的核心所在,重中之重,业务中心的搭建也需要引入大量的开发包。
创建 Dubbo 业务中心项目
1、创建业务中心 Maven 项目,使用快速开始模式(quickstart)
2、修改父项目的 pom.xml 文件,定义 Dubbo 以及相关开发包版本。
Dubbo、Netty、Javassist;
ZooKeeper;
Common;
Log:
Spring;
修改文件部分内容如下:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Define jdk version -->
<jdk.version>1.8</jdk.version>
<!-- Define maven compiler plugin version -->
<maven.compiler.plugin.version>3.7.0</maven.compiler.plugin.version>
<!-- Define maven source plugin version -->
<maven.source.plugin.version>3.0.1</maven.source.plugin.version>
<!-- dubbo -->
<dubbo.version>2.5.5</dubbo.version>
<!-- netty -->
<netty.all.version>4.1.20.Final</netty.all.version>
<!-- javassist -->
<javassist.version>3.22.0-GA</javassist.version>
<!-- zookeeper -->
<zookeeper.version>3.4.11</zookeeper.version>
<zkclient.version>0.10</zkclient.version>
<!-- log -->
<logback.version>1.2.3</logback.version>
<slf4j.version>1.7.25</slf4j.version>
<!-- common tools -->
<commons.lang3.version>3.7</commons.lang3.version>
<commons.beanutils.version>1.9.3</commons.beanutils.version>
<!-- spring relative jar -->
<spring.version>5.0.3.RELEASE</spring.version>
</properties>
复制代码
3、修改业务中心的 pom.xml 文件,引入父项目配置,增加 Dubbo 以及相关开发包的依赖。
引入父项目:
<parent>
<groupId>org.fuys</groupId>
<artifactId>ownbp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../ownbp/pom.xml</relativePath>
</parent>
复制代码
开发导入,注意引入远程接口:
<!-- rapi -->
<dependency>
<groupId>org.fuys</groupId>
<artifactId>ownrapi</artifactId>
<version>${ownrapi.version}</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<!-- netty -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>${netty.all.version}</version>
</dependency>
<!-- javassist -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>${javassist.version}</version>
</dependency>
<!-- zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zookeeper.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>${zkclient.version}</version>
</dependency>
<!-- log -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- common tools -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>${commons.beanutils.version}</version>
</dependency>
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
复制代码
添加 maven 插件:
<build>
<finalName>ownservice</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<!-- <version>${maven.jar.plugin.version}</version> -->
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
复制代码
注意:
开发包的依赖已经配置完毕,但是因为开发包里会包含 pom.xml,出现依赖包之间冲突的问题,因此,需要不断进行修改调整。
定义业务中心配置文件
1、定义远程接口业务实现类,使用 spring 注解
package org.fuys.ownservice.service;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.fuys.ownrapi.service.MessageService;
import org.springframework.stereotype.Component;
@Component
public class MessageServiceImpl implements MessageService {
@Override
public String echo(String message) {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
+ " --> " + message;
}
}
复制代码
2、真实的项目(尤其是 Dubbo 项目)需要考虑不同的项目环境有不同的配置信息,建议创建一个目录 profile,profile 下再创建不同子目录,用于存储不同环境下的文件。
src/main/profile/dev:描述开发环境下的配置信息
src/main/profile/beta:描述测试环境下的配置信息
src/main/profile/product:描述生产环境下的配置信息
3、基于 logback 日志开发包,logback.xml 配置文件保存至/src/main/profile/{dev,beta,product}目录下。
4、定义 dubbo.properties 文件,配置 dubbo 的相关信息,存放于/src/main/profile/{dev,beta,product}/config 目录下。
5、创建 src/main/resources 目录
在该目录再创建 META-INF 目录,用于保存配置文件。为什么要创建 META-INF 目录,这是因为默认情况下 Dubbo 在进行配置文件加载的时候使用 META-INF 作为加载配置文件的标记。
6、将 resources 目录和 profile/xx 目录设置为源代码目录
7、修改 pom.xml 配置文件,重点在于构建 profile 编译的相关处理操作。
<properties>
<profiles.dir>src/main/profile</profiles.dir>
<maven.jar.plugin.version>3.0.2</maven.jar.plugin.version>
</properties>
复制代码
<build>
<finalName>ownservice</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>${profiles.dir}</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
复制代码
<profiles>
<profile>
<id>dev</id>
<properties>
<profile.dir>${profiles.dir}/dev</profile.dir>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>beta</id>
<properties>
<profile.dir>${profiles.dir}/beta</profile.dir>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
<profile>
<id>produce</id>
<properties>
<profile.dir>${profiles.dir}/product</profile.dir>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
</profiles>
复制代码
8、目录 src/main/resources/META-INF 下,创建 config 目录,添加 spring 配置文件 spring-common.xml 文件。
部分内容如下:
<!-- configure AOP annotation support -->
<aop:aspectj-autoproxy/>
<!-- configure annotation -->
<context:annotation-config/>
<context:component-scan base-package="org.fuys.ownservice"/>
<!-- properties file -->
<context:property-placeholder location="classpath:config/*.properties"/>
复制代码
9、在“src/main/resources/META-INF/config”目录下,创建 spring-dubbo.xml 文件,并修改 dubbo.properties 文件
# dubbo service center
dubbo.application.name=ownservice
# dubbo registry address
dubbo.registry.address=zookeeper://192.168.6.128:2181
# dubbo protocol port
dubbo.protocol.port=20880
# dubbo provider timeout
dubbo.provider.timeout=10000
# dubbo service version
dubbo.interface.version=dev
复制代码
<?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: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://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- dubbo service center name -->
<dubbo:application name="${dubbo.application.name}"/>
<!-- dubbo registry -->
<dubbo:registry protocol="zookeeper" address="${dubbo.registry.address}"/>
<!-- dubbo protocol -->
<dubbo:protocol name="dubbo" port="${dubbo.protocol.port}"/>
<!-- dubbo provider timeout -->
<dubbo.provider timeout="${dubbo.provider.timeout}"/>
<!-- dubbo service version -->
<dubbo:service interface="org.fuys.ownrapi.service.MessageService" ref="messageServiceImpl"
version="${dubbo.interface.version}"/>
</beans>
复制代码
启动 Dubbo 服务进行调整
1、定义启动 Dubbo 服务的程序类
package org.fuys.ownservice;
import com.alibaba.dubbo.container.Main;
public class DubboStart {
public static void main(String[] args) {
// start dubbo service
// method 1
// Main.main(args);
// method 2
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] {"META-INF/spring/spring-dubbo.xml","META-INF/spring/spring-common.xml"});
context.start();
// press any key to exit
System.in.read();
// context.close();
}
}
复制代码
注意
可以直接使用 Main.main()启动服务,默认从 META-INF 目录读取信息,对于 spring 的配置文件,需定义在名称为 spring 的目录下,如:META-INF/spring。但是,建议不要使用 Main,因为资源文件读取必须按照定义的目录结构存储,不够灵活。
2、启动之后,比较幸运,没有出现重大的包冲突问题,出现了以下信息
log4j:WARN No appenders could be found for logger (com.alibaba.dubbo.common.logger.LoggerFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
[2018-01-31 15:16:44] Dubbo service server started!
使用 eclipse,打开 pom.xml 文件,进行依赖的层次比较,输入 log,发现 zookeeper 中也包含了 log 日志开发包,故需要将 zookeeper 中的日志开发包排除掉。
修改 pom.xml 文件如下:
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zookeeper.version}</version>
<type>pom</type>
<exclusions>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>${zkclient.version}</version>
<exclusions>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
复制代码
3、重新启动 dubbo 服务,后台打印显示一下信息
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
[2018-01-31 15:31:30] Dubbo service server started!
pom.xml 文件追加日志开发包。
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
复制代码
4、业务中心启动成功后,会在注册中心存储服务信息,建议登陆 zookeeper 客户端进行查看。但是,查看 zookeeper 注册信息,并没有 dubbo 信息,后台显示信息为:
15:57:46,154 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
15:57:46,155 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
15:57:46,155 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/D:/workspace/ownservice/target/classes/logback.xml]
15:57:46,375 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
15:57:46,394 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.rolling.RollingFileAppender]
15:57:46,410 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [FILE-AUDIT]
15:57:46,655 |-INFO in c.q.l.core.rolling.TimeBasedRollingPolicy@1513712028 - No compression will be used
15:57:46,659 |-INFO in c.q.l.core.rolling.TimeBasedRollingPolicy@1513712028 - Will use the pattern c:/logs/archived/debug.%d{yyyy-MM-dd}.%i.log for the active file
15:57:46,674 |-INFO in ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP@3cb5cdba - The date pattern is 'yyyy-MM-dd' from file name pattern 'c:/logs/archived/debug.%d{yyyy-MM-dd}.%i.log'.
15:57:46,674 |-INFO in ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP@3cb5cdba - Roll-over at midnight.
15:57:46,682 |-INFO in ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP@3cb5cdba - Setting initial period to Wed Jan 31 15:50:55 CST 2018
15:57:46,682 |-WARN in ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP@3cb5cdba - SizeAndTimeBasedFNATP is deprecated. Use SizeAndTimeBasedRollingPolicy instead
15:57:46,682 |-WARN in ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP@3cb5cdba - For more information see http://logback.qos.ch/manual/appenders.html#SizeAndTimeBasedRollingPolicy
15:57:46,688 |-INFO in ch.qos.logback.core.rolling.RollingFileAppender[FILE-AUDIT] - Active log file name: c:/logs/debug.log
15:57:46,688 |-INFO in ch.qos.logback.core.rolling.RollingFileAppender[FILE-AUDIT] - File property is set to [c:/logs/debug.log]
15:57:46,692 |-INFO in ch.qos.logback.classic.joran.action.LoggerAction - Setting level of logger [com.mkyong.web] to DEBUG
15:57:46,692 |-INFO in ch.qos.logback.classic.joran.action.LoggerAction - Setting additivity of logger [com.mkyong.web] to false
15:57:46,692 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [FILE-AUDIT] to Logger[com.mkyong.web]
15:57:46,693 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to ERROR
15:57:46,693 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [FILE-AUDIT] to Logger[ROOT]
15:57:46,693 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
15:57:46,694 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@56cbfb61 - Registering current configuration as safe fallback point
[2018-01-31 15:57:47] Dubbo service server started!
复制代码
强烈注意:
一、本系统的目录设置是根据 Main.main()方法进行设置的,默认读取文件的方式,并未进行调整
二、查看 Dubbo 源代码,从而查找出程序如何执行,资源文件如何读取
三、可查看 Dubbo 说明文档,进行文件目录调整
5、登陆进 ZooKeeper 客户端,查看注册服务信息,使用指令“ls /”。
评论