如何健壮你的后端服务

1.怀疑第三方

有兜底最好业务降级方案

  如果第三方服务挂掉怎么办?我们业务也跟着挂掉?显然这不是我们希望看到的结果,如果能制定好降级方案,那将大大提高服务的可靠性。举几个例子以便大家更好的理解。

 

遵循快速失败失败原则,一定要设置好超时时间

 

保护第三方 慎重选择重试机制

 

 

2、防备使用方

设计一个好的api,避免误用

a) 遵循接口最少暴露原则

  使用方用多少接口我们就提供多少,因为提供的接口越多越容易出现乱用现象,言多必失嘛。此外接口暴露越多自己维护成本就越高。

b) 不要让使用方做接口可以做的事情

  如果使用方需要调用我们接口多次才能进行一个完整的操作,那么这个接口设计就可能有问题。比如获取数据的接口,如果仅仅提供getData(int id);接口,那么使用方如果要一次性获取20个数据,它就需要循环遍历调用我们接口20次,不仅使用方性能很差,也无端增加了我们服务的压力,这时提供getDataList(List<Integer> idList);接口显然是必要的。

 

c) 适用方能从其他第三方获取的数据,不要给他处理

 

比如 要获取交易订单列表接口,使用方让给返回会员卡名称 票名称字段,最后核心交易,我也要从依赖第三方区获取这些数据,那就让使用方自己去调用拼接这些数据

 

c避免长时间执行的接口

  还是以获取数据方法为例:getDataList(List<Integer> idList); 假设一个用户一次传1w个id进来,我们的服务估计没个几秒出不来结果,而且往往是超时的结果,用户怎么调用结果都是超时异常,那怎么办?限制长度,比如限制长度为100,即每次最多只能传100个id,这样就能避免长时间执行,如果用户传的id列表长度超过100就报异常。

  加了这样限制后,必须要让使用方清晰地知道这个方法有此限制。之前就遇到误用的情况,某用户一个订单买了超过100个商品,该订单服务需要调用商品中心接口获取该订单下所有商品的信息,但是怎么调用都失败,而且异常也没打出什么有价值的信息,后来排查好久才得知是商品中心接口做了长度限制。

  怎么才能做到加了限制,又不让用户误用呢?

  两种思路:1)接口帮用户做了分割调用操作,比如用户传了1w个id,接口内部分割成100个id列表(每个长度100),然后循环调用,这样对使用方屏蔽了内部机制,对使用方透明;2)让用户自己做分割,自己写循环显示调用,这样需要让用户知道我们方法做了限制,具体方法有:1)改变方法名,比如getDataListWithLimitLength(List<Integer> idList); ;2)增加注释;3)如果长度超过 100,很明确地抛出异常,很直白地进行告知。

 

d)参数易用原则

  避免参数长度太长,一般超过3个后就较难使用,那有人说了我参数就是这么多,那怎么办?写个参数类嘛!

  此外避免连续的同类型的参数,不然很容易误用。

  能用其它类型如int等的尽量不要用String类型,这也是避免误用的方法。

e)异常

 

限流

 

3、做好自己

 

3.1 单一职责原则

  对于工作了两年以上的同学来说,设计模式应该好好看看,我觉得各种具体的设计模式其实并不重要,重要的是背后体现的原则。比如单一职责原则,在我们的需求分析、架构设计、编码等各个阶段都非常有指导意义。

  在需求分析阶段,单一职责原则可以界定我们服务的边界,如果服务边界如果没界定清楚,各种合理的不合理的需求都接,最后导致服务出现不可维护、不可扩展、故障不断的悲哀结局。

  对于架构来讲,单一职责也非常重要。比如读写模块放置在一起,导致读服务抖动非常厉害,如果读写分离那将大大提高读服务的稳定性(读写分离);比如一个服务上同时包含了订单、搜索、推荐的接口,那么如果推荐出了问题可能影响订单的功能,那这个时候就可以将不同接口拆分为独立服务,并独立部署,这样一个出问题也不会影响其他服务(资源隔离);又比如我们的图片服务使用独立域名、并放置到cdn上,与其它服务独立(动静分离)。

  从代码角度上讲,一个类只干一件事情,如果你的类干了多个事情,就要考虑将他分开。这样做的好处是非常清晰,以后修改起来非常方便,对其它代码的影响就很小。再细粒度看类里的方法,一个方法也只干一个事情,即只有一个功能,如果干两件事情,那就把它分开,因为修改一个功能可能会影响到另一个功能。

 

3.2 避免单点

 

不要把鸡蛋放在一个篮子里面,要做好服务多机房部署,异地多活,服务应该做到水平的扩展

对于数据来说避免单点就是 通过分片 分层的方式

 

最近我们公司atop出了一次故障,导致用户中心,联动等都大量超时报警,最后排查到是因为我们的base服务的多语言 缓存存在大value的问题,导致把连接打满,cpu飙升,内存使用率升高,因为其他服务也依赖base服务,但是其他接口大量的超时

 

解决方案 ,临时加机器,马上最大value的拆分工作,等平稳下来再把机器下掉

将大value拆分小value,mget的方式获取

 

也有存在缓存热点问题,80%的请求读到20%的资源

 

将热点数据放到本地缓存

将热点key 随机,避免单个热点key一直打到一台服务上

 

### 使用 C++ 进行后端服务器开发教程与最佳实践 对于希望使用 C++ 开发后端服务器的应用开发者来说,掌握一些核心概念和技术至关重要。尽管某些情况下引入复杂构建系统可能带来不必要的麻烦[^1],但在其他场景下,特别是高性能需求环境中,C++ 的优势显著。 #### 选择合适的框架 为了简化网络编程并提高生产力,建议采用成熟的第三方库或框架来加速开发过程。例如: - **Boost.Beast** 和 **Boost.Asio**: 提供异步 I/O 支持以及 HTTP/HTTPS 协议实现; - **Pistache**: 轻量级 RESTful Web 框架,支持 WebSocket 及 gRPC; - **Crow**: 类似于 Flask (Python) 的微型 web 框架; 这些工具不仅能够帮助处理常见的通信协议,还提供了线程池管理等功能模块,从而让开发者可以专注于业务逻辑的设计上。 #### 设计高效的数据结构和算法 由于 C++ 是一种编译型语言,在性能优化面具有天然的优势。合理利用 STL 容器类(如 `std::vector`, `std::map`),配合自定义数据类型,可以在不牺牲灵活性的前提下获得极高的运行效率。此外,理解内存分配机制、减少动态申请次数也是提升整体表现的重要手段之一。 ```cpp // 示例:创建一个简单的HTTP响应处理器 #include <boost/beast/core.hpp> namespace http = boost::beast::http; void handle_request(http::request<http::string_body>& req, http::response<http::string_body>& res){ // 处理请求... } ``` #### 遵循良好的编码习惯 编写清晰易读且易于维护的代码同样重要。遵循 SOLID 原则有助于保持系统的可扩展性和健壮性;而通过单元测试验证功能正确性的做法也不应被忽视。另外,考虑到多平台兼容性问题时,则需注意不同操作系统间的差异之处。 #### 性能调优技巧 当应用程序达到一定规模之后,对其进行细致入微地调整就显得尤为必要了。这包括但不限于以下几个面: - 减少锁竞争:尽可能降低临界区范围内的操作频率; - 缓存热点资源:避免重复计算已知结果; - 利用 SIMD 指令集:针对特定硬件特性发挥最大效能。 综上所述,虽然相比于解释型脚本语言而言,基于 C++ 构建后台服务确实存在一定的门槛,但从长远来看,其带来的回报无疑是值得期待的。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值