单体架构
在软件设计中,经常提及和使用经典3层模型,即表示层、业务逻辑层、数据访问层。
表示层:用于直接和用户交互,也称为交互层,通常是网页、UI等
业务逻辑层:即业务逻辑处理层,例如用户输入的信息要经过业务逻辑层的处理后才能展现给用户
数据访问层:用于操作数据库,用户在表示层会产生大量的数据,通过数据访问层对数据库进行读写操作
一个经典的单体应用就是将所有的业务场景的表示层、业务逻辑层和数据访问层放在一个工程中最终经过编译、打包,部署在一台服务器上。

LTMJ应用服务器示
如左图所示,LTMJ系统即是
服务器是linux系统,
开发应用程序语言是JAVA,
部署在Tomcat上,
采用MySQL数据库

单体架构有什么问题
随着用户越来越多,程序承受的并发越来越高,单体应用的并发能力有限
单体应用的业务都在用一个程序中,随着业务的扩张、复杂度的增加,单体应用的修改或添加业务和或许会给其他业务带来一定的影响,导致测试难度增加
单体应用集群架构
1 系统仍然为单体应用
2 面对海量用户,数据库将会成为瓶颈,解决方案:分布式数据库,分库分表
3 持续交付能力差,业务越来越复杂,代码越多,修改的和添加代码所需时间长,新人熟悉代码时间长,成本高

什么是微服务
- 微服务最早由Martin Fowler与James Lewis于2014年共同提出,微服务架构风格是一种使用一套小服务来开发单个应用的方式途径,每个服务运行在自己的进程中,并使用轻量级机制通信,通常是HTTP API,这些服务基于业务能力构建,并能够通过自动化部署机制来独立部署,这些服务使用不同的编程语言实现,以及不同数据存储技术,并保持最低限度的集中式管理。
- 微服务的特性:
- 按业务拆分为一个独立运行的程序,即服务单元
- 服务之间通过HTTP协议相互通讯
- 自动化部署
- 可以使用不同编程语言
- 可以使用不同存储技术
- 服务集中化管理
- 微服务是一个分布式系统
微服务单元按业务拆分
微服务的“微”是按照业务拆分,一个大的业务可以拆分成若干的小的业务,一个小的业务又可以拆分成若干更小的业务,业务怎么拆分是有开发人员自己决定
按业务划分的微服务单元独立部署,运行在独立的进程中。这些微服务是高度组件化的模块,并提供了稳定额模块边界,服务与服务之间没有任何的耦合,有非常好的扩展性和复用性。
现有我们开发模式通常由UI团队、服务端团队、数据库和运维团队构成,每个人各司其职,很少跨职能工作。
现在按照业务来划分服务,每个服务都需要UI、服务端、数据库和运维。也就是说一个小的业务的微服务需要动用一个团队的人协作,这显然添加了团队和团队之间交流协作的成本,所以产生了跨职能团队,这个团队复杂一个服务的所有工作,包括UI,服务端和数据库。若这个团队只有1-2个人,就对开发人员提出更高的要求
微服务通过HTTP来互相通信
按照业务拆分的微服务反应独立部署,并允许在各自的进程中。
微服务单元之间的通信方式一般倾向于使用HTTP这种简单的通信机制,更多时候是使用RESTfulAPI
服务与服务之间也可以通过轻量级的消息总线来通信,例如RabbitMQ、Kafaka.通过发送消息或订阅消息来达到服务与服务之间通信的目的
这两种方式有弊端:其通信机制是不可靠的,虽然成功率很高,但还是会有失败的时候
微服务的数据库独立
- 例如 一个应用有这样的几个业务:用户的信息、用户的账户,用户购物车、素报表服务等,所有业务都共用一个数据库,随着业务量的添加,数据库的表数量越来越多,难以管理和维护,并且数据量的添加会导致查询速度越来越慢。

- 每个微服务都有自己的数据库,他们之间数据库是没有联系。每个服务所使用的数据库存储技术å是根据业务需求决定

