Giter Club home page Giter Club logo

waterdrop's Introduction

English | 简体中文

Go codecov Go Report Card Release License

Waterdrop

Waterdrop is a high performance micro-service framework based on gin and grpc. Waterdrop comes from (The Three Body Problem). waterdrop

Features

  • HTTP Server: Based on gin and can reuse all its features
  • RPC Server: Based on the official gRPC-go and use ETCD for service registration and discovery, default load balancing policy is roundrobin
  • Conf: Support YAML, TOML, JSON and other extensions, default TOML parsing, user can decide whether or not to watch the config file changes for hot reload configuration
  • Database: Integrated MySQL, Redis
  • Log: Based on Zap encapsulation
  • Trace: Integrate Opentracing access and use jaeger to record trace records
  • Distribute Lock: distributed Lock is implemented based on Redis and ETCD. The former is suitable for final consistent business locks, while the latter is suitable for strongly consistent business locks
  • Stats: Metrics & Profile for service operation
  • Broker: Support RocketMQ and Kafka
  • Utils: Helper class function
  • Registry: Service Registry discovery, etcd is the default service discovery component
  • Status: Global error handling for error conversion between HTTP/RPC
  • Dashboard: Build metrics dashboard based on Grafana, to be implemented
  • Breaker: Support alibaba sentinel, google sre breaker
  • Middlewares & Interceptors: HTTP/RPC Server common middleware, such as recovery, trace, metric and logger,etc

Installation

go get github.com/UnderTreeTech/waterdrop

Tools

Execute the following command to get waterdrop tool to help you boost your development progress

go get -u github.com/UnderTreeTech/waterdrop/tools/waterdrop

You can use waterdrop help to find out how to use tools

You can generate protobuf codes but make sure you've already installed protc and protoc-gen-go. Here we don't install the two plugins automatically because we are not sure which version you will choose.

  • waterdrop new your_project_name new a standard layout project
  • waterdrop protoc --grpc --swagger xx.proto generate grpc code and swagger api file
  • waterdrop swagger serve xx.swagger.json serve and browse swagger api
  • waterdrop utgen xx.go generate unit tests
  • waterdrop upgrade upgrade tool waterdrop

Contributing

Contributions are always welcomed! You can start with the issues labeled with bug or feature.

waterdrop's People

Contributors

billxunyang avatar bytehello avatar coosir avatar undertreetech avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

waterdrop's Issues

[optimize] http client X-Request-Timeout value wrongly assigned

Here at line 145 we should use timeout that calculate out between line 129~136, but not c.config.Timeout

// adjust request timeout
timeout := c.config.Timeout
if deadline, ok := ctx.Deadline(); ok {
derivedTimeout := time.Until(deadline)
if timeout > derivedTimeout {
timeout = derivedTimeout
}
}
ctx = metadata.NewOutgoingContext(ctx, metadata.MD(request.Header))
ctx, cancel := context.WithTimeout(ctx, timeout)
defer func() {
span.Finish()
cancel()
}()
request.SetHeader(_httpHeaderTimeout, strconv.Itoa(int(c.config.Timeout/1e6)))

bug SendSyncMsg panic

11:49:16: panic: runtime error: invalid memory address or nil pointer dereference
11:49:16: [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x972032]
11:49:16: goroutine 14820 [running]:
11:49:16: github.com/apache/rocketmq-client-go/v2/primitive.(*MessageQueue).String(...)
11:49:16: /go/pkg/mod/github.com/apache/rocketmq-client-go/[email protected]/primitive/message.go:393
11:49:16: github.com/apache/rocketmq-client-go/v2/primitive.(*SendResult).String(0xc000ee1320, 0x7, 0xc00000b700)
11:49:16: /go/pkg/mod/github.com/apache/rocketmq-client-go/[email protected]/primitive/result.go:56 +0x52
11:49:16: github.com/UnderTreeTech/waterdrop/pkg/broker/rocketmq.producerMetricInterceptor.func1(0xf693c0, 0xc0011d8450, 0xdf1fe0, 0xc000278000, 0xcee080, 0xc000ee1320, 0xc0003f6370, 0xc0011d8450, 0xc00020a200)
11:49:16: /go/pkg/mod/github.com/!under!tree!tech/[email protected]/pkg/broker/rocketmq/interceptor.go:55 +0x45e
11:49:16: github.com/apache/rocketmq-client-go/v2/producer.(*defaultProducer).SendSync(0xc0004f0180, 0xf69340, 0xc000036110, 0xc0000b01c8, 0x1, 0x1, 0x74, 0xc0000b01c8, 0x1)
11:49:16: /go/pkg/mod/github.com/apache/rocketmq-client-go/[email protected]/producer/producer.go:163 +0x2e3
11:49:16: github.com/UnderTreeTech/waterdrop/pkg/broker/rocketmq.(*Producer).SendSyncMsg(0xc0004ff920, 0xf69340, 0xc000036110, 0xc00020a180, 0x74, 0x74, 0x0)

