程序员的自我修养

架构师做什么?

0条评论76次浏览

记得我最早思考这个问题的时候还在国企,那会刚参加工作没多久。某天突然看到有人的职位是架构师,于是很好奇,作为一个架构师,他/她的日常工作是做什么?或者这么说,你要能够做些什么,才能成为一个架构师?

然而,作为一个低端码农,对这个问题一直无解。而且还受到国企那些架构师的影响,一度以为架构师就是一群没能力做开发,只会满嘴空炮,开一个又一个浪费生命的会议,写一堆自己都不愿看第二遍的文档的复制粘贴机器。

前几天梳理后端架构,过程中有很多想法,例如这里当初这么设计不是没事找事?这样设计这个模块岂不是没法扩展?当初要是不这样设计现在工作量岂止减少10倍?!突然间我意识到,架构师的工作,是不是就是处理这样的事情——让系统/服务/产品等后期更容易维护/扩展,不至于被后来者诅咒?

程序员为自己写的代码负责,为自己弄出来的bug买单。除此之外,一个系统/服务/产品是否就没有其他方面的问题了?比如程序员按照设计用redis来缓存数据,现在内存不够用了,是程序员的锅吗?当初采用了http+json作为内部通信协议,现在随着业务增长和新的需求,发现http+json的效率更不上了,是谁的锅?某个mysql表的字段设计成了text,导致现在稍微大量点的写入就主从延迟超过阈值,这是谁的锅?

诸如此类,或大或小、或轻或重的问题,我想应该就是架构师来处理的吧。

对于架构师做什么,现在只有这点浅薄的认知,希望以后成为架构师(不是国考的系统架构师)后再写文章补充吧。

如何成为架构师?我觉得除了脑子必须特别好用这种基本要求外,还需要丰富的经验和特别广的知识面,而且需要专精一两个领域。

比如你得知道kafka作为MQ,可靠性有多少,TPS/QPS有多少,作为整个系统的消息中心,是否可以信赖;

你得知道redis的QPS和TPS是多少,是否会因redis存在瓶颈,如何设计key可以方便从单机redis扩展为集群,或者小集群扩展到大集群。

你得知道http/thrift等通信协议的优缺点,不同场合做出不同的选择。

你得知道mysql能撑住的量是多少,字段类型设计成什么样能满足需求又不失性能。

你得知道hbase、mongodb试用什么场合,都有什么坑。

你得知道响应N万QPS http请求需要什么样的框架,需要几台机器。

你得知道处理流数据storm和spark应该选哪个。

如何高可用?需不需要冷备热备?如何监控报警?系统中某个节点挂掉怎么办?服务解耦到哪种粒度?

是否所有需求都应该满足?哪些需求可以判定为不合理需求?
......

(以我目前的见识和经历,也只能想到上面这些。[捂脸])

等一系列的事情,这样才能在设计阶段,就能看到以后可能遇到的坑。

