热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java版SpringCloud+SpringBoot+mybatis+uniapp微服务架构二次浅封装实践

一、背景简介分布式系统中存在很多拆分的服务,在不断迭代升级的过程中,会出现如下常见的棘手情况:某个技术组件版本升级,依赖
一、背景简介

分布式系统中存在很多拆分的服务,在不断迭代升级的过程中,会出现如下常见的棘手情况:

某个技术组件版本升级,依赖包升级导致部分语法或者API过期,或者组件修复紧急的漏洞,从而会导致分布式系统下各个服务被动的升级迭代,很容易引发意外的问题;不同的服务中对组件的依赖和版本各不相同,从而导致不兼容问题的出现,很难对版本做统一的管理和维护,一旦出现问题很容易手忙脚乱,引发蝴蝶效应;

所以在复杂的系统中,对于依赖的框架和组件进行统一管理和二次浅封装,可以较大程度降低上述问题的处理成本与风险,同时可以更好的管理和控制技术栈。

 需要框架源码的朋友可以看我个人简介联系我。推荐分布式架构源码


二、框架浅封装

1、浅封装作用

为什么浅封装,核心目的在于统一管理和协调组件的依赖与升级,并对常用方法做一层包装,实际上很多组件使用到的功能点并不多,只是在业务中的使用点很多,这样给组件本身的迭代升级带来了一定的难度:

例如某个组件常用的API中存在巨大风险漏洞,或者替换掉过期的用法,需要对整个系统中涉及的地方做升级,这种操作的成本是非常高的;

如果是对这种常用的组件方法进行二次包装,作为处理业务的工具方法,那么解决上面的问题就相对轻松许多,只要对封装的工具方法升级,服务的依赖升级即可,降低时间成本和风险。

通过浅封装的手段,可以实现两个方面的解耦:

业务与技术

技术栈中常用的方法进行二次浅封装,这样可以较大程度的降低业务与技术的耦合,如此可以独立的升级技术栈,扩展功能而不影响业务服务的迭代。

框架与组件

不同的框架与组件都需要一定程度的自定义配置,同时分模块管理,在不同的服务中引入特定的依赖,也可以在基础包中做统一依赖,以此实现技术栈的快速组合搭配。

这里说的浅封装,是指包装常规常用的语法,组件本身就是技术层面的深度封装,所以也不可能完全隔开技术栈原生用法。

2、统一版本控制

例如微服务架构下,不同的研发组负责不同的业务模块,然而受到开发人员的经验和能力影响,很容易出现不同的服务组件选型不一致,或者相同的组件依赖版本不同,这样很难对系统架构做标准的统一管理。

对于二次封装的方式,可以严格的控制技术栈的迭代扩展,以及版本冲突的问题,通过对二次封装层的统一升级,可以快速实现业务服务的升级,解决不同服务的依赖差异问题。

三、实践案例

1、案例简介

Java分布式系统中,微服务基础组件(Nacos、Feign、Gateway、Seata)等,系统中间件(Quartz、Redis、Kafka、ElasticSearch,Logstash)等,对常用功能、配置、API等,进行二次浅封装并统一集成管理,以满足日常开发中基础环境搭建与临时工具的快速实现。

  • butte-flyer 组件封装的应用案例;
  • butte-frame 常用技术组件二次封装;

2、分层架构

整体划分五层:网关层、应用层、业务层、中间件层、基础层,组合成一套分布式系统。

服务总览


3、目录结构

butte-frame中对各个技术栈进行二次封装管理,在butte-flyer中进行依赖引用。

butte-frame
├── frame-base 基础代码块
├── frame-jdbc 数据库组件
├── frame-core 服务基础依赖
├── frame-gateway 路由网关
├── frame-nacos 注册与配置中心
├── frame-seata 分布式事务
├── frame-feign 服务间调用
├── frame-security 安全管理
├── frame-search 搜索引擎
├── frame-redis 缓存管理
├── frame-kafka 消息中间件
├── frame-quartz 定时任务
├── frame-swagger 接口文档
└── frame-sleuth 链路日志butte-flyer
├── flyer-gateway 网关服务:路由控制
├── flyer-facade 门面服务:功能协作接口
├── flyer-account 账户服务:用户账户
├── flyer-quartz 任务服务:定时任务
└── flyer-admin 管理服务:后端管理