微服务的自动化部署
- 自动化部署可以提供部署的效率,减少人为的控制,部署过程中出现的错误的概率降低,提供软件的质量
- 构建一个自动化部署的系统,虽然在前期需要开发人员或运维人员学习
- 随着客户实施DevOps,自动化部署必然会成为微服务部署一种方式
如果微服务按照单体架构的部署方式,则部署难度会呈指数增加。随着技术的发展,Docker容器技术、Kubernetes技术的推进,以及自动化部署工具(Jenkins)出现,自动化部署变得越来越简单

服务集中化管理
- 微服务系统是按业务单元来划分,服务数量越多,管理起来就越复杂,因此微服务必须使用集中化管理。目前流行的微服务框架中,例如Spring cloud 采用Eureka来注册服务
分布式架构
- 分布式系统是集群部署,由很多计算机相互协作共同构成,它能够处理海量用户的请求,当分布式系统对外提供服务时,用户是毫不知情的,还以为是一台服务器在提供服务。
- 微服务架构是分布式架构,是集群化部署,会给数据一致性带来困难,分布式系统中的服务通信依赖于网络,网络不好,必然会对分布式系统带来很大的影响,在分布式系统中服务之间相互依赖,如果一个服务出现了故障或网络延迟,在高并发的情况下,会导致线程阻塞,在很短时间内该服务的线程资源会消耗殆尽,最终服务不可用,由于服务的相互依赖,可能会导致整个系统不可用,这就是“雪崩效应”,为了防止此类事件的发生,分布式系统必然要采取相应的措施,例如熔断机制。
熔断机制
- 为了防止雪崩效应事件的发生,分布式系统采用熔断机制。在用Spring cloud构建的微服务系统中,采用了熔断器(即Hystrix组建的Circuit breaker)去做熔断
- 例如在微服务系统中 有a、b、c、d等多个微服务,用户的请求通过网关后再到具体的服务,服务之间相互依赖,例如服务b依赖服务d,一个对外暴露的API需要服务b和服务d相互协作才能完成

如果此时服务b出现故障或者网络延迟在高并发的情况下,服务b会出现大量的线程阻塞,有可能在很短时间内线程资源就会被耗尽,导致服务b的不可用。
如果此时没有熔断机制就会导致雪崩效应
为了解决此问题,引入熔断机制:


当熔断器处于关闭状态时,请求是可以被放行的;
当熔断器统计的失败次数触发开关时,转为打开状态。
当熔断器处于打开状态时,所有请求都是不被放行的,直接返回失败;
只有在经过一个设定的时间窗口周期后,熔断器才会转换到半开状态
当熔断器处于半开状态时,当前只能有一个请求被放行;
这个被放行的请求获得远端服务的响应后,假如是成功的,熔断器转换为关闭状态,否则转换到打开状态。

微服务优势
微服务是松藕合的,无论是在开发阶段或部署阶段都是独立的。
能够快速响应, 局部修改容易, 一个服务出现问题不会影响整个应用。
易于和第三方应用系统集成, 支持使用不同的语言开发, 允许你利用融合最新技术。
每个微服务都很小,足够内聚,足够小,代码容易理解。团队能够更关注自己的工作成果, 聚焦指定的业务功能或业务需求。
开发简单、开发效率提高,一个服务可能就是专一的只干一件事, 能够被小团队单独开发,这个小团队可以是 2 到 5 人的开发人员组成。
微服务的不足
微服务的复杂度
开发人员需要付出一定的学习成本去掌握更多架构知识和框架知识;另外服务与服务之间是相互依赖,若修改一个服务就会对另外一个服务产生影响;
分布式事务
在微服务架构应用中,需要更新不同服务所使用的不同的数据库
服务的划分
如何拆分服务
服务的部署
需要对微服务有足够强的控制力,及自动化部署(例如使用阿里云提供paas服务)
微服务特点
根据微服务的特点,一个微服务应该有以下功能
- 服务的注册和发现
- 服务的负载均衡
- 服务的容错
- 服务的网关
- 服务配置的统一管理
- 链路跟踪
- 实时日志
服务的注册与消费
微服务系统是由很多个单一职责的服务单元组成,需要服务注册中心类统一管理这些微服务实例,方便查看每个微服务实例的健康状态。
服务注册是指向服务注册中心注册一个服务实例,服务提供者将自己的服务信息(服务名、IP地址)告知服务注册中心。
服务发现是指当服务消费者需要消费另外一个服务时,服务注册中心能够告知服务消费者它所要消费服务的实例信息(如服务名,IP地址等)
服务消费者一般使用HTTP协议来进行服务消费
服务注册中心会提供服务的健康检查方案,检查被注册的服务是否可用

