互联网业务介绍(一)--今日头条文章发布

后续会结合互联网具体的业务了解互联网的工作内容、用到的技术栈,主要会讲今日头条的。建议最好先体验下“今日头条”这个APP和头条号这个后台。头条号是给作者发文章用的,跟微信公众号后台类似。如果你入职了头条,那么“今日头条”你肯定是要经常用的,并且还得装内测版,即使你不喜欢。领导们经常没事会刷刷,上班就是刷头条、刷抖音,也是挺爽的,刷的时候还容易发现bug。

为了简化,只挑重点功能和流程做介绍。头条的模式在很多地方都有,csdn基本也是这一套。csdn作者后台发文,发文之后也有审核,审核之后有些好的文章会在首页推荐出来,也可以花钱买推荐。当然csdn的文章大部分还是靠搜索引擎收录,收录之后大家搜关键词的时候有机会看到。因为csdn的用户量远远小于头条,专业性也更强一点,大家不会闲着没事用csdn打发时间,所以推荐不是那么重要。

文章读写的实现

点击头条号发文章的功能,随便输入一些内容,建议用Chrome和火狐浏览器。内容写完之后,先按F12打开浏览器的开发者工具,做互联网开发,浏览器的开发者工具功能是非常常用的,前后端都会用到的。后端主要是看network选项,用于看发起了哪些HTTP请求,请求的数据和返回的数据。然后点击发布文章,这个时候可以找到有个发文章的publish接口,如下图所示:
互联网业务介绍(一)--今日头条文章发布
这个接口就是后台开发工程师开发的,所以后台开发也被调侃为api工程师。这个接口的功能比较多,业务逻辑比较复杂。比如检查标题长度是否够、检查文章是否有错别字,这些就是业内说的业务逻辑也是大家一直吐槽的。比如标题长度最小最大范围一开始可能是5-10,后面有人反馈太短了,又改为5-20。这种改来改去的业务逻辑对技术人员的成长是不利的,有技术追求的不能一直只做这种小需求。

可以结合api的请求数据想象下后台会做哪些数据处理,或者让你去做你会怎么实现?
互联网业务介绍(一)--今日头条文章发布

这个接口最开始就是用python写的,diango框架,当然头条还是对dianggo封装的。之所以用python主要还是开发效率高。头条早期大部分服务都是python开发,也有部分PHP。近几年开始转向golang,新开发的服务都是用golang,老的服务也慢慢重构为golang。golang入门比python慢一些,熟练之后开发效率确实不输python。像头条这种量级的,用golang替换python可以节省大量的服务器资源,golang性能比python好。

文章发布之后后台服务器到底做了哪些工作? 可以先自己想下,就像面试的时候面试官问你让你来设计你会怎么做? 不用考虑做的很完美,就把你能想到的所有点都记下,形成一个方案文档,你会写成什么样?

也就假设项目从0开始,老板那里的需求只有一句话:做一个类似于微信公众号的平台,能够发文章。这就是目标,那么接下来就是一个团队围绕这个目标去做。为了实现这样一个功能,是不是得有产品经理细化需求,产品经理想的需求不一定都对,需求也是需要讨论的,哪些一定要做,哪些可以不做,哪些先做哪些后做。讨论完之后就得有架构师做架构设计不是,如果功能很简单当然不用设计直接写代码,但看看头条号的复杂度,没有技术负责人你觉得能做成什么样。有了方案之后是不是就得开始分工派活了,让底层的小兵一个个api去实现。

先不扯远了,再回到发文这个接口来。普通的图文文章本质就是一些字符串,文章的分段、字体这些通过特殊字符进行区分,也就富文本。文章数据传到后台是不是得存储,用什么存?磁盘、文件、mysql、redis还是其他存储?

这就涉及到技术选型了。至于怎么选,就得看功能和性能。
(1)文章是可以被反复改的,那文章要不要做版本管理?改动之后立又并不是立即发布出去的,还有审核这一步,而且还可以存草稿。
(2) 文章的访问量可能会很大,热门文章阅读量10万+,百万+都是很常见的,怎么支持这么大并发?
(3) publish接口是只支持发表图文? 视频、音频、图片这些体裁要不要支持?
(4) 除了文章内容文章属性也有很多,比如是不是参加了创作者活动、是不是带广告,这些要怎么存储
(5) 另外怎么区分一篇文章?用id? 文章量可能几十、几百亿,这么大的量文章id要怎么设计,怎么避免不同的作者同一时刻发文id是不同的?

