wordpress上传的gif图不会动,百度seo提交,asp网站数据库扫描,哪些网站是做快消品的前言
假设你正在开发一个电商网站#xff0c;那么这里会涉及到很多后端的微服务#xff0c;比如会员、商品、推荐服务等等。 那么这里就会遇到一个问题#xff0c;APP/Browser怎么去访问这些后端的服务? 如果业务比较简单的话#xff0c;可以给每个业务都分配一个独立的域…前言
假设你正在开发一个电商网站那么这里会涉及到很多后端的微服务比如会员、商品、推荐服务等等。 那么这里就会遇到一个问题APP/Browser怎么去访问这些后端的服务? 如果业务比较简单的话可以给每个业务都分配一个独立的域名(https://service.api.company.com)但这种方式会有几个问题:
每个业务都会需要鉴权、限流、权限校验等逻辑如果每个业务都各自为战自己造轮子实现一遍会很蛋疼完全可以抽出来放到一个统一的地方去做。如果业务量比较简单的话这种方式前期不会有什么问题但随着业务越来越复杂比如淘宝、亚马逊打开一个页面可能会涉及到数百个微服务协同工作如果每一个微服务都分配一个域名的话一方面客户端代码会很难维护涉及到数百个域名另一方面是连接数的瓶颈想象一下你打开一个APP通过抓包发现涉及到了数百个远程调用这在移动端下会显得非常低效。每上线一个新的服务都需要运维参与申请域名、配置Nginx等当上线、下线服务器时同样也需要运维参与另外采用域名这种方式对于环境的隔离也不太友好调用者需要自己根据域名自己进行判断。另外还有一个问题后端每个微服务可能是由不同语言编写的、采用了不同的协议比如HTTP、Dubbo、GRPC等但是你不可能要求客户端去适配这么多种协议这是一项非常有挑战的工作项目会变的非常复杂且很难维护。后期如果需要对微服务进行重构的话也会变的非常麻烦需要客户端配合你一起进行改造比如商品服务随着业务变的越来越复杂后期需要进行拆分成多个微服务这个时候对外提供的服务也需要拆分成多个同时需要客户端配合你进行改造非常蛋疼。
API Gateway 更好的方式是采用API网关实现一个API网关接管所有的入口流量类似Nginx的作用将所有用户的请求转发给后端的服务器但网关做的不仅仅只是简单的转发也会针对流量做一些扩展比如鉴权、限流、权限、熔断、协议转换、错误码统一、缓存、日志、监控、告警等这样将通用的逻辑抽出来由网关统一去做业务方也能够更专注于业务逻辑提升迭代的效率。 通过引入API网关客户端只需要与API网关交互而不用与各个业务方的接口分别通讯但多引入一个组件就多引入了一个潜在的故障点因此要实现一个高性能、稳定的网关也会涉及到很多点。 API注册
业务方如何接入网关?一般来说有几种方式。
第一种采用插件扫描业务方的API比如Spring MVC的注解并结合Swagger的注解从而实现参数校验、文档SDK生成等功能扫描完成之后需要上报到网关的存储服务。手动录入。比如接口的路径、请求参数、响应参数、调用方式等信息但这种方式相对来说会麻烦一些如果参数过多的话前期录入会很费时费力。 配置文件导入。比如通过Swagger\OpenAPI等比如阿里云的网关: 协议转换
内部的API可能是由很多种不同的协议实现的比如HTTP、Dubbo、GRPC等但对于用户来说其中很多都不是很友好或者根本没法对外暴露比如Dubbo服务因此需要在网关层做一次协议转换将用户的HTTP协议请求在网关层转换成底层对应的协议比如HTTP - Dubbo, 但这里需要注意很多问题比如参数类型如果类型搞错了导致转换出问题而日志又不够详细的话问题会很难定位。
服务发现
网关作为流量的入口负责请求的转发但首先需要知道转发给谁如何寻址这里有几种方式:
写死在代码/配置文件里这种方式虽然比较挫但也能使用比如线上仍然使用的是物理机IP变动不会很频繁但扩缩容、包括应用上下线都会很麻烦网关自身甚至需要实现一套健康监测机制。域名。采用域名也是一种不错的方案对于所有的语言都适用但对于内部的服务走域名会很低效另外环境隔离也不太友好比如预发、线上通常是同一个数据库因此网关读取到的可能是同一个域名这时候预发的网关调用的就是线上的服务。注册中心。采用注册中心就不会有上述的这些问题即使是在容器环境下节点的IP变更比较频繁但节点列表的实时维护会由注册中心搞定对网关是透明的另外应用的正常上下线、包括异常宕机等情况也会由注册中心的健康检查机制检测到并实时反馈给网关。并且采用注册中心性能也没有额外的性能损耗采用域名的方式额外需要走一次DNS解析、Nginx转发等中间多了很多跳性能会有很大的下降但采用注册中心网关是和业务方直接点对点的通讯不会有额外的损耗。
服务调用
网关由于对接很多种不同的协议因此可能需要实现很多种调用方式比如HTTP、Dubbo等基于性能原因最好都采用异步的方式而Http、Dubbo都是支持异步的比如apache就提供了基于NIO实现的异步HTTP客户端。 因为网关会涉及到很多异步调用比如拦截器、HTTP客户端、dubbo、redis等因此需要考虑下异步调用的方式如果基于回调或者future的话代码嵌套会很深可读性很差可以参考zuul和spring cloud gateway的方案基于响应式进行改造。
优雅下线
优雅下线也是网关需要关注的一个问题网关底层会涉及到很多种协议比如HTTP、Dubbo而HTTP又可以继续细分比如域名、注册中心等有些自身就支持优雅下线比如Nginx自身是支持健康监测机制的如果检测到某一个节点已经挂掉了就会把这个节点摘掉对于应用正常下线需要结合发布系统首先进行逻辑下线然后对后续Nginx的健康监测请求直接返回失败(比如直接返回500),然后等待一段时间(根据Nginx配置决定)然后再将应用实际下线掉。另外对于注册中心的其实也类似一般注册中心是只支持手动下线的可以在逻辑下线阶段调用注册中心的接口将节点下线掉而有些不支持主动下线的需要结合缓存的配置让应用延迟下线。另外对于其他比如Dubbo等原理也是类似。
性能
网关作为所有流量的入口性能是重中之重早期大部分网关都是基于同步阻塞模型构建的比如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等大促时接口的请求量是平时的数倍如果没有评估好容量又没有做限流的话很容易服务整个不可用因此需要根据业务方接口的处理能力做好限流策略相信大家都见过淘宝、百度抢红包时的降级页面。 因此一定要在接入层做好限流策略对于非核心接口可以直接将降级掉保障核心服务的可用性对于核心接口需要根据压测时得到的接口容量制定对应的限流策略。限流又分为几种:
单机。单机性能比较高不涉及远程调用只是本地计数对接口RT影响最小。但需要考虑下限流数的设置比如是针对单台网关、还是整个网关集群如果是整个集群的话需要考虑到网关缩容、扩容时修改对应的限流数。分布式。分布式的就需要一个存储节点维护当前接口的调用数比如redis、sentinel等这种方式由于涉及到远程调用会有些性能损耗另外也需要考虑到存储挂掉的问题比如redis如果挂掉网关需要考虑降级方案是降级到本地限流还是直接将限流功能本身降级掉。 另外还有不同的策略:简单计数、令牌桶等大部分场景下其实简单计数已经够用了但如果需要支持突发流量等场景时可以采用令牌桶等方案。还需要考虑根据什么限流比如是IP、接口、用户维度、还是请求参数中的某些值这里可以采用表达式相对比较灵活。
稳定性
稳定性是网关非常重要的一环监控、告警需要做的很完善才可以比如接口调用量、响应时间、异常、错误码、成功率等相关的监控告警还有线程池相关的一些比如活跃线程数、队列积压等还有些系统层面的比如CPU、内存、FullGC这些基本的。 网关是所有服务的入口对于网关的稳定性的要求相对于其他服务会更高最好能够一直稳定的运行尽量少重启但当新增功能、或者加日志排查问题时不可避免的需要重新发布因此可以参考zuul的方式将所有的核心功能都基于不同的拦截器实现拦截器的代码采用Groovy编写存储到数据库中支持动态加载、编译、运行这样在出了问题的时候能够第一时间定位并解决并且如果网关需要开发新功能只需要增加新的拦截器并动态添加到网关即可不需要重新发布。
熔断降级
熔断机制也是非常重要的一项。若某一个服务挂掉、接口响应严重超时等发生则可能整个网关都被一个接口拖垮因此需要增加熔断降级当发生特定异常的时候对接口降级由网关直接返回可以基于Hystrix或者Resilience4j实现。
日志
由于所有的请求都是由网关处理的因此日志也需要相对比较完善比如接口的耗时、请求方式、请求IP、请求参数、响应参数(注意脱敏)等另外由于可能涉及到很多微服务因此需要提供一个统一的traceId方便关联所有的日志可以将这个traceId置于响应头中方便排查问题。
隔离
比如线程池、http连接池、redis等应用层面的隔离另外也可以根据业务场景将核心业务部署带单独的网关集群与其他非核心业务隔离开。
网关管控平台
这块也是非常重要的一环需要考虑好整个流程的用户体验比如接入到网关的这个流程能不能尽量简化、智能比如如果是dubbo接口我们可以通过到git仓库中获取源码、解析对应的类、方法从而实现自动填充尽量帮用户减少操作另外接口一般是从测试-预发-线上如果每次都要填写一遍表单会非常麻烦我们能不能自动把这个事情做掉另外如果网关部署到了多个可用区、甚至不同的国家那这个时候我们还需要接口数据同步功能不然用户需要到每个后台都操作一遍非常麻烦。 这块个人的建议是直接参考阿里云、aws等提供的网关服务即可功能非常全面。
其他
其他还有些需要考虑到的点比如接口mock文档生成、sdk代码生成、错误码统一、服务治理相关的等这里就不累述了。
总结
目前的网关还是中心化的架构所有的请求都需要走一次网关因此当大促或者流量突增时网关可能会成为性能的瓶颈而且当网关接入的大量接口的时候做好流量评估也不是一项容易的工作每次大促前都需要跟业务方一起针对接口做压测评估出大致的容量并对网关进行扩容而且网关是所有流量的入口所有的请求都是由网关处理要想准确的评估出容量很复杂。可以参考目前比较流行的ServiceMesh采用去中心化的方案将网关的逻辑下沉到sidecar中 sidecar和应用部署到同一个节点并接管应用流入、流出的流量这样大促时只需要对相关的业务压测并针对性扩容即可另外升级也会更平滑中心化的网关即使灰度发布但是理论上所有业务方的流量都会流入到新版本的网关如果出了问题会影响到所有的业务但这种去中心化的方式可以先针对非核心业务升级观察一段时间没问题后再全量推上线。另外ServiceMesh的方案对于多语言支持也更友好。 个人总结当公司项目越来越多提供的服务越来越多必须要统一网关管理统一入口管理这样可以不用重复造轮子比如每个服务都要鉴权等只需要在一个服务中提供鉴权等通用服务即可使用统一网关之后可以对系统安全也有保障其实就类似nignx可以做到统一入口监控各种安全问题接口限流服务限流路由转发路由转发之后对负载均衡配置中心控制平滑稳定上下线开发新服务稳定对外开放与测试高并发时关键服务的稳定提供服务非关键服务可以降级各个服务可以使用不同的语言开发不影响等等
参考API网关 - 腾讯云开发者社区-腾讯云
参考网关的作用 - 简书
参考第九节统一网关Gateway_七号公园的忧伤的博客-CSDN博客_统一网关
如有侵权请联系删除哈