ctrl+c'杀不死'docker container

有时使用ctrl+c杀掉容器时,发现行不通,得用docker stop <container>才行,于是就像弄明白为什么。

从dockerfile官方文档:https://docs.docker.com/engine/reference/builder/#entrypoint,得知ENTRYPOINT有两种形式:

  1. ENTRYPOINT ["executable", "param1", "param2"] (exec格式,推荐使用)
  2. ENTRYPOINT command param1 param2 (shell格式)

使用exec格式,容器的init进程(即PID为1的进程)就是我们指定的可执行程序。

使用shell格式,容器的init进程是/bin/sh,我们的ENTRYPOINT是以/bin/sh -c的子进程启动的。


Read more...

2018-02-16

Golang understanding interface

本文简单总结自Understanding Go Interfaces,对应的PPT

In object-oriented programming, a protocol or interface is a common means for unrelated objects to communicate with each other.


Read more...

2017-12-24

Golang profiling and optimizing

本文总结自Profiling and Optimizing Go,对应的PPT,有梯子的可以直接看视频,没梯子的也可以看下这篇文章:) 。

Golang的runtime内建了强大的分析工具pprof,能帮助我们对程序运行时的CPU、内存进行分析。

首先,跟随视频,将作者提供的代码clone下来。在我们的工作区执行go get -v github.com/prashantv/go_profiling_talk即可。

进入src/github.com/prashantv/go_profiling_talk,master分支是优化过的最快的版本,slow分支是优化前的版本,执行go run main.go即可启动一个http服务。

代码说明:

  • 以一个http服务运行,有两个请求路径/hello/simple
  • /hello的请求会增加一些统计信息的记录,然后输出Hello world
  • /simple的请求则是简单的输出Hello world!
  • 实践目的:通过pprof分析优化/hello接口的性能,使其与/simple接口的性能差距尽量小。

Read more...

2017-12-24

git learn


2017-12-17

ES简单的通用日志方案

本文介绍笔者所使用的ES简单通用的应用日dudp志方案。

首先说明下需求:业务日志希望能够有一个地方能够统一存储,能够检索和展示报表,并且简便地接入新的业务日志。

于是设计了如下的架构:

  1. 业务通过udp协议的方式将日志以json编码的格式发送给udp2kafka服务,并且日志中包含需要写入的index
  2. udp2kafka将接收到的日志写入kafka
  3. kafka2es进行消费,根据日志中的index,写入到es相应的index中

Read more...

2017-10-01

Golang动手写一个Http Proxy

本文主要使用Golang实现一个可用但不够标准,支持basic authentication的http代理服务。

为何说不够标准,在HTTP/1.1 RFC中,有些关于代理实现标准的条目在本文中不考虑。

Http Proxy是如何代理我们的请求


Http 请求的代理如下图,Http Proxy只需要将接收到的请求转发给服务器,然后把服务器的响应,转发给客户端即可。

Https 请求的代理如下图,客户端首先需要发送一个Http CONNECT请求到Http Proxy,Http Proxy建立一条TCP连接到指定的服务器,然后响应200告诉客户端连接建立完成,之后客户端就可以与服务器进行SSL握手和传输加密的Http数据了。

为何需要CONNECT请求? 因为Http Proxy不是真正的服务器,没有www.foo.com的证书,不可能以www.foo.com的身份与客户端完成SSL握手从而建立Https连接。 所以需要通过CONNECT请求告诉Http Proxy,让Http Proxy与服务器先建立好TCP连接,之后客户端就可以将SSL握手消息发送给Http Proxy,再由Http Proxy转发给服务器,完成SSL握手,并开始传输加密的Http数据。


Read more...

2017-09-16

巧用Hash,避免使用锁

业务需求


如下图,业务A 往队列写消息,业务B 负责消费产生的消息,每条消息都会有一个用户id,更新存储A、B中与用户相关的信息,更新操作:

  1. 根据用户id从存储A获取信息valueA
  2. 根据valueA更新存储B中的信息
  3. 更新用户在存储A中的信息为valueB

由于对存储A、B的更新操作无法保证事务性,所以当业务B开了多个消费者的时候,就可能并发地更新同一个用户信息,从而导致用户的信息出现错乱。

问题解决


首先想到的解决方案是通过锁来实现,比如使用redis,以用户id作为key,然后执行set userid '' EX 2 NX',成功执行了set命令的消费者获得锁,当更新完用户信息后,可以执行delete userid来将锁释放掉。

然而,使用锁之后,发现消费者的吞吐量下降了很多,于是就想有没办法不用锁。

认识问题本质

问题产生的根本原因在于多个消费者并行地更新用户的信息,加锁是为了让每个用户信息的更新操作能够被串行执行。

所以只要能够使得对同一个用户的更新操作串行地执行,问题就解决了。在不加锁的情况下,可以想办法使得同一个用户的消息都入到同一个队列,从而只被一个消费者消费。

Hash

那么,问题就变成如何将同一个用户的消息入到同一个队列里了,因为每个用户消息里都会有一个用户id,所以可以利用这个用户id的hash值,然后取模,使得同一个用户的消息映射到同一个队列上,从而避免使用锁。


2017-09-08