4、技术栈组件

系统常用的技术栈:基础框架、微服务组件、缓存、安全管理、数据库、定时任务、工具依赖等。


四、微服务组件

1、Nacos

Nacos在整个组件体系中,提供两个核心能力,注册发现:适配微服务注册与发现标准,快速实现动态服务注册发现、元数据管理等,提供微服务组件中最基础的能力;配置中心:统一管理各个服务配置,集中在Nacos中存储管理,隔离多环境的不同配置,并且可以规避线上配置放开的风险;

连接管理

spring:cloud:nacos:# 配置读取config:prefix: applicationserver-addr: 127.0.0.1:8848file-extension: ymlrefresh-enabled: true# 注册中心discovery:server-addr: 127.0.0.1:8848

配置管理

  • bootstrap.yml :服务中文件,连接和读取Nacos中配置信息;
  • application.yml :公共基础配置,这里配置mybatis组件;
  • application-dev.yml :中间件连接配置,用作环境标识隔离;
  • application-def.yml :各个服务的自定义配置,参数加载;

2、Gateway

Gateway网关核心能力,提供统一的API路由管理,作为微服务架构体系下请求唯一入口,还可以在网关层处理所有的非业务功能,例如:安全控制,流量监控限流,等等。

路由控制:各个服务的发现和路由;

@Component
public class RouteFactory implements RouteDefinitionRepository {@Resourceprivate RouteService routeService ;/*** 加载全部路由* @since 2021-11-14 18:08*/@Overridepublic Flux getRouteDefinitions() {return Flux.fromIterable(routeService.getRouteDefinitions());}/*** 添加路由* @since 2021-11-14 18:08*/@Overridepublic Mono save(Mono routeMono) {return routeMono.flatMap(routeDefinition -> {routeService.saveRouter(routeDefinition);return Mono.empty();});}
}

全局过滤:作为网关的基础能力;

@Component
public class GatewayFilter implements GlobalFilter {private static final Logger logger = LoggerFactory.getLogger(GatewayFilter.class);@Overridepublic Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();String uri = request.getURI().getPath() ;String host = String.valueOf(request.getHeaders().getHost()) ;logger.info("request host : {} , uri : {}",host,uri);return chain.filter(exchange);}
}

3、Feign

Feign组件是声明式的WebService客户端,使微服务之间的调用变得更简单,Feign通过注解手段,将请求进行模板化和接口化管理,可以更加标准的管理各个服务间的通信交互。

响应解码:定义Feign接口响应时解码逻辑,校验和控制统一的接口风格;

public class FeignDecode extends ResponseEntityDecoder {public FeignDecode(Decoder decoder) {super(decoder);}@Overridepublic Object decode(Response response, Type type) {if (!type.getTypeName().startsWith(Rep.class.getName())) {throw new RuntimeException("响应格式异常");}try {return super.decode(response, type);} catch (IOException e) {e.printStackTrace();throw new RuntimeException(e.getMessage());}}
}

4、Seata

Seata组件是开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务,实现AT、TCC、SAGA、XA事务模式,支持一站式的分布式解决方案。

事务配置:基于nacos管理Seata组件的参数定义;

服务注册:在需要管理分布式事务的服务中连接和使用Seata服务;

seata:enabled: trueapplication-id: ${spring.application.name}tx-service-group: butte-seata-groupconfig:type: nacosnacos:server-addr: ${spring.cloud.nacos.config.server-addr}group: DEFAULT_GROUPregistry:type: nacosnacos:server-addr: ${spring.cloud.nacos.config.server-addr}application: seata-servergroup: DEFAULT_GROUP

五、中间件集成

1、Kafka

