V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  lesismal  ›  全部回复第 8 页 / 共 53 页
回复总数  1055
1 ... 4  5  6  7  8  9  10  11  12  13 ... 53  
@iseki
> 但是编程时如果每次自己去搬这一个个砖头这既不符合 DRY 的原则也不够“少”。

这个完全赞同,所以我选了 go 之后基本没再回头写多少 c/cpp 了,因为没必要,go 太省事了,而且绝大多数场景也不需要极致的性能、反而更需要开发效率

> async await 算是结构化并发的一种落地形式。

但这比起 go func()来,便利性可读性还是差得多

> 你不能说封装的程度高就一定是不好的,软件工程是权衡和妥协,君不见 Go 相比 C 不是也隐藏了许多细节吗,每个函数开头插入栈空间检查未必是个多么高效的选择,当年也有人因为用了“高级语言”就被喷浪费了机器性能。
> systemd 出现之前,如今一个 .service 文件搞定的事情要一位 bash 熟练工写上成吨的 .sh 还不一定好好解决问题。看上去 shell 里的每一个命令都好简单啊,但是组合起来的结果你能说这是“简洁”的吗。当然这个我不多说,我相信每一个工程师都很清楚。

我当然不是反对封装程度高,而是反对不必要的过度封装。
而且要分开不同的层次,一个是语言级的,一个是框架级的。
go 也好 java 也好,它们在 runtime 内的实现,都是语言级、不需要使用者去关心太多内部细节。
而框架这一层,至少我觉得 Java 是属于过度封装的,比千层饼的层数还多。。好处是更可靠,坏处当然是牺牲性能、以及真遇到问题时使用者难于深入到一层一层内部去发现和解决问题。