这样细化下来是不是就有很多工作要做了。所以写api是最后的事情也是最体力的活,在写之前想清楚,弄清楚有哪些需求,有哪些异常情况,有哪些性能要求,想清楚了再写代码。

头条的实现是文章属性是存的mysql。对的,就是mysql。全量文章都存的mysql,那么初学者就会问mysql存这么多的数据性能跟的上吗? 这是把mysql用到了极致的,首先不是单机mysql,是做了分库分表的,而且读写分离,然后表的schema也很重要,数据类型、索引都设计合理,增删改查的时候也不允许跨表也就是join。文章属性存的mysql,但文本内容是用的kv存储,视频内容用的对象存储,不然一个视频几十M,几百M还是很废空间的。

另外一些属性是存的redis,点开作品管理,根据分类查看作者有哪些作品。
互联网业务介绍(一)--今日头条文章发布

这里的文章列表能不能直接查mysql? 如果在数据量小肯定是可以的,如果量大,那么直接查mysql对mysql压力太大了,另外查询的SQL会有点复杂,所以会在这里加一层缓存,用的redis,memache在头条很少使用。在redis里面也不会把mysql所有的数据都存进去,只会存id,title这些关键的数据,其他阅读数这些数据会从其他地方拿。

存储作为一个非常重要的基础设施在各个大厂都投入了很多研发,基本都是自研或在开源的基础上改,kv存储(key-value)是一大类,redis属于其中之一,但redis太贵了,因为纯内存,内存比磁盘贵太多了。所以又有了leveldb,rocksdb,头条是自研的abase,在头条的技术公众号也有介绍。

解决了存储那再来看下数据是怎么流动的,是publish接口直接写mysql、redis? 不是的,在小公司里面没这么多讲究,一个HTTP接口的功能基本都在一个HTTP服务里面完成,HTTP服务也会直接操mysql。但在头条是做了区分的,像这种读写数据库的服务避免在HTTP服务做,而是中间会加一层rpc服务。rpc就是远程调用,不是HTTP协议,头条用的thrift协议,是Facebook开源的,可以去学习下。

rpc又是一个知识点,除了thrift还有谷歌的grpc,百度的brpc。那为啥中间要加一层服务?这个服务为啥是rpc服务而不能是HTTP服务? 加一层服务的目的是安全和统一,因为文章存储的数据库不只是发文这个接口访问,还会有读文章,还会有今日头条app也会去访问,所以通过一层专用的服务对读数据库的操作统一起来,避免重复开发也方便管理。那为啥这中间层不用HTTP服务?效率的问题,HTTP协议是文本协议,数据没做压缩,而且协议头有些内容是冗余的,rpc是专门在公司内部间的服务用的,可以做的更高效些。grpc是基于HTTP2.0实现的。

当然大公司的HTTP服务暴露出来,前面还得接负载均衡,负载均衡又是一个大的话题。可以简单了解下现状就是文章读写是独立的HTTP服务,评论也有独立的HTTP服务,还有其他业务也有HTTP服务。单个HTTP服务,为了抗住大流量,会在多台x86服务器上运行这个HTTP进程,那这么多进程要均衡的对外提供服务,避免有些进程一直没事干有些进程干不完的事,那就需要负载均衡了,开源的是nginx,各个大厂也都在nginx的基础上做自己的LB(load banlance)组件。

上面提到独立的文章读写、评论是独立的HTTP服务,那会好奇为啥不放一个服务里面。那即使这两个能放一个服务,那还有登录注册、交易、提现这些服务也都放一起? 放一起就会非常混乱,上线也很麻烦,评论的代码改动上线会把交易修改后没测试完的代码可能也带上去,而且都放一个仓库,代码太乱了。所以诞生了微服务,微服务根据各业务、功能进行拆分,将各个服务独立开来,相应的代码库一般也独立。 微服务又是一大知识点

那么文章读写接口经历的过程大概如下,从上往下看。
互联网业务介绍(一)--今日头条文章发布

数据流的过程也就算比较清楚了,写代码本质就是处理数据,数据从哪来到哪去,要怎么处理,尤其写api的,首先要弄清数据流。有了数据流,一般架构中的分层也就有了。

下篇会介绍头条的统计数据怎么做的。。