假设你正在开发一个电商网站,那么这里会涉及到很多后端的微服务,比如会员、商品、推荐服务等等。
那么这里就会遇到一个问题,APP/Browser怎么去访问这些后端的服务? 如果业务比较简单的话,可以给每个业务都分配一个独立的域名(https://service.api.company.com),但这种方式会有几个问题:
更好的方式是采用API网关,实现一个API网关接管所有的入口流量,类似Nginx的作用,将所有用户的请求转发给后端的服务器,但网关做的不仅仅只是简单的转发,也会针对流量做一些扩展,比如鉴权、限流、权限、熔断、协议转换、错误码统一、缓存、日志、监控、告警等,这样将通用的逻辑抽出来,由网关统一去做,业务方也能够更专注于业务逻辑,提升迭代的效率。
通过引入API网关,客户端只需要与API网关交互,而不用与各个业务方的接口分别通讯,但多引入一个组件就多引入了一个潜在的故障点,因此要实现一个高性能、稳定的网关,也会涉及到很多点。
API 注册
业务方如何接入网关?一般来说有几种方式。
协议转换
内部的API可能是由很多种不同的协议实现的,比如HTTP、Dubbo、GRPC等,但对于用户来说其中很多都不是很友好,或者根本没法对外暴露,比如Dubbo服务,因此需要在网关层做一次协议转换,将用户的HTTP协议请求,在网关层转换成底层对应的协议,比如HTTP ->Dubbo, 但这里需要注意很多问题,比如参数类型,如果类型搞错了,导致转换出问题,而日志又不够详细的话,问题会很难定位。
服务发现
网关作为流量的入口,负责请求的转发,但首先需要知道转发给谁,如何寻址,这里有几种方式:
服务调用
网关由于对接很多种不同的协议,因此可能需要实现很多种调用方式,比如HTTP、Dubbo等,基于性能原因,最好都采用异步的方式,而Http、Dubbo都是支持异步的,比如apache就提供了基于NIO实现的异步HTTP客户端。
因为网关会涉及到很多异步调用,比如拦截器、HTTP客户端、dubbo、redis等,因此需要考虑下异步调用的方式,如果基于回调或者future的话,代码嵌套会很深,可读性很差,可以参考zuul和spring cloud gateway的方案,基于响应式进行改造。
优雅下线
性能
网关作为所有流量的入口,性能是重中之重,早期大部分网关都是基于同步阻塞模型构建的,比如Zuul 1.x。但这种同步的模型我们都知道,每个请求/连接都会占用一个线程,而线程在JVM中是一个很重的资源,比如Tomcat默认就是200个线程,如果网关隔离没有做好的话,当发生网络延迟、FullGC、第三方服务慢等情况造成上游服务延迟时,线程池很容易会被打满,造成新的请求被拒绝,但这个时候其实线程都阻塞在IO上,系统的资源被没有得到充分的利用。另外一点,容易受网络、磁盘IO等延迟影响。需要谨慎设置超时时间,如果设置不当,且服务隔离做的不是很完善的话,网关很容易被一个慢接口拖垮。
而异步化的方式则完全不同,通常情况下一个CPU核启动一个线程即可处理所有的请求、响应。一个请求的生命周期不再固定于一个线程,而是会分成不同的阶段交由不同的线程池处理,系统的资源能够得到更充分的利用。而且因为线程不再被某一个连接独占,一个连接所占用的系统资源也会低得多,只是一个文件描述符加上几个监听器等,而在阻塞模型中,每条连接都会独占一个线程,而线程是一个非常重的资源。对于上游服务的延迟情况,也能够得到很大的缓解,因为在阻塞模型中,慢请求会独占一个线程资源,而异步化之后,因为单条连接所占用的资源变的非常低,系统可以同时处理大量的请求。
如果是JVM平台,Zuul 2、Spring Cloud gateway等都是不错的异步网关选型,另外也可以基于Netty、Spring Boot2.x的webflux、vert.x或者servlet3.1的异步支持进行自研。
缓存
对于一些幂等的get请求,可以在网关层面根据业务方指定的缓存头做一层缓存,存储到Redis等二级缓存中,这样一些重复的请求,可以在网关层直接处理,而不用打到业务线,降低业务方的压力,另外如果业务方节点挂掉,网关也能够返回自身的缓存。
限流
限流对于每个业务组件来说,可以说都是一个必须的组件,如果限流做不好的话,当请求量突增时,很容易导致业务方的服务挂掉,比如双11、双12等大促时,接口的请求量是平时的数倍,如果没有评估好容量,又没有做限流的话,很容易服务整个不可用,因此需要根据业务方接口的处理能力,做好限流策略,相信大家都见过淘宝、百度抢红包时的降级页面。
因此一定要在接入层做好限流策略,对于非核心接口可以直接将降级掉,保障核心服务的可用性,对于核心接口,需要根据压测时得到的接口容量,制定对应的限流策略。限流又分为几种:
稳定性
稳定性是网关非常重要的一环,监控、告警需要做的很完善才可以,比如接口调用量、响应时间、异常、错误码、成功率等相关的监控告警,还有线程池相关的一些,比如活跃线程数、队列积压等,还有些系统层面的,比如CPU、内存、FullGC这些基本的。
网关是所有服务的入口,对于网关的稳定性的要求相对于其他服务会更高,最好能够一直稳定的运行,尽量少重启,但当新增功能、或者加日志排查问题时,不可避免的需要重新发布,因此可以参考zuul的方式,将所有的核心功能都基于不同的拦截器实现,拦截器的代码采用Groovy编写,存储到数据库中,支持动态加载、编译、运行,这样在出了问题的时候能够第一时间定位并解决,并且如果网关需要开发新功能,只需要增加新的拦截器,并动态添加到网关即可,不需要重新发布。
熔断降级
熔断机制也是非常重要的一项。若某一个服务挂掉、接口响应严重超时等发生,则可能整个网关都被一个接口拖垮,因此需要增加熔断降级,当发生特定异常的时候,对接口降级由网关直接返回,可以基于Hystrix或者Resilience4j实现。
日志
由于所有的请求都是由网关处理的,因此日志也需要相对比较完善,比如接口的耗时、请求方式、请求IP、请求参数、响应参数(注意脱敏)等,另外由于可能涉及到很多微服务,因此需要提供一个统一的traceId方便关联所有的日志,可以将这个traceId置于响应头中,方便排查问题。
隔离
比如线程池、http连接池、redis等应用层面的隔离,另外也可以根据业务场景,将核心业务部署带单独的网关集群,与其他非核心业务隔离开。
网关管控平台
这块也是非常重要的一环,需要考虑好整个流程的用户体验,比如接入到网关的这个流程,能不能尽量简化、智能,比如如果是dubbo接口,我们可以通过到git仓库中获取源码、解析对应的类、方法,从而实现自动填充,尽量帮用户减少操作;另外接口一般是从测试->预发->线上,如果每次都要填写一遍表单会非常麻烦,我们能不能自动把这个事情做掉,另外如果网关部署到了多个可用区、甚至不同的国家,那这个时候,我们还需要接口数据同步功能,不然用户需要到每个后台都操作一遍,非常麻烦。
这块个人的建议是直接参考阿里云、aws等提供的网关服务即可,功能非常全面。
其他
其他还有些需要考虑到的点,比如接口mock,文档生成、sdk代码生成、错误码统一、服务治理相关的等,这里就不累述了。
目前的网关还是中心化的架构,所有的请求都需要走一次网关,因此当大促或者流量突增时,网关可能会成为性能的瓶颈,而且当网关接入的大量接口的时候,做好流量评估也不是一项容易的工作,每次大促前都需要跟业务方一起针对接口做压测,评估出大致的容量,并对网关进行扩容,而且网关是所有流量的入口,所有的请求都是由网关处理,要想准确的评估出容量很复杂。可以参考目前比较流行的ServiceMesh,采用去中心化的方案,将网关的逻辑下沉到sidecar中,
sidecar和应用部署到同一个节点,并接管应用流入、流出的流量,这样大促时,只需要对相关的业务压测,并针对性扩容即可,另外升级也会更平滑,中心化的网关,即使灰度发布,但是理论上所有业务方的流量都会流入到新版本的网关,如果出了问题,会影响到所有的业务,但这种去中心化的方式,可以先针对非核心业务升级,观察一段时间没问题后,再全量推上线。另外ServiceMesh的方案,对于多语言支持也更友好。
网络管理员90%的工作往往是诊断和解决各种各样的故障。虽然说没有人喜欢麻烦,但麻烦总是自己找上门来。只有拥有高超的诊断技能,你才能在紧急情况下迅速响应,保障网络流畅地运行。当你面临网络故障的挑战时,首先向自己问几个简单的问题:有哪些地方被改变了?这个问题以前遇到过吗?如果是,是什么时候?是否有可能让问题再次出现?用户做了什么特别的操作吗?其他用户有没有遇到过同样的问题?
接下来尝试隔离问题,每次排除一部 分可能引起该问题的因素,逐步找出问题的真正根源。例如,如果一个工作站不能连接到服务器,那就先确定是网络问题还是工作站本身的问题。如果能够迅速地肯定问题出在工作站本身,你就排除了一大半可能导致问题的因素,向真正的故障根源接近一大步了。即使你最终拿不出解决办法,不得不寻找外援,隔离问题也会节省你大量的时间。
为了说明诊断网络故障的一般过程,本文例举了几种故障情形,有的是常见的小问题,有的是比较艰巨的挑战。当你遇到类似的问题时,就可以按照本文例子的介绍,先问自己几个简单的问题,逐步隔离问题所在,最后找到真正的问题根源。
一、找不到验证密码的域服务器
毫无疑问,你也一定遇到过这样的情形:当你坐在一台工作站之前准备登录网络,windows却报告说找不到用来验证密码的域服务器。要解决这个故障,首先要确定问题到底出在网络、工作站还是服务器上。从下面几个问题开始:
→哪些地方改变了?最近是否改动过网络,而这些改动可能导致当前的问题?有没有添加新的服务器、拆除原有的服务器、改动过交换机或HUB?有没有添加或减少域控制器、将成员服务器提升为DC(域控制器)或者相反?
→其他工作站也存在类似的问题吗?
→服务器正在运行吗?
经过检查,你发现此前工作站一直顺利地运行,其他工作站没有遇到类似的问题,服务器也正常。根据故障现象,基本上可以确定故障出在工作站本身。接下来要确定工作站的那个地方出了故障,试试下面几个问题:
→工作站能够Ping到服务器吗?
→工作站获得了一个IP地址吗?
检测表明,工作站能够Ping到服务器,但Ping操作有时超时,这表明工作站和服务器之间只有断断续续的通信。在命令行上执行ipconfig /renew命令,多执行几次,工作站有时会更新IP地址,有时不会。这是工作站和服务器之间断续通信的症状。
现在将问题工作站的网络连接和另一台工作站的对换一下,新工作站在问题工作站的位置上也不能连接网络,而问题工作站却能从另一个网络位置顺利地连接网络。现在已经很清楚:问题工作站所在位置的电缆或Hub出了问题。
拆下故障位置上网络电缆连接Hub的那一端,将它接到另一个Hub上,故障依旧。现在可以肯定电缆就是引起故障的罪魁祸首了。
二、windows服务不能启动
在一台Windows 2000服务器上,部分服务设置成不用本地的系统帐户启动。一次重新启动Windows 2000服务器之后,发现这些服务没有启动,必须手工打开服务,重新输入密码,然后启动服务。每次重新输入密码,都收到消息说:<用户名字>已被授予作为服务登录的权限。
要解决该故障,首先回答下面几个问题:
→哪些地方改变了?是否有人修改了服务器?
→这个服务以前能够启动吗?
→用户名称和密码正确吗?
查询修改记录发现,该服务器是一个DC,不久之前还是域控制器组织单元(OU,Organizational Unit)的成员。在移出该OU之前,这些服务一直能够顺利启动。另外,用来启动这些服务的用户名称和密码都是合法的。进一步研究发现,域控制器OU的成员有一些特殊的权限,其中包括作为服务登录的权限。当出现问题的服务器移出该OU时,服务器失去了那些权限。现在要做的是恢复服务器的权限。
要将权限授予服务器,请按照如下步骤操作:
→在管理控制台(MMC)中打开活动目录用户和计算机管理单元,再打开域控制器OU的“属性”对话框。
→在组策略页中,点击“默认域控制器策略”,然后点击“编辑”,打开组策略管理器。
→依次扩展计算机配置/Windows设置/安全设置,再扩展“本地策略”,然后点击“用户权利指派”。
→在右边的窗格中,右击“作为服务登录”,选择菜单“安全”。
→把用来启动服务的用户帐户加入到策略,完成后点击“确定”。
有关该问题的更多资料,请参见微软的文章“如何解决服务启动权限问题”(http://support.microsoft.com/?kbid=259733)。
三、无法收到外面发来的邮件
单位用Exchange 2000 Server作为内部和外部的邮件服务器。有一天原来的ISP不能再提供服务了,所以你迅速换了一个新的ISP。用户仍旧能够照常访问Internet,却收不到外面来的邮件。不过,发出去的邮件看来没有问题。
要排解这一故障,第一个要问的问题是:
→在改变ISP之前,邮件系统工作正常吗?
要确定Exchange Server是否正常工作,防火墙配置是否正确,可以从Internet连接到Exchange Server 25端口(具体操作办法,请参见微软文章:Telnet 到 IMC 的端口 25 以测试 IMC 通信, http://support.microsoft.com/?kbid=153119),发送一个测试消息,确认服务器和防火墙都在正常运行。故障的原因很可能是因为改变ISP。
再回答下面这个问题:
→域名信息正确转移到了新的ISP吗?
用Nslookup工具,测试一下是否能够找到域的邮件交换(MX)记录,结果却什么也没有找到。根据这一现象,可以推断在更换ISP时,域名注册公司没有正确转移域名信息。现在你可以联系域名注册公司,要求登记MX记录,以及将域名信息正确转到新的ISP。只要MX记录在Internet上一传播开,Exchange Server又可以收到外面来的邮件了。
四、网络上看不到服务器
Win2K Pro工作站遇到了奇怪的问题:偶尔能够看到Win 2K Server,但大部分时间里服务器就象从网络上消失了一样。在排解这一网络故障的过程中,首先要回答的问题是:
→过去出现过该故障吗?
→是否所有的工作站都出现相同的情况?
经调查后发现,这一故障现象自服务器从 Windows NT 4.0升级到Win2K就开始存在了,网络上的所有工作站都出现同样的现象。现在要确定的是:故障的根源是服务器呢,还是网络。
登录一个工作站,打开命令控制台,执行ping/pathping命令来连接服务器。结果发现,Ping服务器的IP地址没有问题,但却Ping不到服务器的名字。可以肯定,故障的原因是名称解析或DNS错误。
接下来执行ipconfig/all,注意到工作站上DNS服务器指向了ISP的DNS服务器。Win2K将DNS作为其基本的名称解析机制,但现在工作站却用ISP的DNS服务器来解析本地网络的Win2K服务器名称。当工作站向ISP的DNS服务器查询Win2K服务器名称时,只能得到超时错误,导致Win2K服务器从网络上隐身了。要解决该故障,必须把主DNS服务器指向内部的Win2K DNS服务器,让内网的工作站向Win2K DNS服务器查询本地服务器名称。
首先证实Win2K服务器上确实已经安装了DNS服务,且DNS服务在正常运行,然后修改Win2K DNS服务器IP地址指向它自己。接下来利用DNS管理器,验证DNS服务器位于根位置,且已经启用转发。启用转发之后,就可以解析非本地的任何IP地址了。不要忘记将ISP的DNS服务器输入转发栏。最后配置一下服务器上的DHCP,将DNS服务器从ISP的改成Win2K服务器,刷新工作站上的IP地址。现在网络已经能够稳定地运行了。有关在这类环境下配置DNS的信息,请参见微软的文章“HOW TO:配置 DNS 以访问 Internet”(http://support.microsoft.com/?kbid=300202)。
五、LAN连接到多个WAN
不久前在A市安装了一个LAN,它有两个WAN连接,其中一个连接通向私有的帧中继网络,另一个连接通向Internet,这是为了防止出现故障和提高性能(图二显示了网络结构)。现在出现的故障是:A市的用户有时不能顺利访问B市的服务器。
要解决该故障,首先要搞清楚下面两个问题:
→故障何时出现?
→默认网关是什么?
故障出现是间歇性的。在A市的DHCP配置中,默认网关是192.168.1.11(即防火墙)。由于A市LAN里面的所有机器都会出现同样的故障现象,所以问题很可能出在A市网络上的全局性路由配置上。
在防火墙上有一条静态路由,从192.168.2.0(掩码255.255.255.0)到192.168.1.10,用Route Print可以验证这一规则。A市服务器有时可以Ping到B市的服务器,但有时不能。运行Tracert,结果如图三所示,它显示出了数据包应当通过的路径。但有的时候,运行Tracert却显示出数据包在第一个跃点(192.168.1.11)之后遇到超时错误。根据这一现象,可以推测防火墙没有可靠地将数据包转发到控制192.168.2.0通信的Cisco路由器。
查阅防火墙的日志,可以看到数据包有时被禁止转发到192.168.1.10,虽然存在这样一条转发规则也无济于事。防火墙的种类很多,但大多数防火墙厂商都反对将防火墙当作路由器,如果防火墙被攻击者劫持,有关WAN连接的大量信息就会泄露。
因此现在要重新配置网络,使用默认的网关192.168.1.10(即路由器),执行命令Ip route 0.0.0.0 0.0.0.0 192.168.1.11在路由器上建立一个默认的路由。用户访问Internet时先通过路由器,再穿越防火墙。
如果A市的路由器(192.168.1.10)出现故障,会对Internet访问产生哪些影响?如果帧中继网络失效,但Internet连接仍正常,情况又如何?一旦A市的路由器故障,Internet连接也会丢失,这是因为默认的网关指向了该路由器,该路由器故障导致数据包不能转发到防火墙。在A市,将DHCP默认网关配置成防火墙可以恢复Internet连接,当然,在恢复A市路由器之前,其他地区的私有WAN和Internet访问仍旧无效。
六、工作站不能连接网络
办公大楼五楼的工作站看不到服务器,也不能访问Internet。故障间歇性出现。首先要搞清楚的问题是:
→故障出现多长时间了?
→有哪些地方被改变了?
经Pathping工具测试,检测到一些数据包丢失错误。问题看来可以归结到五楼之内。
利用信号发生器或线缆扫描器追踪故障,跟踪网络连接一直到了六楼的Ethernet交换机,五楼和六楼共用该交换机。考虑到可能是交换机端口故障,所以将端口和六楼的一台机器对换了一下,但故障仍旧存在,而且仍只出现在五楼的工作站上,由此推断,交换机应该没有问题。
返回五楼,注意到一个办公室里有个五口的小Hub。进一步查看,注意到还有四个小Hub菊形相连。现在故障的根源找到了。在100 Base-T Ethernet中,每个网络只能有一个Class I转发跃距(0.7毫秒延迟),或者两个Class II转发跃距(0.4毫秒延迟)(由于这个原因,所以不推荐在重要场合使用大量小Hub)。现在拆除所有小Hub,将线头直接接到六楼的交换机,故障消失。
总地来说,不能认为靠死记硬背就能够解决所有常见的网络问题,相反地,应当以开放的心态审视每一种故障现象,从几个简单的问题开始,逐步排除可能的故障原因。记住,隔离问题是迅速排解故障的关键所在。
七、附录:常用网络诊断工具
Windows XP和Windows 2000提供了许多基本的网络检测工具:
■ Pathping
Pathping用来检验是否能够联系到指定的主机。命令行语法是:pathping 。pathping将显示出数据包丢失情况的基本信息。
■ Ipconfig
Ipconfig命令用来显示出工作站的IP配置。命令行语法是:ipconfig /all。通过ipconfig命令的运行结果,至少可以:
→验证工作站具有正确的IP地址和子网掩码。错误的IP地址和子网掩码会导致连接出错。 →如果启用了DHCP,则可以验证工作站已经租到了一个IP地址。如果不能获得IP地址,则表明与DHCP服务器联系方面出了问题。
→验证默认的网关。如果网关错误,连接远程网络或Internet时就会出现问题。
→验证DNS服务器。XP和Win 2K依靠DNS进行名称解析。一般地,工作站应当指向一台Win 2K服务器以获得DNS解析。
■ Nslookup
Nslookup即名称服务器查找(Name Server Lookup),用来查找DNS服务器上的DNS记录。命令语法:nslookup。在前文的例子中,我们用NSLookup来验证邮件交换(MX)记录,排解Internet邮件传送问题。
■ Route Print
Route Print命令显示出本地机器上的路由规则。这个工具和Ping、Tracert以及Pathping命令结合很有用,能够帮助确定数据包通过的路由器。命令语法是:route print。另外,利用Route Add可以将静态路由规则加入到服务器或工作站。
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)