业界良心!Github热榜第七的SpringBoot笔记(阿里内测版)终于开源

业界良心!Github热榜第七的SpringBoot笔记(阿里内测版)终于开源,第1张

对于Java程序员来讲,SpringBoot对我们的开发效率的提升有多大想必不用我多说了!它不仅仅能让开发者少量配置代码,更加专注于业务逻辑,还是Java领域微服务架构最优落地技术!并且,它也是现在 面试时的高频考点,不论是应届还是社招,你都会被问到很多SpringBoot相关的问题。

SpringBoot虽然易学,但是难精。 如果你想快速系统化学习和全面掌握SpringBoot知识的话,光靠自己在网上看几篇博客或者去视频网站里看几个学习视频肯定是不够的,这时站在巨人的肩膀上学习才是最省时省力的。借此机会,LZ就把前段时间从阿里离职的一位朋友手上搞来的 SpringBoot(内测学习版)小册 分享给大家,肯定能对大家有所帮助!

不多bb,来看内容

目录与部分内容一览

Spring Boot搭建实际项目开发中的架构

之前也写过一篇关于 Spring Validation 使用的文章,不过自我感觉还是浮于表面,本次打算彻底搞懂 Spring Validation 。

本文会详细介绍 Spring Validation 各种场景下的最佳实践及其实现原理,死磕到底!

Java API 规范 ( JSR303 ) 定义了 Bean 校验的标准 validation-api ,但没有提供实现。 hibernate validation 是对这个规范的实现,并增加了校验注解如 @Email 、 @Length 等。 Spring Validation 是对 hibernate validation 的二次封装,用于支持 spring mvc 参数自动校验。接下来,我们以 spring-boot 项目为例,介绍 Spring Validation 的使用。

如果 spring-boot 版本小于 23x , spring-boot-starter-web 会自动传入 hibernate-validator 依赖。如果 spring-boot 版本大于 23x ,则需要手动引入依赖:

对于 web 服务来说,为防止非法参数对业务造成影响,在 Controller 层一定要做参数校验的!大部分情况下,请求参数分为如下两种形式:

下面我们简单介绍下 requestBody 和 requestParam/PathVariable 的参数校验实战!

POST 、 PUT 请求一般会使用 requestBody 传递参数,这种情况下,后端使用 DTO 对象 进行接收。 只要给 DTO 对象加上 @Validated 注解就能实现自动参数校验。比如,有一个保存 User 的接口,要求 userName 长度是 2-10 , account 和 password 字段长度是 6-20 。如果校验失败,会抛出 MethodArgumentNotValidException 异常, Spring 默认会将其转为 400(Bad Request) 请求。

DTO 表示数据传输对象(Data Transfer Object),用于服务器和客户端之间交互传输使用的 。在 spring-web 项目中可以表示用于接收请求参数的 Bean 对象。

这种情况下, 使用 @Valid 和 @Validated 都可以

前面说过,如果校验失败,会抛出 MethodArgumentNotValidException 或者 ConstraintViolationException 异常。在实际项目开发中,通常会用 统一异常处理 来返回一个更友好的提示。比如我们系统要求无论发送什么异常, >

在客户那部署 Springboot项目,启动非常慢要2-3分钟 因为开发的时候本地windows启只要7s,测试环境也是centos只要7s

因为客户那是虚拟化了3台机器, 安装同样的 *** 作系统,但其中1台很快7s,其他两台很慢这就非常奇怪了

网上大部份都说random的原因, 我们全都照着改了依然很慢

通过strace确切知道改成功了,没改之前全是random,改了之后有urandom

但是可以发现还是会调random, 而且机器的随机数值一直在3000左右,所以可以排除random原因

奇怪的是系统也没有报错,就是启动慢,启动成功后接口页面都没有问题关键是有1台机器又很快,所以让我们只能考虑是机器原因或虚拟化的原因然后我们复制了一台那个没有问题的机器, 在这一台上重新部署,结果依然是很慢查看cpu 内存 io 都没有什么问题

通过starce也只能看出是 futex 花费了大量时间,下图上11254这个进程id,这个futex花费了189s,然后往上找到11254的源头也看不出什么原因导致

然后怀疑应该不是我们项目问题,我拿一个最简单的springboot项目测试也是很慢

