(一)对SpringMVC架构进行SOA分布式改造之工程拆分

        经过一个月的开发,一个单一的SpringMVC教育类创业项目正式上线,随着时间的推移,业务流量逐渐增大,最近对这个单一的工程从零进行SOA分布式改造,改造包括dubbo改造,集成化部署、高可用集群,负载均衡。

        刚开始不打算把各个业务模块进行全部拆分,拆分计划如下:

        总工程名字为 mogo-education-manager、拆分为 common\client\service\web 四个子工程, 后面如果负载仍然比较大,那么考虑把每个模块独立出来,成为单独的client 和 service、即 mogo-education-manager-common、mogo-education-manager-client、mogo-education-manager-service、mogo-education-manager-web。

       拆分后的工程结构如下:

       

        拆分的大体流程,具体的dubbo拆分网上一搜一大堆,我这边记录大体流程和我在拆分中遇到的各种坑:

1、父工程的pom文件中需要制定所有子工程的所有版本,便于统一管理:

父工程pom.xml

<modelVersion>4.0.0</modelVersion>

    <groupId>com.mogo</groupId>
    <artifactId>mogo-education-manager</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0-SNAPSHOT</version>

    <properties>
        <mogo.education.client.version>1.0.0-SNAPSHOT</mogo.education.client.version>
        <mogo.education.service.version>1.0.0-SNAPSHOT</mogo.education.service.version>
        <mogo.education.common.version>1.0.0-SNAPSHOT</mogo.education.common.version>
        <mogo.education.web.version>1.0.0-SNAPSHOT</mogo.education.web.version>
        <!-- spring版本号 -->
        <spring.version>4.1.5.RELEASE</spring.version>
        <!-- log4j日志文件管理包版本 -->
        <slf4j.version>1.6.6</slf4j.version>
        <!-- <logback.version>1.2.3</logback.version> <logback.ext.version>0.1.5</logback.ext.version> -->
        <log4j.version>1.2.12</log4j.version>
        <!-- junit版本号 -->
        <junit.version>4.10</junit.version>
        <!-- mybatis版本号 -->
        <mybatis.version>3.2.1</mybatis.version>
        <!-- jackson版本号 -->
        <com.fasterxml.jackson.core.version>2.8.5</com.fasterxml.jackson.core.version>
    </properties>

    <modules>
        <module>common</module>
        <module>client</module>
        <module>service</module>
        <module>web</module>
    </modules>

子工程pom.xml

<parent>
        <artifactId>mogo-education-manager</artifactId>
        <groupId>com.mogo</groupId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>mogo-education-manager-service</artifactId>
    <version>${mogo.education.service.version}</version>

    <dependencies>
        <dependency>
            <groupId>com.mogo</groupId>
            <artifactId>mogo-education-manager-client</artifactId>
            <version>${mogo.education.client.version}</version>
        </dependency>
        <dependency>
            <groupId>com.mogo</groupId>
            <artifactId>mogo-education-manager-common</artifactId>
            <version>${mogo.education.common.version}</version>
        </dependency>
   </dependencies>

2、client 和 common 中是没有引入resource 文件。 在service的resource下引入了jdbc、mapper、application等配置文件,至于redis等配置后续添加。

新加 dubbo-provider.xml 配置,用来注册服务。样例如下。

    <dubbo:service interface="com.mogo.education.api.service.agent.AgentPolicyService" ref="agentPolicyService"/>
    <dubbo:service interface="com.mogo.education.api.service.agent.AgentReportsDailyService" ref="agentReportsDailyService"/>
    <dubbo:service interface="com.mogo.education.api.service.agent.AgentReportsDetailService" ref="agentReportsDetailService"/>
    <dubbo:service interface="com.mogo.education.api.service.agent.AgentReportsSchoolService" ref="agentReportsSchoolService"/>
    <dubbo:service interface="com.mogo.education.api.service.agent.AgentReportsService" ref="agentReportsService"/>

    <bean id="agentPolicyService" class="com.mogo.education.biz.agent.service.impl.AgentPolicyServiceImpl"/>
    <bean id="agentReportsDailyService" class="com.mogo.education.biz.agent.service.impl.AgentReportsDailyServiceImpl"/>
    <bean id="agentReportsDetailService" class="com.mogo.education.biz.agent.service.impl.AgentReportsDetailServiceImpl"/>
    <bean id="agentReportsSchoolService" class="com.mogo.education.biz.agent.service.impl.AgentReportsSchoolServiceImpl"/>
    <bean id="agentReportsService" class="com.mogo.education.biz.agent.service.impl.AgentReportsServiceImpl"/>

新加 dubbo.properties 对dubbo进行配置,样例如下:

dubbo.container=log4j,spring
dubbo.application.name=mogo-education-service
dubbo.application.logger=slf4j
dubbo.spring.config=classpath*:application.xml
dubbo.registry.address=zookeeper://主机名(或主机IP):2182
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

然后将dubbo-provider.xml 的引用加入到application.xml中,如下:

<import resource="classpath:dubbo-provider.xml" />

dubbo工程需要引入的包如下:

         <!-- dubbo 用到的包 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.netty</groupId>
            <artifactId>netty</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
        </dependency>

3、web 工程当做消费者,进行配置,简单版配置目录结构如下:

新增 dubbo-consumer.xml 进行配置消费者,内容样例如下:

    <dubbo:application name="mogo-education-web"/>

    <!-- use multicast registry center to discover service -->
    <dubbo:registry protocol="zookeeper" address="主机名(或IP):2182"/>

    <!-- 消费者需要引用的服务-->
    <dubbo:reference check="false" interface="com.mogo.education.api.service.res.ResSchoolService" id="resSchoolService"/>
    <dubbo:reference check="false" interface="com.mogo.education.api.service.res.ResStudentService" id="resStudentService"/>
    <dubbo:reference check="false" interface="com.mogo.education.api.service.res.ResSchoolApplyService" id="resSchoolApplyService"/>
    <dubbo:reference check="false" interface="com.mogo.education.api.service.res.ResCompanyService" id="resCompanyService"/>
    <dubbo:reference check="false" interface="com.mogo.education.api.service.res.ResClassService" id="resClassService"/>

application.xml 中 基本不需要特殊配置:

   <context:annotation-config/>
    
   <!--  加载Spring上下文 -->
   <bean id="springContextUtil" class="com.mogo.education.common.util.SpringContextUtil"></bean>
    
   <import resource="classpath:spring/dubbo-consumer.xml" />

web.xml 基本不需要修改。

ok ,基本搭建完成。至于zookeeper的搭建和安装,请自行查看我的<a href=”https://www.cnblogs.com/huxipeng/p/8455950.html”>zookeeper相关博客</a>

接下来,我将介绍,我在整个搭建过程中遇到的各种吐血的坑。

4、因为子工程要引用父工程的jar的maven配置,但是子工程是去掉<version>标签的,那么需要在父工程的pom.xml 的 <dependencies>标签外面套一层 <dependencyManagement> 标签,这样子工程才能引到。

5、安装zookeeper后,记得开启相应的防火墙端口。 后面出现了 dubbo 去注册中心注册时候,连接超时,发现zookeeper 连接的是内网,这个需要配置zookeeper机器的 etc/hosts 文件,配置格式如下 IP  主机名

      例如   192.168.2.104  izwz90gbaaaq67071xh11  至于怎么看主机名, 就看 etc/hostname 文件,也可以直接修改主机名。

后面基本上就是在解决 web 工程启动报错的问题了。

6、发现web 启动后 service 生成的对应的jar 不是一个 jar 而是一个文件夹,这个需要在 service 工程上右键-属性

7、tomcat 需要做如下改动,要不然tomcat 启动没有报错,那么也会无法访问。

如果发现无法改变,那么移除工程,clean 当前server。

8、后来发现在web 使用tomcat 启动的时候,一直报 apache的common-log包找不到,后来发现是maven编译的所有的jar 并没有加载到tomcat中,需要在工程右键-属性:

9、现在jar 包是加载成功了,但是发现maven 并没有编译,生成对应的web-resources。然后在pom.xml中加入build 块。

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>utf-8</encoding>
                    <compilerArguments>
                        <extdirs>${basedir}/lib</extdirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <!-- maven打包 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <webResources>
                        <resource>
                            <directory>${basedir}/lib</directory>
                            <targetPath>WEB-INF/lib</targetPath>
                        </resource>
                    </webResources>
                </configuration>
            </plugin>
            <!-- 打包跳过测试 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>

10、ok,到现在启动终于出现了业务类型的错误,发现是 各种服务无法注入的错误,这个是因为所有web工程中用到的服务,必须全部配置成消费者,也就是全部需要在consumer.xml中配成如下的形式。

<dubbo:reference check="false" interface="com.mogo.education.api.service.res.ResSchoolService" id="resSchoolService"/>

11、到目前为止,web工程成功启动。

现在我们创建main方法 使用 com.alibaba.dubbo.container.Main.main(args) 来启动 服务提供者。 不建议使用加载上下文的方式启动,dubbo 提供的这种方式,可以实现优雅关机(不会马上停掉正在处理业务的服务)。

12、打开dubbo 服务管控台,发现所有服务全部注册,待消费者接入。dubbo-admin的工程代码,我回头会上传到git上供大家下载,具体的搭建方式,自行百度。

接下来启动web 工程,充当消费者。

 

 

 

 

 

 

 

 

 

至此搭建完毕,下篇将进行工程的打包部署。