Java编程详解-基于 dubbo 的分布式架构

简介: 前言现在越来越多的互联网公司还是将自己公司的项目进行服务化,这确实是今后项目开发的一个趋势,就这个点再凭借之前的 SSM 项目来让第一次接触的同学能快速上手。

前言

现在越来越多的互联网公司还是将自己公司的项目进行服务化,这确实是今后项目开发的一个趋势,就这个点再凭借之前的 SSM 项目来让第一次接触的同学能快速上手。

浅谈分布式架构

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

我们拿一个电商系统来说:

单系统

Java编程技术-基于 dubbo 的分布式架构

 

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

这时候所有的业务逻辑都是在一个项目中就可以满足。

垂直拆分-多应用

Java编程技术-基于 dubbo 的分布式架构

 

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

SOA服务化

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

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

等系统。

如果每次修改了其中一个系统就要重新发布上线的话那么耦合就太严重了。

所以需要将整个项目拆分成若干个独立的应用,可以进行独立的开发上线实现快速迭代。

Java编程技术-基于 dubbo 的分布式架构

 

如上图所示每个应用之间相互独立,每个应用可以消费其他应用暴露出来的服务,同时也对外提供服务。

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

基于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。

登陆界面如下图:

Java编程技术-基于 dubbo 的分布式架构

 

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

消费服务

为了能够更直观的体验到消费服务,我新建了一个项目:

https://github.com/crossoverJie/SSM-CONSUMER 。

其中在 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配置文件时的路径一致:

Java编程技术-基于 dubbo 的分布式架构

 

<!-- 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));

}

}

Java编程技术-基于 dubbo 的分布式架构

 

消费者

Java编程技术-基于 dubbo 的分布式架构

 

提供者

可以看到确实是调用成功了的。

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

Java编程技术-基于 dubbo 的分布式架构

 

会看到多了一个消费者所提供的服务 com.crossoverjie.consumer.api.SalaryInfoApi ,同时

com.crossoverJie.api.UserInfoApi 服务已经正常,说明已经有消费者了。

Java编程技术-基于 dubbo 的分布式架构

 

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

总结

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

再提一点:

在实际的生产环境一般同一个服务我们都会有一个 master , slave 的主从服务,这样在上线的过程中不至于整个应用出现无法使用的尴尬情况。

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

相关文章
|
9天前
|
Java 程序员
Java编程中的异常处理:从基础到高级
在Java的世界中,异常处理是代码健壮性的守护神。本文将带你从异常的基本概念出发,逐步深入到高级用法,探索如何优雅地处理程序中的错误和异常情况。通过实际案例,我们将一起学习如何编写更可靠、更易于维护的Java代码。准备好了吗?让我们一起踏上这段旅程,解锁Java异常处理的秘密!
|
13天前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####
|
13天前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####
|
6天前
|
安全 算法 Java
Java多线程编程中的陷阱与最佳实践####
本文探讨了Java多线程编程中常见的陷阱,并介绍了如何通过最佳实践来避免这些问题。我们将从基础概念入手,逐步深入到具体的代码示例,帮助开发者更好地理解和应用多线程技术。无论是初学者还是有经验的开发者,都能从中获得有价值的见解和建议。 ####
|
4天前
|
存储 算法 安全
分布式系统架构1:共识算法Paxos
本文介绍了分布式系统中实现数据一致性的重要算法——Paxos及其改进版Multi Paxos。Paxos算法由Leslie Lamport提出,旨在解决分布式环境下的共识问题,通过提案节点、决策节点和记录节点的协作,确保数据在多台机器间的一致性和可用性。Multi Paxos通过引入主节点选举机制,优化了基本Paxos的效率,减少了网络通信次数,提高了系统的性能和可靠性。文中还简要讨论了数据复制的安全性和一致性保障措施。
19 1
|
6天前
|
Java 调度
Java中的多线程编程与并发控制
本文深入探讨了Java编程语言中多线程编程的基础知识和并发控制机制。文章首先介绍了多线程的基本概念,包括线程的定义、生命周期以及在Java中创建和管理线程的方法。接着,详细讲解了Java提供的同步机制,如synchronized关键字、wait()和notify()方法等,以及如何通过这些机制实现线程间的协调与通信。最后,本文还讨论了一些常见的并发问题,例如死锁、竞态条件等,并提供了相应的解决策略。
24 3
|
12天前
|
NoSQL Java 数据处理
基于Redis海量数据场景分布式ID架构实践
【11月更文挑战第30天】在现代分布式系统中,生成全局唯一的ID是一个常见且重要的需求。在微服务架构中,各个服务可能需要生成唯一标识符,如用户ID、订单ID等。传统的自增ID已经无法满足在集群环境下保持唯一性的要求,而分布式ID解决方案能够确保即使在多个实例间也能生成全局唯一的标识符。本文将深入探讨如何利用Redis实现分布式ID生成,并通过Java语言展示多个示例,同时分析每个实践方案的优缺点。
27 8
|
8天前
|
消息中间件 架构师 数据库
本地消息表事务:10Wqps 高并发分布式事务的 终极方案,大厂架构师的 必备方案
45岁资深架构师尼恩分享了一篇关于分布式事务的文章,详细解析了如何在10Wqps高并发场景下实现分布式事务。文章从传统单体架构到微服务架构下分布式事务的需求背景出发,介绍了Seata这一开源分布式事务解决方案及其AT和TCC两种模式。随后,文章深入探讨了经典ebay本地消息表方案,以及如何使用RocketMQ消息队列替代数据库表来提高性能和可靠性。尼恩还分享了如何结合延迟消息进行事务数据的定时对账,确保最终一致性。最后,尼恩强调了高端面试中需要准备“高大上”的答案,并提供了多个技术领域的深度学习资料,帮助读者提升技术水平,顺利通过面试。
本地消息表事务:10Wqps 高并发分布式事务的 终极方案,大厂架构师的 必备方案
|
11天前
|
开发框架 安全 Java
Java 反射机制:动态编程的强大利器
Java反射机制允许程序在运行时检查类、接口、字段和方法的信息,并能操作对象。它提供了一种动态编程的方式,使得代码更加灵活,能够适应未知的或变化的需求,是开发框架和库的重要工具。
32 2
|
12天前
|
安全 Java 开发者
Java中的多线程编程:从基础到实践
本文深入探讨了Java多线程编程的核心概念和实践技巧,旨在帮助读者理解多线程的工作原理,掌握线程的创建、管理和同步机制。通过具体示例和最佳实践,本文展示了如何在Java应用中有效地利用多线程技术,提高程序性能和响应速度。
48 1