> 一份2021年2月25日的信息流提炼 ### 每天学点Golang #### 优化Golang服务减少CPU40%使用率 原文:[Optimizing a Golang service to reduce over 40% CPU](https://medium.com/coralogix-engineering/optimizing-a-golang-service-to-reduce-over-40-cpu-366b67c67ef9) > 10年前,Google因为C++过长的编译时间,开发出了Go。新语言借鉴了C++的精华部分(主要是性能与安全),结合了Python的速度让Go能能够快速利用多核实现并发。 想起了自己以前做过的googletest(C++ )框架的单元测试项目 改了一行代码要等40~50分钟编译完成.... ##### Coralogix做的优化代码的工作 - 升级Go版本: v1.12.4 → v1.13.8 (根据文档,1.13版本对运行时库和其他一些主要利用内存的组件有重大改进。) - 内存使用~800MB → ~180MB. - 使用自带的`pprof` 剖析Golang服务 ```go import _ "net/http/pprof" go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }() // 访问以下网址 // http://localhost:6060/debug/pprof ``` 报告汇总发现很多运行时的包活动,几乎CPU的`29%`都被GC占用了。由于内存使用率比较低,所以怀疑是对象分配率过高。 因为目前实例类型内存冗余多而瓶颈在于CPU,所以换成了相反的配置。另外Golang有一个叫**GOGC**的flag,默认堆达到`100`%时就触发GC。做了几个基准测试后发现最佳性能时GOGC设置为`2000`的时候。 结果是内存从`~200MB`升至`~2.7GB`,CPU使用率降低了`~10%` 整个GC使用率现在是`~13%`,减少了一半。 关于对象分配过多,继续获取内存快照 ```bash http://localhost:6060/debug/pprof/heap # 运行以下命令分析 go tool pprof -alloc_objects # 分析相关方法 list ``` 这里发现了时Prometheu对指标的调用创建了大量对象,为了把客户ID从int转为字符串。因为我们数据库中的顾客有限,就没有用Prometheus的把变量转为字符串接收的方法,而是在对象初始化时定义了一个映射,包括了1~100k的所有数字,然后在其中执行获取操作。 再次分析时CPU利用率降低了1%。 既然提到Prometheus了,随手分享大神新鲜出炉解说:[技术分享:Prometheus是怎么存储数据的](https://www.youtube.com/watch?v=qB40kqhTyYM&t=1468s) #### Golang Interface 原文:[A Real-World Example of Go Interfaces](https://betterprogramming.pub/a-real-world-example-of-go-interfaces-98e89b2ddb67) 实战Go Interfaces。 主要用Interface实现了不同方法通知用户的功能。 ※参考 Snippets > [Golang Interface](#golang-interface) ### 每天学点网络:ARP协议 原文: [一文详解 ARP 协议](https://juejin.cn/post/6916674783593627655#heading-3) 复习十分不牢靠的网络知识... - 网络层: IP 地址 - 数据链路层: MAC 地址 (`Media Access Control Address`) > MAC 地址长 48 bit,在使用`网卡(NIC)` 的情况下,MAC 地址一般都会烧入 ROM 中。因此,任何一个网卡的 MAC 地址都是唯一的。MAC 地址中的 3 - 24 位表示厂商识别码 **ARP** Address Resolution Protocol(地址解析协议) 是 TCP/IP 实现中的一个基本协议 ,只用于 **IPv4** 协议中,IPv6 协议使用的是 Neighbor Discovery Protocol ARP 高效运行的关键就是维护每个主机和路由器上的 `ARP 缓存(或表)`。这个缓存维护着每个 IP 到 MAC 地址的映射关系。通过把第一次 ARP 获取到的 MAC 地址作为 IP 对 MAC 的映射关系到一个 ARP 缓存表中,下一次再向这个地址发送数据报时就不再需要重新发送 ARP 请求了 `arp -a `查看ARP 缓存 `tcpdump` 截获 ARP 数据包 **RARP** `RARP(Reverse Address Resolution Protocol)` 是将 ARP 反过来,从 MAC 地址定位 IP 地址的一种协议,将打印机服务器等小型嵌入式设备接入网络时会使用到。 ### 每天学点WEB: Session & CSS Layout #### Session & JWT 原文:[有关 Session 的那些事儿,希望我这篇冗长的内容能讲清楚](https://www.v2ex.com/t/656457) - 概念 - **Session**: 『会话』,它代表了『一次』相互沟通,这次会话中,可能包括了多次通信。 - **Server Side Session**: 客户端储存Session-ID,服务端储存Session-Data - **Client Side Session**: 直接将 Session-Data 存储在客户端(浏览器)的 Cookies 里。(需要**加密机制**或**签名机制**来进行校验) - **JWT** : [JSON Web Token](https://tools.ietf.org/html/rfc7519) 一种 Token 生成方式。生成方式大致是这样:将数据按特定格式进行序列化,标记过期时间,对数据进行『签名』后编码为 URL Safe 的 Base64URL - 理解 - 对于 Session 机制来说,Session-Data / Session-ID 才是本体,Cookies 只是一个**存储容器** - JWT 只是一种处理数据的手法,它通过签名保证了信息的不可篡改,特定的格式也具备其它一些小特性。 - JWT 的特性,让它可以成为 Client Side Session 的**数据处理方式**。 #### CSS布局 原文:[你可能不太熟知的CSS布局技巧](https://juejin.cn/post/6932768256683933703#heading-0) 永恒的居中问题... 感觉flex是应对大的响应式页面布局,grid是响应式模块布局。 参考 Snippets > [CSS Layout](#css-layout) ### 程序员:写更好的技术文档 文档:[Documentation system Divio](https://documentation.divio.com/introduction/#) 文档需要包括并围绕其四种不同的功能来构建:教程、操作指南、技术参考和解释。它们中的每一种都需要一种不同的写作模式。从事软件工作的人在不同的时间、不同的情况下需要这四种不同的文档--所以软件通常需要这四种文档,而且它们都应该被整合到你的文档中。 而且文档需要围绕着它们进行明确的结构化,它们都必须相互分离,相互区别。 | | [Tutorials \| 教程](https://documentation.divio.com/tutorials/#tutorials) | [How-to guides \| 操作指南](https://documentation.divio.com/how-to-guides/#how-to) | [Reference \| 技术参考](https://documentation.divio.com/reference/#reference) | [Explanation \| 解释](https://documentation.divio.com/explanation/#explanation) | | ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | 面向 | 学习 | 目标 | 信息 | 理解 | | 必须 | 新人入门 | 如何解决一个具体问题 | 描述各部分结构 | 说明 | | 形式 | 课程 | 一系列步骤 | 描述 | 一些主题发散的说明 | | 例如 | 教孩子做饭 | 一个菜谱 | 一个参考用百科全书 | 一篇烹饪史的文章 | ### 有趣的相遇 - [US Air Force](https://airforceecho.com/) | WebGL很酷炫 - 7个免费的API - 原文:[7 Free APIs That Nobody Is Talking About](https://js.plainenglish.io/7-free-apis-that-nobody-is-talking-about-cf974e15917) - 侮辱生成器:[Evil Insult Generator](https://evilinsult.com/generate_insult.php?lang=en&type=json) (黑人问号) - 电影/电视剧:[TMDb](https://www.themoviedb.org/documentation/api) ,[YouTube API ](https://developers.google.com/youtube/),[Harry Potter API](https://www.potterapi.com/), [API of Ice And Fire](https://anapioficeandfire.com/) - 可交互地图API:[Mapbox](https://docs.mapbox.com/api/) - NASA: [NASA API](https://api.nasa.gov/) - GIF:[GIF Search](https://developers.giphy.com/docs/api) - 格言API:[Favourite Quotes API](https://favqs.com/api/) - 养生:[Edamam Nutrition and Recipe Analysis API](https://www.edamam.com/) ### 今天的收获 - JS oneline: `function test(a){ console.log(a===undefined)}` - 一个前端建议:用**SVG**放弃Icon Fonts - **iTerm2**使用`Esc(Opt)+b/f` 移动光标: Preferences > Profile > Keys - Left Option: Change 「Normal」→「Esc+」 ### Snippets #### SVG ```text foobar .icon { width: 1em; height: 1em; } ``` #### CSS Layout ```css /* Flexbox水平垂直居中 */ .flex__container { display: flex; justify-content: center; align-items: center; /* 让多个元素实现水平垂直居中的效果 */ flex-direction: column; } /* Grid中实现水平垂直居中 */ .grid { display: grid; // 或 inline-grid place-items: center } /* Grid中实现水平垂直居中 2 column */ .grid__container { display: grid; place-items: center; grid-template-columns: repeat(2, 1fr); gap: 2vh; } .grid__item { display: grid; place-items: center; } /* Sticky Footer */ body { display: flex; flex-direction: column; } footer { margin-top: auto; } /* 均分列 flex */ .flex__container { inline-size: 50vw; display: flex; } .flex__item { flex: 1; } /* 均分列 grid */ .grid__container { display: grid; grid-template-columns: repeat(3, 1fr); /*这里的3表示具体的列数*/ } /* 圣杯布局 Holy Grail Layout */ body { width: 100vw; display: flex; flex-direction: column; } main { flex: 1; min-height: 0; display: flex; align-items: stretch; width: 100%; } footer { margin-top: auto; } nav { width: 220px; order: -1; } article { flex: 1; } aside { width: 220px; } /* 两端对齐 */ ``` #### Golang Interface ```golang type User struct { Name string Email string } // target interface type UserNotifier interface { SendMessage(user *User, message string) error } type EmailNotifier struct {} // Implemented the method on the struct func (notifier EmailNotifier) SendMessage(user *User, message string) error { _, err := fmt.Printf("Sending email to %s with content %s\n", user.Name, message) return err } type SmsNotifier struct {} func (notifier SmsNotifier) SendMessage(user *User, message string) error { _, err := fmt.Printf("Sending SMS to %s with content %s\n", user.Name, message) return err } func (user *User) notify(message string) error { return user.Notifier.SendMessage(user, message) } func main() { user1 := User{"Dirk", "dirk@email.com", EmailNotifier{}} user2 := User{"Justin", "bieber@email.com", SmsNotifier{}} user1.notify("Welcome Email user!") user2.notify("Welcome SMS user!") } ``` #### AWS S3 跨账号使用流程 [Amazon S3 バケットにあるオブジェクトへのクロスアカウントアクセス](https://aws.amazon.com/jp/premiumsupport/knowledge-center/cross-account-access-s3/) ``` 1. A账号:创建S3 bucket 2. B账号:创建IAM用户(S3許可) 3. A账号:S3 bucket的policy里允许B账号IAM用户的访问 ```