> 此外 Java 的轻量级线程和 Go 的 goroutine 差不多一回事,当然 syscall 该卡还是卡,go 也是在 IO 等等地方特殊处理掉的,这个不是应用程序自己做点什么就能解决的。(其它关于 Java 的内容我就不评论了,这个看场合见仁见智

这个 `当然 syscall 该卡还是卡` 要看是怎么个卡的方式,是卡协程但协程会被调度、还是卡了系统线程。
我前面 #135 里提到的 `系统调用之类的接口` 其实没说完整,准确点讲应该是 `把系统调用那些封装起来然后提供给用户的接口`,例如 go 标准库 net.Conn.Read:虽然它是阻塞的,但它不会阻塞系统线程,实现方式就是当前读不到数据时就调度了并且等待可读,runtime 里的 iocp/epoll/kqueue 等待可读事件到来再唤起。go 里直接去调用可能阻塞的 syscall 也还是可能阻塞,但标准库对于 socket fd 封装出来的 net.Conn 之类的接口都是被 poller+调度这样搞定了的,所以使用标准库的这些是真的可以写同步代码也不会导致线程池阻塞耗尽之类的。
Java 的轻量级线程如果没有配套实现全套的类似 go net.Conn 这些的话,那可能还是没有解决阻塞系统线程的问题,那至少从语言级上,就不是一个类型、不是同一可用级别的协程系统、是没有可比性的
#137
> 我们做架构、框架,最头疼的往往就是进程线程模型、并发之间的通信和一致性这些基本点的设计。

补充:
我们做架构、框架,最头疼的往往就是进程线程模型、并发之间的通信和一致性这些基本点的设计;
我们做业务写逻辑,最头疼的就是写回调,不写回调性能不给力。
语言上大概有学院派、工程派这些不同种类的人,工程上又有 CURD 派、架构派这些不同种类的人。
每个角度上的不同派别,各自的着重点都不一样。
多数学院派讲究茴字的写法是否优雅却忽略了性能之类的指标考量,所以我经常看到这类人概念大把大把地往外掏,经常让我自愧不如、因为不知道他们在说什么,但多数时候等我缓过神来,探究这些概念、优雅的玩意背后真正的实用主义,都觉得似乎并没有什么卵用,然后也就不用耿耿于怀;
工程派追求写法与实用的平衡,当然,实用的基础上也能非常优雅是最好的,但鱼和熊掌难两全,踏实做事情的人,我更倾向于实用主义;
CURD 派,就如我前面所说,能让他们自己舒服的才是最好的,什么性能优雅完全不 care 的感觉,就比如异常处理这档子事,java 的社区惯性用法就真优雅吗?审美可是没有统一标准的,怕是中尉 javaer 自娱自乐自封这样最好罢了;
架构派要考虑好多细节,但凡好点的,也都是工程派,讲求实用主义,多数 java 社区的所谓架构师,我个人都是不认同的,八成就是社区方案一把梭,什么东西适合什么场景都未必去思考过,学以致用,至于用得对不对,反正社区都是用这些东西。。。

当然,业务大了都是堆屎山,大家都是混口饭吃,能挣钱就行。世界本就复杂、好的和不好的共存,大势所趋,被下一阶段的事物取代,代码这档子智慧进化进程中的一个阶段性技术,早晚是 AI 的天下
而除去 erlang ,在 golang 之前:
我们做架构、框架,最头疼的往往就是进程线程模型、并发之间的通信和一致性这些基本点的设计。c/cpp 也好,java 也好,虽然不是什么难事,但代码仍然都相对麻烦。而 golang 里,go 、chan 、mutex 这三个关键字,几乎就搞定了这一切,绝大多数场景也不用去为 callback hell 头疼。

c/c++的一些协程库,还有一些脚本语言的手动档 yield 协程,包括现在那些 async await ,相比于 go 都显得更加难于理解。所以我完全不觉得它们有资格用来跟 go 比较,如果没有 go ,相比于它们,我宁愿回头自己写系统线程、IPC 那些逻辑。
在 go 之前,erlang 的”进程“就已经存在多年,它的并发友好是真的挺不错,但主要还是在连接之间、模块之间不需要复杂交互的场景下更简单易用。涉及到复杂内部交互的,我觉得 actor 也并不算是友好。至于函数式更不知道说什么好,喜欢它的人也基本上都不怎么关心性能,而且类似“代码量少就是美”的这种审美看上去很好,代码少的前提式隐藏了大量细节,几种不同的简单写法之间就可能存在由于拷贝带来的很大的性能差异,所以美倒是“美”了,工程上的更重要的东西却被忽略抛弃了。erlang 的指令性能也不强。整体下来,我觉得 erlang 作者当初发明它用来做电信业务这种“进程”间不需要太多交互、并且主要处理 IO 的业务式很 ok 的,但并不适合拿出来普及到所有业务,所以它手持一代目语言级“进程”(本质是协程)却没有大火起来,很是理所当然。
@iseki
> 我似乎并没有鄙视 Go 这种 panic 即退出的设计,我只是说下这个设计在没有结构化并发时几乎是必然的,不知道你在激动什么……

可能是顺着你前面几层楼看下来,感觉整体上是个对 go 不屑或者其他非积极的语气。有些词严格考究那确实算是中性,但是组合到一块就会让人觉得是在说“g 不咋地、也就那样、很多缺陷”的样子。

> Go 的 goroutine 本身设计我不认为太大问题,但它的暴露形式就值得商榷了。难以直接被使用的 "go" 变成了关键字

我没 get 到 "go 难以直接被使用" 的点在哪里,当年就是看到了"go"、"chan"这两个大杀器我才义无反顾开始写写 go ,写了一些后,就再也不想碰 c/cpp 和其他一些脚本了,更不要提 java 这种臃肿的丑八怪

> errgroup 这种东西反而变成了 x 库。

标准库的严格新增导致了特性的缓慢,但这也恰恰把很多垃圾挡在了标准库之外,各有利弊吧。而且这也不是什么难度很大的必须由标准库提供才行的功能,所以倒还好。
至少,相比于 node module 的肆意泛滥,go 社区不至于这么乱七八糟

> “标准库没有就值得一喷”,标准库什么都半残那还叫什么标准库?我也没说标准库必须要带一套结构化并发,毕竟 go 出现的相对来说还是比较早的,但是 go 关键字的存在,除了更好打广告外,几乎看不到什么必要性。

我不知道什么是结构化并发,我觉得多进程多线程以及语言及协程这些,加上进程间通信线程同步或者其他各种用于并发的机制,这些是大厦的基础。从 c 到各种语言,这些程序架构/结构设计,本质上都是这些东西在搭积木。
本来我自己对这些基础的东西比较熟,设计个架构、结构大概都能了然于胸,然而当我刚刚搜了下结构化并发,看得我更懵逼了,又是一堆概念机制需要学习,然而并没有让我觉得变得方便了。golang 的 go 、chan 两个关键字可以弄各种组合,时序的一致性的东西也都能保障,即使退回到 c/cpp ,多进程多线程、锁、各种 IPC 、以及 socket 各种也是类似的足够实现业务所需。c/cpp 这些老牌强者主要的劣势是开发效率,go 牺牲性能提高开发效率做的已经非常好了,go+chan 的组合,足以让我省去很多不必要的麻烦。

> 事实上如果 Java 在绿色线程出现之后不能及时安排好结构化并发,我敢说 unhandled exception 可以被静默忽略的特性一定会成为灾难。

这些非系统线程的语言级协程方案,都需要语言级上支持各种系统调用之类的接口与语言 runtime 调度的结合,否则任意一个调用可能直接阻塞住一个系统线程的行为都会造成大量的 cpu 闲置,如果各个线程都被这种阻塞占了,系统效率可就太低下了。我不知道 java 绿色线程出现后有没有解决这个问题,如果也像 go 一样都支持了,那还有得对比,否则仍然是不适合普及,否则估计很大比例的开发者分辨不出来哪里可能会导致问题。
然而即使支持了又如何,java 的臃肿、吃内存,就足以让人生厌。
@iseki
其他语言里但凡哪个语言的协程或者绿色线程之类的能像 erlang 或者 golang 这么方便的,再对比也行。我暂时还没看到一个其他语言有 erlang 、golang 这么并发友好的

panic 导致整个程序退出这也能算问题吗,入门级的新手 go func 不 defer recover 那是写着玩,但凡正规点的公司稍微封装下框架脚手架都不至于,如果是用协程池也通常自带了一层 recover wrap ,或者知名 web 框架那些 recover 、logger 都是最基础的中间件、通常都要加的

所以我建议,摒弃那种“但凡标准库没有就值得一喷”的思想,做工程可没人强制大伙只能使用标准库并且不要做任何封装。如果是那样要求,那也请先把 java 社区的各种轮子都拿掉再来对比,看看裸奔的时候谁更优雅,但这显然毫无意义
@yannxia #82

或许 panic 的时候自动包装一层 stack 或许就没人这么喷 go 了,毕竟小白们好些人只看标准库没有就一顿喷,好像即使额外封装下(虽然封装也很简单)也实现不了他们说的这些似的。
众多 CURDer 在某些垃圾语言的舒适区里呆的久了,但凡让他们自己亲自去上厕所、他们都嫌累,殊不知自己亲自上厕所可以舒筋活血。

go 的标准库定位简单点挺好的
> java 也可以用处理错误的方式处理错误的. java 没限制你的返回类型, 你可以返回一个 result<err, data>, 然后再处理就是.

@bthulu 我也没说 java 不能,我的意思是 java 非要用异常处理的方式去处理错误,社区这样用习惯了就继续习惯用就是了,但是拿这个来喷别的语言不这样做,就有点自以为是了,而且 go 也不是不能那样做、稍微封装下就可以了。
go 这块的本质就是:
用错误处理的方式处理错误
用异常处理的方式处理异常

java 那些:
用异常处理的方式处理错误
用异常处理的方式处理异常

好奇你们哪里来的自信喷 go
看名字就知道了,一个是错误处理,一个是异常处理。

go 用 panic 照样能像 java 那样处理异常,但本来就是为了处理错误所以用 if error 怎么了?而且哪里有错就现场处理、代码的可读性更好。只是那些其他语言习惯了用异常的人一直不这样搞才会觉得别扭。你看写 c 的人有几个说 go 错误处理垃圾的?即使 cpp ,也少有项目把错误处理都搞成 java 那种用异常处理的方式

反倒是 java 和一些其他语言,错误处理的场景和异常处理的场景,都用处理异常的方式来处理。习惯了自己的这种用异常处理去处理错误的方式,然后来鄙视 go 的该用啥用啥的鲁棒性,这帮人可真逗
126 天前
回复了 wuxidixi 创建的主题 职场话题 大家都是工作多久后达到的月入 2 万
没被降过薪,所以还没到
129 天前
回复了 RedBeanIce 创建的主题 Go 编程语言 golang 应该如何选择 api 网关呢
@coderxy 嗯嗯,也祝你成功,并且欢迎来体验下我的库 ~
129 天前
回复了 RedBeanIce 创建的主题 Go 编程语言 golang 应该如何选择 api 网关呢
> 比如 server 也可以直接推送数据给 client 、client 也可以只推送数据不需要 server response
> -grpc 的双向数据流模式
> -grpc 一样做吧,这个业务场景跟协议没啥关系。IM 都可以用 grpc 的双向数据流模式写,如果你想的话。

@coderxy
这么说吧,grpc 双向流之上封装也能搞定这些,但双向流就相当于 TCP 之于 arpc ,双向流只是支持了基础的网络交互方式、相当于网络传输层相当于 TCP ;
对于复杂场景的协议交互、应用层仍然需要很多 Cmd/Method/Router 所以对于这些场景,用户仍然需要额外的协议封装,arpc 开箱即用的双向 Call 、Notify 都已经封装好了;
双向流太难用了,性能也一般
129 天前
回复了 RedBeanIce 创建的主题 Go 编程语言 golang 应该如何选择 api 网关呢
@coderxy 闭门造车这个词可能不对,但闭门这个词还算是比较准确,因为我造车的时候确实没有参考它们、主要是按照自己的设计来做的
兄弟如果你的从业经验主要是应用层的工作、公司里头不需要你造轮子、那你可能只要有轮子并且够用就可以了也不关心轮子好坏,但你可能就 get 不到这些造轮子的重点、也不太能够对轮子之间的重点进行合理的对比,这没错,大多数人都是这样工作的,但请不要以为自己用的就是最好的、其他的就都是闭门造车了,这样就有点一叶障目了
129 天前
回复了 RedBeanIce 创建的主题 Go 编程语言 golang 应该如何选择 api 网关呢
@coderxy #39
先看#41 吧,别乱用闭门造车这个词,grpc 这种破车有什么好的值得你如此喜欢,拿块烂铁当宝贝呢。。
对比我自己造的、grpc 的主要优势就是跨语言支持更强罢了,没办法啊,我精力有限,不可能多个语言都搞一轮
129 天前
回复了 RedBeanIce 创建的主题 Go 编程语言 golang 应该如何选择 api 网关呢
@coderxy #37

> 比如不只是 server 之间可以用、client 也可以请求 server
> -你这个指的是 grpc 编译生成 client?

不是。
是指用户直接访问,比如 web 前端直接请求:
https://github.com/lesismal/arpc/blob/master/examples/webchat/chat.html#L81


> 比如 server 也可以直接推送数据给 client 、client 也可以只推送数据不需要 server response
> -grpc 的双向数据流模式
> -grpc 一样做吧,这个业务场景跟协议没啥关系。IM 都可以用 grpc 的双向数据流模式写,如果你想的话。
> 比如可以做的业务类型也不限于微服务,游戏、IM 、推送各种业务都可以做

这倒确实是可以,但使用起来更麻烦,普通的推送服务还好。
复杂点的业务比如游戏,每个协议包也都可能是不同的 CMD/Method/Router ,你可能需要在 stream 基础上再二次封装一道 router handler 的逻辑


> 比如 arpc 不限制序列化方式,相同或者不同的 method 的每次请求都可以是不同的序列化,甚至也可以直接使用一段 buffer
> -grpc 的自定义编码集
> 中间件之类的也都支持,而且是支持两个维度的中间件:编解码、路由,用户可以自己定制、扩展更多东西
> -grpc 的 Interceptor?

你说的这些,很多需要再扩展之类的,像我这种不熟悉它们的"小白"去研究怎么扩展就已经很难受了,而 arpc 里这些默认是开箱即用了,另外还有性能因素。


> 或者这么说吧,正常大家能想到的常用的场景,grpc thrift 这种级别的项目基本上都已经有了,都不用想的。 所以,切勿闭门造车。

闭门造车这个词,建议也先对比下,如果造出来的比原来的差,那确实没必要,如果造出来的比原来的好,那就不叫闭门造车了。
反倒是建议你,不要闭关锁国、多开眼看看世界比较好吧

另外,百度、腾讯、字节各种大厂,也都有开源自己的 rpc ,就像你前面举例大厂都用 api gateway 来做论点一样,我想以彼之道问你一句:这些大厂自己造 rpc 而不是直接用 google 家的、它们算不算是闭门造车?
请不要说它们是大厂有资格闭门造车,我个人太弱没这个资格。还是前面的论点:不要虚空用 xxx 在做这种逻辑来辩论,要用实际的好坏来做逻辑


再另外,我还真就喜欢造车,但造的东西肯定也不是为了瞎折腾,而是为了能解决一些痛点:
https://github.com/lesismal/nbio
https://www.v2ex.com/t/945827
129 天前
回复了 RedBeanIce 创建的主题 Go 编程语言 golang 应该如何选择 api 网关呢
@coderxy #34
不是 100%的纯抵触,而是,用它和不用它对比之下,它可能没有带来真正的优势。只有在我确认它能带来提升的时候我才会去搞它,OP 这种场景,我觉得没必要,甚至即使改造成微服务,如果数据量不是很大,我都不建议在微服务中引入任何 RPC 。
因为相比于直达、RPC 是纵向链条新增了一层,新增一层对于开发、维护、问题排查,就新增了一个复杂度,这个复杂度可能不是+1 ,而是+N 。
129 天前
回复了 RedBeanIce 创建的主题 Go 编程语言 golang 应该如何选择 api 网关呢
@coderxy

当年造出 RPC 这个概念的人、以及 HTTP 作者,他们这些大佬本身对互联网发展做出了巨大贡献,但是单就这俩玩意而言,造成了很多开发者对网络只知道或者只会用 request-response 这种模式。
而实际业务种这种单一的 request-response 模式无法满足复杂需求。网络交互本质就是相互发数据,对于 client 、server 两个点而言,就是 c->s 和 s->c 两个方向,发数据也不一定要对方响应,不需要回复可以叫 notify 或者 push 、只发不收,需要响应的可以叫 request and response 。
2 个方向*是否响应 2 种=4 种交互,但 RPC 和 HTTP 都只搞了一种,HTTP2 的 stream 都是后话了、而且使用方式仍然局限。

arpc 本质上其实不是 RPC ,而是更广义的网络交互库,支持 c->s 和 s->c 两个方向上的 notify 和 request and response ,就是相当于上面说的 2*2=4 种交互,所以能用来实现各种业务。

对比之下,传统的 RPC 框架,模式局限、也主要是 server 之间的,用起来感觉就像是被阉割过、老觉得裤裆一紧。
所以,我是真的不喜欢那些传统 RPC 框架,太弱太难用了,可能 web 圈主流只有这些所以你们只能用这些吧。。。
129 天前
回复了 RedBeanIce 创建的主题 Go 编程语言 golang 应该如何选择 api 网关呢
@coderxy
即使我自己的 arpc ,我都不允许自家内部服务之间乱引入 rpc 的,能减少 rpc 调用就减少 rpc 调用,#16 里我举例子那些合理场景、或者其他一些合理的场景下才用
架构设计遵循奥卡姆剃刀,less is more ,我这个 id 也是根据 less is more 演化出来的,就不喜欢那种都没论证清楚成本与收益就随便引入更多内容到架构里的,有多少公司跟风微服务然后搞的一团糟的
uber 当年吹微服务凶,后来又发帖说试验宏服务,aws 前几个月也有个团队说把某些功能改成单体还是啥了之后各种成本降低了维护便利性提升了之类的。
我不是完全反对微服务,毕竟单体能力有限,但也就 web 娱乐圈整天搞新概念新名词然后炒作,微服务本质仍然是分布式,分布式早就有了,只是早期那个年代只有游戏行业比较注重分布式的说法因为 mmorpg 之类的游戏服务确实性能问题不好突破确实需要分布式上的很多优化,那个年代 web 的业务量还没那么性能紧缺,等到后来互联网发达了 web 服务性能瓶颈多了的时候微服务开始火起来,结果就各种妖魔化。很多中小团队根本不需要微服务、搞成微服务后基本都是软硬件成本增加、人员成本增加、维护成本增加、问题排查难度增加,这些中小团队的技术管理者都是属于盲目跟风的,自己连点架构设计能力都没有。当然,倒是学习了一些基础知识,然后对于他们去参加面试把自己忽悠进你所谓的大厂之类的有些帮助,但这仍然无法否认这个事实:他们不具备优秀的架构设计、具体问题具体分析的能力
1 ... 4  5  6  7  8  9  10  11  12  13 ... 53  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5164 人在线   最高记录 6543   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 27ms · UTC 09:37 · PVG 17:37 · LAX 02:37 · JFK 05:37
Developed with CodeLauncher
♥ Do have faith in what you're doing.