SSM(十一) 基于 dubbo 的分布式架构

前言

如今愈来愈多的互联网公司仍是将本身公司的项目进行服务化,这确实是从此项目开发的一个趋势,就这个点再凭借以前的SSM项目来让第一次接触的同窗能快速上手。java

浅谈分布式架构

分布式架构单看这个名字给人的感受就是高逼格,但其实从历史的角度来分析一下就比较明了了。git

咱们拿一个电商系统来讲:github

单系统

E65B5547-AF84-4D31-836D-72892C7AC7EA.png

对于一个刚起步的创业公司项目确定是追求越快完成功能越好,而且用户量也不大。

这时候全部的业务逻辑都是在一个项目中就能够知足。spring

垂直拆分-多应用

QQ20170406-230056@2x.jpg

当业务量和用户量发展到必定地步的时候,这时通常会将应用同时部署到几台服务器上,在用户访问的时候使用 Nginx进行反向代理和简单的负载均衡。

SOA服务化

当整个系统以及发展的足够大的时候,好比一个电商系统中存在有:api

  • 用户系统
  • 订单系统
  • 支付系统
  • 物流系统

等系统。
若是每次修改了其中一个系统就要从新发布上线的话那么耦合就太严重了。服务器

因此须要将整个项目拆分红若干个独立的应用,能够进行独立的开发上线实现快速迭代。mybatis

dubbo.png

如上图所示每一个应用之间相互独立,每一个应用能够消费其余应用暴露出来的服务,同时也对外提供服务。架构

从架构的层面简单的理解了,接下来看看如何编码实现。app

基于dubbo的实现

dubbo应该算是国内使用最多的分布式服务框架,基于此来实现对新入门的同窗应该颇有帮助。负载均衡

其中有涉及到安装dubbo服务的注册中心zookeeper等相关知识点能够自行查看官方文档,这里就不单独讲了。

对外提供服务

首先第一步须要在SSM-API模块中定义一个接口,这里就搞了一个用户查询的接口

/** * Function:用户API * @author chenjiec * Date: 2017/4/4 下午9:46 * @since JDK 1.7 */
public interface UserInfoApi {

    /** * 获取用户信息 * @param userId * @return * @throws Exception */
    public UserInfoRsp getUserInfo(int userId) throws Exception;
}复制代码

接着在SSM-SERVICE模块中进行实现:

import com.alibaba.dubbo.config.annotation.Service;
/** * Function: * @author chenjiec * Date: 2017/4/4 下午9:51 * @since JDK 1.7 */
@Service
public class UserInfoApiImpl implements UserInfoApi {
    private static Logger logger = LoggerFactory.getLogger(UserInfoApiImpl.class);

    @Autowired
    private T_userService t_userService ;

    /** * 获取用户信息 * * @param userId * @return * @throws Exception */
    @Override
    public UserInfoRsp getUserInfo(int userId) throws Exception {
        logger.info("用户查询Id="+userId);

        //返回对象
        UserInfoRsp userInfoRsp = new UserInfoRsp() ;
        T_user t_user = t_userService.selectByPrimaryKey(userId) ;

        //构建
        buildUserInfoRsp(userInfoRsp,t_user) ;

        return userInfoRsp;
    }


    /** * 构建返回 * @param userInfoRsp * @param t_user */
    private void buildUserInfoRsp(UserInfoRsp userInfoRsp, T_user t_user) {
        if (t_user ==  null){
            t_user = new T_user() ;
        }
        CommonUtil.setLogValueModelToModel(t_user,userInfoRsp);
    }
}复制代码

这些都是通用的代码,但值得注意的一点是这里使用的dubbo框架所提供的@service注解。做用是声明须要暴露的服务接口。

再以后就是几个dubbo相关的配置文件了。

spring-dubbo-config.xml

<dubbo:application name="ssm-service" owner="crossoverJie" organization="ssm-crossoverJie" logger="slf4j"/>

    <dubbo:registry id="dubbo-registry" address="zookeeper://192.168.0.188:2181" file="/tmp/dubbo.cachr" />

    <dubbo:monitor protocol="registry" />

    <dubbo:protocol name="dubbo" port="20880" />

    <dubbo:provider timeout="15000" retries="0" delay="-1" />

    <dubbo:consumer check="false" timeout="15000" />复制代码

其实就是配置咱们服务注册的zk地址,以及服务名称、超时时间等配置。

spring-dubbo-provider.xml

<dubbo:annotation package="com.crossoverJie.api.impl" />复制代码

这个配置扫描注解包的位置,通常配置到接口实现包便可。

spring-dubbo-consumer.xml

这个是消费者配置项,代表咱们须要依赖的其余应用。
这里咱们在SSM-BOOT项目中进行配置:

<dubbo:reference id="userInfoApi" interface="com.crossoverJie.api.UserInfoApi" />复制代码

直接就是配置的刚才咱们提供的那个用户查询的接口,这样当咱们本身的内部项目须要使用到这个服务只须要依赖SSM-BOOT便可,不须要单独的再去配置consumer。这个我有在上一篇SSM(十) 项目重构-互联网项目的Maven结构中也有提到。

