资讯专栏INFORMATION COLUMN

我所理解的服务化

YFan / 2257人阅读

摘要:当不用服务时,非常容易写事务或者其他逻辑保持数据一致性,服务化后难以做到这一点回滚可能都是调用服务,依然可能失败不必要的服务间请求增多。

讲故事环节

我先讲个故事

很久很久以前(其实现在大部分网站都是这样),我们做一个网站,所有的功能代码都会在一个代码库中,部署的时候 db 几台机器、nginx 几台机器、业务 server 几台机器。其中业务 server 的所有逻辑都是在一个进程中的,例如网站的登录、用户的评论、新建问题、某个活动等等。

一起看起来很美好。

突然有一天,老板说我们搞个红包活动吧,微信红包,上线后由于中国人的薅羊毛心态,活动页面 qps 瞬间暴增,导致网站的登录逻辑 qps 也暴增,活动页面压垮的同时,所有其他业务全部504,扩容时也是整个 server 一台一台的加。扩容后发现,其实 qps 大的页面就只有这个活动也,容器上其他页面全部都是资源浪费。

所以造成上面现象的问题有这么几个

降级逻辑,一个边缘东西跪了不应该影响全站(除非是极为核心逻辑、例如登录)

不能定点扩容

这时候就在想,如果登录是一个服务,自己的业务也写成一个服务,主站的其他业务不动,登录、活动、主站业务分机器部署,活动 qps 来的时候我只要扩展登录和活动的容器就好了。而且这样在活动的这个服务中可以方便的接入登录的降级。

什么是降级

简单的理解,降级就是指需要被降级的东西跪了的时候,业务不会5xx。

土办法的做法就是加 try except,这样就会有这么一个问题,例如下面的代码中,do_something 可能是 mysql 的一次写,其他耗时操作的一次查,当 do_something 彻底跪了的时候,如果用 try except,每个 qps 来的时候,do_something 会依然执行,例如 mysql 跪了起不来,do_something 每次都会去连接 mysql,然后500。

    try:
        do_something()
    except Exception as ex:
        logging.error(ex, exc_info=1)

那么我们明知道这个地方跪了,为什么还要一直打他呢?降级时可不可以在一定时间内返回一个默认值,不去真实的做 do_something,或者在接下来的一定次数的 qps 返回一个默认值?

Hystrix的降级策略

所以什么是服务化

看看下面知乎的这个专栏好了

知乎服务化
知乎的一个回答
实施微服务,我们需要哪些基础框架? 这个捡着看

服务化的优点和缺点

优点

根据服务扩容简单

降级容易做(就可以评论跪了整个网站其他功能还活着)

上线时只上自己对应的服务即可,不影响其他业务(数据相关还会影响)

缺点

业务拆分定级,否则会服务爆炸(是个功能就写个服务,后期服务巨多无比)

数据一致性难以保持。当不用服务时,非常容易写事务或者其他逻辑保持数据一致性,服务化后难以做到这一点(回滚可能都是调用服务,依然可能失败)

不必要的服务间请求增多。不用服务时,很多东西查一次可以用上下文的形式传递,服务化后服务内部可能需要自己重新查一遍。

批量接口难以实现

服务间解耦,一般采用消息系统(kafka),需要消息系统稳定

非 rpc 层的单测是骗自己的,毕竟 rpc 调用的地方都会 mock

怎么服务化

业务拆分是逃不掉的,服务化后还需要慢慢替换原有实现。

我们重点说下技术手段

你可以选择 rest 或者 rpc,协议的话 HTTP 开销比较大,业界现在似乎比较主流的选择是 thrift 协议,然后做一个 rpc。给出饿了么实现的一套 python 版本 thriftpy。

所以坑爹的点就在于,你拿到一套 thrift 的协议的时候,例如 thriftpy,他不像 django、ruby on rails之类的会有非常明确的代码分层要求,如果内部不在强行定义规范,每个开发写出的服务都不一样。

那么当你服务有多个容器后,怎么方便分组部署呢?首先你需要服务发现 consul, 例如我们定义一个服务叫做用户服务 member,他可能在物理机 A 3001端口,3002端口,物理机 B 3001端口起了3个 rpc server,consul 可以注册一个 member,物理机端口的事儿同样注册在里面,业务方只要用 member 这个名字就好了,不必知道具体打的是哪一台物理机的那个 server。

配套食用的可能还有 haproxy 做负载均衡的,我没用过表示只知道这玩意儿。

你真的需要服务化么

这个是非常需要思考的问题。如果你的网站 qps 非常低,搞毛幺蛾子。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/40752.html

相关文章

  • 我所理解接口设计

    摘要:前言自己做接口开发的时间也算不短了三年,想写这篇文章其实差不多已经有一年多的时间了。 前言 自己做接口开发的时间也算不短了(三年),想写这篇文章其实差不多已经有一年多的时间了。我将从下面的方向来对我所理解的接口设计做个总结: 接口参数定义 -> 接口版本化的问题 -> 接口的安全性 -> 接口的代码设计 -> 接口的可读性 -> 接口文档 -> 我遇到的坑 接口参数定义 接口设计中往可...

    taoszu 评论0 收藏0
  • 简述我所理解 PHP Trait

    摘要:和组合的语义定义了一种减少复杂性的方式,避免传统多继承和类相关典型问题。队列的目的是将耗时的任务延时处理,比如发送邮件,从而大幅度缩短请求和相应的时间。同样的道理,根据引入不同的来完成对应的功能。 showImg(https://segmentfault.com/img/remote/1460000010868178); Trait 概念 在常规的 PHP 开发中,我们都习惯于先编写一...

    gecko23 评论0 收藏0
  • Why Kubernetes ,我所理解docker与k8s

    摘要:去年换工作后,开始真正在生产环境中接触容器与。今天想先谈谈,我理解的容器是什么,以及为什么它们能火起来。一个容器镜像的实质就是程序进程加所有运行时环境及配置依赖的集合。这里再谈谈我理解的。而,就是目前的容器编排的平台的事实标准了。 去年换工作后,开始真正在生产环境中接触容器与Kubernetes。边恶补相关知识的同时,也想把学到的内容和自己的理解整理出来。学习的途径包括k8s官方文档...

    Taste 评论0 收藏0
  • Why Kubernetes ,我所理解docker与k8s

    摘要:去年换工作后,开始真正在生产环境中接触容器与。今天想先谈谈,我理解的容器是什么,以及为什么它们能火起来。一个容器镜像的实质就是程序进程加所有运行时环境及配置依赖的集合。这里再谈谈我理解的。而,就是目前的容器编排的平台的事实标准了。 去年换工作后,开始真正在生产环境中接触容器与Kubernetes。边恶补相关知识的同时,也想把学到的内容和自己的理解整理出来。学习的途径包括k8s官方文档...

    maochunguang 评论0 收藏0
  • 我所理解原型&原型链

    摘要:有以下几点三图片解析是原型链的链接通过查找到,是原型的关键字是实例对象是构造函数通过找到所以构造器的原型属于对象,也就是说是出来的。同理找到,发现属性,输出五参考资料原型与原型链如果有理解不对的地方,欢迎大佬指正 一、题目 我们先看一道题目 var F = function() {}; Object.prototype.a = function() { ...

    Allen 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<