咱们打开新浪微博,然后随便找个带皇冠的,按下F12键(Mac用户按command+option+i)然后选中控制台的箭头,再点击皇冠:再点开这个图片可以发现:可以看到那些大 V 图标皇冠图标以及各种微博认证等图标,都是放在了一张雪碧图里(即使再牛的大 V,身份标志也是放在雪碧图中的)。
注册微信小程序账号,获取到 AppID,我们后面配置的时候会用到。在 HBuilderX 工具栏,点击发行,选择小程序-微信。输入小程序名称和 AppID,单击发行就可以了。这样我们就会获得一个微信小程序的打包文件,接下来我们来发布微信小程序项目,打开微信小程序开发者工具,导入刚刚生成的微信小程序项目的打包文件,在微信小程序开发者工具中先测试一下,项目运行是否正常,项目测试没有问题后,点击右上角>>按钮,上传代码就可以发布微信小程序了,最后等待微信团队审核通过,别人就可以在线上访问到你的项目了。
全称 Distributed Denial of Service,中文意思为“分布式拒绝服务”,就是利用大量合法的分布式服务器对目标发送请求,从而导致正常合法用户无法获得服务。DDoS 攻击方式简单粗暴,可以达到直接摧毁目标的目的。另外,相对其他攻击手段 DDoS 的技术要求和发动攻击的成本很低,只需要购买部分服务器权限或通过技术手段控制一批肉鸡即可。另一方面,DDoS 具有攻击易防守难的特征,服务提供商为了保证正常客户的需求需要耗费大量的资源才能和攻击发起方进行对抗。这些特点使得 DDoS 成为黑客们手中的一把很好使的利剑,而且所向披靡。DDos 的攻击形式多种多样,有针对资源消耗类攻击、服务消耗性攻击、反射性攻击、混合型攻击等等,最终达到对端服务不可用的目的。互联网发展至今,DDoS 攻击就一直存在,而且随着技术的发展,DDoS 的攻击方式也变化多端。目前而言,对于 DDoS 攻击仍旧是一个令人头疼的问题,许多创业公司或者规模较小的公司,不愿过多投入到防御体系的建设上,这就导致大部分公司面对高流量的 DDoS 攻击时都是直接投降,毫无还手之力。目前,安全产业对 DDoS 的防护系统本质上是一个基于资源较量和规则过滤的智能化系统,主要的防御手段和策略包括:资源隔离用户规则大数据智能分析资源对抗随着目前人工智能和深度学习技术的火热发展,在 Web 安全领域已经开展了许多关于这方面的实践研究,也相信不久的将来,DDoS 攻击能彻底被深度学习技术打败,不再成为大部分业内公司的噩梦。
XSS 跨站脚本攻击(Cross-site scripting)使用到的技术主要为 HTML 和 Javascript 脚本。攻击者将对客户端有危害的代码放到服务器上作为一个网页内容,用户不经意打开此网页时,这些恶意代码会注入到用户的浏览器中并执行,从而使用户受到攻击。一般而言,利用跨站脚本攻击,攻击者可窃取会话 Cookie,从而获得用户的隐私信息,甚至包括密码等敏感信息。
uni-app 的 API 与微信小程序 API 基本一致。掌握微信小程序 API 对后面的开发很有帮助。微信小程序 API 文档:https://developers.weixin.qq.com/miniprogram/dev/api/
DDOS(Distributed Denial of Service)也是一种经典的攻击模式,它不是利用服务器存在什么漏洞,而是直接粗狂的用大流量来访问你的网站,使你的网站承受不了这么多流量而崩溃。这种模式有时候还挺难处理的,因为流量的来源可能是一种变化的,都没有固定 IP 防不胜防。而这些攻击你的电脑可能是来自各地的私人电脑,只是被黑客利用了的傀儡机。
使用 Zookeeper 客户端连接 Zookeeper 服务,我们需要使用 ./zkCli.sh 命令:# 进入 bin 文件夹cd /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/bin/# 连接命令./zkCli.sh # 连接时输出信息Connecting to localhost:2181...# 出现下面这一行时,表示我们连接成功[zk: localhost:2181(CONNECTED) 0] 这里我们就可以使用上一节学习过的命令来操作节点了,我们来测试一下:# 获取根节点的子节点ls /# 输出默认的子节点 zookeeper[zookeeper]# 创建根节点的子节点 imooccreate /imooc# 输出创建成功信息Created /imooc# 创建后再次获取根节点的子节点ls /# 输出两个子节点[imooc, zookeeper]# 我们可以给节点设置数据set /imooc wiki# 然后我们再获取 imooc 节点的数据get /imooc# 输出我们设置的信息wiki# 最后我们测试一下删除命令delete /imooc# 删除后再次获取根节点的子节点ls /# 输出子节点 zookeeper,imooc 节点被删除[zookeeper]# 退出 Zookeeper 客户端命令quit通过上面的学习,我们知道了如何部署单机模式的 Zookeeper 服务,以及如何通过 Zookeeper 客户端连接 Zookeeper 服务端,来对 Znode 节点进行操作。那么 Zookeeper 是如何为我们提供服务的呢,接下来我们就来了解单机模式下的 Zookeeper 的工作流程。
CSRF(Cross-site request forgery),中文名称:跨站请求伪造。可以这么简单理解CSRF攻击:攻击者盗用了你的身份(获取登录正规网站的 cookie 信息), 并以你的名义发送恶意请求(比如转账、提交订单等)。CSRF 主要会导致个人的隐私泄露并威胁财产安全。我们用下面一幅图来描述一下 CSRF 攻击的形成与危害:从上面的示例过程可以看出,要完成一次 CSRF 攻击,受害者必须依次完成两个步骤:登录受信任网站A,并在本地生成Cookie;在不登出A的情况下,访问危险网站B;上面这几种情况看似很难一起发生,但在现实场景中却是很容易发生的。这主要是基于以下几个原因导致的:我们往往登录了一个网站后,打开多个 tab 页面去访问多个其他网站,类似于下图:关闭浏览器了后,本地的 Cookie 并不会立即过期,上次会话也并不意味着结束,除非我们点击登出(logout)或者主动清除浏览器缓存;所谓的危险网站,可能是经常被人访问的正规网站。该网站由于存在某种漏洞被人恶意攻击,并在网站中放入恶意链接诱导用户点击;基于以上三点,CSRF 攻击很可能每天在我们身边上演。但是网站必须要确保不存在相应的 CSRF 漏洞,否则极容易黑客攻击。关于 CSRF 攻击的主要防御手段便是在网页上添加一个随机的校验 token 值。由于 CSRF 的本质在于攻击者欺骗用户去访问自己设置的地址,所以如果要求在访问敏感数据请求时,要求用户浏览器提供不保存在 cookie 中,并且攻击者无法伪造的数据作为校验,那么攻击者就无法再执行 CSRF 攻击。这种数据通常是表单中的一个数据项。服务器将其生成并附加在表单中,其内容是一个伪乱数。当客户端通过表单提交请求时,这个伪乱数也一并提交上去以供校验。正常的访问时,客户端浏览器能够正确得到并传回这个伪乱数,而通过 CSRF 传来的欺骗性攻击中,攻击者无从事先得知这个伪乱数的值,服务器端就会因为校验 token 的值为空或者错误,并拒绝这个可疑请求。
在将 Swagger Codegen 的依赖引入到 Spring Boot 中去后,我们就可以使用 Maven 自带的命令来将上述配置信息分别生成服务端和客户端代码,命令如下:首先,将上述配置好的文件利用 Swagger Codegen 来生成服务端和客户端代码 java -jar swagger-codegen-cli.jar generate -i swagger.yaml -c swaggerConfig.json -l spring -o server代码解释:第一行,使用 generate 命令来将配置在 swagger.yaml 文件中的服务端代码进行生成。第一行,使用 -c 参数,表明使用 json 配置文件,并且该配置文件的名称为 swaggerConfig.json。第二行,使用 -l 参数,表明客户端所使用的语言为 spring 。第二行,使用 -o 参数来指定代码最终的存放位置,server 表示将生成的代码存放到名为 server 的文件夹下。然后我们使用 cd 命令来进到我们生成代码后所存放的目录: cd server最后我们将生成的代码打成 Jar 包: mvn package这是 Maven 自带的打包命令,执行该命令之后,Maven 会默认读取项目中的 pom 文件中配置的打包规则,即 packaging 节点,如果该节点没有配置任何规则,则 Maven 会默认打成 Jar 包 (这里我们配置了 Jar)。这样我们就可以在项目的 target 目录下,找到我们利用 Swagger Codegen 所生成的服务端和客户端代码的 Jar 包了,我们可以把该 Jar 包放到其他环境中使用,也可以供其他项目使用,这就是我们利用 Swagger Codegen 所生成的服务端和客户端代码的最终使用目的。
技巧 1如果我们的微服务监控平台没有任何数据,或者说,在打开微服务平台之后,各参数一直处于 loading 状态,这个时候,我们只需要在服务端调用任意一个服务接口即可,这样在微服务监控平台,我们就能看到被监控实例的参数了。技巧 2如果我们在访问 /actuator/hystrix.stream 路径时,系统找不到对应的路径,即报 404 异常,那么我们需要在对应项目的启动类中添加一个 Bean :@Beanpublic ServletRegistrationBean hystrixMetricsStreamServlet() { ServletRegistrationBean registration = new ServletRegistrationBean(new HystrixMetricsStreamServlet()); registration.addUrlMappings("/hystrix.stream"); return registration;}这样我们就能正常访问 /actuator/hystrix.stream 下的路径了。
SQL 注入是网站存在最多也是最简单的漏洞,主要原因是程序员在开发用户和数据库交互的系统时没有对用户输入的字符串进行过滤,转义,限制或处理不严谨,导致用户可以通过输入精心构造的字符串去非法获取到数据库中的数据。SQL 注入是一种注入攻击,可以执行恶意 SQL 语句。它通过将任意 SQL 代码插入数据库查询,使攻击者能够完全控制 Web 应用程序后面的数据库服务器。攻击者可以使用 SQL 注入漏洞绕过应用程序安全措施;可以绕过网页或 Web 应用程序的身份验证和授权,并检索整个 SQL 数据库的内容;还可以使用 SQL 注入来添加,修改和删除数据库中的记录。有一个经典的例子如下:一个网站后台管理系统存在 SQL 注入漏洞。它使用 url 传递的参数 username 和 password 去数据库校验对应的用户名和密码是否正确,形成的 SQL 语句如下:SELECT * FROM user WHERE username='admin' AND password='passwd'如果后台服务对输入的用户名和密码做任何处理,前台直接构造用户名为:’ or 1=1#。此时后台形成的查询 SQL 语句为:SELECT * FROM user WHERE username='' or 1=1#' AND password='xxx'这条语句也是可以执行的,而且可以得到所有的用户记录。因为 “or 1” 让 SQL 的查询条件永远为 True,而 ‘#’ 屏蔽了后面的密码校验。早期这种后台管理系统的漏洞屡见不鲜。很多人只需要通过黑客工具找到存在 SQL 注入漏洞的后台管理系统,然后使用这个万能密码就能直接进入网站的管理系统页面,达到入侵的目的。SQL 注入攻击方式主要有以下三种:带内注入:攻击者可以通过相同的通信通道发起攻击并获得结果,主要通过以下两种方式完成。基于错误的SQL注入:从显示的错误消息中获取有关数据库的信息基于联合的SQL注入:依赖于攻击者能够将UNION ALL被盗信息的结果与合法结果连接起来盲注入:也称为推理SQL注入;带外注入:攻击者通过精心制作的 SQL 语句注入到数据库,可以触发数据库系统创建与攻击者控制的外部服务器的连接。通过这种方式,攻击者可以收集数据或可能控制数据库的行为。对于 SQL 的注入攻击,在开发 Web 系统时只需要遵循以下几点建议,就能避免绝大部分的 SQL 注入漏洞了:避免将用户提供的输入直接放入 SQL 语句中,最好使用准备好的语句和参数化查询;不要将敏感数据保留在纯文本中;限制数据库权限和特权;避免直接向用户显示数据库错误。大部分的时候,我们需要拦截相关异常,然后定制化输出数据库异常信息;对访问数据库的Web应用程序使用Web应用程序防火墙(WAF);及时更新数据库至最新版,防止黑客利用旧版本漏洞发起攻击。
客户端,是指发起请求的一方。也就是浏览器,或者指爬虫程序。通过发起请求,来获取想要的网页。服务端,请求的响应端,是 web 服务端。web 服务,是一个虚拟意思上的机器的概念。可以是一个计算机集群,也可以是一个软件或者程序。客户端,通过发送一个请求给服务端,然后进行等待。服务端按照客户端的请求,返回客户端需要的数据。这个过程,我们称之为经典的客户端——服务端模型。
XSS 攻击又称 CSS,全称Cross Site Script (跨站脚本攻击),其原理是攻击者向有 XSS 漏洞的网站中输入恶意的 HTML 代码,当用户浏览该网站时,这段 HTML 代码会自动执行,从而达到攻击的目的。XSS 攻击可以分成两种类型:非持久型 XSS 攻击:顾名思义,非持久型 XSS 攻击是一次性的,仅对当次的页面访问产生影响。非持久型 XSS 攻击要求用户访问一个被攻击者篡改后的链接,用户访问该链接时,被植入的攻击脚本被用户游览器执行,从而达到攻击目的;持久型 XSS 攻击:持久型 XSS,会把攻击者的恶意代码数据存储在服务器端,攻击行为将伴随着恶意代码的存在而一直存在。XSS 的攻击防范主要是对提交的各种字符串数据进行校验,避免出现可执行的前端代码。主要的防范措施有:对输入内容的特定字符进行编码,例如表示 html 标记的 < > 等符号;对重要的 cookie 设置 httpOnly,防止客户端通过 document.cookie 读取 cookie,此 HTTP 头在服务端设置;将不可信的值输出 URL 参数之前,进行 URLEncode 操作,而对于从 URL 参数中获取值一定要进行格式校验;不要使用 eval 来解析并运行不确定的数据或代码,对于 JSON 解析可使用 JSON.parse() 方法;后端接口也要对关键的字符进行过滤,防止将恶意的脚本代码保存到数据库中。
Hystrix 中的服务监控平台,就是对微服务项目进行监控的平台,包括服务运行的状态、服务有无宕机、服务异常信息监控等内容,为开发者和运维者提供了比较友好地界面支持,开发者和运维者可以直接通过观察服务平台界面,来判断具体微服务的状态信息,从而更好地对微服务进行控制。默认的 Hystrix 中间件已经为我们封装好了微服务监控平台,但是需要通过引入依赖的方式来使用它,接下来就让我们来看一下如何搭建该服务监控平台吧。
点击工具栏–运行–运行到内置浏览器,测试H5平台。点击工具栏–运行–运行到小程序模拟器–微信开发者工具,测试微信小程序平台。
点击工具栏–运行–运行到内置浏览器,测试H5平台。点击工具栏–运行–运行到小程序模拟器–微信开发者工具,测试微信小程序平台。
本节我们讨论了如何利用第三方平台做我们系统的 OAuth2.0 认证中心,主要的知识点如下:Spring Security 实现了 OAuth2.0 客户端的常用功能,开发者可以轻松的将 Spring Boot 应用作为 OAuth2.0 客户端集成到安全体系中;在使用第三方作为 OAuth2.0 认证服务器时,首先要在第三方平台上完成应用注册,并获取到 Client ID 和 Client Secret 两个重要参数;使用第三方 OAuth2.0 认证源,可以简化系统开发中的关于认证的操作,并且可以更轻易的实现单点登录;使用第三方 OAuth2.0 认证源的时候,用户在本系统内的权限、详细用户信息等,仍需要在本地系统内维护;目前在国内支持度比较好的第三方认证源有:QQ、微信、微博、Github 等。下一节中,我们继续在 OAuth2.0 协议的基础上,构造出属于自己的认证中心。
微前端 尚处在发展时期,其核心概念和 微服务 相似。现阶段较为常用的微前端框架为 single-spa 和 qiankun,后者是基于前者实现的。该技术能做到 技术栈无关,即一个应用,能由多个不同技术的子应用构成,同时做到子应用的相互隔离,这里的隔离就可以选择采用 Web Components 实现。
业务场景: 模拟微信聊天,每个客户端和服务端建立连接,并且可以实现点对点通信(单聊),点对多点通信(群聊)。设计思路: 我们要实现的是点(客户端)对点(客户端)的通讯,但是我们大部分情况下接触的业务都是客户端和服务端之间的通讯,客户端只需要知道服务端的 IP 地址和端口号即可发起通讯了,那么客户端和客户端应该怎么去设计呢?思考:难道是手机和手机之间建立通讯连接,互相发送消息吗?这种方案显然不是很好的方案,第一: 客户端和客户端之间通讯,首先需要确定对方的 IP 地址和端口号,显然不是很现实。第二: 即使有办法拿到对方的 IP 地址和端口号,那么每个点(客户端)既作为服务端还得作为客户端,无形之中增加了客户端的压力。其实,我们可以使用服务端作为中转站,由服务端主动往指定客户端推送消息,如果是这种模式的话,那么 Http 协议是无法支持的,Http 是无状态的,只能一请求一响应的模式,只能使用 TCP 协议去实现了。
服务熔断机制的服务快速失败所实现的目标,和我们在上述小节中所介绍的普通的服务快速失败所实现的目标相同,都是为了保证,在某一微服务发生故障时,不影响后续微服务的正常运行。雪崩效应产生原理在上述小节中,各位同学已经对什么是雪崩效应有所了解,如上图所示,我们所讲的服务熔断也是为了避免和解决雪崩现象的发生,只不过所采用的手段不同而已,那么接下来,就让我们来看一下基于服务熔断机制的服务快速失败的概念是什么吧。针对服务熔断机制,我们先来介绍什么是熔断?熔断这一名词,其实不是来源于计算机相关专业,而是来源于电子工程相关专业。熔断的核心是断路器,对于断路器来说,我们可以将断路器理解为一根保险丝,在日常生活中,当我们家庭用电超过负载时,保险丝就会迅速烧断,阻止由于电流过大而烧毁整个家庭电路。同样地,熔断我们也可以像保险丝那样理解,即在计算机相关领域中,由于中断上游的故障服务,而保全整体的服务的措施就被称为熔断,而实现中断上游的故障服务所采取的核心措施就是我们的断路器。服务熔断机制就是把这些概念都统一起来,然后封装到 Hystrix 中,且最终应用于我们的微服务项目中间,通过配置断路器,来保全我们整体的微服务项目,这就是 Hystrix 所提供的服务熔断机制。Tips: 1. 在实际工作中,我们需要灵活的去配置微服务项目中,各个领域的微服务所对应的断路器配置,包括间隔时间、持续时间等关键属性,切记不要凭感觉去配置; 2. Hystrix 本身所提供的服务熔断机制并不是很好用,往往需要我们在项目中集成其他的微服务服务中间件来一起集成使用,单独使用 Hystrix 服务熔断机制的项目很少见。
http 最常用的协议,用于客户端主动向服务器发送请求,单向传递;ajax HTTP 的扩展版,底层还是 HTTP 协议,只不过客户端是无刷新的;comet 也是基于 HTTP 封装的,使用 HTTP 长连接的方式,原理大致是将 HTTP 的timeout 设置较长,服务器有数据变化时返回数据给客户端,同时断开连接,客户端处理完数据之后重新创建一个 HTTP 长连接,循环上述操作(这只是其中一种实现方式);websocket 这是 HTML5 中的新标准,基于 socket 的方式实现客户端与服务端双向通信,需要浏览器支持 HTML5;Adobe Flash Socket 这个也是使用 socket 的方式,需要浏览器支持 flash 才行,为了兼容老版本的浏览器;ActiveX object 只适用于 IE 浏览器;目前尚没有一种方式能兼容所有的浏览器,只能针对软件的目标客户人群做一定的兼容。sse 服务端单向推送。
2.2.1 微软的 FrontPage 和 Visial Studio相比于 Dreamweaver 中重量级设计软件,FrontPage 就显得更加轻巧,因此可以把它定义为一款轻量级的网页设计软件,甚至可以称作一种工具。这个软件的优点是它可以和熟悉微软 office 办公套件中 word 的同学和谐相处。由于它的操作方式和 word 十分相似,大家可以在熟悉微软 office-word 基础上,轻松入门上手 FrontPage。它同样具有 Dreamweaver 所见即为所得的特点,且具有强大的站点管理功能。支持 CGI 脚本,支持 CSS,提供了各种类型的模版。缺点目前来看,对云办公的支持便捷性可能不如 Adobe 公司的 Dreamweaver,而且需要对微软公司的相关组件支持比较好的系统才有可能更好的运行这一软件。而 Visual Studio 则是一款重量级的集网页开发,设计,部署的软件。以目前软件行业的现状来看,Visual Studio 已经成为了众多前后端开发工程师的首选利器,它具备前沿的设计理念和交互方式,充分服务于一般性质的开发,也完美支持特殊种类的开发。Visual Studio(简称VS)的优点是显而易见的,那就是集成化功能强大。但是这个优点有的时侯可能对于某些用户来说会成为缺点:入门难度高,灵活运用存在一定难度。但不得不承认的是,相比 Dreamweaver ,微软的 VS 这款产品具备更加广的受众面。但和 Dreamweaver 不能比拟的是:使用 Dreamweaver 你可以在 PS,AI,PR 等Creative Cloud 平台软件中无缝切换。但使用 VS,大概率下将享受不到这种便利。2.2.2 网景公司的 Netscape 编辑器网景公司在今天大家已经很少能看到它的足迹。它的这款工具类产品,却在当初的浏览器历史上有着很出名的应用。这是一款非常复古的网页编辑器,而且多数出现在Netscape浏览器中,在浏览器浏览网页的时候,你只需要点击编辑按钮,就可以显示网页源代码,进而实现对网页的编辑。而且它的使用方式有些地方是和 FrontPage 很像的。Netscape 编辑器更像是一个轻量级的网页编辑工具,如果你是初学者,从这里入门也是不错的选择。它的优点是操作编辑,在浏览器里操作,对于用户较为友好。缺点是功能比不上大型的开发环境,应用场景受限等。2.2.3 JbuilderJava 开发程序员可能用过这款网页设计软件,它更像是为 JSP 量身定做的一款开发工具。JSP 是一种Java 服务器端页面,可以提供交互非常广泛的网页,曾经倍受 Java 开发工程师的宠爱。但近几年已经基本抛弃了直接开发 JSP 页面的开发模式。Jbuilder 优点就是适合 Java 程序员,对 Java 语言有着很友好的支持。缺点就是它更适合高级开发人员,有一定门槛。
同样,我们展示了通过 C 语言 Socket API 编写 UDP 客户端和服务器程序的步骤,如下:图中的矩形方框都是 C 函数。对比 TCP 客户端、服务器的建立过程,我们发现 UDP 客户端可以调用 connect 函数,但是并不会去连接服务器,只是和本地接口做绑定;UDP 服务器是没有 listen 和 accept 调用的。对于 UDP 客户端来说,connect 函数的调用是可选的。接下来,我们就探讨一下如何用 Java 语言编写 UDP 客户端和服务器程序。
整个 Hystrix 微服务监控平台分为平台首页和平台内容页,在平台首页,我们需要配置被监控项目的信息,包括被监控项目的地址、获取被监控项目参数的间隔时间,以及服务监控平台的标题。在平台内容页才是我们真正查看被监控项目之参数的地方,接下来就让我们先看平台首页中都有哪些内容。平台首页Hystrix 微服务监控平台登录界面如下图所示:Hystrix Dashboard 登录界面我们按照图中字母顺序依次进行介绍。1 表示需要进行监控的服务访问地址。2 表示获取服务监控信息的刷新频率,即间隔多长时间之后重新获取被监控服务的信息。3 表示进入微服务监控平台之后,所展示的标题名称,往往这里会被设置为项目的名称。4 表示进入微服务监控平台的按钮,当我们将 1 2 3 的信息都填写正确之后,点击 4 按钮,即可进入微服务监控平台内容页面,如果 1 2 3 信息中有一项填写错误,则在微服务监控平台的内容页面就无法看到任何服务监控信息。Tips: 上面的 1 2 3 项中,只有 1 是必填项,如果 2 3 没有填写,则 Hystrix 会启用默认的配置进入微服务监控平台。平台首页一共就需要我们了解以上这些信息就可以了,接着我们来看平台内容页。平台内容页Hystrix Dashboard 内容页面整个平台内容页面被分为了 Circuit 和 Thread Pools 两部分,分别表示项目熔断的监控,以及项目线程池的监控。我们首先来看平台内容界面的 Circuit 部分。上图中,在 Circuit 部分的右上角位置,我用箭头标出了每个名词的对应关系,接下来我们一一来说明。success : 表示请求服务成功的数量。short-circuited : 表示请求服务被熔断的请求数量。bad request : 表示不能访问的请求的数量。timeout : 表示请求服务时,服务超时的请求数量。rejected :表示请求服务时,被拒绝的请求数量。failure :表示请求服务时,请求失败的数量。error :表示请求服务时,错误的服务的数量。然后,我们接着来看,在 Circuit 部分的中间位置,有一个 Circuit 的单词,该单词表示被监控项目此时的断路器的状态,当 Circuit 的值为 Closed 时,表示当前项目的断路器处于关闭状态,即当前服务的项目熔断没有启用。当项目的断路器打开时,此时的 Circuit 的值为 Open ,表示,此刻当前被监控的项目使用了服务熔断机制。在 Circuit 单词的上方,还有两个重要的参数,分别是:Host、Cluster ,Host 表示当前被监控项目的主机的请求频率,Cluster 表示当前被监控项目的项目集群的请求频率。Circuit 部分的左上方是一个图标,其由实心圆和曲线组成,其中,实心圆会根据实例的健康程度来改变自身的颜色,健康程度从绿色、黄色、橙色、红色递减,而实心圆的大小则表示请求流量的变化,流量越大该实心圆就越大,所以可以在大量的实例中快速发现故障实例和高压实例。曲线则记录了在 2 分钟内请求流量的相对变化程度,可以通过它来观察流量的上升和下降趋势。Tips: 由于本项目只是用来演示,并没有请求流量产生,所以这里就不会出现曲线,当我们有请求过来时,曲线就会发生变化。Circuit 部分最下面的 Hosts 、Median 、 Mean 我们不需要可以去了解分别代表什么含义,我们只需要知道这三个参数都是用来表示延迟时间的就可以了。最后,我们来看平台内容页的 Thread Pools 部分。在 Thread Pools 部分的左上方,同样也有一个由实心圆和曲线所构成的图标,其含义同 Circuit 部分的图标,这里不再赘述。在 Thread Pools 图标的右侧,同样也有 Host 和 Cluster 的请求频率的记录,这个和 Circuit 部分也是一样的。在 Thread Pools 图标的下方,有两列非常重要的参数,如下图:Hystrix Dashboard-Thread Pools 重点监控属性Active : 表示当前活跃的线程数量。Max Active : 表示当前最大活跃线程数量。Queued : 表示当前线程等待队列中的线程数量。Executios : 表示正在执行的线程的数量。Pool Size : 表示当前线程池的大小。Queue Size : 表示当前线程等待队列的长度。最后,我们再来看一下 Circuit 部分和 Thread Pools 部分的最上方位置,均有一个 Sort 名词,在这个名词的后面,也有很多单词,这表示我们查看服务监控参数时的顺序,当我们点击后面的一个单词时,HystrixDashboard 就会根据我们所点击的单词来对服务监控参数进行一个排序,仅此而已。Tips: Thread Pools 部分可以为我们展示被监控项目中线程池的活跃状态,我们可以直接从这些参数中分析出来当前线程池的活跃程度,从而动态地去调整每个微服务项目的线程池内容。
在 Zookeeper 服务端接收到 Zookeeper 客户端发送过来的请求后,首先解析请求头,识别请求的类型,发现客户端的请求类型是 auth 时,也就是权限类请求时,Zookeeper 会使用 scheme 来判断授权类型,找具体处理授权的实现类,在实现类中来进行权限验证,然后把认证用户保存到认证信息的集合中。在 Zookeeper 客户端使用刚才添加的认证用户信息来进行节点操作时,向 Zookeeper 服务端发送权限请求,服务端解析完成请求类型和授权类型后,再去具体的认证信息集合中去匹配请求中携带的授权信息,匹配成功则执行具体操作,匹配不到则说明该请求无授权,返回 NoAuthException 异常信息。
点击工具栏–运行–运行到内置浏览器,内置浏览器是H5平台,所以登录弹窗会显示。点击工具栏–运行–运行到小程序模拟器–微信开发者工具,因为我们用条件编译设置了仅在H5平台显示登录弹窗,所以登录弹窗不会显示。运行到其他平台也不会显示登录弹窗,大家可以自己测试一下。
如果状态码是 4xx,服务器就应该向用户返回出错信息。一般来说,返回的信息是键值对形式的数据,将 error 作为键名,出错信息作为键值即可。比如,在一个提供查询学生信息的 API 中,要求客户端提供正确的 API key(可以理解为输入了正确的用户名和密码)才能访问,如果提供的 API key 不正确,此时服务器应拒绝访问,并返回错误信息。这样,客户端就知道了为何没能查到信息,修改成正确的 API key 即可。{ error: "Invalid API key"}
在 Zookeeper 客户端中,当我们使用 addauth digest mooc:mooc 命令来添加认证用户信息时,Zookeeper 客户端会使用 ClientCnxn 客户端类的 addAuthInfo 方法来封装请求信息,把请求类型包装成权限类请求,封装完毕后发送给服务端。// 添加认证信息,参数一:授权类型,参数二:认证信息的字节数组public void addAuthInfo(String scheme, byte[] auth) { // 判断当前客户端状态 if (this.state.isAlive()) { // 封装认证信息 scheme:digest this.authInfo.add(new ClientCnxn.AuthData(scheme, auth)); // 封装请求头 -4为请求头的xid,100为请求类型:auth this.queuePacket(new RequestHeader(-4, 100), (ReplyHeader)null, new AuthPacket(0, scheme, auth), (Record)null, (AsyncCallback)null, (String)null, (String)null, (Object)null, (WatchRegistration)null); }}简单地介绍了 Zookeeper 客户端处理权限类请求的过程,接下来就是 Zookeeper 服务端的处理过程了。
Hystrix 将原生特性和服务监控平台分为了两部分进行集成,目前,我们所引入的 Hystrix 依赖是下面这样的:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency>这个依赖只提供了 Hystrix 的基本特性,就是我们前面所介绍的服务容错与降级、服务熔断、服务快速失败等基础内容,并没有把微服务监控台集成到该依赖中,所以,如果我们想搭建微服务监控平台,就需要引入专门支持微服务监控平台的依赖,如下所示:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId> spring-cloud-starter-netflix-hystrix-dashboard </artifactId></dependency>从上述 artifactid 可以看出,基础的 Hystrix 依赖只比微服务监控平台的依赖名称少一个 dashboard ,这就是 Spring Cloud 潜在的命名规范,大家可以参考学习。在服务提供者的项目中,我们还需要引入一个依赖,如下所示:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId></dependency>这个依赖是 Spring boot 框架提供的一个监控器,HystrixDashboard 需要配置这个监控器来完成对微服务项目的监控。由于我们的项目是基于 Maven 包管理工具所构建的项目,所以我们需要将微服务监控平台的依赖引入到我们的项目中去。在将微服务监控平台的依赖引入项目中去后,等待我们的编译器解析完成,没有报任何的红色错误,说明我们已经将 Hystrix 的微服务监控平台引入到了项目中去。在将依赖引入成功后,我们需要对我们的 Spring Cloud 微服务项目做一下简单的配置,以可以使用 Hystrix 的服务监控平台。首先,找到我们项目的启动类,然后在启动类的上方,添加 @EnableHystrixDashboard 注解,表明在项目中启用 Hystrix 的微服务项目监控平台,如下代码所示:@SpringBootApplication@EnableHystrix@EnableHystrixDashboardpublic class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }}代码解释:第 3 行,我们在项目启动类的上方添加了 EnableHystrixDashboard 注解,表明在项目中已经开启了 Hystrix 微服务监控平台的使用,可以在项目中使用微服务监控平台了。经过上述配置之后,运行我们的项目,然后在浏览器地址栏输入:localhost:8060/hystrix即项目地址 + 项目端口号 + hystrix 路径,当看到下面截图时,说明我们的 Hystrix 微服务监控平台已经成功集成到了我们的项目中来。Hystrix Dashboard 登录界面这就是搭建 Hystrix 微服务监控平台的全部流程,希望同学们可以一次成功。Tips: 1. 各位同学在选择 HystrixDashboard 的依赖时,一定要确保 HystrixDashboard 的依赖版本与我们所使用的 Hystrix 的依赖版本保持一致,否则就会出现由于版本不一致而引起的兼容问题,导致我们的 HystrixDashboard 无法引入到项目中去; 2. 在配置项目启动类时,需要保证 @EnableHystrix 注解和 @EnableHystrixDashboard 注解同时存在,这两个注解少一个,我们的微服务监控平台就无法正常使用,这点需要同学们注意。 3. 在访问 Hystrix 的微服务项目监控平台时,/hystrix 为 Hystrix 提供的默认访问路径,不需要我们进行额外的配置,实际工作中,也很少有人会专门对这个路径名称进行修改; 4. 使用 Hystrix 的微服务监控平台,需要至少存在 2 个微服务项目,Hystrix 不能自己监测自己本身,这一点请同学们注意。
我们在服务提供者的同级新建项目服务消费者,使用 Spring Initializr 来初始化,以下是服务消费者的项目信息:pom.xml初始化完成,我们在 pom.xml 文件中加入需要的依赖。<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>cn.cdd</groupId> <artifactId>zookeeper-consumer</artifactId> <version>0.0.1-SNAPSHOT</version> <name>zookeeper-consumer</name> <description>zookeeper-consumer Demo project for Spring Boot</description> <properties> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- curator 客户端 --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>5.1.0</version> </dependency> <!-- curator 客户端 --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>5.1.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>application.properties依赖导入后,我们在 application.properties 配置端口信息server.port=9090接下来我们编写使用 Curator 客户端连接 Zookeeper 服务的代码。CuratorService在项目主类的同级新建目录 service 目录,在 service 目录下新建 CuratorService 类:@Componentpublic class CuratorService implements ApplicationRunner { private static CuratorFramework client; private static final String PROVIDER_NODE = "/imooc/provider"; private static List<String> PROVIDER_SERVER_LIST; private static int NUMBER_OF_REQUESTS = 0; @Override public void run(ApplicationArguments args) throws Exception { // 构建 CuratorFramework 客户端,并开启会话 buildCuratorClient(); // 获取服务列表 getAListOfServiceAddresses(); // 开启对 PROVIDER_NODE 子节点变化事件的监听 startMonitoring(); } /** * 构建 CuratorFramework 客户端,并开启会话 */ private void buildCuratorClient() { // 使用 CuratorFrameworkFactory 构建 CuratorFramework client = CuratorFrameworkFactory.builder() .sessionTimeoutMs(10000) // Zookeeper 地址 .connectString("127.0.0.1:2181") // 重连策略 .retryPolicy(new RetryForever(10000)) .build(); // 开启会话 client.start(); System.out.println(">>> 服务消费者连接 Zookeeper "); } /** * 获取服务列表 * * @throws Exception Exception */ private void getAListOfServiceAddresses() throws Exception { Stat stat = client.checkExists().forPath(PROVIDER_NODE); if (stat == null) { throw new RuntimeException("服务地址未注册到 Zookeeper"); } else { PROVIDER_SERVER_LIST = client.getChildren().forPath(PROVIDER_NODE); } } /** * 开启对 PROVIDER_NODE 子节点变化事件的监听 */ public void startMonitoring() { // 构建 CuratorCache 实例 CuratorCache cache = CuratorCache.build(client, PROVIDER_NODE); // 使用 Fluent 风格和 lambda 表达式来构建 CuratorCacheListener 的事件监听 CuratorCacheListener listener = CuratorCacheListener.builder() // 开启对 PROVIDER_NODE 节点的子节点变化事件的监听 .forPathChildrenCache(PROVIDER_NODE, client, (curator, event) -> // 重新获取服务列表 PROVIDER_SERVER_LIST = curator.getChildren().forPath(PROVIDER_NODE)) // 初始化 .forInitialized(() -> System.out.println(">>> CuratorCacheListener 初始化")) // 构建 .build(); // 注册 CuratorCacheListener 到 CuratorCache cache.listenable().addListener(listener); // CuratorCache 开启缓存 cache.start(); } /** * 轮询策略,按顺序获取服务地址 * * @return 服务地址 */ public String roundRobin() { if (PROVIDER_SERVER_LIST.isEmpty()){ throw new RuntimeException(">>> 服务提供者地址列表为空"); } int i = NUMBER_OF_REQUESTS % PROVIDER_SERVER_LIST.size(); NUMBER_OF_REQUESTS++; return PROVIDER_SERVER_LIST.get(i); }}在 CuratorService 中,我们提供了创建 Curator 客户端的方法,获取服务地址列表的方法,对父节点的子节点变化事件开启监听的方法,以及对服务的负载均衡策略的方法轮询策略。在服务消费者启动时,连接 Zookeeper 服务,获取已注册的服务地址列表,并对服务地址临时节点的父节点开启监听。监听到子节点的变化事件时,则重新获取服务地址列表。ConsumerController这里我们使用 RESTful 的风格来调用服务消费者的方法,在 service 同级创建目录 controller ,在 controller 中创建 ConsumerController 类:@RestController@RequestMapping("/consumer")public class ConsumerController { @Autowired private CuratorService curatorService; @Autowired private RestTemplate restTemplate; /** * 调用方法 * http://localhost:9090/consumer/callMethod * * @return String */ @GetMapping("/callMethod") public String callMethod() { // 轮询策略获取服务地址 String s = curatorService.roundRobin(); // 使用 RestTemplate 远程调用服务的 /provider/callMethod 方法,String.class 为返回值类型 return restTemplate.getForObject("http://" + s + "/provider/callMethod", String.class); }}我们使用了 RestTemplate 来远程调用 RESTful 风格的接口,所以我们需要把 RestTemplate 注入到 Spring IOC 容器中。RestTemplate我们在服务消费者项目的主类中注入Bean RestTemplate :package cn.cdd.zookeeper.consumer;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Bean;import org.springframework.web.client.RestTemplate;@SpringBootApplicationpublic class ZookeeperConsumerApplication { public static void main(String[] args) { SpringApplication.run(ZookeeperConsumerApplication.class, args); } @Bean public RestTemplate restTemplate(){ return new RestTemplate(); }}controller 编写完毕后,我们就可以对我们的服务消费者进行测试了。