From 9075c6f87c7395e3c646e732708c63d9f711565f Mon Sep 17 00:00:00 2001 From: Andrey Ivanov Date: Sat, 13 Feb 2021 04:28:56 -0500 Subject: [PATCH] nysql master + 2slaves --- cicd/docker-compose.yml | 2 +- cmd/main.go | 2 +- internal/application/application.go | 27 +++++++++++++++++++++------ internal/auth/user.go | 2 +- internal/handlers/handlers.go | 27 ++++++++++++++++----------- internal/models/config.go | 16 +++++++++------- test/dz002.sh | 12 ++++++------ test/dz002/post.lua | 5 +++++ test/dz003.sh | 3 +++ test/dz003/post.lua | 5 +++++ 10 files changed, 68 insertions(+), 33 deletions(-) mode change 100644 => 100755 test/dz002.sh create mode 100644 test/dz002/post.lua create mode 100755 test/dz003.sh create mode 100644 test/dz003/post.lua diff --git a/cicd/docker-compose.yml b/cicd/docker-compose.yml index 1688d7a..a7dbfc3 100644 --- a/cicd/docker-compose.yml +++ b/cicd/docker-compose.yml @@ -52,7 +52,7 @@ services: environment: APP_SERVER_ADDRESS: 0.0.0.0 APP_SERVER_PORT: 8080 - APP_DSN_HOST: mysql_master + APP_DSN_MASTER: mysql_master APP_DSN_PORT: 3306 APP_DSN_USER: app APP_DSN_PASS: app diff --git a/cmd/main.go b/cmd/main.go index 598ac94..8dd5c1b 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -29,7 +29,7 @@ func main() { if err != nil { log.Fatal(fmt.Errorf("can't build app: %w", err).Error()) } - go dataset.FillDB(app.DB, 1000000) + go dataset.FillDB(app.DBMaster, 1000000) m.Map(log.New(os.Stdout, "[app]", log.Lshortfile)) m.Map(app) diff --git a/internal/application/application.go b/internal/application/application.go index 4f83cef..e4b05f1 100755 --- a/internal/application/application.go +++ b/internal/application/application.go @@ -10,23 +10,38 @@ import ( type App struct { Config *models.Configuration - DB *sql.DB + DBMaster *sql.DB + DBSlave1 *sql.DB + DBSlave2 *sql.DB } -func New(configFile, envPrefix string) (App, error) { - conf, err := configure(configFile, envPrefix) +func New(configFile, envPrefix string) (app App, err error) { + app.Config, err = configure(configFile, envPrefix) if err != nil { return App{}, fmt.Errorf("can't apply config: %w\n", err) } - db, err := sql.Open("mysql", conf.DSN.User+":"+conf.DSN.Pass+"@tcp("+conf.DSN.Host+":"+conf.DSN.Port+")/"+conf.DSN.Base+"?charset=utf8&collation=utf8_unicode_ci") + app.DBMaster, err = sql.Open("mysql", app.Config.DSN.User+":"+app.Config.DSN.Pass+"@tcp("+app.Config.DSN.Master+":"+app.Config.DSN.Port+")/"+app.Config.DSN.Base+"?charset=utf8&collation=utf8_unicode_ci") if err != nil { return App{}, err } - if err = dbInit(db); err != nil { + if err = dbInit(app.DBMaster); err != nil { return App{}, err } - return App{Config: conf, DB: db}, nil + if app.Config.DSN.Slave1 != "" { + app.DBSlave1, err = sql.Open("mysql", app.Config.DSN.User+":"+app.Config.DSN.Pass+"@tcp("+app.Config.DSN.Slave1+":"+app.Config.DSN.Port+")/"+app.Config.DSN.Base+"?charset=utf8&collation=utf8_unicode_ci") + if err != nil { + return App{}, err + } + } + + if app.Config.DSN.Slave2 != "" { + app.DBSlave2, err = sql.Open("mysql", app.Config.DSN.User+":"+app.Config.DSN.Pass+"@tcp("+app.Config.DSN.Slave2+":"+app.Config.DSN.Port+")/"+app.Config.DSN.Base+"?charset=utf8&collation=utf8_unicode_ci") + if err != nil { + return App{}, err + } + } + return app, nil } func configure(fileName string, envPrefix string) (*models.Configuration, error) { diff --git a/internal/auth/user.go b/internal/auth/user.go index 25ea3d0..8650a27 100644 --- a/internal/auth/user.go +++ b/internal/auth/user.go @@ -52,7 +52,7 @@ func (u *UserModel) UniqueId() interface{} { func (u *UserModel) GetById(app application.App, id interface{}) error { var v string query := fmt.Sprintf("SELECT username, name, surname, birthdate, gender, city, interests FROM users WHERE id=%d", id) - err := app.DB.QueryRow(query).Scan(&u.Username, &u.Name, &u.Surname, &v, &u.Gender, &u.City, &u.Interests) + err := app.DBMaster.QueryRow(query).Scan(&u.Username, &u.Name, &u.Surname, &v, &u.Gender, &u.City, &u.Interests) if err != nil { return err } diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index e50f640..eb8d5b0 100755 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -22,7 +22,7 @@ func GetHome(app application.App, r render.Render, user auth.User) { var users []auth.UserModel var tmp auth.UserModel var tmpTime string - var results, err = app.DB.Query(`SELECT + var results, err = app.DBMaster.Query(`SELECT users.id as id, users.name as name, users.surname as surname, @@ -79,7 +79,7 @@ func PostSignup(app application.App, postedUser auth.UserModel, r render.Render) if err != nil { err500("can't generate password hash: ", err, r) } - _, err = app.DB.Exec(`INSERT INTO users (username, password, name, surname, birthdate, gender, city, interests) + _, err = app.DBMaster.Exec(`INSERT INTO users (username, password, name, surname, birthdate, gender, city, interests) values (?, ?, ?, ?, ?, ?, ?, ?)`, postedUser.Username, pHash, @@ -100,7 +100,7 @@ func GetUserList(app application.App, r render.Render) { doc := make(map[string]interface{}) doc["UsersFound"] = 0 var tmp int - if err := app.DB.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&tmp); err != nil { + if err := app.DBMaster.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&tmp); err != nil { err500("can't get total of user profiles from DB: ", err, r) } doc["UsersTotal"] = tmp @@ -115,7 +115,7 @@ func PostUserList(app application.App, user auth.User, r render.Render, req *htt var users []auth.UserModel var tmp auth.UserModel var tmpTime string - var results, err = app.DB.Query(`SELECT + var results, err = app.DBMaster.Query(`SELECT users.id as id, users.name as name, users.surname as surname, @@ -159,7 +159,7 @@ func PostUserList(app application.App, user auth.User, r render.Render, req *htt doc["table"] = users doc["UsersFound"] = len(users) var uTotal int - if err := app.DB.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&uTotal); err != nil { + if err := app.DBMaster.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&uTotal); err != nil { err500("can't get total of user profiles from DB: ", err, r) } doc["UsersTotal"] = uTotal @@ -167,13 +167,18 @@ func PostUserList(app application.App, user auth.User, r render.Render, req *htt } func PostUserSearch(app application.App, r render.Render, req *http.Request) { + db := app.DBMaster + if app.Config.DSN.Slave1!="" { + db = app.DBSlave1 + } + postName := req.FormValue("name") postSurname := req.FormValue("surname") doc := make(map[string]interface{}) var users []auth.UserModel var tmp auth.UserModel var tmpTime string - var results, err = app.DB.Query(`SELECT + var results, err = db.Query(`SELECT users.id as id, users.name as name, users.surname as surname, @@ -207,7 +212,7 @@ func PostUserSearch(app application.App, r render.Render, req *http.Request) { doc["table"] = users doc["UsersFound"] = len(users) var uTotal int - if err := app.DB.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&uTotal); err != nil { + if err := db.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&uTotal); err != nil { err500("can't get total of user profiles from DB: ", err, r) } doc["UsersTotal"] = uTotal @@ -216,7 +221,7 @@ func PostUserSearch(app application.App, r render.Render, req *http.Request) { func PostLogin(app application.App, session sessions.Session, postedUser auth.UserModel, r render.Render, req *http.Request) { user := auth.UserModel{} - err1 := app.DB.QueryRow("SELECT id, password FROM users WHERE username=?", postedUser.Username).Scan(&user.Id, &user.Password) + err1 := app.DBMaster.QueryRow("SELECT id, password FROM users WHERE username=?", postedUser.Username).Scan(&user.Id, &user.Password) err2 := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(postedUser.Password)) if err1 != nil || err2 != nil { doc := map[string]interface{}{ @@ -246,11 +251,11 @@ func GetSubscribe(app application.App, r render.Render, user auth.User, req *htt if err != nil { err500("can't convert URL query value: ", err, r) } - _, err = app.DB.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, user.(*auth.UserModel).Id, did) + _, err = app.DBMaster.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, user.(*auth.UserModel).Id, did) if err != nil { err500("can't create relation in DB: ", err, r) } - _, err = app.DB.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, did, user.(*auth.UserModel).Id) + _, err = app.DBMaster.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, did, user.(*auth.UserModel).Id) if err != nil { err500("can't create relation in DB: ", err, r) } @@ -266,7 +271,7 @@ func GetUnSubscribe(app application.App, r render.Render, user auth.User, req *h if err != nil { err500("can't convert URL query value: ", err, r) } - _, err = app.DB.Exec(`DELETE FROM relations WHERE (userId,friendId) IN ((?, ?),(?, ?))`, user.(*auth.UserModel).Id, did, did, user.(*auth.UserModel).Id) + _, err = app.DBMaster.Exec(`DELETE FROM relations WHERE (userId,friendId) IN ((?, ?),(?, ?))`, user.(*auth.UserModel).Id, did, did, user.(*auth.UserModel).Id) if err != nil { err500("can't remove relation from DB: ", err, r) } diff --git a/internal/models/config.go b/internal/models/config.go index 271b283..d78de70 100755 --- a/internal/models/config.go +++ b/internal/models/config.go @@ -1,8 +1,8 @@ package models type Configuration struct { - Server Server - DSN DSN + Server Server + DSN DSN } type Server struct { @@ -11,9 +11,11 @@ type Server struct { } type DSN struct { - Host string - Port string - User string - Pass string - Base string + Master string + Slave1 string + Slave2 string + Port string + User string + Pass string + Base string } diff --git a/test/dz002.sh b/test/dz002.sh old mode 100644 new mode 100755 index cded9d2..8807e6d --- a/test/dz002.sh +++ b/test/dz002.sh @@ -1,13 +1,13 @@ #/bin/sh -docker run --rm -v /root/scripts:/scripts williamyeh/wrk -t1 -c1 -d1m --timeout 30s http://lab.tiburon.su:8080/search -s /scripts/post.lua -- debug true +docker run --rm -v dz002:/scripts williamyeh/wrk -t1 -c1 -d1m --timeout 30s http://lab.tiburon.su:8080/search -s /scripts/post.lua -- debug true -docker run --rm -v /root/scripts:/scripts williamyeh/wrk -t1 -c10 -d10m --timeout 30s http://lab.tiburon.su:8080/search -s /scripts/post.lua -- debug true +docker run --rm -v dz002:/scripts williamyeh/wrk -t1 -c10 -d10m --timeout 30s http://lab.tiburon.su:8080/search -s /scripts/post.lua -- debug true -docker run --rm -v /root/scripts:/scripts williamyeh/wrk -t1 -c20 -d10m --timeout 30s http://lab.tiburon.su:8080/search -s /scripts/post.lua -- debug true +docker run --rm -v dz002:/scripts williamyeh/wrk -t1 -c20 -d10m --timeout 30s http://lab.tiburon.su:8080/search -s /scripts/post.lua -- debug true -docker run --rm -v /root/scripts:/scripts williamyeh/wrk -t1 -c30 -d10m --timeout 30s http://lab.tiburon.su:8080/search -s /scripts/post.lua -- debug true +docker run --rm -v dz002:/scripts williamyeh/wrk -t1 -c30 -d10m --timeout 30s http://lab.tiburon.su:8080/search -s /scripts/post.lua -- debug true -docker run --rm -v /root/scripts:/scripts williamyeh/wrk -t1 -c40 -d10m --timeout 30s http://lab.tiburon.su:8080/search -s /scripts/post.lua -- debug true +docker run --rm -v dz002:/scripts williamyeh/wrk -t1 -c40 -d10m --timeout 30s http://lab.tiburon.su:8080/search -s /scripts/post.lua -- debug true -docker run --rm -v /root/scripts:/scripts williamyeh/wrk -t1 -c50 -d10m --timeout 30s http://lab.tiburon.su:8080/search -s /scripts/post.lua -- debug true +docker run --rm -v dz002:/scripts williamyeh/wrk -t1 -c50 -d10m --timeout 30s http://lab.tiburon.su:8080/search -s /scripts/post.lua -- debug true diff --git a/test/dz002/post.lua b/test/dz002/post.lua new file mode 100644 index 0000000..ed97ee3 --- /dev/null +++ b/test/dz002/post.lua @@ -0,0 +1,5 @@ +wrk.method = "POST" +wrk.body = "name=ан&surname=ан" +wrk.headers["Content-Type"] = "application/x-www-form-urlencoded" +response = function(status, headers, body) +end diff --git a/test/dz003.sh b/test/dz003.sh new file mode 100755 index 0000000..c9ecb85 --- /dev/null +++ b/test/dz003.sh @@ -0,0 +1,3 @@ +#/bin/sh + +docker run --rm -v /root/scripts:/scripts williamyeh/wrk -t1 -c10 -d5m --timeout 30s http://localhost:8080/search -s /scripts/post.lua -- debug true diff --git a/test/dz003/post.lua b/test/dz003/post.lua new file mode 100644 index 0000000..ed97ee3 --- /dev/null +++ b/test/dz003/post.lua @@ -0,0 +1,5 @@ +wrk.method = "POST" +wrk.body = "name=ан&surname=ан" +wrk.headers["Content-Type"] = "application/x-www-form-urlencoded" +response = function(status, headers, body) +end