一份2021年2月25日的信息流提炼
每天学点Golang
优化Golang服务减少CPU40%使用率
原文:Optimizing a Golang service to reduce over 40% CPU
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服务-
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%,减少了一半。
关于对象分配过多,继续获取内存快照
-
http://localhost:6060/debug/pprof/heap # 运行以下命令分析 go tool pprof -alloc_objects <HEAP.PROFILE.FILE> # 分析相关方法 list <FunctionName>
这里发现了时Prometheu对指标的调用创建了大量对象,为了把客户ID从int转为字符串。因为我们数据库中的顾客有限,就没有用Prometheus的把变量转为字符串接收的方法,而是在对象初始化时定义了一个映射,包括了1~100k的所有数字,然后在其中执行获取操作。
再次分析时CPU利用率降低了1%。
-
既然提到Prometheus了,随手分享大神新鲜出炉解说:技术分享:Prometheus是怎么存储数据的
Golang Interface
原文:A Real-World Example of Go Interfaces
实战Go Interfaces。
主要用Interface实现了不同方法通知用户的功能。
※参考 Snippets > Golang Interface
每天学点网络:ARP协议
原文: 一文详解 ARP 协议
复习十分不牢靠的网络知识...
-
网络层: 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 的那些事儿,希望我这篇冗长的内容能讲清楚
- 概念
- Session: 『会话』,它代表了『一次』相互沟通,这次会话中,可能包括了多次通信。
- Server Side Session: 客户端储存Session-ID,服务端储存Session-Data
- Client Side Session: 直接将 Session-Data 存储在客户端(浏览器)的 Cookies 里。(需要加密机制或签名机制来进行校验)
- JWT : JSON Web Token 一种 Token 生成方式。生成方式大致是这样:将数据按特定格式进行序列化,标记过期时间,对数据进行『签名』后编码为 URL Safe 的 Base64URL
- 理解
- 对于 Session 机制来说,Session-Data / Session-ID 才是本体,Cookies 只是一个存储容器
- JWT 只是一种处理数据的手法,它通过签名保证了信息的不可篡改,特定的格式也具备其它一些小特性。
- JWT 的特性,让它可以成为 Client Side Session 的数据处理方式。
CSS布局
永恒的居中问题...
感觉flex是应对大的响应式页面布局,grid是响应式模块布局。
参考 Snippets > CSS Layout
程序员:写更好的技术文档
文档需要包括并围绕其四种不同的功能来构建:教程、操作指南、技术参考和解释。它们中的每一种都需要一种不同的写作模式。从事软件工作的人在不同的时间、不同的情况下需要这四种不同的文档--所以软件通常需要这四种文档,而且它们都应该被整合到你的文档中。
而且文档需要围绕着它们进行明确的结构化,它们都必须相互分离,相互区别。
Tutorials | 教程 | How-to guides | 操作指南 | Reference | 技术参考 | Explanation | 解释 | |
---|---|---|---|---|
面向 | 学习 | 目标 | 信息 | 理解 |
必须 | 新人入门 | 如何解决一个具体问题 | 描述各部分结构 | 说明 |
形式 | 课程 | 一系列步骤 | 描述 | 一些主题发散的说明 |
例如 | 教孩子做饭 | 一个菜谱 | 一个参考用百科全书 | 一篇烹饪史的文章 |
有趣的相遇
-
US Air Force | WebGL很酷炫
-
7个免费的API
- 原文:7 Free APIs That Nobody Is Talking About
-
侮辱生成器:Evil Insult Generator (黑人问号)
-
电影/电视剧:TMDb ,YouTube API ,Harry Potter API, API of Ice And Fire
-
可交互地图API:Mapbox
-
NASA: NASA API
-
GIF:GIF Search
-
格言API:Favourite Quotes API
-
- 原文:7 Free APIs That Nobody Is Talking About
今天的收获
- 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
<!-- Should be in all your pages -->
<svg style="display: none" aria-hidden="true">
<defs>
<symbol id="icon-circle" viewBox="0 0 20 20"><circle fill="currentColor" cx="10" cy="10" r="10" /></symbol>
<!-- other icons here -->
</defs>
</svg>
<!-- In some other template -->
<button>
<svg class="icon"><use xlink:href="#icon-circle"></use></svg>
<span>foobar</span>
</button>
<!-- in your CSS -->
.icon { width: 1em; height: 1em; }
CSS Layout
/* 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
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 バケットにあるオブジェクトへのクロスアカウントアクセス
1. A账号:创建S3 bucket
2. B账号:创建IAM用户(S3許可)
3. A账号:S3 bucket的policy里允许B账号IAM用户的访问