codahale/hdrhistogram repo url has been transferred under the github HdrHstogram umbrella

Problem

The codahale/hdrhistogram repo has been transferred under the github HdrHstogram umbrella with the help from the original author in Sept 2020 (new repo url https://github.com/HdrHistogram/hdrhistogram-go). The main reasons are to group all implementations under the same roof and to provide more active contribution from the community as the original repository was archived several years ago.

The dependency URL should be modified to point to the new repository URL. The tag "v0.9.0" was applied at the point of transfer and will reflect the exact code that was frozen in the original repository.

If you are using Go modules, you can update to the exact point of transfer using the @v0.9.0 tag in your go get command.

go mod edit -replace github.com/codahale/hdrhistogram=github.com/HdrHistogram/[email protected]

Performance Improvements

From the point of transfer, up until now (mon 16 aug 2021), we've released 3 versions that aim support the standard HdrHistogram serialization/exposition formats, and deeply improve READ performance.
We recommend to update to the latest version.

Support Distributed Transaction

分布式事务概述

分布式事务本质上是一次业务请求,操作了不同库的不同数据。而在业务上是要求此次业务请求最终的结果是各数据库的数据是可对帐且一致的。

分布式事务解决方案有符合XA规范的2PC、3PC,最终一致性方案TCC、Saga、Seata及MQ事务消息;XA方案能最大程度保证一致性但性能开销大;TCC等方案对业务侵入深,对开发不友好,RTT损耗约为10%;本设计最终落地选择MQ事务消息,其对业务侵入相对较小、保证吞吐的同时最大程度保证数据最终一致。

MQ事务消息基于两个前提:

  • MQ保证消息不丢失且至少消费一次(At Least Once)

可选RabbitMQ、RocketMQ、Kafka

  • 消费方要确保幂等

Redis保证幂等防重入

阿里云RocketMQ支持事务消息,但本组件并不采用事务消息。如下图所示为阿里云事务消息流程。

RocketMQ事务消息

RocketMQ事务消息需要先发送半消息,发送成功才能执行本地事务,半消息投递成功还需要提供callback供broker回查本地事务执行状态。然而实际生产中这样操作并不一定合理。

  • 投递MQ成功与否并不能决定是否执行本地事务

  • 如果MQ能保证投递的消息不丢失且至少消费一次,提供回查接口其实增加了业务复杂度

MQ事务设计

基于以上归纳,以用户购买储值卡后,需要更新积分、帐户余额、更改会员等级为例(单体应用时,下单与这些操作属于同一事务),选型RocketMQ提出以下事务消息设计方案:

下单事务逻辑包括:(下单业务逻辑+事务消息处理) => local transaction

伪代码如下:

tx = db.beginTransaction()
try {
	addOrder(ctx,params)
	//事务消息
	addTransactionMsg(ctx,topic,body,tags)
	tx.Commit()
} catch {
	tx.Rollback()
}
  • 下单业务逻辑

根据业务逻辑生成主订单、子订单(如果有)

  • 事务消息处理

1、生成一条事务消息,字段如下:

字段 类型 描述
id uint64 自增ID
msgid int64 消息ID ,此ID可用作投递至MQ中的消息的Key,MQ生成的MsgId并不一唯一,业务方应以自己的Key为准
body varchar 消息体
topic varchar topic
tags varchar tags,需要投递的tag
is_delivery uint32 是否已投递,0未投递 1已投递
retry_times uint32 已重试次数
max_retry_times uint32 最大重试次数
created_time uint64 创建时间
updated_time uint64 更新时间

2、根据步骤1的事务消息生成需要投递的MQ消息并先投递到本地发送队列中

  • 将步骤1中的消息加入本地发送队列,有异步线程不断消费该队列投递至RocketMQ

  • 如果投递失败,将失败的消息加入本地延迟队列中(根据失败次数决定重试时间点),有异步线程不断拿出该发送的消息投至本地发送队列

注意: 以上两个操作是包含在一个本地事务中,要么成功返回下单成功,要么失败返回下单失败。

  • MQ事务组件内部功能
  • 定期清理已投递的消息(硬删即可,事务消息表要保证轻量)
  • 同时对于超出最大重试次数的消息进行报警,通知人工尽快介入异常业务事务处理
  • 记录所有调用日志,方便回查问题

服务协调

  • 积分服务幂等消费订单创建消息

  • 帐户余额服务幂等消费订单创建消息

  • 用户会员等级变更服务幂等消费订单创建消息

结论

该方案对业务侵入小,对于需要强一致性的业务,直接在正常的事务业务代码中调用addTransactionMsg方法即可(具体实现逻辑全部屏蔽在组件层),保证业务吞吐的同时,性能损耗非常小。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.