服务的负载均衡
在微服务架构中,服务之间的相互调用一般是通过HTTP通信协议来实现。但网络往往不可靠,为了保证服务的高可用,服务单元往往集群化部署。那服务消费者该调用哪个服务提供者的实例呢?
如图所示:所有服务都向服务注册中心注册(IP,服务名),服务消费者集成负载均衡组件,该组件会向服务消费者获取服务的注册列表信息,每隔一段时间重现刷新获取改列表。当服务消费者消费服务时,负载均衡组件获取服务提供者所有实例注册信息,并通过一定的负载均衡策略,选择一个服务提供者的实例,向该实例进行服务消费。
另外服务注册中心不但需要定时接收每个服务的心跳(用来检查服务是否可用),而且每个服务会定期获取服务注册列表的信息,当服务实例数量很多,服务注册中心承担了非常大的负载。由于服务注册中心很重要,所以必须实现高可用。

服务的容错
熔断机制
服务网关

服务配置的统一管理
- 在微服务架构中,需要有统一管理配置文件的组件,例如Spring cloud的config,阿里Nacos
如图所示:
* 1 )首先Config server读取配置文件仓库的配置信息,仓库可以是本地仓库或git
* 2) 配置服务启动时,读取配置文件信息,缓存在内存中
* 3 )由于a、b、c等服务指定了向配置服务读取配置信息,所以这些服务启动时就会向配置中心读取配置

服务链路跟踪
微服务系统有很多个服务,且服务与服务之间的调用有可能很复杂,一旦出现异常和错误很难定位。
所以微服务架构中必须实现分布式链路跟踪,去跟进一个请求到底有哪些服务参与,参与的顺序又是怎么样的。从而使每个请求链路清晰可见
如果所示 一个接口首先调服务A,后再调用B,而B需要调用C,对于这样一个请求需要三个服务,怎么样将它的请求过程的数据记录下,这就需要服务链路跟踪
目前链路跟踪组件:Google的Dapper、Twitter的Zipkin

Spring Cloud

SpringCloud
- SpringCloud是基于Spring boot的。而Spring boot是简化了Spring的复杂的配置和依赖管理,从而提高在开发和部署上的效率。
- 目标:通过一系列的开发组件和框架,帮助开发者迅速搭建一个分布式的微服务系统。
常用组件:



构建微服务
- 开发环境:Jdk1.8,MAVEN3.2.3,Eclipse
- spring cloud版本:Greenwich.SR2
- Spring boot:2.1.6.RELEASE

- 部署环境:
- k8s matser: 2核cpu 系统 cenots 7.9 硬盘20g 内存2048m ip:192.168.31.59 docker版本:18.09.7,k8s:1.15.1
- k8s node :2核cpu 系统 cenots 7.9 硬盘20g 内存3072 m ip:192.168.31.181 docker版本:18.09.7,k8s:1.15.1
- docker:CPU1个,内存521M硬盘20G, 含有JAVA和MAVEN环境 镜像仓库使用阿里云
- 部署说明
下载[soft.zip]链接: https://pan.baidu.com/s/1jp2UuZUX-DtpVz51ucsAFA 提取码: 3ahf
百度网盘不能下载请及时联系