然后把springboot日志级别调成debug, 刚开始查问题的时候就已经试过了调日志,因为发现出现Spring那个logo之前很慢而且也没有日志, 然后后面的日志又太长,以为找不出什么有用的信息,试过一次后就又调成info级别了

我们启动慢的情况是这样的,启动后, 等几十秒出现Spring logo, 然后跑了一会儿,又等几十秒,然后系统启动成功

所以这一次想到,虽然启动前没有日志,但是中间的慢,应该可以知道它停在哪里然后google那个停在那里的日志

点进去后有一句话看的我心头一愣 , 这个用户说,似乎这20s的等待是由于NetworkInterfacegetAll

方法

那么也就是说根本原因就是 InetAddressgetLocalHost 导致很慢的原因了

然后用那个最简单的Springboot项目调用一下这个方法,果然不出所料花了20s的时间

找到根本原因随便一搜就知道,是因为在/etc/hosts 里并没有加入当前主机的名字,

在正式环境下加入了主机名后果然快了

那为什么有一台很快了,因为那一台是另一个同事装了mq,他修改了这个hosts文件加了主机名

然后复制这台机器的时候会填一个新主机名,所以复制的那一台机器也很慢

最终解决掉了这个奇怪的问题,通过这一次经历,也学会了使用strace,jstack等调试工具,也有不少的收获

1 Spring Boot是什么,解决哪些问题

   1) Spring Boot使编码变简单

   2) Spring Boot使配置变简单

   3) Spring Boot使部署变简单

   4) Spring Boot使监控变简单

   5) Spring Boot的不足

2 Spring Boot在平台中的定位,相关技术如何融合

   1) SpringBoot与SEDA +MicroService + RESTful

   2) SpringBoot与Mock

3 采用了SpringBoot之后,技术管理应该如何进行

首先,我们来看一下spring boot是什么,它帮助我们解决了哪些问题:

SpringBoot是伴随着Spring40诞生的;

从字面理解,Boot是引导的意思,因此SpringBoot帮助开发者快速搭建Spring框架;

SpringBoot帮助开发者快速启动一个Web容器;

SpringBoot继承了原有Spring框架的优秀基因;

SpringBoot简化了使用Spring的过程。

Spring由于其繁琐的配置,一度被人认为“配置地狱”,各种XML、Annotation配置,让人眼花缭乱,而且如果出错了也很难找出原因。

Spring Boot更多的是采用Java Config的方式,对Spring进行配置。

可以看到,采用了spring-boot-start-actuator之后,直接以REST的方式,获取进程的运行期性能参数。

当然这些metrics有些是有敏感数据的,spring-boot-start-actuator为此提供了一些Basic Authentication认证的方案,这些方案在实际应用过程中也是不足的。

Spring Boot作为一个微框架,离微服务的实现还是有距离的。

没有提供相应的服务发现和注册的配套功能,自身的acturator所提供的监控功能,也需要与现有的监控对接。没有配套的安全管控方案,对于REST的落地,还需要自行结合实际进行URI的规范化工作。

下面,我们研究一下Spring Boot在平台中的定位,相关技术如何融合。

上图比较复杂,整体是采用SEDA,也就是Stage-EDA。可以看到,整体是以处理顺序进行展示的,响应过程类似。在处理过程中,主要会有前置过滤,核心功能处理,后置过滤几大部分。

图中的过滤器都是可插拔式的,并且可以根据实际场景进行扩展开发。每个过滤器都是Stage,比如ClientInstance合法性检查、调用鉴权、解密、限流等等。

一个请求Stage与Stage的转换,实现上是切换不同的线程池,并以EDA的方式驱动。

对于业务逻辑的开发者而言,只需要关心CORE部分的业务逻辑实现,其他的非功能都由框架进行统一实现。

Mock不应当再是测试的专有名词了,当然对于测试这个角色而言,mockito这样的工具,依然可以为他们提升不少效率。

SpringBoot为创建REST服务提供了简便的途径,相比之下,采用阿里的dubbo在做多团队、多进程联调时,mock的难度就陡增。

Mock是解耦并行开发的利器,在理性的情况下,软件从开发期Mock联调,到开发与开发的真实联调,只需要切换一个依赖的域名即可,比如:

mockURI:>

devURI:>