安装管理控制台

还有一个须要作的就是安装管理控制台,这里能够看到咱们有多少服务、调用状况是怎么样等做用。

这里咱们能够将dubbo的官方源码下载下来,对其中的dubbo-admin模块进行打包,将生成的WAR包放到Tomcat中运行起来便可。

可是须要注意一点的是:
须要将其中的dubbo.properties的zk地址修改成本身的便可。

dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.admin.root.password=root
dubbo.admin.guest.password=guest复制代码

到时候登录的话使用root,密码也是root。
使用guest,密码也是guest。

登录界面以下图:

QQ20170407-001924@2x.jpg

其中咱们能够看到有两个服务以及注册上去了,可是没有消费者。

消费服务

为了可以更直观的体验到消费服务,我新建了一个项目:
github.com/crossoverJi…

其中在SSM-CONSUMER-API中我也定义了一个接口:

/** * Function:薪资API * @author chenjiec * Date: 2017/4/4 下午9:46 * @since JDK 1.7 */
public interface SalaryInfoApi {

    /** * 获取薪资 * @param userId * @return * @throws Exception */
    public SalaryInfoRsp getSalaryInfo(int userId) throws Exception;
}复制代码

由于做为消费者的同时咱们也对外提供了一个获取薪资的一个服务。

SSM-CONSUMER-SERVICE模块中进行了实现:

/** * Function: * @author chenjiec * Date: 2017/4/4 下午9:51 * @since JDK 1.7 */
@Service
public class SalaryInfoApiImpl implements SalaryInfoApi {
    private static Logger logger = LoggerFactory.getLogger(SalaryInfoApiImpl.class);

    @Autowired
    UserInfoApi userInfoApi ;

    /** * 获取用户信息 * * @param userId * @return * @throws Exception */
    @Override
    public SalaryInfoRsp getSalaryInfo(int userId) throws Exception {
        logger.info("薪资查询Id="+userId);

        //返回对象
        SalaryInfoRsp salaryInfoRsp = new SalaryInfoRsp() ;

        //调用远程服务
        UserInfoRsp userInfo = userInfoApi.getUserInfo(userId);

        salaryInfoRsp.setUsername(userInfo.getUserName());

        return salaryInfoRsp;
    }


}复制代码

其中就能够直接使用userInfoApi调用以前的我的信息服务。

再调用以前须要注意的有点是,咱们只须要依赖SSM-BOOT这个模块便可进行调用,由于SSM-BOOT模块已经为咱们配置了消费者之类的操做了:

<dependency>
            <groupId>com.crossoverJie</groupId>
            <artifactId>SSM-BOOT</artifactId>
        </dependency>复制代码

还有一点是在配置SSM-BOOT中的spring-dubbo-cosumer.xml配置文件的时候,路径要和咱们初始化spring配置文件时的路径一致:

QQ20170407-005850@2x.jpg

<!-- Spring和mybatis的配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring/*.xml</param-value>
    </context-param>复制代码

接下来跑个单测试一下可否调通:

/** * Function: * * @author chenjiec * Date: 2017/4/5 下午10:41 * @since JDK 1.7 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:/spring/*.xml" })
public class SalaryInfoApiImplTest {

    @Autowired
    private SalaryInfoApi salaryInfoApi ;

    @Test
    public void getSalaryInfo() throws Exception {
        SalaryInfoRsp salaryInfo = salaryInfoApi.getSalaryInfo(1);
        System.out.println(JSON.toJSONString(salaryInfo));
    }

}复制代码

消费者.jpg

消费者

提供者.jpg

提供者
能够看到确实是调用成功了的。

接下来将消费者项目也同时启动在来观察管理控制台有什么不同:

QQ20170407-003413@2x.jpg

会看到多了一个消费者所提供的服务 com.crossoverjie.consumer.api.SalaryInfoApi,同时
com.crossoverJie.api.UserInfoApi服务已经正常,说明已经有消费者了。

QQ20170407-003456@2x.jpg

点进去即可查看具体的消费者。

总结

这样一个基于dubbo的分布式服务已经讲的差很少了,在实际的开发中咱们便会开发一个大系统中的某一个子应用,这样就算一个子应用出问题了也不会影响到整个大的项目。

再提一点:
在实际的生产环境通常同一个服务咱们都会有一个master,slave的主从服务,这样在上线的过程当中不至于整个应用出现没法使用的尴尬状况。

谈到了SOA的好处,那么天然也有相对于传统模式的不方便之处:

  • 拆分一个大的项目为成百上千的子应用就不可能手动上线了,即须要自动化的部署上线,如Jenkins
  • 还有一个须要作到的就是监控,须要一个单独的监控平台来帮咱们实时查看各个服务的运行状况以便于及时定位和解决问题。
  • 日志查看分析,拆分以后不可能再去每台服务器上查看日志,须要一个单独的日志查看分析工具如elk

以上就是我理解的,若有差错欢迎指正。

项目地址:github.com/crossoverJi…

我的博客地址:crossoverjie.top

GitHub地址:github.com/crossoverJi…

相关文章
相关标签/搜索