系统设计与构架群社群活动
加微信ID onetptp 好友注明加系统设计群
有奖征文活动
奖金是 0.1 个 ETH / 文章,如果有多个人发的话,把奖金一分为三,第一名取其二,第二名取其一
https://github.com/puncsky/system-design-and-architecture/issues
已经结束的往期有奖征文
-
- Designing web crawler
-
- Designing typeahead search or autocomplete
-
- designing hotel booking system
运营准则
- 问/答/分享。欢迎问问题、回答问题、分享知识。推广可以有,非原创可以有,但是必须要切题,质量要高。问问题之前先学习如何问问题。
- 主观高于客观。客观的知识你总能搜索到,所以我们更看重你个人的实际体验和感受。注重速成,一句话的精妙解释优于一本书的故弄玄虚。
- 7:3 的信噪比。希望我们的讨论既有用又有趣 —— 7:3 是个不错的比例。
讨论精选
Natee
想实现一个模式,对后端服务的 login 请求经过网关层的基础验证以后,转发给 ‘登陆服务器’,‘登陆服务器’在验证过request中的username&password之后将用户的部分信息,例如分组,权限以JWT存入token中,返回给客户,客户在后续请求中带上此token,随后在网关中解析token将payload里面的分组,权限信息解码放到header中,供后面服务模块调用。 但是我遇到一个问题,我使用的api网关KONG在解析token需要有iss,就是consumer,对应的consumer做成的jwt中有issuser,指明token是给谁用的,然而我在生成token时候是在登陆服务模块生成的,这样子的话,我在做token的时候就需要把iss写到payload中去,但是iss是在网关里配置consumer的jwt时候生成的key,这个key也可以指定,不指定的话随机生成。这样子就出现问题了,在登陆服务器验证时候一定要放入一个iss进jwt的payload,然而这个iss是在网关层生成的
这个要看你 jwt 具体的算法 algo ,你们 iss 到底是用不同的用户的不同的 key 签的,还是所有的 jwt 共享一个 iss。我的意思是,在对称加密algo 的情况下,不同用户有不同的 sub,但是 iss 是可以共享用一个 master key 签名的
这样只需要让登陆服务器和 api 网关共享一个 master key 就可以了
Jack
- 我想知道enterprise service bus,像Apache camel,是过时了吗? 是不是不符合Smart endpoints dumb channel?
- 还有event vs threads, 现在有个定论哪个好吗?还看到说akka, Haskell就是综合两者的优点,可以讨论一下
York
用java的akka写过一点点很简单的actor model的代码,在用debugger的时候还是看到下面起的还是 thread。个人觉得akka只是对thread进行封装,用actor model(event/message processing)的套路呈现给你一系列API用来处理concurrency。所以就event和thread而言,就看你的app对计算资源的控制需要多细的粒度。event更high level一些更接近业务逻辑。直接用thread的话,假设你实现的好overhead应该还是会比用akka要小吧
大小说家👻
同意,我们组用的scala akka stream,高度封装的akka actor, 仍然需要implicit的传入一个executionContext,(相当于Java的线程池)。返回future的时候,实际上是通过这个线程池新开了一个线程异步处理+call back。
写起来比多线程需要考虑的少一些,也安全一点,因为通过map, reduce 的stream处理方式避免了shared variable的使用
开发的时候能更关注于业务本身
Jack
谢谢分享,你的体验和这里说的一样: https://blog.acolyer.org/2014/12/12/scala-actors-unifying-thread-based-and-event-based-programming/ “Compared to a purely event-based approach, users are relieved from writing their own ad hoc thread pooling code. Since the internal thread pool can be global to the web application server, the thread pool controller can leverage more information for its decisions. Finally, accesses to an actor’s mailbox are race-free. Therefore, resources such as user profiles can be protected by modeling them as (thread-less) actors.” 真的是两种的好处都有。
我感觉 actor 应该等同于CSP (communicating sequential processes)里的 sequential process, 是用artibter做了serialization
这篇文章说events不好 https://blog.acolyer.org/2014/12/10/why-events-are-a-bad-idea/ , 还不如threads, 作者包括Eric brewer, 他们发现除了pub-sub以外用threads又快(用系统的threads, 没有event loop的bottleneck),又容易写,又容易发现错误(stack, not heap),是不是说核心的components就应该用threads,还是说现在语言,操作系统,硬件等都进步了,这篇文章也过时了?
这个网站推荐用event driven/messaging based/async microservices,而不是synchronous restful microservices https://solace.com/blog/experience-awesomeness-event-driven-microservices/ https://solace.com/blog/achieving-microservices-flexibility-patterns/ 我觉得有点牵强,大家能不能看看,有没有可取的地方
Jack
架构师之路说“服务读写分离架构,绝不推荐” https://blog.csdn.net/z50L2O08e2u4afToR9A/article/details/78841727
solace 说:“What you do sacrifce with CQRS(读写分离) is consistency, but you enhance both performance and availability and, as mentioned earlier, embracing eventual consistency alleviates this concern for most use cases.”
Martin fowler 都说用cqrs要小心,一般都效果不好: https://martinfowler.com/bliki/CQRS.html
Such
https://juejin.im/post/5da2f8fee51d457849547305 golang的interface实现的理解
Tian
补充一下背景知识,并发模型大比拼
- threading/multiprocessing, lock-based concurrency
- protecting critical section vs. performance
- Communicating Sequential Processes (CSP)
- Golang or Clojure’s
core.async
. - process/thread passes data through channels.
- Golang or Clojure’s
- Actor Model (AM): Elixir, Erlang, Scala
- asynchronous by nature, and have location transparency that spans runtimes and machines - if you have a reference (Akka) or PID (Erlang) of an actor, you can message it.
- powerful fault tolerance by organizing actors into a supervision hierarchy, and you can handle failures at its exact level of hierarchy.
- Software Transactional Memory (STM): Clojure, Haskell
- like MVCC: commit / abort / retry
- Single threaded - Callbacks, Promises, Observables and async/await: JS
event driven/messaging based/async microservices vs. sync restful microservices 这个我觉得还是以业务需求为主要的决定因素,比如用户注册时的 fraud detection 必须实时做决定这个请求要不要block,必须是 sync 的;银行的支付系统就是特别的慢,十几秒用户等不起,那么只能够做成 async 的;大企业构架很混乱,为了解耦加入一个 message queue,把很多 n^2 的关系复杂度变成 1
CQRS 出现的主要原因是写比读成本高而且互联网服务的读写比大概 200:1,而我们想要优化吞吐量。具体实现上是做在服务层还是数据层要看情况。我在 Uber 见到的奇葩的情况:数据层主从数据库读写分离,上游是一个 monolithic API 层,再往上是一个超大的 Cache 层,再往上是 realtime api 层。
Facebook TAO 在我看来本质上也是读写分离,而这个分离跨越了主从 cache,数据库,还有跨区域的数据中心
所以说读写分离在数据层还是服务层做不是一个值得讨论的问题,因为数据也是一种服务,服务于具体的需求
Jack
https://www.oreilly.com/library/view/microservices-for-java/9781492038290/ch04.html
“Real applications could have dozens or even hundreds of microservices. A simple process like buying a book from an online store like Amazon can cause a client (your web browser or your mobile app) to use several other microservices. A client that has direct access to the microservice would have to locate and invoke them and handle any failures they caused itself. So, usually a better approach is to hide those services behind a new service layer. This aggregator service layer is known as an API gateway.”
"Apache Camel is an open source integration framework that is well suited to implementing API gateways. "
Adrianliu & 周宇超 & 低调 & Kai: idempotent key 在服务端还是客户端产生
请教个问题:如果想让整个 system idempotent, 比如payment system 防止duplicate pay, 一般来说是在client 发送请求时生成一个UUID 发给server,还是让server 去产生一个UUID给client,然后client 再发送request?
这个是2 phase commit吧?
不是。我的问题是防止客户端retry 导致duplicated request
我知道是防止duplicate这种事要从全局去避免。但是我现在主要在纠结客户端的duplicate request 那种情况
payment系统一般比这复杂,我明白你意思了,你相当于用UUID作为token唯一识别一次transaction
嗯嗯嗯对的对的
我们组之前做过类似的,是在server生成UUID
这样的弊端是不是多了一个round trip ,客户端拿到UUID,然后再发送真正的请求
感觉都可行,是取舍的问题,客户端生成UUID有什么弊端?不安全吗?
没想明白暂时。。
这篇我看了,感觉他说就是用一个library啥的
这篇文章还是没说那个idempotency key 哪里产生的
payment还是看uber的吧,气床毕竟不算高并发
这个重要么?如果数据库已经有了这个key就插不进去,如果没有那么就意味着可以
重不重要我不知道,只是想知道哪种比较好
嗯嗯那个看了。有个疑问,如果第三方Payment provider 失败了,这个时候我们把这个record 放到retry queue去,这样还能保证同一个user的多个request的order吗
Uber那个缺了个对账环节,就是有可能银行那边数据和uber这边数据不一致
怎么讲?每天对一次账这样么
自己根据数据量来定对账频率
cron job?
这个需要银行那边对完帐再发给我们系统,然后我们来对吧。
所以得依赖第三方的频率
这里是跟PSP对账还是银行?
总结:idempotent key 在服务端产生的好处是比较安全,坏处是多了一个 round trip; 因为格式是固定的,还可能是随机的,比如 UUID,那么客户端产生也可以,但是要注意检查这个 idempotent key 与 order ID 的联系,确保客户端不能够用之前已经成功的 order 支付的 idempotent key 算做最新的 order 的支付
王博睿: grpc + kinesis
请假大家一下。我如果想搭一个grpc和aws kinesis的服务,整个构架应该怎么弄呢?
整个服务很简单,只需要用户通过grpc的服务来访问读取kinesis的数据就好了
双双:请问下大家如何模拟分布式系统三个服务器统计一本书的字频,需要实现选举。慕清、大小说家、Elias、低调、=.=
想到了当年的 master slave, map reduce
我觉得主要还是解决一致性问题,可以通过paxos协议实现,保证选举。或者最近我有看区块链技术,也可以通过区块链的共识算法实现选举,这个是我个人想法。
插科打诨:一本书哪需要三台服务器😝
我们这个是作业,老师就让模拟下,说可以用paxos
可以考虑一下bully算法,实现简单,节点数少的时候还不错
这个群藏龙卧虎啊,感谢大家,我都看看[Whimper]
请问下大家实现整个系统的流程嘛,刚开始接触分布式系统,完全小白[Whimper]
主要是老师说要先选出leader,把任务分成一堆chunk,cluster里的各个server要处理不同的chunk,最后再汇总到leader那里,再传给client。这个过程我感觉就是MapReduce的过程。除了选leader和paxos一样。所以我不太清楚要在那里使用zookeeper。希望大佬们可以帮忙解惑一下
zookeeper就是用来解决选举的,如果使用paxos了 就不用管了
没要求用什么方法,就说要实现这个功能,举了个例子说paxos
还可以用pseudo random
区块链流行 PBFT, 我们公司在实现的时候用的 libp2p + PBFT
System Security: Natee
请问下,这个是要什么回答?
engineering security education (e.g. owasp top 10) + code review + product security review + bug bounty
@Natee 碰巧遇到一个答案 https://mp.weixin.qq.com/s/DtGLFwcwNMCZseOKOAOC9Q
如果这篇文章对你有帮助
下载 硅谷io App
使用我们的 Android App 接收最新的更新,用手机收藏和复习好文章