国际化的功能离不开错误码的支持,客户端指定语言到服务端去请求,当出错了服务端会根据错误码和语言找到对应的国际化提示语。从上面图中我们发现,错误码不仅仅是客户端与服务端的交互,后台各个服务间的交互也需要约定的一套错误码。一般一个系统的错误码 code 都是唯一确定的。msg 不同场景下可能不一样,提供给用户的肯定是需要友好且不能暴露底层细节,给开发人员看的就要详细专业的错误内容。网关服务上面维护着多套不同语言的错误码提示语,响应的时候会根据客户端带的 Lang 信息进行国际化转译。模块模块编码错误编码底层描述中文提示语英文提示语库存10001商品规格表关联有误商品不存在goods don’t exist一般国际化的系统中会有多份 xxx_lang.properties文件,每一份代表一种语言的消息提示语。中文一般会转为 Unicode 编码进行存储(这个过程一般开发工具可以设置自动转),这样的处理可以规避不同开发环境下不同编码导致中文乱码。
上述例子发现输出的结果是英文的,显然是不适合在国内环境使用,moment.js 提供了国际化支持,在现有的库中,moment 支持的语言可以说是相对完备了。通过引入对应的国际化资源(语言文件),来切换语言。<script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.27.0/moment.min.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.27.0/locale/zh-cn.min.js"></script><script> var now = moment().calendar(); console.log(now);// 输出当前日历时间 moment().startOf('hour').fromNow(); // 相对这个小时过去了多少分钟 var timestamp = 1593933593236; // 2020年7曰5日下午15点20分38秒 moment(timestamp).fromNow(); // 相对时间戳多久前</script>有关国际化的更多内容可以参考文档。
uni-app 的 API 与微信小程序 API 基本一致。掌握微信小程序 API 对后面的开发很有帮助。微信小程序 API 文档:https://developers.weixin.qq.com/miniprogram/dev/api/
注册微信小程序账号,获取到 AppID,我们后面配置的时候会用到。在 HBuilderX 工具栏,点击发行,选择小程序-微信。输入小程序名称和 AppID,单击发行就可以了。这样我们就会获得一个微信小程序的打包文件,接下来我们来发布微信小程序项目,打开微信小程序开发者工具,导入刚刚生成的微信小程序项目的打包文件,在微信小程序开发者工具中先测试一下,项目运行是否正常,项目测试没有问题后,点击右上角>>按钮,上传代码就可以发布微信小程序了,最后等待微信团队审核通过,别人就可以在线上访问到你的项目了。
业务场景描述有这样一个真实的业务场景:在某大厂某销售业务项目中,由于某大厂销售业务板块业务的持续增加,导致之前原本设计好的项目架构出现了问题,不足以支撑持续增长的业务需要,于是,某大厂程序员对项目架构做了拆分,并最终形成了以 Spring Cloud 为基础架构的微服务分布式项目架构。在拆分了项目架构之后,虽然可以支撑持续增长的业务需要,但是,在拆分后的项目架构中,Hystrix 无法对所有项目进行监控,即 Hystrix 服务监控平台只能监控一个分散的项目,无法对项目整体进行监控。问题原因分析在解决问题之前,我们首先来分析一下这种问题产生的原因。上述场景场景中,项目的架构方式是微服务的分布式架构,而一般来说的 Hystrix 微服务监控平台默认只对一个项目实例起作用,所以,也就导致了一个微服务平台只对一个微服务实例起作用。
在了解了秒杀抢购的业务场景流程之后,接下来我们就需要实现这一业务场景了,那么,这种业务场景我们应该怎么用 RabbitMQ 和 Redis 去实现呢?在使用 RabbitMQ 打造扛得住的高并发环境系列小节内容的第二小节中,我们使用 RabbitMQ 消息通信中间件和 Redis 缓存中间件,对 RabbitMQ 自身的消息队列进行了改造,改造成了一种 Redis 承载的高可用的消息队列,在本节,我们就会用到这一高可用的消息队列。在实现上述实际高并发业务场景时,由于篇幅原因,我们并不会从用户登录开始,逐步地去实现每一个过程,我们只实现在秒杀抢购业务场景中,最核心的部分,也就是,当我们在秒杀抢购商品区域,点击立即购买这个秒杀按钮时,我们后台所需要应对高并发处理的内容。让我们来看看具体应该怎么设计实现吧。
其实真实的原因是因为雪碧的英文名字是Sprite,而雪碧图的英文名是CSS Sprites,他俩同样都有Sprite这个词。左边是雪碧在国内的 Logo,右边是国外的 Logo。可以看到本来在没进入中国市场之前人家就叫Sprite(精灵),只不过进入了中国市场之后,中国区的负责人表示:用户去商店买汽水的时候如果对老板说:老板你这里有没有精灵?听起来就会感觉很奇怪,所以咱们不要被Sprite这个单词给限制住了,咱们应该起一个更符合中文语义的名字,于是乎“雪碧”诞生了。而雪碧图在国外叫做 CSS Sprite(CSS精灵)反正 Sprite 在国内被叫雪碧,那干脆不如咱们就叫它雪碧图吧!——来自最先接触到这项技术的人。所以后来接触这项技术的人也就跟随前人一起叫它雪碧图了。
微前端 尚处在发展时期,其核心概念和 微服务 相似。现阶段较为常用的微前端框架为 single-spa 和 qiankun,后者是基于前者实现的。该技术能做到 技术栈无关,即一个应用,能由多个不同技术的子应用构成,同时做到子应用的相互隔离,这里的隔离就可以选择采用 Web Components 实现。
为了便于理解和展示,我们假设只有两种家具----椅子和桌子。首先定义每种家具的接口,只有一个方法用来获取家具说明。椅子:public interface Chair { void getChairIntroduction();}桌子:public interface Desk { void getDeskIntroduction();}以椅子为例,我们分别实现简约现代和欧式两种风格。简约现代风格椅子:public class ModernStyleChair implements Chair { @Override public void getChairIntroduction() { System.out.println("这是一个现代简约风格的椅子"); }}欧式风格椅子:public class EuropeanStyleChair implements Chair { @Override public void getChairIntroduction() { System.out.println("这是一个欧式风格的椅子"); }}桌子也有两种实现,代码这里省略。产品我们已经编写完成。接下来我们来看看工厂的代码。首先我们定义一个家具工厂接口,可以生产椅子和桌子:public interface FurnitureFactory { Chair createChair(); Desk createDesk();}由于我们支持两种不同的风格,所以我们编写两个实现类。简约风格家具工厂:public class ModernFurnitureFactory implements FurnitureFactory{ @Override public Chair createChair() { return new ModernStyleChair(); } @Override public Desk createDesk() { return new ModernStyleDesk(); }}欧式风格家具工厂:public class EuropeanFurnitureFactory implements FurnitureFactory{ @Override public Chair createChair() { return new EuropeanStyleChair(); } @Override public Desk createDesk() { return new EuropeanStyleDesk(); }}上面的代码中,每种工厂各自实现如何生产两种不同的家具。客户端代码如下:public class Client { public static void main(String[] args) { FurnitureFactory furnitureFactory = new EuropeanFurnitureFactory(); Chair chair = furnitureFactory.createChair(); Desk desk = furnitureFactory.createDesk(); chair.getChairIntroduction(); desk.getDeskIntroduction(); }}客户端代码中,我们实例化的是欧式家具工厂,那么所生产的椅子和桌子应该是欧式风格。执行后输出如下:这是一个欧式风格的椅子这是一个欧式风格的桌子和我们的预期相符。如果想要更换产品族,从现代简约切换到欧式,我们只需要修改一处代码。FurnitureFactory furnitureFactory = new ModernFurnitureFactory();仅通过更换抽象工厂的实现即可实现。修改后执行结果如下:这是一个现代简约风格的椅子这是一个现代简约风格的桌子可以看到已经切换到简约风格的产品族。这个过程中并不需要改任何产品使用的代码。如果增加别的风格产品族,只需要新建新风格的产品族产品,增加新风格产品族的工厂实现即可。类图:
本部分内容,老师会详细介绍本套课程最终需要实现的一种业务场景,此种业务场景是老师自己在实际工作中遇到的真实的业务场景,同学们一定要先对这种业务场景有个清晰地了解之后,在继续学习本小节后续地内容,如果你对这种业务场景没有充分地了解,那么后面的实现思路你将不会看懂,这点同学们注意。本业务场景实际上并不算复杂,我们每个同学在真实的日常生活中,或多或少都会接触到,只不过平时同学们可能不会注意观察或者思考。这种业务场景有一个专有的代名词,相信大家都已经听说过了,那就是’秒杀’业务场景。那么,什么是秒杀业务场景呢?这个秒杀的业务场景,出现在销售行业的居多,比如日常生活中,我们在超市中去购买一种商品,这种商品的价格要比往常的价格要低很多,但是,这种商品的库存数量是有限的,当我们购买这种商品时,必须要在一瞬间完成抢购这一动作。随着互联网时代的快速发展,越来越多的线上电子商城已经出现在人们的日常生活中,以淘宝、京东为代表性的互联网电子商城巨头率先将这些线下的商品购买行为,转换为线上的商品购买功能。针对与上述这种秒杀抢购的业务场景,目前在各互联网电子商城巨头中都是有所体现的,比如我们熟知的双十一活动,以及 618 商品大促活动,这些都是秒杀抢购业务场景的典型代表,那么,这种业务场景在线上又是如何实现的呢?在分析一秒杀抢购业务场景的一个完整的线上业务流程是什么样的之前,我们先来看一下,一般地线上商品购买的一个完整的业务流程是什么样的,如下图所示:首先,用户在有这种秒杀抢购的实际需求之后,用户首先会登录我们的线上商城系统,在用户成功登录本系统之后,用户需要到我们线上商城系统的秒杀抢购专区,用户可以在这个秒杀抢购专区中看到本商城系统中参与秒杀抢购活动的商品,这一过程我们称为用户挑选商品阶段。用户在挑选完自己所需要的商品之后,可以将所需的商品放入购物车中,也可以直接点击下单按钮,来迅速完成对某一具体商品的下单操作。如果用户是将商品放入购物车中,那么用户只能进行一个批量下单的动作,即用户前往自己的购物车中,选中商品之后,点击下单按钮,进行一个批量下单操作,这一过程我们称为用户预下单阶段。在用户将订单创建完毕之后,就需要用户选择对应的支付方式,来完成商品价格的支付动作,对于线上电子商城而言,用户可以选择不同厂家的扫码支付功能来完成支付,这一过程我们称为用户支付阶段。在用户对所购商品支付完成之后,我们需要将用户的商品支付结果返回给用户,告知用户商品支付的状态,是支付成功了,还是支付过程中遇到问题,导致支付失败了,这一过程往往我们会采取轮询的方式实现,这一过程我们称为用户支付状态回调阶段。在用户的支付状态成功回调给用户之后,一个完整的线上商品购买流程就结束了,至于后续地商品物流信息等其他信息就不属于我们商品购买的流程了。在清楚了一般地商品购买全流程之后,我们就不难理解秒杀抢购的业务场景流程了。其实,秒杀抢购的业务场景流程和一般地商品购买流程是一模一样地,只不过在用户预下单阶段,以及用户支付阶段,在同一时刻会有大量的用户请求需要我们处理,这就是秒杀业务场景和一般地商品购买流程中最大的区别点,其他地方并没有什么区别。在本小节中,我们需要实现上述业务场景,并对核心的秒杀抢购业务场景中的用户预下单阶段,以及用户支付阶段,做好高并发场景下的处理。Tips: 同学们一定要清楚地理解上述所介绍的业务流程,如果看一遍不理解,那就反复多看几遍,直到自己理解了即可。
Flask 是一个 Python 实现的 Web 开发微框架,但是这个“微”并不代表着 Flask 功能比较简陋、有所欠缺。微框架中的 “微” 意味着:Flask 旨在保持核心简单而易于扩展;Flask 不会替用户做出太多决策,比如使用何种数据库;Flask 的选项(比如使用何种模板引擎) 通常有多个,用户很容易替换。默认情况下,Flask 不包含数据库抽象层、模板引擎、身份认证或其它任何已有多种库可以胜任的功能,如下图所示。然而,Flask 支持用扩展来给应用添加这些功能,应用程序可以很方便的集成这些扩展。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。
实现思路分析针对上述场景,我们需要将所有拆分出来的微服务都要集成到 Hystrix 的微服务监控平台中去,但是我们应该怎么集成呢?Hystrix 针对不同场景下,提供了不同的微服务监控方式:针对单体架构或只需要对一个服务实例进行监控的业务场景,我们只需要像我在介绍微服务监控平台时那样,进行配置即可;针对分布式的项目结构,或同时需要监控多个微服务的场景,Hystrix 提供了一个名为 Turbine 的多服务器微服务监控组件。我们只需要将 Turbine 引入到我们的项目中去,即可实现分布式架构下的多微服务监控了。实操要想在项目中引入 Turbine ,我们首先需要将 Turbine 的依赖引入到项目中:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-turbine</artifactId></dependency>在引入了 Turbine 依赖之后,我们需要对 Turbine 进行一些简单的配置,在 yml 配置文件中:turbine: aggregator: clusterConfig: default appConfig: service-one,service-two,service-three clusterNameExpression: "'default'"代码解释第 3 行,我们通过 clusterConfig 属性来配置 turbine 采用的集群策略,一般我们配置 default 即可。第 4 行,我们通过 appConfig 属性来配置需要继承到 turbine 中的微服务,即需要同时刻进行监控的微服务,多个微服务使用英文状态下的逗号隔开。第 5 行,我们通过 clusterNameExpression 属性来配置集群的名称表达式,一般也是采用 default 配置即可。yml 配置文件配置完成后,我们需要在项目的启动类中添加 turbine 的注解:@SpringBootApplication@EnableHystrix@EnableHystrixDashboard@EnableTurbinepublic class SaleApplication { public static void main(String[] args) { SpringApplication.run(SaleApplication.class, args); }代码解释第 4 行,我们添加了 @EnableTurbine 注解,来在项目中开启 turbine 服务,以支持同时监控多个微服务。在配置完了上述两部分后,我们的 Hystrix Turbine 组件就引入到了我们的项目中,我们就可以对多个微服务进行监控了。配置完成后,运行我们的项目,在浏览器地址栏中输入我们的监控地址:http://localhost:port/turbine.stream我们即可在浏览器中看到多个微服务已经被监控了,如下图所示:Hystrix Dashboard 多微服务同时监控从上图可知,这里我们对两个微服务进行了监控,其图中的各项监控参数和我们在之前介绍 Hystrix 微服务监控平台中的参数一样,这里就不再赘述了。Tips: 1. 在 appConfig 属性配置中,属性的值为每个需要监控的微服务的 serviceId 名称,同学们不要配置错了。 2. 各位在引入 Turbine 的依赖时,注意不要引错依赖了,如果大家引入了 aitifactId 为 spring-cloud-starter-turbine 的依赖,我们是无法使用 Turbine 的,因为这个依赖并不是 Spring Cloud 微服务组件中所提供的 Turbine 服务,而是单独的 Turbine 服务,我们无法在微服务项目中使用。 3. 各位同学在访问 Turbine 多微服务监控平台时,注意访问地址发生了变化,大家使用之前的微服务监控平台访问地址时访问不到的,这点需要同学们注意。
咱们打开新浪微博,然后随便找个带皇冠的,按下F12键(Mac用户按command+option+i)然后选中控制台的箭头,再点击皇冠:再点开这个图片可以发现:可以看到那些大 V 图标皇冠图标以及各种微博认证等图标,都是放在了一张雪碧图里(即使再牛的大 V,身份标志也是放在雪碧图中的)。
在上一章中,我们对 Hystrix 中的所有的微服务治理特性都做了学习和了解,同时我也通过 demo 样例的形式,来对每一个特性都做了代码实现,可是这些代码并不是我们真实业务场景下的代码,只能用来学习特性所用。为了将我们所学习和了解到的微服务治理特性应用于真实项目中,于是规划了 4 节在实际业务场景下 Hystrix 微服务治理特性的应用内容,希望可以通过这 4 节的介绍,大家可以了解到如何在实际项目中去应用这些特性。在本节中,我将为大家介绍真实业务场景下,服务容错与降级的应用方法,及代码实现。本节主要内容:服务容错与降级真实业务场景描述;业务场景实现思路分析与实操。
就业市场和所有的市场相同,影响就业指标的关键就是供需关系。在互联网行业,供需主要分为两类,需求方是作为招聘方的互联网公司,供给方则是作为候选人的程序员。如果互联网公司对于程序员的需求大于市场上流动的人员数量,此时求职的程序员就会有更大的议价能力,这种情况一般发生在每年的金三银四时间段。如果程序员数量过剩,互联网公司则会普遍提高选拔指标,尝试筛选出更符合条件的候选人。从供给侧来看,根据 2021 年高考填报志愿的统计数据,计算机和金融已经明显成为两大金砖专业,越来越多的高水平学生流入到计算机专业,以及观察考研数据,可以发现计算机已经是最受欢迎的目标专业。从需求侧来看,国内互联网经历了 2010 年之后的移动互联网流量大爆炸时期,增速已经逐渐放缓,各种大厂的竞争也从寻找增量的用户转为到存量市场博弈,例如在电商领域继淘宝和京东之后出现的拼多多、唯品会等各种细分应用,或者从企业微信、阿里钉钉以及字节跳动飞书的办公软件领域的竞争都可以看出存量市场竞争的激烈。蛋糕已经很难做大,所以大家都开始花精力研究如何分到更多的蛋糕。所以未来的趋势很明显,互联网的供给增速飞快,但是需求增速放缓,作为找工作的一方,不管是应届在校生还是工作时间不长的程序员,都需要提高自己的核心专业素养。
在之前的小节中,我们已经对 Hystrix 提供的微服务监控平台做了详细的介绍,基本上已经把这个微服务监控平台的常用内容都介绍完毕了,那么在本节中,将会结合这些基本参数对我们的微服务进行一个监控和配置。本节主要内容:实际业务场景描述;业务场景实现思路分析与实操。
安全密钥交换与非对称密钥算法,推动了网络安全通信的发展,在认证与安全诉求越来越迫切的环境下,一些厂商嗅探到市场的机遇,逐渐推出了相应的认证服务。信息的安全关系到国家安全和经济利益,因此我国这几年也在积极探索网络安全的标准化建设,这些标准并不仅仅局限于证书的签名算法,也包括了物理厂房的建设,人员的管理流程规则制度。当然我们的网络安全建设一方面要保证自己足够安全,另一方面也要对接国际,毕竟今天的网络今天的经济都是全世界共同的。
可以通过 CDN 引入 ECharts 文件:<!-- bootstrap 服务 --><!-- bootstrap 提供的免费CDN服务,亲测非常稳定 --><script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script><!-- 七牛云存储服务 --><!-- 国内速度稳定,开放性强 --><script src="//cdn.staticfile.org/echarts/4.5.0/echarts.common.js"></script><!-- jsdeliver 服务 --><!-- 微软的CDN服务,虽然国内访问速度比不上国内CDN,但速度不至于太慢,有国际化需求的可以试试 --><script src="//cdn.jsdelivr.net/npm/echarts@4.5.0/echarts.common.js"></script><!-- cdnjs 服务 --><!-- 一个非常全的CDN服务,存储了大多数主流的js、css、图片库 --><script src="//cdnjs.cloudflare.com/ajax/libs/echarts/4.5.0/echarts.common.js"></script>
什么是标准?标准是对重复性事物和概念所做的统一规定,他以科学技术和实践经验的结合成果为基础,经有关方面协商一致,由主管机构批准,以特定形式发布作为共同遵守的准则和依据。在这个标准概念大行其道的今天,如果大家在生活中稍微注意一下,其实可以很容易发现,我们生活在一个标准化的世界里,每个产品的外包装或者标签上都会注明相应的执行标准。标准贯穿着我们的衣食住行。。总而言之,标准无处不在。当然标准具有行业性与地域性。每个国家基本都有自己的标准,这些标准有些是自己独立创造的,但更多的,为了与国际上大部分标准兼容,基本上会使用国际上一些通用的标准,只是改一下名字就可以了。作为软件行业中的老大哥级人物。C 语言也有自己的标准,而且是国际标准。如果大家遵循同一个标准,那么就会避免分歧的产生,避免出现很多不必要的麻烦和困扰。按照这统一标准就不会出现不兼容的问题。我们先来看下 C 语言标准的发展历史:
实现思路分析鉴于上述业务场景中所描述的问题,我们只要为每个业务模块分配不同的工作线程,使各模块间不再一同共用一个工作线程,就可以有效解决上述问题。当我们通过技术手段为每一个业务模块都分配了不同的工作线程之后,各模块的业务处理操作都会有专门的工作线程来完成,不会再出现各模块共用一个工作线程的情况。如果一个模块中的请求处理出现问题而等待,由于我们分配了不同的工作线程,所以这种情况不会影响到其他模块,这就解决了上述业务场景中出现的问题。Hystrix 提供了通过线程池或信号量隔离的方式来对服务资源进行隔离,以解决雪崩现象的发生,接下来让我们分别来看一下代码实现。实操以线程池隔离为例,我们先给订单服务配置资源隔离:@RequestMapping("make_order.do")@ResponseBody@HystrixCommand(threadPoolKey = "userMakeOrderThread")public CommonResponse<String> makeOrder(@RequestBody("order")Order order, @RequestBody("user")User user){ return orderService.makeOrder(order, user);}代码解释第 3 行,我们用户下订单服务中通过添加 HystrixCommand 注解的 threadPoolKey 属性来为用户下订单服务单独分配了一个名为 userMakeOrderThread 的线程池,当我们再有用户下订单的请求需要处理时,就会使用这个线程池中的线程。同样的方法,我们为用户支付服务配置资源隔离:@RequestMapping("aliPay.do")@ResponseBody@HystrixCommand(threadPoolKey = "userAliPayThread")public CommonResponse<String> aliPay(@RequestBody("shipping")Shipping shipping, @RequestBody("user")User user){ return payService.aliPay(shipping, user);} 可以看到,我们为支付模块分配了一个名为 userAliPayThread 的线程池。基于信号量隔离的服务隔离的配置,和上述基于线程池隔离的配置大同小异,下面我将关键代码放到下方,各位同学只需要替换掉上述的线程池配置即可。以用户下订单服务为例:@HystrixCommand(fallbackMethod="makeOrderFailed", commandProperties = {@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY, value = "SEMAPHORE"),@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS, value = "50")})代码解释第 3- 8 行,使用信号量隔离需要显式声明服务资源隔离策略,SEMAPHORE 表示使用信号量隔离策略。Tips: 1. 在实际项目开发中,像这种订单服务和支付服务互相依赖的业务场景不在少数,各位同学在工作时,一定要在这种业务场景中配置好服务资源隔离,不要等在线上出现问题之后再解决,那就晚了; 2. 线程池隔离和信号量隔离之间的区别有很多,这里就不做介绍了,希望各位同学可以自行查阅,他们之间的区别可以帮助你确定不同业务场景下采用哪种隔离方式比较合适。
1. 独立的页面维护了全局 错误码错误码由5位整数构成2. 每个接口一个独立的 参数说明页面正常情况下出参只返回业务实体异常情况才有 errCode errMsg每个接口下也可能有自己的业务错误码
实现思路分析鉴于上述业务场景中所描述的问题,我们可以在该用户注册服务上,通过添加 Hystrix 的服务容错与降级的注解,再结合相关配置项来实现该用户注册服务的容错与降级。在为该用户注册服务配置了容错与降级之后,当在大流量情况下,如果我们的服务器或数据库不能继续处理更多的请求时,此时会给用户一个提示,并且拒绝处理后续的服务请求。由于我们的本套课程不涉及 Open Feign ,所以这里为大家介绍以注解形式配置服务容错与降级。实操@RequestMapping("register.do")@ResponseBody@HystrixCommand(fallbackMethod = "register_failed")public CommonResponse<String> register(@RequestBody User user){ return userService.register(user);} public CommonResponse<String> register_failed(){ return CommonResponse.errorResponse("服务拒绝处理,请联系系统管理员");}代码解释第 3 行,我们使用 HystrixCommand 注解的 fallbackMethod 属性,来为用户注册服务添加容错与降级,此时,当该服务出现上述业务场景问题时,就会返回 register_failed 方法所对应的响应,并且后续服务不会继续处理。Tips: 1. 配置服务容错与降级时,首先需要清楚对应服务下都可能会出现哪些问题,出现这些问题的产生原因主要是什么,我们只有在清楚了这些错误产生的原因之后,我们才能合理地去编写服务容错与降级时的响应结果,这点同学们需要注意。 2. 在实际项目开发中,基本上每个承载大流量的接口服务都会配置服务容错与降级,这种配置方式可能在微服务项目中已经成为了一种习惯。
RabbitMQ:企业内部微服务,例如内部人员管理系统的消息通讯场景。因为基于 Erlang 开发语言,对小型企业来说,开发维护成本相对较高;Kafka:大数据系统中常用,例如日志处理以及数据实时分析场景,目前 Kafka 几乎是日志采集场景的首选消息队列。
DoubleAdder 经常用于多线程并发做收集统计数据的场合,而不是细粒度的同步控制。下面我们用 DoubleAdder 工具类实现一个生活案例:某商场为了掌握客流特征,在商场所有出入口架设了人体特征识别设备,此类设备可以有效识别客人性别等信息。基于此,商场管理办公室计划制作一个客流性别流量图表,用于决策商场的服务内容。
业务场景描述有这样一个真实的业务场景:在某大厂的订单与支付模块,当有用户下了订单之后,需要在支付模块进行支付,支付动作完成之后,支付模块会将支付完成的结果返回给订单模块来通知用户,该订单是否支付成功,即商品是否已经成功购买了。在微服务分布式架构模式下,上述业务场景中出现了一种异常现象:当用户下了订单之后,在支付模块进行支付时,系统一直没有响应,无论是否成功支付,用户都收不到任何通知信息。程序员在排查对应的业务实现代码时,证实了业务实现代码没有问题,这就导致无法定位问题所在。最终经过几名同事一起排查,发现是订单模块与支付模块之间进行数据传输时,支付模块收到了订单模块传递过来的数据,但是由于服务器高压工作,导致支付模块始终无法处理该支付请求,这就导致系统一直没有响应。问题原因分析在解决问题之前,我们首先来分析一下这种问题产生的原因。在前面我们介绍什么是 Hystrix 资源隔离小节中,我为大家阐述了在我们的 Web 项目中,进程与线程之间的关系。我们知道,在一般情况下,一个 Web 项目中只有一个工作线程来负责处理用户调用的请求和服务,当该工作线程所负责的请求处理缓慢时,该线程就会一直处理当前的请求,导致后续请求只能等待处理,这就是我们说的雪崩现象。雪崩效应产生原理在微服务分布式架构模式下,由于我们没有对线程进行处理,至此在处理所有业务请求时,扔是只有一个工作线程,这就导致上述业务场出现了我们所说的雪崩现象,不过还好,这种雪崩现象比较轻微,只影响到了一个业务模块。很多时候,当我们的项目架构演变为基于微服务的分布式架构时,服务器也需要同步进行更新,有很多企业为了节约成本,则只更新很少数量的服务器,或者压根就不更新服务器,这就导致经常会出现由于服务器高压工作而出现的请求处理缓慢,或请求无法继续处理的情况。
拦截器可以解决很多实际问题:日志记录: 记录请求信息的日志,以便进行信息监控、信息统计、计算 PV(Page View)等;权限检查: 如登录检测,进入处理器前检测用户是否登录,如果没有直接返回到登录页面;性能监控: 通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间;通用行为: 读取 cookie 得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取 Locale、Theme 信息等只要是多个处理器都需要的即可使用拦截器实现 OpenSessionInView: 如 Hibernate,在进入处理器打开 Session,在完成后关闭 Session。除以上应用场景之外,你可以根据自己的业务需要灵活选择。
1969年,IBM 的技术人员 Charles Goldfarh 和 Edward Mosher 等人一起发明了通用标记语言 GML(Generalized Marked Language)。1985年在英国成立了国际 SGML 用户组织,在1986年,SGML 成为国际标准ISO8879:信息处理标准通用标记语言(Information processing Text and office system Standard generalized markup language)。HTML 和 XML 派生于 SGML,XML 可以被认为是它的一个子集,而 HTML 是它的一个应用。为了告诉浏览器我们需要展示什么内容,HTML 定义了一整套符号标记规范,这些规范包括设置文字的格式;创建列表;显示图片;显示多媒体;显示超链接;等等。
现实生活中的很多实际问题都可以归结到某种算法实现,比如我们经常用到的地图导航软件,不知道大家有没有思考过导航软件是如何为我们规划出出行路线规划的了?其实里面就会涉及到算法领域的一些图算法知识(这里不做过多介绍,在后续的章节里面会有详细说明)。还有现在很多的抖音小视频 APP,大家都发现一不小心刷个抖音就过去了一个小时了,为什么推荐给你的小视频会对你如此有吸引力了?其实这是因为在抖音内部实现中有一套规则复杂的视频推荐算法,可以给每个用户推荐自身喜欢看的小视频。总而言之,算法知识可以用来解决现实生活和开发场景中的各种问题。
计算机的网络模型定义了计算机数据的传输过程,当前有以下 2 种主流模型:国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为 OSI 参考模型或七层模型;工业生产中实际用到的 TCP/IP 四层模型。这两者者的关系就好比,车间里面一个贴在墙上很规范的流程图,一个是实际生产中因为成本/便捷/效率等因素最终采用的流程。但是不管是七层模型还是四层模型,他们实现的目无非是为了解决两个问题:数据转成电信号;目标主机的寻址。
本节我们讨论了如何利用第三方平台做我们系统的 OAuth2.0 认证中心,主要的知识点如下:Spring Security 实现了 OAuth2.0 客户端的常用功能,开发者可以轻松的将 Spring Boot 应用作为 OAuth2.0 客户端集成到安全体系中;在使用第三方作为 OAuth2.0 认证服务器时,首先要在第三方平台上完成应用注册,并获取到 Client ID 和 Client Secret 两个重要参数;使用第三方 OAuth2.0 认证源,可以简化系统开发中的关于认证的操作,并且可以更轻易的实现单点登录;使用第三方 OAuth2.0 认证源的时候,用户在本系统内的权限、详细用户信息等,仍需要在本地系统内维护;目前在国内支持度比较好的第三方认证源有:QQ、微信、微博、Github 等。下一节中,我们继续在 OAuth2.0 协议的基础上,构造出属于自己的认证中心。