这里再记录下现在工作中遇到的一些坑:

  • mysql的某字段设计成为text,实际上设置成为varchar完全能够满足。text导致主从延迟十分大。如何确定的?弄了另外一张完全一样的表,将text改成varchar,就完全没有主从延迟了。但现有数据量太大,改变字段类型起码会锁表30分钟以上,完全不可接受,最后只能切换到另外一张表才解决问题。
  • 无效devicetoken存放在单机redis中,设计成为以app为key的set,某些巨型app的无效devicetoken可能上千万。后来单机redis的qps满足不了高峰期的查询需求,只能改成集群redis。但现有的key设计导致同一个app的数据只能存在一台redis上,根本解决不了问题,高峰期压力无法分散开来。最后将key设计成appkey+devicetoken的形式才解决问题。
  • redis集群的proxy问题。最开始我以为codis/twenproxy的proxy和hbase的master/zookeeper一样,不负责数据传输,只负责存储些meta信息,真正的数据交互式client和实际worker交互。结果发现只有一个proxy的情况下,qps和单机一模一样。后来进一步了解到原来proxy是要进行数据传输的,想要提高qps就得增加proxy数量。比如4台redis组成的集群,需要4个proxy才能发挥出全部的性能。
  • 同样的mongodb的proxy(mongos)也进行数据传输,后来全部改成多个proxy了,既发挥出了集群的全部性能,又消除了proxy的单点故障。
  • alias和tag的设计问题。这个就涉及到具体的业务了,大致的情况就是对这2个接口没有做任何的限制,基本的长度限制都没有,导致开发者/黑客滥用接口,alias库里面各种超过4MB长度的数据,有的甚至把整个网页当成alias,有的全部是各种攻击注入sql。而更多的开发者弄不明白alias和tag的区别,把两者混用,把tag当成alais,导致后端查询压力巨大,把alias当成tag,导致数据库完全存储不下。这个问题至今没有完美的解决方案,当初设计上的想法是好的,可不是每个用户都是按照设计的想法来的。永远不能小瞧用户的创造力/破坏力。从最开始,就应该有严格的限制来引导开发者正确的使用各个接口。没有限制往往带来的是灾难。
  • 存储在redis中的数据没有设置ttl。当初选择将数据存放在redis时就应该考虑到ttl。现在的结果是接近1T的数据,用了9台价值7-8W的机器,存放在redis集群中。而这个集群的qps是多少?1W都不到!一台redis就可以满足qps,但因为历史数据无法删除,导致只能不断扩展集群大小。根据dau等其他方面推测,这接近1T的存放在redis中的数据,最多只有30G的数据是有效的数据。
  • 没有防爆量设计。每个集成了sdk的app都会在一些事件的触发下发送http请求到服务器上。而有的集成有误的app可能会导致请求量暴涨到服务端无法处理的地步,可能只是log文件就能撑爆硬盘。这个问题到现在也没有解决,现在每次遇到爆量都只能硬编码。其实解决起来很简单,方案我也出了,但因为一年可能都遇不到两三次爆量,所以老大就一直觉得无所谓不用浪费时间开发这个功能。
  • 定时任务太多。很多业务数据都靠定时脚本上传数据到hdfs上再计算,每当遇到新增服务到新机器,服务转移到其他机器等情况,就会出现忘记部署定时任务的情况,从而导致业务数据计算有误差。现在解决方案是所有需要上传的数据写kakfa(实际上本来就会写kafka),然后后端spark streaming消费并写到hdfs上。干掉所有定时任务真是一身轻松。
  • 不合理的需求应该拒绝。某汪*带盐的网站家的app,大概累积设备量不到30W,每次广播打开数在7000左右。就算这7000个打开都在同1秒,那他们的服务器的qps也不过7000,况且这7000个打开是24小时甚至更长时间内陆续打开的。就这样的压力,他们就受不了了,要求我们把发送速度降到100/s。如果真的降到100/s正常情况下也就不到10s能发送完的任务我们需要40min才能发完,这意味着一台服务器在40min里只能龟龟龟龟速的发送这个任务。为了这个需求修改服务?我觉得除非吃多了,不然绝对不可能满足这样的需求。然而,我觉得的没用,你们懂的。[大哭]
分类:杂七杂八, 随想
标签:

玄学出奇迹

1条评论176次浏览

2016-11-03开始,APNs HTTP/2 API速度突然变得奇慢无比,建立连接各种超时,handshake各种超时。50个channel的情况下每秒能发送的消息只有个位数。简直哔了狗了。

初步排除一番后,发现10台服务器当中只有5台服务出了上述问题,另外5台的发送速度居然比平常还要快。于是怀疑集团为了双十一把网络调整了,让pe联系集团网络部的查了一通,返回结果,并没有任何调整。

接着怀疑是不是这五台机器的硬件出问题了,又查了一通,发现并没有。

最后怀疑程序出问题了。为啥最后才怀疑程序?我这服务线上无故障跑了好几个月了,突然出问题,还是几台机器在同一时间出问题,打死我都不相信。结果也表示,程序没有任何异常。