Kafka是由Apache开源,具有分布式、分区的、多副本的、多订阅者,基于Zookeeper协调的分布式消息处理平台,由Scala和Java语言编写。还常用于搜集用户在应用服务中产生的日志数据。

消息发送:封装消息发送的基础能力;

@Component
public class KafkaSendOperate {@Resourceprivate KafkaTemplate kafkaTemplate ;public void send (SendMsgVO entry) {kafkaTemplate.send(entry.getTopic(),entry.getKey(),entry.getMsgBody()) ;}
}

消息消费:消费监听时有两种策略;

  • 消息生产方自己消费,通过Feign接口去执行具体消费服务的逻辑,这样有利于流程跟踪排查;
  • 消息消费方直接监听,减少消息处理的流程节点,当然也可以打造统一的MQ总线服务(文尾);

public class KafkaListen {private static final Logger logger = LoggerFactory.getLogger(KafkaListen.class);/*** Kafka消息监听* @since 2021-11-06 16:47*/@KafkaListener(topics = KafkaTopic.USER_TOPIC)public void listenUser (ConsumerRecord record, Acknowledgment acknowledgment) {try {String key = String.valueOf(record.key());String body = record.value();switch (key){ }} catch (Exception e){e.printStackTrace();} finally {acknowledgment.acknowledge();}}
}

2、Redis

Redis是一款开源组件,基于内存的高性能的key-value数据结构存储系统,它可以用作数据库、缓存和消息中间件,支持多种类型的数据结构,如字符串、集合等。在实际应用中,通常用来做变动频率低的热点数据缓存和加锁机制。

KV数据缓存:作为Redis最常用的功能,即缓存一个指定有效期的键和值,在使用时直接获取;

@Component
public class RedisKvOperate {@Resourceprivate StringRedisTemplate stringRedisTemplate ;/*** 创建缓存,必须带缓存时长* @param key 缓存Key* @param value 缓存Value* @param expire 单位秒* @return boolean* @since 2021-08-07 21:12*/public boolean set (String key, String value, long expire) {try {stringRedisTemplate.opsForValue().set(key,value,expire, TimeUnit.SECONDS);} catch (Exception e){e.printStackTrace();return Boolean.FALSE ;}return Boolean.TRUE ;}
}

Lock加锁机制:基于spring-integration-redisRedisLockRegistry,实现分布式锁;

@Component
public class RedisLockOperate {@Resourceprotected RedisLockRegistry redisLockRegistry;/*** 尝试一次加锁,采用默认时间* @param lockKey 加锁Key* @return java.lang.Boolean* @since 2021-09-12 13:14*/@SneakyThrowspublic Boolean tryLock(T lockKey) {return redisLockRegistry.obtain(lockKey).tryLock(time, TimeUnit.MILLISECONDS);}/*** 释放锁* @param lockKey 解锁Key* @since 2021-09-12 13:32*/public void unlock(T lockKey) {redisLockRegistry.obtain(lockKey).unlock();}}

3、ElasticSearch

ElasticSearch是一个基于Lucene的搜索服务器,它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口,Elasticsearch是用Java开发的,是当前流行的企业级搜索引擎。

索引管理:索引的创建和删除,结构添加和查询;

基于ElasticsearchRestTemplate的模板方法操作;

@Component
public class TemplateOperate {@Resourceprivate ElasticsearchRestTemplate template ;/*** 创建索引和结构* @param clazz 基于注解类实体* @return java.lang.Boolean* @since 2021-08-15 19:25*/public Boolean createPut (Class clazz){boolean createIf = template.createIndex(clazz) ;if (createIf){return template.putMapping(clazz) ;}return Boolean.FALSE ;}
}

基于RestHighLevelClient原生API操作;

@Component
public class IndexOperate {@Resourceprivate RestHighLevelClient client ;/*** 判断索引是否存在* @return boolean* @since 2021-08-07 18:57*/public boolean exists (IndexVO entry) {GetIndexRequest getReq = new GetIndexRequest (entry.getIndexName()) ;try {return client.indices().exists(getReq, entry.getOptions());} catch (Exception e) {e.printStackTrace();}return Boolean.FALSE ;}
}