而上述的域名切换,只需要在开发期定义好一个配置项,在做环境切换的时候自动注入即可,省时、省心、省力。

如上图和docker的集成可以有AB两种方案:

A方案的核心是,把docker作为 *** 作系统环境的交付基线,也就是不同的fat jar 使用相同的 *** 作系统版本、相同的JVM环境。但对于docker image来说都是一样的。

B方案的核心是,不同的fat jar,独立的编译为docker image,在启动时直接启动带有特定版本的image。

A相比与B方案的特点是对于docker registry(也就是docker的镜像仓库)的依赖性较低,对于前期编译过程的要求也较低。

采用了Spring Boot之后,技术管理应该如何进行?

正因为Spring Boot是与Spring一脉相承的,所以对于广大的Java开发者而言,对于Spring的学习成本几乎为零。

在实践Spring Boot时学习重点,或者说思维方式改变的重点在于:

1)对于REST的理解,这一点尤为重要,需要从设计、开发多个角色达成共识,很多时候都是对于>

2)对于YAML的理解和对于JavaConfig的理解,这两点相对较为简单,本质上是简化了xml文件,并提供等价的配置表述能力。

1 丰富的工具链为SpringBoot的推广带来了利好。

2 SpringBoot的工具链主要来自于两个方面:

  1) 原有Spring积累的工具链;

  2) SpringMVC或者其他REST框架使用>

SpringBoot自身对于前面提到的配置文件:“applicationyml”提供了多个“Profile”,可以便于开发者描述不同环境的配置,这些配置例如数据库的连接地址、用户名和密码。

但是对于企业用户而言,把不同环境的配置,写到同一个配置文件中,是极其不安全的,是一个非常危险的动作。

有一个经常被提及的例子是,随着开源的进行,很多互联网公司,都由于把相关的代码提交到github之类的开源代码社区,并且没有对代码进行严格的配置审查,导致一些”password”被公开。有些不良用心的人,就利用搜索工具,专门去挖掘这些关键字,进而导致数据库被“拖库”。

所以对于企业用户,更多的应该是采用集中式的配置管理系统,将不同环境的配置严格区分地存放。

虽然SpringBoot的actuator自身提供了基于“用户名+口令”的最简单的认证方式,但它保护的是对框架自身运行期的性能指标敏感数据的最基本的保护。这种保护在实际应用过程中,“用户名+口令”的管理是缺乏的,“用户名+口令”的安全配置过程是缺失的。

SpringBoot也不提供对于我们自己开发的功能的任何防护功能。

一般来讲,一个安全的信道(信息传输的通道),需要通信双方在进行正式的信息传输之前对对方进行身份认证,服务提供方还需要在此基础之上,对请求方的请求进行权限的校验,以确保业务安全。这些内容也需要基于SpringBoot进行外围的安全扩展,例如采用前面提到的S-EDA进行进程级别的安全管控。这些还需要配套的安全服务提供支持。

一般来说,只要企业与互联网对接,那么随便一个面向消费者的“市场活动”,就有可能为企业带来井喷的流量。

传统企业内,更多的系统是管理信息类的支撑系统,这类系统在设计时的主要用户是企业内部员工以及有限的外部供应商。这类系统存在于企业内部的时间一直很长,功能耦合也很多,在功能解耦前,是非常不适合的,或者说绝对不可以直接为互联网的用户进行服务的。

SpringBoot自身并没有提供这样的流控措施,所以需要结合前面提到的S-EDA进行流量的控制,并结合下层的水平扩展能力(例如,Kubernets)进行流量负载合理的动态扩容。

另外,在长业务流程的设计上,也尽可能地采用异步的方式,比如接口调用返回的是一个“受理号”,而不是业务的处理结果,避免井喷业务到来时,同步调用所带来的阻塞导致系统迅速崩溃,这些也都是SpringBoot自身并不解决的问题。

下面我们总结一下:

以上就是关于业界良心!Github热榜第七的SpringBoot笔记(阿里内测版)终于开源全部的内容,包括:业界良心!Github热榜第七的SpringBoot笔记(阿里内测版)终于开源、SpringBoot 参数校验,高级特性,非常实用、Centos 启动Spring boot项目慢的原因等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9667543.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-30
下一篇2023-04-30

发表评论

登录后才能评论

评论列表(0条)

    保存