最后只能让苹果背锅了,认定是苹果的APNs HTTP/2 API服务抽风了,和这5台服务器命中相克。于是只能将大部分发送任务放到老版本API上去,少部分流量放到APNs HTTP/2 API上,然后关闭了出问题的那5台机器。

经过3天的观察,发现之前认为没有问题的另外5台服务器居然也出现了同样的问题。又是各种查后无果。期间抓包发现居然有高达20%的网络重传。

就在我即将崩溃,准备裸奔释放情绪的时候。突然间无意的发现,貌似这些发送比较慢的任务的remote ip地址第三位比较集中。苹果服务器ip前两位是固定的17.188。而那些发送比较慢的第三位基本上都是12X、13X以及少量的14Y(y<4)。难道是巧合?于是把所以机器上的所有发送慢的任务的ip全部查了一通,发现居然没有一个反例。于是我不由自主的得出一个玄学结论:remote ip第三位比较小的(比如小于145)发送速度慢,大于145的发送速度快。为了验证我的猜想,我又把所有服务器上的所有发送速度快的任务查了一遍,发现卧了个槽,居然还是没有反例,没有一个例外能推翻我的玄学猜测。

然后我将所有的结果汇总,发现remote ip第三位小于等于142的速度奇慢,各种超时,而且没有例外。而第三位大于等于144的速度奇快。然后让pe那边分析了一下抓到的包,发现20%的网络重传也全部都是remote ip第三位小于等于142的ip。进一步证实了我的玄学猜测是正确的。

接下来,修改程序上线,不连接那些remote ip第三位小于等于142的。经过1天的观察,卧槽,真的没有一个慢的任务。

对此我只想说,玄学出奇迹。

至于为何会这样,我只能猜测要么苹果的这2组ip地址的服务器在不同机房,有一个机房出了问题;要么就是苹果在灰度测试新的服务,因为抛开那些发送速度离奇慢的任务,其他的任务发送速度都翻了2-3倍。然而苹果官网上找遍了也没有一个公告什么的。

什么是玄学?玄学就是,今天编程不宜面朝东面,不然bug多;今天不宜上线,不然服务必挂之类的迷信。
1

分类:APNs
标签:,

Redis设置密码的那些坑

0条评论95次浏览

最近集团安全部扫描到我们组的redis没有设置密码。如何扫描的?一个脚本,登陆到服务器上查看固定路径下的redis配置,没有配置密码就被扫出来。简单无脑暴力。

于是开始虐心的添加redis密码之旅。

Server端配置

方法1:redis-cli -h xxx -p xxx CONFIG SET requirepass xxx

方法2:修改redis.conf文件,配置requirepass

对于twemproxy,可以升级到最新版本,然后配置redis_auth xxx。

Client端配置(Jedis)

项目中都是用的JedisPool。我们的方案是给所有代码进行如下处理:

看起来应该没问题,实际上测试了下,也一切ok,于是开始了第一次改密码尝试。将涉及到的七八个应用、几十处代码全部修改完毕上线后,一切正常。然后redis server端添加密码,瞬间崩溃了四五个服务,只剩两三个服务正常运转。于是立马去掉密码,开始查原因。

JedisPool初始化的坑

经过一轮排查,发现出问题的服务都是用的上面的方式初始化JedisPool。而没有出问题的都是下列方式初始化:

然后看了下源码,果然在有database参数且不等于0时,会进行一次select操作,而我们的password用的是null,所以就会报错。于是又一次将涉及到的七八个应用、几十处代码全部修改完毕,开始第二次改密码尝试。所有应用上线后,一切正常。开始redis server端添加密码,瞬间又是几个服务崩溃,几个服务正常。于是立马去掉密码,开始第二次查原因。

setTestOnBorrow的坑