数据管理:数据新增、主键查询、修改、批量操作,业务性质的搜索封装复杂度很高;

数据的增删改方法;

@Component
public class DataOperate {@Resourceprivate RestHighLevelClient client ;/*** 批量更新数据* @param entry 对象主体* @since 2021-08-07 18:16*/public void bulkUpdate (DataVO entry){if (CollUtil.isEmpty(entry.getDataList())){return ;}// 请求条件BulkRequest bulkUpdate = new BulkRequest(entry.getIndexName(),entry.getType()) ;bulkUpdate.setRefreshPolicy(entry.getRefresh()) ;entry.getDataList().forEach(dataMap -> {UpdateRequest updateReq = new UpdateRequest() ;updateReq.id(String.valueOf(dataMap.get("id"))) ;updateReq.doc(dataMap) ;bulkUpdate.add(updateReq) ;});try {// 执行请求client.bulk(bulkUpdate, entry.getOptions());} catch (IOException e) {e.printStackTrace();}}
}

索引主键查询,分组查询方法;

@Component
public class QueryOperate {&#64;Resourceprivate RestHighLevelClient client ;/*** 指定字段分组查询* &#64;since 2021-10-07 19:00*/public Map groupByField (QueryVO entry){Map groupMap &#61; new HashMap<>() ;// 分组APIString groupName &#61; entry.getGroupField()&#43;"_group" ;SearchSourceBuilder sourceBuilder &#61; new SearchSourceBuilder();sourceBuilder.size(0) ;TermsAggregationBuilder termAgg &#61; AggregationBuilders.terms(groupName).field(entry.getGroupField()) ;sourceBuilder.aggregation(termAgg);// 查询APISearchRequest searchRequest &#61; new SearchRequest(entry.getIndexName());searchRequest.source(sourceBuilder) ;try {// 执行APISearchResponse response &#61; client.search(searchRequest, entry.getOptions());// 响应结果Terms groupTerm &#61; response.getAggregations().get(groupName) ;if (CollUtil.isNotEmpty(groupTerm.getBuckets())){for (Terms.Bucket bucket:groupTerm.getBuckets()){groupMap.put(bucket.getKeyAsString(),bucket.getDocCount()) ;}}} catch (IOException e) {e.printStackTrace();}return groupMap ;}
}

4、Logstash

Logstash是一款开源的数据采集组件&#xff0c;具有实时管道功能。Logstash能够动态的从多个来源采集数据&#xff0c;进行标准化转换数据&#xff0c;并将数据传输到所选择的存储容器。

