add cloud deploy
This commit is contained in:
parent
344e2840bd
commit
7f18d0fb0d
@ -1,4 +1,4 @@
|
||||
FROM daocloud.io/atsctoo/golang:1.15
|
||||
FROM golang:1.15
|
||||
WORKDIR /app/dtm
|
||||
RUN go env -w GO111MODULE=on
|
||||
RUN go env -w GOPROXY=https://goproxy.io,direct
|
||||
|
||||
@ -23,19 +23,19 @@
|
||||
* 一站式解决分布式事务需求
|
||||
- 支持TCC、SAGA、XA、事务消息、可靠消息
|
||||
* 支持跨语言栈事务
|
||||
- 适合多语言栈的公司使用。支持Go、Python、PHP、Nodejs、Java、c# 各类语言SDK。
|
||||
- 支持多语言栈混合的分布式事务。支持Go、Python、PHP、Nodejs、Java、c# 各类语言SDK。
|
||||
* 自动处理子事务乱序
|
||||
- 首创子事务屏障技术,框架层自动处理悬挂、空补偿、幂等网络异常问题
|
||||
* 支持单服务多数据源访问
|
||||
- 通过子事务屏障技术,保证单服务多数据源访问的一致性,也能保证本地长事务拆分多个子事务后的一致性
|
||||
* 开箱即用,提供云上服务
|
||||
- 支持通用的HTTP、gRPC协议接入,云原生友好。支持Mysql接入。提供测试版本的云上服务,方便新用户测试
|
||||
- 支持通用的HTTP、gRPC协议接入,云原生友好。支持Mysql接入。提供测试版本的云上服务,方便新用户测试接入
|
||||
|
||||
## 与其他框架对比
|
||||
|
||||
目前开源的分布式事务框架,暂未看到非Java语言有成熟的框架。而Java语言的较多,其中以seata应用最为广泛。
|
||||
|
||||
下面是dtm和seata的主要特性对比:
|
||||
下面是DTM和SEATA的主要特性对比:
|
||||
|
||||
| 特性| DTM | SEATA |备注|
|
||||
|:-----:|:----:|:----:|:----:|
|
||||
@ -46,7 +46,7 @@
|
||||
|AT事务|<span style="color:red">✗</span>|<span style="color:green">✓</span>|AT与XA类似,性能更好,但有脏回滚|
|
||||
| SAGA事务 |<span style="color:orange">简单模式</span> |<span style="color:green">状态机复杂模式</span> |dtm的状态机模式在规划中|
|
||||
|事务消息|<span style="color:green">✓</span>|<span style="color:red">✗</span>|dtm提供类似rocketmq的事务消息|
|
||||
|通信协议|HTTP、GRPC|dubbo等协议,无HTTP||
|
||||
|通信协议|HTTP、gRPC|dubbo等协议,无HTTP||
|
||||
|star数量|<img src="https://img.shields.io/github/stars/yedf/dtm.svg?style=social" alt="github stars"/>|<img src="https://img.shields.io/github/stars/seata/seata.svg?style=social" alt="github stars"/>|dtm从20210604发布0.1,发展快|
|
||||
|
||||
从上面对比的特性来看,如果您的语言栈包含了Java之外的语言,那么dtm是您的首选。如果您的语言栈是Java,您也可以选择接入dtm,使用子事务屏障技术,简化您的业务编写。
|
||||
|
||||
@ -125,16 +125,22 @@ func DbGet(conf map[string]string) *DB {
|
||||
type dtmConfigType struct {
|
||||
TransCronInterval int64 `yaml:"TransCronInterval"` // 单位秒 当事务等待这个时间之后,还没有变化,则进行一轮处理,包括prepared中的任务和committed的任务
|
||||
DB map[string]string `yaml:"DB"`
|
||||
DisableLocalhost int64 `yaml:"DisableLocalhost"`
|
||||
RetryLimit int64 `yaml:"RetryLimit"`
|
||||
}
|
||||
|
||||
// DtmConfig 配置
|
||||
var DtmConfig = dtmConfigType{}
|
||||
|
||||
func getIntEnv(key string, defaultV string) int64 {
|
||||
return int64(dtmcli.MustAtoi(dtmcli.OrString(os.Getenv(key), defaultV)))
|
||||
}
|
||||
|
||||
func init() {
|
||||
if len(os.Args) == 1 {
|
||||
return
|
||||
}
|
||||
DtmConfig.TransCronInterval = int64(dtmcli.MustAtoi(dtmcli.OrString(os.Getenv("TRANS_CRON_INTERVAL"), "10")))
|
||||
DtmConfig.TransCronInterval = getIntEnv("TRANS_CRON_INTERVAL", "10")
|
||||
DtmConfig.DB = map[string]string{
|
||||
"driver": dtmcli.OrString(os.Getenv("DB_DRIVER"), "mysql"),
|
||||
"host": os.Getenv("DB_HOST"),
|
||||
@ -142,6 +148,8 @@ func init() {
|
||||
"user": os.Getenv("DB_USER"),
|
||||
"password": os.Getenv("DB_PASSWORD"),
|
||||
}
|
||||
DtmConfig.DisableLocalhost = getIntEnv("DISABLE_LOCALHOST", "0")
|
||||
DtmConfig.RetryLimit = getIntEnv("RETRY_LIMIT", "2000000000")
|
||||
cont := []byte{}
|
||||
for d := MustGetwd(); d != "" && d != "/"; d = filepath.Dir(d) {
|
||||
cont1, err := ioutil.ReadFile(d + "/conf.yml")
|
||||
|
||||
@ -16,6 +16,7 @@ func addRoute(engine *gin.Engine) {
|
||||
engine.POST("/api/dtmsvr/registerTccBranch", common.WrapHandler(registerTccBranch))
|
||||
engine.POST("/api/dtmsvr/abort", common.WrapHandler(abort))
|
||||
engine.GET("/api/dtmsvr/query", common.WrapHandler(query))
|
||||
engine.GET("/api/dtmsvr/all", common.WrapHandler(all))
|
||||
engine.GET("/api/dtmsvr/newGid", common.WrapHandler(newGid))
|
||||
}
|
||||
|
||||
@ -74,3 +75,14 @@ func query(c *gin.Context) (interface{}, error) {
|
||||
db.Must().Where("gid", gid).Find(&branches)
|
||||
return M{"transaction": trans, "branches": branches}, nil
|
||||
}
|
||||
|
||||
func all(c *gin.Context) (interface{}, error) {
|
||||
lastId := c.Query("last_id")
|
||||
if lastId == "" {
|
||||
lastId = "2000000000"
|
||||
}
|
||||
lid := dtmcli.MustAtoi(lastId)
|
||||
trans := []TransGlobal{}
|
||||
dbGet().Must().Where("id < ?", lid).Order("id desc").Limit(100).Find(&trans)
|
||||
return M{"transactions": trans}, nil
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package dtmsvr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@ -222,6 +223,7 @@ func (t *TransGlobal) saveNew(db *common.DB) {
|
||||
branches := t.getProcessor().GenBranches()
|
||||
if len(branches) > 0 {
|
||||
writeTransLog(t.Gid, "save branches", t.Status, "", dtmcli.MustMarshalString(branches))
|
||||
checkLocalhost(branches)
|
||||
db.Must().Clauses(clause.OnConflict{
|
||||
DoNothing: true,
|
||||
}).Create(&branches)
|
||||
@ -271,3 +273,14 @@ func TransFromDb(db *common.DB, gid string) *TransGlobal {
|
||||
e2p(dbr.Error)
|
||||
return &m
|
||||
}
|
||||
|
||||
func checkLocalhost(branches []TransBranch) {
|
||||
if config.DisableLocalhost == 0 {
|
||||
return
|
||||
}
|
||||
for _, branch := range branches {
|
||||
if strings.HasPrefix(branch.URL, "http://localhost") || strings.HasPrefix(branch.URL, "localhost") {
|
||||
panic(errors.New("url for localhost is disabled. check for your config"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,3 +19,16 @@ func TestUtils(t *testing.T) {
|
||||
CronExpiredTrans(1)
|
||||
sleepCronTime(10)
|
||||
}
|
||||
|
||||
func TestCheckLocalHost(t *testing.T) {
|
||||
config.DisableLocalhost = 1
|
||||
err := dtmcli.CatchP(func() {
|
||||
checkLocalhost([]TransBranch{{URL: "http://localhost"}})
|
||||
})
|
||||
assert.Error(t, err)
|
||||
config.DisableLocalhost = 0
|
||||
err = dtmcli.CatchP(func() {
|
||||
checkLocalhost([]TransBranch{{URL: "http://localhost"}})
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
25
helper/compose.cloud.yml
Normal file
25
helper/compose.cloud.yml
Normal file
@ -0,0 +1,25 @@
|
||||
version: '3.3'
|
||||
services:
|
||||
api:
|
||||
build: .
|
||||
environment:
|
||||
IS_DOCKER: 1
|
||||
DISABLE_LOCALHOST: 1
|
||||
RETRY_LIMIT: 6
|
||||
ports:
|
||||
- '9080:8080'
|
||||
volumes:
|
||||
- .:/app/dtm
|
||||
mysql:
|
||||
image: 'mysql:5.7'
|
||||
environment:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: 1
|
||||
TZ: Asia/shanghai
|
||||
command:
|
||||
[
|
||||
'--character-set-server=utf8mb4',
|
||||
'--collation-server=utf8mb4_unicode_ci',
|
||||
'--default-time-zone=+8:00',
|
||||
]
|
||||
ports:
|
||||
- '3306:3306'
|
||||
@ -105,6 +105,9 @@ func transQuery(t *testing.T, gid string) {
|
||||
dtmcli.MustUnmarshalString(resp.String(), &m)
|
||||
assert.Equal(t, nil, m["transaction"])
|
||||
assert.Equal(t, 0, len(m["branches"].([]interface{})))
|
||||
|
||||
resp, err = dtmcli.RestyClient.R().Get(examples.DtmServer + "/all")
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestSqlDB(t *testing.T) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user