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

基于postman/newman实现的HTTP接口监控

本文主要分两部分,第一部分是介绍postman的一些使用tips,第二部分是简单介绍下自己基于postman/newman写的一个HTTP接口监控的程序~

postman


postman作为一个http请求模拟工具相信很多人都已经用到了。postman有pc app,也有基于chrome 的app,在使用体验上,pc app会更好(比如打开太多tab时可以方便地关掉,跑collection时展示效果更好)。

目前,有一点chrome app更好用的就是,它可以利用附带的一个chrome扩展Postman Interceptor,方便地捕获chrome的请求。而pc app需要通过它的proxy功能来捕获请求。


Read more...

2017-07-20

HTTPS 性能优化学习

最近在学习https性能优化,虽然网上已经有许多的关于https性能优化的文章了,但还是想写下这篇文章,作为学习总结=^_^=,文中对于一些概念性或实现细节上的东西并不会展开,但会给出相应的引用,有些图片也来自网上资源。

章节规划:

  • 认识SSL/TLS
  • 算法选择
  • 会话恢复
  • OCSP stapling
  • TLS 缓冲区优化
  • TLS false start
  • 其他优化

认识SSL/TLS


SSL和TLS都是用于保障端到端之间连接的安全性。SSL最初是由Netscape开发的,后来为了使得该安全协议更加开放和自由,更名为TLS,并被标准化到RFC中,现在主流的是TLS 1.2版本。

从上图,可以看出SSL/TLS是介于应用层和传输层之间,并且分为握手层(Handshake Layer)和记录层(Record Layer)。

  • 握手层:端与端之间协商密码套件、连接状态。
  • 记录层:对数据的封装,数据交给传输层之前,会经过分片-压缩-认证-加密

从TLS 1.2 RFC可以了解更多:https://www.ietf.org/rfc/rfc5246.txt


Read more...

2017-05-13

关于消息队列的思考

消息队列是服务架构中常见的组件,可用于服务间解耦、事件广播、任务异步/延迟处理等,本文对于消息队列的实现如何满足几种消费语义进行了阐述。

消息队列组成

  • 生产者(Producer):负责产生消息
  • 消息代理(Message Broker):负责存储/转发消息(转发分为推和拉两种,拉是指Consumer主动从Message Broker获取消息,推是指Message Broker主动将Consumer感兴趣的消息推送给Consumer)
  • 消费者(Consumer):负责消费消息


Read more...

2017-03-22 消息队列

golang singleflight 用武之地

缓存更新问题


当缓存失效时,需要去数据存储层获取数据,然后存储到缓存中。

通常缓存更新方案:

  1. 业务代码中,根据key从缓存拿不到数据,访问存储层获取数据后更新缓存
  2. 由专门的定时脚本在缓存失效前对其进行更新
  3. 通过分布式锁,实现只有一个请求负责缓存更新,其他请求等待:一种基于哨兵的缓存访问策略

服务中某个接口请求量暴增问题


比如某个帖子突然很火,帖子下有非常多的跟帖回复,负责提供帖子内容、回帖内容的接口,对于该帖子的请求量就会非常多。

如果每个请求都落到下游服务,通常会导致下游服务瞬时负载升高。如果使用缓存,如何判断当前接口请求的内容需要缓存下来?缓存的过期、更新问题?


Read more...

2017-03-07