  • Sleuth&#xff1a;管理服务链路&#xff0c;提供核心TraceId和SpanId生成&#xff1b;
  • ElasticSearch&#xff1a;基于ES引擎做日志聚合存储和查询&#xff1b;
  • Logstash&#xff1a;提供日志采集服务&#xff0c;和数据发送ES的能力&#xff1b;

logback.xml&#xff1a;服务连接Logstash地址&#xff0c;并加载核心配置&#xff1b;


${DES_URI:- }:${DES_PORT:- }UTC{"severity": "%level","service": "${APP_NAME:-}","trace": "%X{X-B3-TraceId:-}","span": "%X{X-B3-SpanId:-}","exportable": "%X{X-Span-Export:-}","pid": "${PID:-}","thread": "%thread","class": "%logger{40}","rest": "%message"}

5、Quartz

Quartz是一个完全由java编写的开源作业调度框架&#xff0c;用来执行各个服务中的定时调度任务&#xff0c;在微服务体系架构下&#xff0c;通常开发一个独立的Quartz服务&#xff0c;通过Feign接口去触发各个服务的任务执行。

配置参数&#xff1a;定时任务基础信息&#xff0c;数据库表&#xff0c;线程池&#xff1b;

spring:quartz:job-store-type: jdbcproperties:org:quartz:scheduler:instanceName: ButteSchedulerinstanceId: AUTOjobStore:class: org.quartz.impl.jdbcjobstore.JobStoreTXdriverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegatetablePrefix: qrtz_isClustered: trueclusterCheckinInterval: 15000useProperties: falsethreadPool:class: org.quartz.simpl.SimpleThreadPoolthreadPriority: 5threadCount: 10threadsInheritContextClassLoaderOfInitializingThread: true

6、Swagger

Swagger是常用的接口文档管理组件&#xff0c;通过对API接口和对象的简单注释&#xff0c;快速生成接口描述信息&#xff0c;并且提供可视化界面可以快速对接口发送请求和调试&#xff0c;该组件在前后端联调中&#xff0c;极大的提高效率。

配置基本的包扫描能力即可&#xff1b;

&#64;Configuration
public class SwaggerConfig {&#64;Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage("com.butte")).paths(PathSelectors.any()).build();}
}

访问&#xff1a;服务:端口/swagger-ui.html即可打开接口文档&#xff1b;

六、数据库配置

1、MySQL

微服务架构下&#xff0c;不同的服务对应不同的MySQL库&#xff0c;基于业务模块做库的划分是当前常用的方式&#xff0c;可以对各自业务下的服务做迭代升级&#xff0c;同时可以避免单点故障导致雪崩效应。

2、HikariCP

HikariCP作为SpringBoot2版本推荐和默认采用的数据库连接池&#xff0c;具有速度极快、轻量简单的特点。

spring:datasource:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/${data.name.mysql}?${spring.datasource.db-param}username: rootpassword: 123456db-param: useUnicode&#61;true&characterEncoding&#61;UTF8&zeroDateTimeBehavior&#61;convertToNull&useSSL&#61;falsehikari:minimumIdle: 5maximumPoolSize: 10idleTimeout: 300000maxLifetime: 500000connectionTimeout: 30000

连接池的配置根据业务的并发需求量&#xff0c;做适当的调优即可。

3、Mybatis

Mybatis持久层的框架组件&#xff0c;支持定制化SQL、存储过程以及高级映射&#xff0c;MyBatis-Plus是一个MyBatis的增强工具&#xff0c;在MyBatis的基础上只做增强不做改变&#xff0c;可以简化开发、提高效率。

mybatis-plus:mapper-locations: classpath*:/mapper/**/*.xmlconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

七、源代码地址

应用仓库&#xff1a;
https://gitee.com/cicadasmile/butte-flyer-parent组件封装&#xff1a;
https://gitee.com/cicadasmile/butte-frame-parent


推荐阅读
  • 第二章:Kafka基础入门与核心概念解析
    本章节主要介绍了Kafka的基本概念及其核心特性。Kafka是一种分布式消息发布和订阅系统,以其卓越的性能和高吞吐量而著称。最初,Kafka被设计用于LinkedIn的活动流和运营数据处理,旨在高效地管理和传输大规模的数据流。这些数据主要包括用户活动记录、系统日志和其他实时信息。通过深入解析Kafka的设计原理和应用场景,读者将能够更好地理解其在现代大数据架构中的重要地位。 ... [详细]
  • 本文推荐了六款高效的Java Web应用开发工具,并详细介绍了它们的实用功能。其中,分布式敏捷开发系统架构“zheng”项目,基于Spring、Spring MVC和MyBatis技术栈,提供了完整的分布式敏捷开发解决方案,支持快速构建高性能的企业级应用。此外,该工具还集成了多种中间件和服务,进一步提升了开发效率和系统的可维护性。 ... [详细]
  • 解决Bootstrap DataTable Ajax请求重复问题
    在最近的一个项目中,我们使用了JQuery DataTable进行数据展示,虽然使用起来非常方便,但在测试过程中发现了一个问题:当查询条件改变时,有时查询结果的数据不正确。通过FireBug调试发现,点击搜索按钮时,会发送两次Ajax请求,一次是原条件的请求,一次是新条件的请求。 ... [详细]
  • 秒建一个后台管理系统?用这5个开源免费的Java项目就够了
    秒建一个后台管理系统?用这5个开源免费的Java项目就够了 ... [详细]
  • 本文介绍了如何利用 `matplotlib` 库中的 `FuncAnimation` 类将 Python 中的动态图像保存为视频文件。通过详细解释 `FuncAnimation` 类的参数和方法,文章提供了多种实用技巧,帮助用户高效地生成高质量的动态图像视频。此外,还探讨了不同视频编码器的选择及其对输出文件质量的影响,为读者提供了全面的技术指导。 ... [详细]
  • 在软件开发过程中,经常需要将多个项目或模块进行集成和调试,尤其是当项目依赖于第三方开源库(如Cordova、CocoaPods)时。本文介绍了如何在Xcode中高效地进行多项目联合调试,分享了一些实用的技巧和最佳实践,帮助开发者解决常见的调试难题,提高开发效率。 ... [详细]
  • 该大学网站采用PHP和MySQL技术,在校内可免费访问某些外部收费资料数据库。为了方便学生校外访问,建议通过学校账号登录实现免费访问。具体方案可包括利用学校服务器作为代理,结合身份验证机制,确保合法用户在校外也能享受免费资源。 ... [详细]
  • 技术日志:使用 Ruby 爬虫抓取拉勾网职位数据并生成词云分析报告
    技术日志:使用 Ruby 爬虫抓取拉勾网职位数据并生成词云分析报告 ... [详细]
  • 尽管我们尽最大努力,任何软件开发过程中都难免会出现缺陷。为了更有效地提升对支持部门的协助与支撑,本文探讨了多种策略和最佳实践,旨在通过改进沟通、增强培训和支持流程来减少这些缺陷的影响,并提高整体服务质量和客户满意度。 ... [详细]
  • 本文深入探讨了 Git 与 SVN 的高效使用技巧,旨在帮助开发者轻松应对版本控制中的各种挑战。通过详细解析两种工具的核心功能与最佳实践,读者将能够更好地掌握版本管理的精髓,提高开发效率。 ... [详细]
  • 美团优选推荐系统架构师 L7/L8:算法与工程深度融合 ... [详细]
  • 人人租机作为国内领先的信用免押租赁平台,为企业和个人提供全方位的新租赁服务。通过接入支付宝小程序功能,该平台实现了从零到百的迅猛增长,成为全国首家推出“新租赁小程序”开发服务的阿里巴巴小程序服务商(ISV)。这一创新举措不仅提升了用户体验,还显著增强了平台的市场竞争力。 ... [详细]
  • 修复一个 Bug 竟耗时两天?真的有那么复杂吗?
    修复一个 Bug 竟然耗费了两天时间?这背后究竟隐藏着怎样的复杂性?本文将深入探讨这个看似简单的 Bug 为何会如此棘手,从代码层面剖析问题根源,并分享解决过程中遇到的技术挑战和心得。 ... [详细]
  • 深入解析十大经典排序算法:动画演示、原理分析与代码实现
    本文深入探讨了十种经典的排序算法,不仅通过动画直观展示了每种算法的运行过程,还详细解析了其背后的原理与机制,并提供了相应的代码实现,帮助读者全面理解和掌握这些算法的核心要点。 ... [详细]
  • 本书《.NET Core 2.* 开发者指南》是面向开发者的全面学习与实践手册,涵盖了从基础到高级的各个层面。书中详细解析了 .NET Core 的核心概念,包括如何创建 .NET Core 网站,并通过视频教程直观展示操作过程。此外,还深入探讨了 Startup 类的作用、项目目录结构的组织方式以及如何在应用中使用静态文件等内容。对于希望深入了解 .NET Core 架构和开发技巧的开发者来说,本书提供了丰富的实践案例和详尽的技术指导。 ... [详细]
author-avatar
浪迹天涯沃热尔_441
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有