SpringCloud+Nginx架构的主要组件
以crazy-springcloud开发脚手架为例,一个SpringCloud+Nginx应用的架构如图1-1所示。
图1-1基于SpringCloud+Nginx的应用架构
Nginx作为反向代理服务器,代理内部Zuul网关服务,通过Nginx自带的负载均衡算法实现客户端请求的代理转发、负载均衡等功能。
Zuul网关主要实现了微服务集群内部的请求路由、负载均衡、统一校验等功能。虽然在路由服务和负载均衡方面,Zuul和Nginx的功能比较类似,但是Zuul是自身注册到Euka/Nacos,通过微服务的serviceID实现微服务提供者之间的路由和转发。
Euka、Nacos都是SpringCloud技术体系中提供服务注册与发现的中间件。Euka是Netflix开源的一款产品,提供了完整的服务注册和发现,是SpringCloud“全家桶”中的核心组件之一。
Nacos是阿里巴巴推出来的一个开源项目,也是一个服务注册与发现中间件,它用于完成服务的动态注册、动态发现、服务管理,还兼具了配置管理的功能。Nacos提供了一组简单易用的特性集,用于实现动态服务发现、服务配置、服务元数据及流量管理。
由于新版本的Euka已经闭源,而阿里巴巴的Nacos除了具备Euka注册中心功能外,还具备SpringCloudConfig配置中心的功能,因此大大地降低了使用和维护的成本。另外,Nacos还具有分组隔离功能,一套Nacos集群可以支撑多项目、多环境。综合上述多个原因,在实际的开发场景中,推荐大家使用Nacos。但是,本文出于学习目的,注册中心和配置中心的内容还是介绍Euka+Config组合,其实在原理上,Nacos和Euka+Config组合是差不多的。
除了一系列基础设施中间件技术组件之外,微服务架构中大部分独立业务模型都是以服务提供者的角色出现的。一般来说,系统可以按照各类业务模块进行细粒度的微服务拆分,例如秒杀系统中的用户、商品等,每个业务模块拆分成一个微服务提供者Provider组件,作为独立应用程序进行启动和执行。
在SpringCloud生态中,微服务提供者Provider之间的远程调用是通过Feign+Ribbon+Hystrix组合来完成的:Feign用于完成RPC远程调用的代理封装;Ribbon用于在客户端完成各远程目标服务实例之间的负载均衡;Hystrix用于完成自动熔断降级等多个维度的RPC保护。在Nginx+SpringCloud架构中还存在一系列辅助中间件,包括日志记录、链路跟踪、应用监控、JVM性能指标、物理资源监控等等。本文并没有对上述辅助中间件做专门的介绍。
SpringCloud和SpringBoot的版本选择
SpringCloud是基于SpringBoot构建的,它们之间的版本有配套的对应关系。在构建项目时,要注意版本之间的这种对应关系,版本若对应不上则会出现问题。
SpringCloud和SpringBoot的版本配套关系如表1-1所示。
表1-1 SpringCloud与SpringBoot的版本配套关系
表1-1SpringCloud与SpringBoot的版本配套关系
SpringCloud包含一系列子组件,如SpringCloudConfig、SpringCloudNetflix、SpringCloudOpenfeign等,为了防止与这些子组件的版本号混淆,SpringCloud的版本号全部使用英文单词形式命名。具体来说,SpringCloud的版本号使用了英国伦敦地铁站的名称来命名,并按字母A~Z的次序发布版本,它的第一个版本叫作Angel,第二个版本叫作Brixton,以此类推。另外,每个大版本在解决了一个严重的Bug后,SpringCloud会发布一个ServiceRelease版本(小版本),简称SRX版本,其中X是顺序的编号,比如Finchley.SR4是Finchley大版本的第4个小版本。
大家做技术选型时非常喜欢用最高版本,但是对于Spring全家桶的选择来说,高版本不一定是最佳选择。比如,目前最高的SpringCloudHoxton版本是基于SpringBoot2.2构建的,SpringBoot2.2又是基于SpringFramework5.2构建的,也就是说,这是一次整体的、全方位的大版本升级。大家在项目上会用到非常多的第三方组件,总会有一些组件没有来得及进行配套升级而不能兼容SpringBoot2.2或SpringFramework5.2,如果贸然地进行基础框架的整体升级,就会给项目开发带来各种各样的疑难杂症,甚至带来潜在的线上Bug。
除此之外,SpringCloud高版本推荐了不少自家的新组件,但是这些新组件没有经过大规模实践应用的考验,其功能尚待丰富和完善。以负载均衡组件为例,SpringCloudHoxton推荐的自家组件springcloud-loadbalancer在功能上与Ribbon的负载均衡功能相比就弱很多。
SpringCloudFinchley到Genwich版本的升级其实很小,可以说微乎其微,主要是提升了对Java11的兼容性。然而,在当前的生产场景中Java8才是各大项目的主流选择,另外Java11(年4月之后的升级补丁)已经不完全免费了。当然,和Java11一样,Java8在年4月之后的补丁版本也面临收费的问题。使用Java8的理由是,自年3月18日发布起至目前,Java8被广泛使用,且被维护了这么多年,已经非常成熟和稳定了。
综上所述,本文选用了SpringCloudFinchley作为学习、研究和使用的版本,推荐使用的子版本为Finchley.SR4。具体的Maven依赖坐标如下:
dependencyManagementdependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversionFinchley.SR4/versiontypepom/typescopeimport/scope/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-dependencies/artifactIdversion2.0.8.RELEASE/versionscopeimport/scopetypepom/type/dependency/dependencies/dependencyManagement
SpringCloud微服务开发所涉及的中间件
在基于crazy-springcloud脚手架(其他的脚手架类似)的微服务开发和自验证过程中,所涉及的基础中间件大致如下:
1.ZooKeeper
ZooKeeper是一个开放源码的分布式协调应用程序,是大数据框架Hadoop和HBase的重要组件。在分布式应用中,它能够高可用地提供保
障数据一致性的很多基础功能:分布式锁、选主、分布式命名服务等。
在crazy-springcloud脚手架中,高性能分布式ID生成器用到了ZooKeeper。
2.Redis
Redis是一个高性能的缓存数据库。在高并发的场景下,Redis可以对关系数据库起到很好的缓冲作用;在提高系统的并发能力和响应速度方面,Redis至关重要。crazy-springcloud脚手架的分布式Session用到了Redis。
3.Euka
Euka是Netflix开发的服务注册和发现框架,它本身是一个REST服务提供者,主要用于定位运行在AWS(Amazon云)上的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud将Euka集成在子项目spring-cloud-netflix中,以实现SpringCloud的服务注册和发现功能。
4.SpringCloudConfig
SpringCloudConfig是SpringCloud全家桶中最早的配置中心,虽然在生产场景中很多企业已经使用Nacos或者Consul整合型的配置中心替代了独立的配置中心,但是Config依然适用于SpringCloud项目,通过简单地配置即可使用。
5.Zuul
Zuul是Netflix开源网关,可以和Euka、Ribbon、Hystrix等组件配合使用,SpringCloud对Zuul进行了整合与增强,使用它作为微服务集群的内部网关,负责给集群内部的各个Provider(服务提供者)提供RPC路由和对请求进行过滤。
6.Nginx/OpenResty
Nginx是一个高性能HTTP和反向代理服务器,是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点开发的Web服务器。Nginx源代码以类BSD许可证的形式对外发布,它的第一个公开版本0.1.0在年10月4日发布,1.0.4版本在年6月1日发布。Nginx因高稳定性、丰富的功能集、内存消耗少、并发能力强而闻名全球,并被广泛使用,百度、京东、新浪、网易、腾讯、淘宝等都是它的用户。OpenResty是一个基于Nginx与Lua的高性能Web平台,它的内部集成了大量精良的Lua库、第三方模块以及大多数的依赖项,用于快速搭建能够处理超高并发的扩展性极高的动态Web应用、Web服务和动态网关。
以上中间件的端口配置以及部分安装与使用的演示视频如表1-2所示。
表1-2 本文案例涉及的主要中间件的端口配置以及部分安装与使用的演示视频
SpringCloud微服务开发和自验证环境
在开始学习SpringCloud核心编程之前,先来介绍一下开发和自验证环境的准备、中间件的安装以及抓包工具的准备。
开发和自验证环境的系统选项和环境变量配置
首先介绍开发和自验证系统的选型。大部分开发人员学习开发都用过Windows环境,在这种情况下,强烈建议使用虚拟机装载CentOS作为自验证环境。为什么要推荐CentOS呢?
1.提前暴露生产环境中的问题
在生产环境上,90%以上的Java应用都是使用Linux环境(如CentOS)来部署的。因此,使用CentOS作为自验证环境可以提前暴露生产环境中的潜在问题,避免在开发时没有发现有问题的程序,一旦部署到生产环境中就出现问题(笔者亲历)。
2.学习Shell命令和脚本
在生产环境中定位、分析、解决线上Bug时,需要用到基础的Shell命令和脚本,因此平时要多使用、多练习。另外,Shell命令和脚本是Java程序员必知必会的面试题。使用CentOS作为自验证环境能方便大家学习Shell命令和脚本。
当然,可以借助一些文件同步或共享工具提高开发效率。比如,可以通过VMwaTools共享Windows和CentOS之间的文件夹,这样在后续的Lua脚本的开发和调试过程中能避免来回地复制文件。
这里给大家介绍一下crazy-springcloud脚手架开发和自验证环境的准备,主要涉及两个方面:
(1)中间件(含Euka、Redis、MySQL等)相关信息的环境变量的配置。
(2)主机名称的配置。
对于中间件相关信息(如IP地址、端口、用户账号等),很多项目都是直接以明文编码的方式存放在配置文件中,这样存在安全隐患甚至会引发泄密的风险。对于这些信息,建议通过操作系统环境变量进行配置,然后在配置文件中使用环境变量而不是明文编码。
例如,可以对Euka的IP提前配置好环境变量EUREKA_ZONE_HOST,然后在应用的配置文件bootstrap.yml中按照如下方式来使用:
euka:client:serviceUrl:defaultZone:${SCAFFOLD_EUREKA_ZONE_HOSTS: