版本号 | 作者 | SpringCloud版本号 | 备注 | |
---|---|---|---|---|
v20200717 | 学生宫布 | 8416837 | Hoxton.SR4 | 微服务 |
课题 | 基于springCloud的微服务架构的实现 | |
---|---|---|
目标 | 了解微服务;学会搭建基础的微服务项目结构;学会服务通信; |
|
时间 | 根据基础 分钟 | |
分享人 | 研发部-学生宫布 |
SpringCloud微服务日常操作-持续更新
点击目录直达↓
尊重版权,转载请注明出处,点击进入原文
微服务介绍
什么是微服务?
定义
简单地说,微服务架构风格就是一种将单个应用
拆分成一组
小服务开发的方法,每一个小服务运行在它自己的进程
中并且使用轻量的协议通信,通常是一个HTTP
资源API。这些服务围绕业务能力构建并且由自动化部署
机器部署。这些服务有着最小化的中央管理,这个中央管理可以使用不同语言编写,并使用不同的数据存储
技术。
———— James Lewis and Martin Fowler
开发起来有什么不同
- 把基础框架、CI/CD建设好后,和单体项目开发没两样
选择微服务的理由
单体架构的缺陷日益增长
技术栈成熟
社区活跃
优势
-
简单,解决复杂性
:架构复杂,但开发业务相对简单, -
易于开发和维护
: 一个微服务只会关注一个特定的业务功能,所以它业务清晰、代码量较少。 开发和维护单个微服务相对简单。而整个应用是由若干个微服务构建而成的,所以整个应用也会被维持在一个可控状态。 -
单个微服务启动较快
: 单个微服务代码量较少, 所以启动会比较快。 -
迭代方便
: 单体应用只要有修改,就得重新部署整个应用,微服务解决了这样的问题。 一般来说,对某个微服务进行修改,只需要重新部署这个服务即可。 -
技术栈不受限
: 在微服务架构中,可以结合项目业务及团队的特点,合理地选择技术栈。例如某些服务可使用关系型数据库MySQL;某些微服务有图形计算的需求,可以使用Neo4j;甚至可根据需要,部分微服务使用Java开发,部分微服务使用Node.js等开发。 -
易于定位BUG
: 排查范围缩小了 -
坚固
:处理好熔断,系统不会因为单一模块的崩溃而全盘宕机 -
降低了耦合度
: 松耦合。把模块拆分,使用接口或消息通信,降低模块之间的耦合度 -
责任清晰
: 把项目拆分成若干个子项目,不同的团队负责不同的子项目 -
扩展方便
: 增加功能时只需要再增加一个子项目 -
部署方便
: 可以灵活的进行分布式部署 -
细粒度较细,提高代码的复用性
: 比如 service 层,如果不采用分布式 REST 服务方式架构就会在手机 wap 商城,微信商城,PC,Android,IOS 每个端都要写一个 service 层逻辑,开发量大,难以维护一起升级,这时候就可以采用分布式 REST 服务方式,公用基础服务层。 -
弹性节点
:灵活集群,针对某一服务增减节点 -
开发难度
:当基础架构搭建完毕后,开发者基于模板开发,学习成本几乎是0
单体架构缺点
-
复杂性高: 以一个百万行级别的单体应用为例,整个项目包含的模块非常多、模块的边界模糊、 依赖关系不清晰、 代码质量参差不齐、 混乱地堆砌在一起。可想而知整个项目非常复杂。 每次修改代码都心惊胆战, 甚至添加一个简单的功能, 或者修改一个 Bug 都会带来隐含的缺陷。
-
技术债务: 随着时间推移、需求变更和人员更迭,会逐渐形成应用程序的技术债务, 并且越积 越多。“ 不坏不修”, 这在软件开发中非常常见, 在单体应用中这种思想更甚。 已使用的系统设计或代码难以被修改,因为应用程序中的其他模块可能会以意料之外的方式使用它。
-
部署频率低: 随着代码的增多,构建和部署的时间也会增加。而在单体应用中, 每次功能的变更或缺陷的修复都会导致需要重新部署整个应用。全量部署的方式耗时长、 影响范围大、 风险高, 这使得单体应用项目上线部署的频率较低。 而部署频率低又导致两次发布之间会有大量的功能变更和缺陷修复,出错率比较高。
-
可靠性差: 某个应用Bug,例如死循环、内存溢出等, 可能会导致整个应用的崩溃。
-
定位BUG效率低,不细化,排查范围较大。
-
扩展能力受限: 单体应用只能作为一个整体进行扩展,无法根据业务模块的需要进行伸缩。例如,应用中有的模块是计算密集型的,它需要强劲的CPU; 有的模块则是IO密集型的,需要更大的内存。 由于这些模块部署在一起,不得不在硬件的选择上做出妥协。
-
阻碍技术创新: 单体应用往往使用统一的技术平台或方案解决所有的问题, 团队中的每个成员可能都必须使用相同的开发语言和框架,要想引入新框架或新技术平台会非常困难。
-
日益臃肿:依赖、废弃代码等
学习微服务的其它好处
- 对单体项目、系统集成的理解更深,有其指导、融会贯通意义
演变
- 单体项目 -> 面向服务的架构 -> 微服务
PS
:图片来自网络 - MVC框架的缺点
系统按照Controller、Service、Dao层次划分,虽然在建设初期技术结构清晰。但每个业务逻辑代码都分散到不同代码框,业务结构不直观,不利于后期业务重构。 业务代码与MVC技术栈深度耦合( 而微服务可以使用不同的技术栈),某层技术框架升级,导致整体服务不可复用。 由于代码分散,支持版本化成本很高。
体系
- SpringCloud Struct Tree
应用场景
多系统的项目;
持续迭代的大项目;
单体项目拆分迭代;
- 典型的分布式系统:
ps:图片来自网络 - 架构图-简版
服务划分
划分原则:业务划分和功能划分:业务层、基础服务层(做底层技术支撑)
既互相独立,又彼此联系,这叫松散耦合
实际例子:订单服务、产品服务、财务服务、工具服务为基础服务,其它各个业务模块的服务会调用这些基础服务。各个业务模块的服务都是根据业务领域进行划分的,同一业务领域下实现技术不同会被划分为两个服务,比如产品展示和订单原本属于同一个大的领域,但其因为实现技术和质量要求不同需要划分为两个服务。因为短险接入量大,而且大部分是跟第三方合作接入,因此设计短险接入公共接口服务平台处理大量短险订单.
技术栈
技术栈表格
技术栈 | 释义 |
---|---|
spring-cloud-alibaba-dependencies | 依赖管理 |
OAuth2.0 | 授权 |
SpringSecurity | 安全 |
Swagger | 文档 |
Nacos | 注册中心&&配置中心 |
FeignClient | 声明式HTTPClient |
Ribbon | 软负载 |
alibaba-sentinel | 熔断器&&仪表盘&&控制台 |
spring-cloud-starter-zipkin | 链路追踪 |
SkyWalking | 链路追踪 |
spring-admin | 服务监控 |
Netty | 网关服务器 |
HikariCP | 连接池 |
Redis | 消息通道&&缓存 |
Kafka | 消息 |
Docker | 部署环境 |
Jenkins Shell Python | CI&&CD |
RSA | 加解密 |
区块链 | 超级账本 |
等等 |
项目结构
根节点项目
微服务父项目
微服务工程A
微服务工程B
微服务工程C
基础服务
服务A
服务B
服务C
网关
好处是便于批量执行构建工具的命令,如Maven命令;分类清晰,便于理解工程之间的关系,是服务还是辅助工具一目了然。
命名规范
代码级别的相关命名
- 包名:
com.abc.api
,com.abc.storage
,大包名三级,com.公司.功能
,或com.公司+公司产品小驼峰写法.功能
- 类名:
AbcConchWebApp
,公司-产品-工程类型-类类型,Web指视图层,App指启动类后缀 - 服务名 公司名称简写-产品名称-功能+Service后缀,三级,否则不便于管理和命名意义连接。正例如
Abc-conch-adminService
,即京信海螺平台系统管理服务 - And so on
LB - 负载均衡
- 软负载 代码做的非硬件负载
- 轮询、随机、一致性hash、活跃度
如图:
由图可知,当集群时,无论是代理服务器,还是局域网微服务,都须有负载均衡或路由技术。
一般来说,负载均衡的大概原理是客户端智能轮询访问服务端集群,甚至根据服务端的繁忙度做出合适路由判断。比如,有3个服务端集群A1/A2/A3(3个集群各自都能执行完整业务逻辑,是平级关系)。有了负载均衡器,当客户端请求蜂拥而至时,会轮询请求服务端A1、A2、A3,使请求达到均衡,减轻单个服务端受压,保证集群服务端均衡受力,提高项目稳定性。SpringCloud微服务使用FeignClient,默认实现负载均衡和熔断器。
前后端分离
- 通过网关调用微服务,结构清晰
- 后端服务开放接口,使用安全SDK调用后端API
优势
多客户端灵活
提高响应速度
模块部署
便于前后端人员分离
治理体系
Web容器
- Netty
- Tomcat
注册中心
技术栈 | 特点 | 备注 |
---|---|---|
Nacos | 阿里生态、活跃、上升期 | 赞 |
Eureka | ||
Zookeeper | ||
Consul |
注册中心智能:
作用
服务发现、路由广播、多播
技术:
- 长连接 保证实时更新路由表;保证高可用。心跳机制,一旦增减路由,实时通知到位。
- 路由映射表 维护服务与地址的映射表,集群时,消费者通过服务名称/负载均衡及路由调用具体服务;如果不通过注册中心,写死一个url地址调用服务,也是可以的,这相当于普通的HttpClient请求,只要合法,就能请求成功;
- 有效的水平扩展
注册中心自身高可用
多节点部署,数据同步。同步复制、异步刷盘。
兼容各种微服务
- 各个模块的技术栈不同,如:编程语言不同,亦可。
服务通信-RPC风格
- 单体项目通信,调用本地方法
- 微服务通信,就像调用本地方法一样
- 远程调用,像调用本地函数-方法一样优雅。封装了实现细节。
public interface HelloWorldService {
String sayHello(String msg);
}
public class HelloWorldServiceImpl implements HelloWorldService {
@Override
public String sayHello(String msg) {
String result = "hello world " + msg;
System.out.println(result);
return result;
}
}
Dubbo 缺省使用单播发送提供者地址信息给消费者,如果一个机器上同时启了多个消费者进程,消费者需声明 unicast=false,否则只会有一个消费者能收到消息。类似消息队列技术栈的广播消费、集群消费。
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- provider's application name, used for tracing dependency relationship -->
<dubbo:application name="demo-provider"/>
<dubbo:registry address="multicast://224.5.6.7:1234" />
<!-- use dubbo protocol to export service on port 20880 -->
<dubbo:protocol name="dubbo"/>
<!-- service implementation, as same as regular local bean -->
<bean id="HelloWorldService" class="org.apache.dubbo.demo.provider.HelloWorldServiceImpl"/>
<!-- declare the service interface to be exported -->
<dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService"/>