又一轮排查后,发现出问题的服务都是JedisPoolConfig::setTestOnBorrow(true),没有出问题的要么是设置为false,要么是没有设置,而没有设置的默认情况下就是false。然后再次看了下源码,setTestOnBorrow应该是从pool中获取到实例的时候会去ping一下,然而此时没有auth过,于是又报错了。无奈,只能将所有的JedisPoolConfig::setTestOnBorrow(true)注释掉,开始第三次尝试。

还好,没有其他幺蛾子了,这次终于没有问题,加上密码,去掉密码,服务都正常运转。心塞。

分类:Redis, 战5渣
标签:,

APNs http2接口速度调优

0条评论125次浏览

第一招:釜底抽薪

简介:通过去除无效devicetoken,本地减少发送数,来提高整个任务的发送速度。

有效性:视app决定,有的app卸载用户少,作用不明显,有的app卸载用户90%以上,效果杠杠的。

什么样的devicetoken是无效的,如何识别?简单来说apns返回发送失败时,reason内容为BadDeviceToken和Unregistered的可以判定成无效devicetoken。关于BadDeviceToken很好理解,而Unregistered又是个什么鬼?有如下测试:

  1. 关闭推送,1小时内发送消息,apns返回success,但是app没有收到消息
  2. 打开推送,在关闭期间发送的消息收不到,打开后的消息正常收到。devicetoken没有变化
  3. 关闭推送,第二天发送消息,apns返回success,但是app没有收到消息
  4. 第二天打开推送,在关闭期间发送的消息收不到,打开后的消息正常收到。devicetoken没有变化
  5. 卸载后,立马发送消息,apns返回Unregistered
  6. 重装后,生成新的deivcetoken,对老的deivcetoken发送消息,apns返回success,但是app没有收到消息;对新的deivcetoken发送消息,apns返回success,app收到消息

以上测试基于ios9,ios10还没测试。不过根据历史发送结果来看,Unregistered十有八九就是被卸载了。

第二招:调虎离山

简介:使用netty的发送程序,可以尽量将耗时的代码从EventLoopGroup中移出,或用线程来处理。

有效性:视代码时间开销而定。

最近在弄美国服务器进行发送速度的测试,测试结果后面说。过程中发现,读取/写入国内的redis速度慢的令人发指,导致发送速度不到10条/秒。于是将可以异步处理的写入redis放到线程中去处理了(读取直接删除,反正是测试)。结果发现速度突突突突突突的快。于是国内也将写入redis做了相同的处理,虽然速度提升不是太明显,但总体的感觉还是快了一些。之前想着读写redis肯定非常快,不会造成多少时间开销,但从结果来看还是不能想当然。

第三招:无中生有

其实和无中生有半毛钱关系都没有,只是三十六计里面找不到合适的随便选了个。

简介:提高发送的并行度。

  1. 单服务器模式下增加channel的个数。
  2. 大型任务则分发到多个服务器上去执行。至于如何实现调度、如何统计结果、如何处理子任务失败、如何处理长尾问题、如何处理XX问题就不在这里讨论了。

反正自从我实现完多机器并行处理一个任务后,再也没有开发者反馈我们发送速度慢了[大哭]。比如以前慢的时候40分钟、快的时候7分钟发送完的任务,现在变成快的时候90s、慢的时候10分钟。好想给我自己一个赞。

终级大招:走为上计

去美国搞台服务器,性能不用多牛逼,内存够用、cpu还行,虚拟机也可以,速度就是一个突突突突的快啊,同样的程序,速度是国内的10倍以上。还考虑什么分布式调度、考虑什么子任务单点失败、考虑什么长尾、考虑什么结果汇总,麦什么破、锐什么丢死,直接突突突突的单线程都比国内快,就是这么暴力。

最后

速度调优什么的最讨厌了,懒得弄?很简单,来用友盟push,分分钟带你突突突突。

怎么感觉变广告贴了,摔!

分类:APNs
标签:

战5渣系列——Scala map()

0条评论168次浏览

Twitter的Scala School上面对map()函数介绍如下:

Evaluates a function over each element in the list, returning a list with the same number of elements.

Scala官网上面的介绍:

Twitter的解释是对一个list的每个element作用一个function,并返回数量相同的list。Scala官网则只说对一个collection的每个元素作用一个function,并返回一个新的collection。

对于只认真看过Scala School的我而言,map的作用就是对一个collection的每个元素作用一个function,并返回一个相同大小的collection。[哭笑不得]
(更多…)

分类:Scala语言, 战5渣
标签:,

gc老生常谈

0条评论167次浏览

算是笔记吧。看了很多次的jvm、gc,但都没记住。这次遇到了自己写得线上服务出现了oom+死锁+频繁full gc(扶额),总算是记住了jvm和gc的基础知识。也是醉了。

jvm模型

主要分3个模块吧:堆、栈、本地方法栈。

堆=young(eden + survivor(from + to)) + tenured + permanent,也有说permanent不属于堆的,不过从gc日志来看我更倾向前者,但从gc参数来看应该是后者。

结合java8的gc来看:

young

par new generation就是新生代young,其大小等于eden区+from/to区,注意这里不是eden+from+to。为什么呢?因为你永远不能同时使用from和to。eden、from和to的比例默认是8:1:1,可以通过参数-XX:SurvivorRatio调节。

新对象的分配发生eden区域内,当新对象(非大对象)无法在该区域分配时便引发Minor GC。大对象放不下的时候直接去tenured区分配。Minor GC就是将eden+from/to的存活对象copy到to/from中去,顺带存活了若干次的会放到tenured区,而且放不下的也会去old区。
(更多…)

分类:Java语言
标签:,

百度做了哪些恶?

1条评论231次浏览

逼乎回答被跪舔百度py的人举报了,这里存个档。

已经过了愤青的年龄,对于这种事情已经没有任何情绪波动。
1
2
3

作者:yurnom穆

链接:https://www.zhihu.com/question/45204818/answer/121729765

来源:知乎

著作权归作者所有,转载请联系作者获得授权。

年轻的时候,家里锁坏了,百度了下开锁。选了结果中的第一条,是个百度认证+推广的网站,点进去,发现是个1500外包就能做出来的网站。犹豫了下,还是选择相信百度。

电话打过去,一个男人接了电话,开口直接问你家住那?我问开xx样的锁多少钱?对方继续问你家在哪?我说在xx小区,开xx样的锁多少钱?对方继续问,几号楼?我说xx号楼,开xx样的锁多少钱?对方问,几单元几号?我说x单元x号,开xx样的锁多少钱?对方说,300。我问能便宜点吗?对方说,没得便宜。我说那我考虑下,然后挂了电话。

对方立马回播过来,开口就骂娘,我回了句然后挂机。结果那天从挂这个电话开始,收到了无数的电话轰炸,有的打过来骂几句,有的直接挂,有的就响几声,有的接了不说话。。。。然后去百度上维权,提交了全部截图证据和过程描述,系统告诉我等待x个工作日(具体不记得了)。然后过了很久终于收到了百度的回复,只有一句话:
你的财产受到了损害吗?

没有。我也就被骂了一天,也就家庭地址暴露了家人可能受到人身伤害,也就接了无数个骚扰电话,也就白白浪费了一些时间而已。谢谢你百度,没有让我的财产受到损失。

至今这个网站依然是百度认证+推广,虽然全部评价都是差评+警告其他人不要上当,但依然阻止不了百度帮其推广。

分类:未分类
标签:

leetcode shell

0条评论199次浏览

不知不觉中对各种shell命令熟练了起来,居然完成了所有的leetcode shell题目。撒花!谁在那嘀咕全部shell题目就4题的,你站出来!

Tenth Line

awk

sed

Word Frequency

awk

Transpose File

awk

Valid Phone Numbers

分类:Linux, Shell
标签:, ,

mapreduce二次排序

0条评论230次浏览

之前离职的哥们的mr任务留了一堆的坑,他把value当成排序过的,于是reduce里面全部是如此统计dau、设备数的:

心好累,手动微笑。

正所谓前人挖坑后人填,我不入地狱谁入地狱。于是开始一个个mr的改代码。

方法一:用set统计

用set的好处就是改动极小,但存在oom的风险。实际跑了下线上的数据,果然oom了。摔!

方法二:bloom filter

好处是改动也不大,也不会oom,但就统计的结果可能会比实际的值要小。考虑到数据量也没有大到要用bloom filter的地步,且希望数据尽量的精准,放弃!

方法三:mr二次排序

(更多…)

标签:,

scala笔记

2条评论541次浏览

apply

先上代码,builder模式:

scala初学者第一反大概object对象怎么能有构造参数,就算可以带参数那也应该在并发上有问题吧。

实际上是apply这个语法糖的作用:

至于这么写有什么好处?其实我觉得没啥好处,除了看起来特别舒服。但代码就是写给人看的不是么,给机器看的那是0和1。掀桌!!

模式匹配

就不背书了,模式匹配相当强大,特别对于多个条件联合判断的时候,比如条件a/b/c,组合起来多达8种可能。若用if else写到最后肯定晕,这时候用模式匹配感觉代码会清晰很多。

(更多…)

分类:Scala语言
标签:
profile
  • 文章总数:76篇
  • 评论总数:208条
  • 分类总数:29个
  • 标签总数:40个
  • 运行时间:899天

大家好,欢迎来到selfup.cn。

这不是一个只谈技术的博客,这里记录我成长的点点滴滴,coding、riding and everthing!

最新评论
  • EVIL: 我在运行完C4.5的代码后,显示 defined object DecisionTreeTest 是什么意思?这是有错误吗?运行结果在哪里看?
  • sf: 楼主的问题,我都遇到。。。没办法项目已经定型了,最后都硬着头 皮一个一个的改了源码
  • zz: 我去,楼主你真及时,我们今天上了新的HTTP2 push之后也发现速度曲线很奇怪,开始有200k/min,跟 另一台老的推送协议速度差不多,但是过了一会,立马降到只有几k /min,百思不得其解,我们还用了一个海外代理,在...
  • qi365: :mad: 很可恶,百度助纣为虐~
  • qi365: :? :shock: haha~ very good~
  • 张是大: 《深入浅出Spark机器学习实战(用户行为分析)》 课程网盘下载:http://pan.baidu.com/s/ 1mixvUli 密码:1pfn
  • Anonymous: :???:
  • Anonymous: 我用着sqoop感觉还可以,select 几十个字段也没事,估计是版本低。。
  • Anonymous: :grin:
  • Sorheart: 顺带博主可以加个好友吗,我给你邮箱发过邮件的,不过你没回
  • Sorheart: 是的,经你这么一说很有道理,我也是速度下降非常明显,同时大量 的goaway
  • yurnom: 看了下日志,确实很多MAX_CONCURRENT_STREA MS=1
  • yurnom: 最近发送速度降的特别厉害,而且大量的connection reset by peer。我和一些开发者交流后大家都有这个现象,最后觉得应该 是奥运期间苹果服务器压力太大导致的。
  • Sorheart: 并且一直收到苹果服务器的goaway frame
  • Sorheart: 最近发消息时频繁出现苹果服务器设置max_cocurrent _stream为1的情况,导致单个连接发送变慢 Received settings from APNs gateway:...
  • yurnom: 测过百万级别的消息,没遇到你说的情况。我这边测试的结果是pa yload越大发送越慢,channel保持时间越长发送越慢。
  • QQ892101668: 博客不错,嘎嘎!
  • Anonymous: 楼主,请问这句代码哪里来: StreamingExamples.setStreaming LogLevels(); ? 请指教
  • Anonymous: 这个很程序猿
  • JTY: 读取中文乱码:BufferedReader d = new BufferedReader(new InputStreamReader(fsdis)); 即使这样,中文仍然乱码:BufferedReader buffData...