springcloud.zip

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| ------------------------------使用阿里云镜像仓库----
https://help.aliyun.com/document_detail/60945.html?spm=a2c4g.11186623.6.542.48983d31EbMHWT
tr -d '\r' </root/soft/installDocker.sh > /root/soft/installDocker_new.sh && chmod +x /root/soft/*.sh && /root/soft/installDocker_new.sh init installDocker
tr -d '\r' </root/soft/installDocker.sh > /root/soft/installDocker_new.sh && chmod +x /root/soft/*.sh && /root/soft/installDocker_new.sh loadJavaDockerImage
tr -d '\r' </root/soft/installDocker.sh > /root/soft/installDocker_new.sh && chmod +x /root/soft/*.sh && /root/soft/installDocker_new.sh configJava
cd /root/springcloud/deployment
tr -d '\r' <buildDocker.sh > buildDocker_bew.sh && chmod +x *.sh && ./buildDocker_bew.sh -Dver=1.0.0 -Denv=aliyun_dev
tr -d '\r' <buildDocker.sh > buildDocker_bew.sh && chmod +x *.sh && ./buildDocker_bew.sh -Dver=1.0.0 -Denv=aliyun_dev EurekaServer tr -d '\r' <buildDocker.sh > buildDocker_bew.sh && chmod +x *.sh && ./buildDocker_bew.sh -Dver=1.0.0 -Denv=aliyun_dev configServer tr -d '\r' <buildDocker.sh > buildDocker_bew.sh && chmod +x *.sh && ./buildDocker_bew.sh -Dver=1.0.0 -Denv=aliyun_dev ServiceClient tr -d '\r' <buildDocker.sh > buildDocker_bew.sh && chmod +x *.sh && ./buildDocker_bew.sh -Dver=1.0.0 -Denv=aliyun_dev ServiceClientB tr -d '\r' <buildDocker.sh > buildDocker_bew.sh && chmod +x *.sh && ./buildDocker_bew.sh -Dver=1.0.0 -Denv=aliyun_dev gateway
tr -d '\r' </root/soft/installk8sMaster.sh > /root/soft/installk8sMaster.sh_new.sh && chmod +x /root/soft/*.sh && /root/soft/installk8sMaster.sh_new.sh
tr -d '\r' </root/soft/installk8sMaster.sh > /root/soft/installk8sMaster.sh_new.sh && chmod +x /root/soft/*.sh && /root/soft/installk8sMaster.sh_new.sh configMaster
kubectl get nodes
kubeadm token create --print-join-command
tr -d '\r' </root/soft/installk8sNode.sh > /root/soft/installk8sNode.sh_new.sh && chmod +x /root/soft/*.sh && /root/soft/installk8sNode.sh_new.sh
echo "192.168.31.200 apiserver.demo" >> /etc/hosts
kubectl get nodes -o wide
tr -d '\r' </root/soft/installk8sMaster.sh > /root/soft/installk8sMaster.sh_new.sh && chmod +x /root/soft/*.sh && /root/soft/installk8sMaster.sh_new.sh configKubectl
tr -d '\r' </root/soft/installk8sMaster.sh > /root/soft/installk8sMaster.sh_new.sh && chmod +x /root/soft/*.sh && /root/soft/installk8sMaster.sh_new.sh installIngress
eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJvYXJkIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6Imt1Ym9hcmQtdXNlci10b2tlbi01OTk4ZiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJvYXJkLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJjMjMzM2Y2Mi00OTdlLTQwNGUtYmRmOS1kMWMwNjg4OWQwZWEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3Vib2FyZDprdWJvYXJkLXVzZXIifQ.fGttYtIb3w6YrqYIrZodd7J0PXz5cCT8P7w7L_0V0ddCJY8gaEm-n5dTQurfigJuTcSUAzjJgHXAyp4sb-XZ8ma5jnnipZfW3543oiFo-gcbKwvVGPQYUqJ-UrCQlw_yW43iJ6Y7DzFPrVwfQ1ByfoUCDnEvDTLxG6yC3qNlzlVAsBMtreeUXqNl-xMIUAa-GQZL7gaddRiBQhmY96a67NFhqgiU8Lz_lv8NiQxAZT5ECDsoCl9-qzx7pm04I5W3tS2wPrew06Fqlpf0sxLWY__bd_SnTbFKlCGRA9_-h4uDZW9x3vn6FxfS-RT_o9Yd8GZYKr8I2P5cPZ8Xqx094w
kubectl get nodes -o wide
tr -d '\r' </root/soft/installk8sMaster.sh > /root/soft/installk8sMaster.sh_new.sh && chmod +x /root/soft/*.sh && /root/soft/installk8sMaster.sh_new.sh createSecret
tr -d '\r' </root/soft/installk8sMaster.sh > /root/soft/installk8sMaster.sh_new.sh && chmod +x /root/soft/*.sh && /root/soft/installk8sMaster.sh_new.sh deploy
demodev.yanwen.com.cn--ingress 配置 svc-nginx:80, nginx访问http://svc-ing-gateway-gateway:6083 demodev.intranet.local --ingress 配置http://svc-ing-gateway-gateway:6083
eureka.intranet.local ingress 配置svc-ing-eureka-springclouddemoeureka:6080
eureka: eureka.intranet.local gateway: http://demodev.yanwen.com.cn/searviceA/users/111 http://demodev.yanwen.com.cn/searviceB/users/11 内网 http://demodev.intranet.local/searviceA/users/111 http://demodev.intranet.local/searviceB/users/11
扩容searviceA 待启动后 kubectl get deployment --all-namespaces kubectl scale --replicas=2 deployments/rs-serviceclient -n springclouddemo
kubectl scale --replicas=1 deployments/rs-serviceclient -n springclouddemo
在访问 测试ribbon负载均衡组件 http://demodev.yanwen.com.cn/searviceB/users/11
helm delete --pruge configserver helm delete --pruge gateway helm delete --pruge nginx helm delete --pruge serviceclient helm delete --pruge serviceclientb helm delete --pruge springclouddemoeureka helm delete --pruge svcingress
dir=/root/springcloud/deployment cd $dir
tr -d '\r' <deploy.sh > deploy_bew.sh && chmod +x $dir/*.sh && ./deploy_bew.sh -Dver=1.0.0 -Denv=ali_dev -Dnamespace=springclouddemo -Dname=springclouddemoeureka eureka tr -d '\r' <deploy.sh > deploy_bew.sh && chmod +x $dir/*.sh && ./deploy_bew.sh -Dver=1.0.0 -Denv=ali_dev -Dnamespace=springclouddemo -Dname=configserver configServer tr -d '\r' <deploy.sh > deploy_bew.sh && chmod +x $dir/*.sh && ./deploy_bew.sh -Dver=1.0.0 -Denv=ali_dev -Dnamespace=springclouddemo -Dname=serviceclient ServiceClient tr -d '\r' <deploy.sh > deploy_bew.sh && chmod +x $dir/*.sh && ./deploy_bew.sh -Dver=1.0.0 -Denv=ali_dev -Dnamespace=springclouddemo -Dname=serviceclientb ServiceClientB tr -d '\r' <deploy.sh > deploy_bew.sh && chmod +x $dir/*.sh && ./deploy_bew.sh -Dver=1.0.0 -Denv=ali_dev -Dnamespace=springclouddemo -Dname=svcingress ingress
tr -d '\r' <deploy.sh > deploy_bew.sh && chmod +x $dir/*.sh && ./deploy_bew.sh -Dver=1.0.0 -Denv=ali_dev -Dnamespace=springclouddemo -Dname=gateway gateway tr -d '\r' <deploy.sh > deploy_bew.sh && chmod +x $dir/*.sh && ./deploy_bew.sh -Dver=1.16.1 -Denv=ali_dev -Dnamespace=springclouddemo -Dname=nginx nginx ------------------------------使用阿里云镜像仓库----
|


本文标题:微服务
文章作者:peter.tan
发布时间:2022-09-03
最后更新:2022-09-05
原始链接:https://petertanblog.github.io/2022/09/03/%E5%BE%AE%E6%9C%8D%E5%8A%A1/
版权声明:Copyright © 2022 Peter.tan