nysql master + 2slaves

main
Andrey Ivanov 2021-02-13 04:28:56 -05:00 committed by Andrey Ivanov
parent 174c72dc2f
commit 9075c6f87c
10 changed files with 68 additions and 33 deletions

View File

@ -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

View File

@ -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)

View File

@ -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) {

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

12
test/dz002.sh Normal file → Executable file
View File

@ -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

5
test/dz002/post.lua Normal file
View File

@ -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

3
test/dz003.sh Executable file
View File

@ -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

5
test/dz003/post.lua Normal file
View File

@ -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