未分類

秘密の議事録ちゃん

 

スタートダッシュ Source->GitLab->EC2デプロイまで

ISUCONスタートダッシュ GitLab CDによるデプロイができるところまで

 

ぐぬさんによるまとめ><
0. 事前準備
	・デプロイコマンドを先に準備する
 		・アプリ再起動、キャッシュ削除など
	・チェックリスト用意
	
 1. まずベンチマークを実行する
  →ベンチマークを実行して、スコアやログはコミット時点なのかも記録
		※MYSQLの設定、nginXの設定などもコミットするように
		※gitのタグを使ってスコアを記録するのもある

ーーベンチマーク重要ポイントーーーーーーーーー
 ・細かく書いて1コミットをする。
	・1コミットをして1ベンチぐらいが最高
	・ぶれる可能性がるので2、3回ぐらい実行する
	
	・測定すべき指標
	 ・CPU占有率の高いプロセスがいないか
			→htopをベンチ実行しながら確認
			
	 ・アクセスログにどんな記録がされているか
			→alpを利用、LTSVにする巣にぺっとを事前、思いエントポイントから直すAVG高いもの
			
	 ・データベースに発行されていないくりは何か
		・各種リソースはベンチマーク実行中どう使われているか
		 ・CPU、メモリ、帯域、IO
		
ーーーーーーーーーーーーーーーーーーーーーーー
		
 2. マニュアルを1時間見る、以下の項目確認
 ・採点ルール
 ・原点ルール
 ・ユーザーエージェントの確認
		※クローラ巡回拒否対策&検証方法
			https://qiita.com/comefigo/items/1e0265b342c4166ee8bf)
			
3. サーバーの状態を確認
 ・cpu確認:cat /proc/cpuinfo
 ・メモリ:free -h
 ・サービス:systemctl list-units --type=service --state=running

4. git管理
	・git init してgit add .&& git commit -m "initial state"
	
5. 開発
 ・アプリのログを残して、ボトルネックとかを解決

6. やれることがないへの対象(何をすればいいかわからないの時)
 ・スキーマ、アクセスローグ、メトリクス、マニュアルを読み直す
 ・計測をして情報量を増やす

7. 便利なツールを入れてみる
 ・netdata, New relic、pprof

8. 掃除しておく
 ・MySql再起動しておく
 ・便利なツールを外す(リソースを食う)
 ・最終ベンチに向けて、アプリに必要なもの以外をきちんと止められるように準備
 ・案外忘れられるRACK_ENVなどをちゃんと付ける

9. 他の人のスコアを見る
 ・解決できる部分をもっと調べる

0-1

  • 最初にレギュレーションを3人で
  • どんなアプリなのか。
  • alp アクセスログ、スロウクエリで遅いクエリ

 

  •  EC2
  • 評価スクリプト
  • 何が原因で加点なのか?減点なのか?
  • ルールの穴
    ・1秒で切れるようにキャッシュするようにするには?
  • ベンチマークしながら
    コミットの点数をまとめていく
    ・点数高いやつ
    ・対応できそうなやつ
  • EC2へデプロイする為のGitの構築
    ・GitLabにリポジトリ … 今日つくっておいて
    ・UbuntuとGitLab
  • Git + SSH + Stashとかでシミュレーション(金広)

alp

  • alp nginx
    調べておく  avg, countでcountが多くて
    sum(count * avg) = そうレスポンスタイム

 

決めること

  • チーム名(5分)
    ・ぐぬぬ!ぱんだちゃんハッカー(仮)
  • 戦術案(20分)
    Go言語
    ●担当
  • 当日までにやること(15分)
    ・ISUCON
    https://github.com/isucon/isucon8-qualify
    ・H2O
    ・Goフレームワーク
    ・gin(岡田)
    ・Echo(金広)
    ・go redis cache echo
    ・毎週チェック

 

 

下記は草案

 

最初にやること

  • アプリ全体をざっくり把握する
  • スコア評価スクリプトを叩く
  • スコア評価スクリプトが判定している内容を把握する
  • Google Chromeのデベロッパーツールや、Firefoxのネットワークによって遅いAPIの処理を見つける

 

キャッシュ is King

  • 値が変わらないキャッシュできるAPI
    NoSQL RedisによるCacheをする
  • 値の変更が発生するAPI
    ・更新時にRedisのCacheをクリアし、再度キャッシュする

GO

  • N^2になっているループ処理は修正する必要がある

 

GOインストール

Go Echo isconに向けたお勉強

VS Code プラグインチェック!

  • 補完
  • 関数ジャンプ

Go言語文法

金広はこれやってる

 

    • Go言語からRedisにレスポンス内容をキャッシュ、POSTでの更新時にパージする方法
    • 配列 … 要素数が固定  arr := [3]int{2, 3, 5}
    • スライス … 要素数が可変 sl := []int{2, 3, 5}
      ・append() … 要素を追加
      ・make() … スライスを作成
      ・len() … 要素数取得
      ・cap() … 要素数最大取得。容量以上の要素が追加された時にメモリを2倍取得してしまう。メモリを気にするプログラミングで使う。またメモリを過剰に取得すると速度も落ちるので速度パフォーマンスを重視する時に使う。

      	sl := []int{100, 200}
      	fmt.Println(sl) // [100 200]
      
      	sl = append(sl, 300)
      	fmt.Println(sl) // [100 200 300]
      
      	sl = append(sl, 400, 500, 600)
      	fmt.Println(sl) // [100 200 300 400 500 600]
      
      	sl2 := make([]int, 5) // 配列の作成
      	fmt.Println(sl2) // [0 0 0 0 0]
      	fmt.Println(len(sl2)) // 5 ... 要素数取得
      	fmt.Println(cap(sl2)) // 5 ... 容量 ... メモリを気にするような時に使う
      
      	sl3 := make([]int, 5, 10) // ... make([]T, 初期値で埋める要素数, 容量)
      	sl4 := append(sl3, 1, 2, 3, 4, 5, 6, 7)
      	fmt.Println(len(sl4)) // 12
      	fmt.Println(cap(sl4)) // 20
      

      ・range … GO言語にforeachがないのでforとrangeでforeachを実現

      	sl := []string{"Python", "PHP", "GO"}
      	for i, v := range sl {
      		fmt.Println(i, v)
      	}
      	/*
              0 Python
              1 PHP
              2 GO
      	*/
      

       

    • copy() … PHPのclone()
	sla := []string{"PHP", "GO"}
	slb := sla
	slb[0] = "Kotlin"
	fmt.Println(sla) // [Kotlin GO] ... PHPが上書きされてしまった

	sl := []int{1, 2, 3, 4, 5}
	sl2 := make([]int, 5, 10)
	n:= copy(sl2, sl) // sl2にslをコピーして代入。nにはコピーできた要素数が代入される
	fmt.Println(n, sl2) // 5 [1 2 3 4 5]
        • スプレッド演算子 […]
      func Sum(s ...int) int {
      	n := 0
      	for _, v := range s {
      		n += v
      	}
      	return n
      }
      
      func main() {
          fmt.Println(Sum(1, 2, 10)) // 13
      
      	sl := []int{4, 5}
      	fmt.Println(Sum(sl...)) // 9
      }
      
    • map … 連想配列  … m := map[string]int{“apple”: 100, “banana”: 160}
          m := map[string]int{"apple": 100, "banana": 200}
      	for k, v := range m {
      		fmt.Println(k, v)
      	}
      	/*
      	banana 200
          apple 100
      	*/
      
      	// 要素追加
      	fmt.Println(m["apple"]) // 100
      	m["grape"] = 400
      	fmt.Println(m) // map[apple:100 banana:200 grape:400]
      
      	// エラーハンドリング
      	_, ok := m["hoge"] // 変数okにはboolが入る。hogeというキーは存在しないのでfalseが代入
      	if !ok {
      		fmt.Println("error")
      	}
      	// error
      
    • for, range … foreach

      	sl := []string{"A", "B", "C"}
      	fmt.Println(sl) // [A B C]
      
      	for i := range sl {
      		fmt.Println(i)
              // 0
              // 1
              // 2
      	}
      	for i, v := range sl {
      		fmt.Println(i, v)
      		// 0 A
      		// 1 B
      		// 2 C
      	}
      	for i := 0; i < len(sl); i++ {
      		fmt.Println(sl[i])
      		// A
      		// B
      		// C
      	}
      
    • 型アサーション … 型の復元と評価
func main() {
	i := interface{}("hello1")
	s := i.(string)
	fmt.Println(s) // hello1

	// i2 := interface{}("hello2")
	// s2 := i2.(int)
	// fmt.Println(s2) // panic: interface conversion: interface {} is string, not int

	i3 := interface{}("hello3")
    n, ok := i3.(int) // 引数を2つ取ることでpanicを防止
    fmt.Println(n, ok) // 0 false ... panicにならない

    s3, ok := i3.(string)
    fmt.Println(s3, ok) // hello3 true

	var x interface{} = 3
	if x == nil {
		fmt.Println("None")
	} else if _, isInt := x.(int); isInt {
		fmt.Println(x, "x is Int")
	} else if s4, isString := x.(string); isString {
		fmt.Println(s4, "x is String")
	} else {
		fmt.Println("I don't know")
	}
	// 3 x is Int

	// switchで再現
	switch x.(type) {
	case int:
		fmt.Println(x, "x is Int")
	case string:
		fmt.Println(x, "x is String")
	default:
		fmt.Println("I don't know")
	}
	// 3 x is Int

	// switchで再現
	switch v5 := x.(type) {
	case int:
		fmt.Println(v5, "v5 is Int")
	case string:
		fmt.Println(v5, "v5 is String")
	default:
		fmt.Println("I don't know")
	}
	// 3 v5 is Int
}
    • defer() … 処理の最後に実行するもの ex.
func TestDefer() {
	defer fmt.Println("End")

	fmt.Println("Start")
}

func main() {
	TestDefer()

	defer func() {
		fmt.Println("1")
		fmt.Println("2")
		fmt.Println("3")
	}()
	// Start
	// End
	// 1
	// 2
	// 3
}

 

    • 実践的な例

 

package main

import (
	"fmt"
	"os"
)

func main() {
	file, err := os.Create("test.txt")
	if err != nil {
		fmt.Println(err)
	}
	defer file.Close() // 最後に実行される

	file.Write([]byte("Hello"))
}
      • エラーハンドリング … panic(), defer()
        func main() {
            defer func() {
        		if x := recover(); x != nil {
        			fmt.Println(x)
        		}
        	}()
        	panic("runtime error")
        	fmt.Println("Start")
        	// runtime error
        }
        
      • 平行処理 go routin
        package main
        
        import (
        	"fmt"
        	"time"
        )
        
        func sub() {
        	for {
        		fmt.Println("Sub Loop")
        		time.Sleep(100 * time.Millisecond)
        	}
        }
        
        func main() {
        	go sub()
        	go sub()
        
        	for {
        		fmt.Println("Main Loop")
        		time.Sleep(200 * time.Millisecond)
        	}
        }
        
      • 構造体 struct
    package main
    
    import "fmt"
    
    type User struct {
    	Name string
    	Age int
    	// X, Y int
    }
    
    // コピーに対して更新していて更新できない関数
    func UpdateUser(user User) {
    	user.Name = "A"
    	user.Age = 1000
    }
    
    // こう書く🐱
    func UpdateUser2(user *User) {
    	user.Name = "A"
    	user.Age = 1000
    }
    
    func main() {
    	var user1 User
    	fmt.Println(user1) // { 0}
    	user1.Name = "user1"
    	user1.Age = 10
    	fmt.Println(user1) // {user1 10}
    
    	user2 := User{}
    	fmt.Println(user2) // { 0}
    	user2.Name = "user2"
    	fmt.Println(user2) // {user2 0}
    
    	user3 := User{Name: "user3", Age: 30}
    	fmt.Println(user3) // {user3 30}
    
    	user4 := User{Name: "user4", Age: 40}
    	fmt.Println(user4) // {user4 40}
    
    	user7 := new(User)
    	fmt.Println(user7) // &{ 0} ... ポインタ型になる
    
    	// 🐱基本はこの書き方
    	user8 := &User{}
    	fmt.Println(user8) // &{ 0} ... ポインタ型になる
    
    	UpdateUser(user1)
    	fmt.Println(user1) // {user1 10} ... 変わらない
    	UpdateUser2(user8)
    	fmt.Println(user8) // &{A 1000} ... 更新することができている🐱
    }
    

    構造体 メソッド

     

    package main
    
    import "fmt"
    
    type User struct {
    	Name string
    	Age int
    	// X, Y int
    }
    
    func (u User) sayName() {
    	fmt.Println(u.Name)
    }
    
    // これだとコピーしたインスタンスのNameを更新していることになるので、更新できない
    func (u User) setName(name string) {
    	u.Name = name
    }
    
    // 🐱こう書く
    func (u *User) setName2(name string) {
    	u.Name = name
    }
    
    func main() {
    	user1 := &User{"user1", 999}
    	fmt.Println(user1) // &{user1 999}
    	user1.sayName() // user1
    
    	user1.setName("A")
    	user1.sayName() // user1 ... 変わってない
    	user1.setName2("B")
    	user1.sayName() // B ... 変わってる🐱
    }
    

    構造体 埋め込み

    package main
    
    import "fmt"
    
    type User struct {
    	Name string
    	Age int
    	// X, Y int
    }
    
    type T struct {
    	User User
    }
    
    type T2 struct {
    	User
    }
    
    func main() {
    	t := T{User: User{Name: "user1", Age: 10}}
    	fmt.Println(t) // {{user1 10}}
    	fmt.Println(t.User) // {user1 10}
    	fmt.Println(t.User.Name) // user1
    
    	t2 := T2{User: User{Name: "user1", Age: 10}}
    	fmt.Println(t2.User.Name) // user1
    }
    

    構造体 コンストラクタ

    package main
    
    import "fmt"
    
    type User struct {
    	Name string
    	Age int
    	// X, Y int
    }
    
    func (u User) sayName() {
    	fmt.Println(u.Name)
    }
    
    func NewUser(name string, age int) *User {
    	return &User{Name: name, Age: age}
    }
    
    func main() {
    	user1 := NewUser("user1", 999)
    	fmt.Println(user1) // &{user1 999}
    }
    
    • チャネル + go routin
package main

import (
	"fmt"
	"time"
)

func reciver(c chan int) {
	for {
		i := <-c
		fmt.Println(i)
	}
}

func main() {
	ch1 := make(chan int)
	ch2 := make(chan int)

	go reciver(ch1)
	go reciver(ch2)

	i := 0
	for i < 100 {
		ch1 <- i
		ch2 <- i
		time.Sleep(50 * time.Millisecond)
		i++
	}
}

 

    • チャネル + go routin + close
package main

import "fmt"

func reciver(c chan int) {

}

// func main() {
// 	ch1 := make(chan int, 2)

// 	close(ch1)
// 	ch1 <- 1 // panic: send on closed channel
// }

func main() {
    ch1 := make(chan int, 2)
	ch1 <- 1

	close(ch1)
	i, ok := <-ch1
	fmt.Println(i, ok)
    // 1 true
	i2, ok := <-ch1
	fmt.Println(i2, ok)
	// 0 false
}

 

          • 応用
          package main
          
          import (
          	"fmt"
          	"time"
          )
          
          func reciver(name string, ch chan int) {
          	for {
          		i, ok := <-ch
          		if !ok {
          			break
          		}
          		fmt.Println(name, i)
          	}
          	fmt.Println(name, "End")
          }
          
          func main() {
              ch1 := make(chan int, 2)
          	ch1 <- 1
          
          	go reciver("1.goroutin", ch1)
          	go reciver("2.goroutin", ch1)
          	go reciver("3.goroutin", ch1)
          
          	i := 0
          	for i < 100 {
          		ch1 <- i
          		i++
          	}
          	close(ch1)
          	time.Sleep(3 * time.Second)
          
          	// 3.goroutin 1
          	// 2.goroutin 1
          	// 1.goroutin 0
          	// 1.goroutin 4
          	// 1.goroutin 5
          	// 1.goroutin 6
          	// 2.goroutin 3
          
          	// (略)
          
          	// 1.goroutin 83
          	// 1.goroutin 84
          	// 1.goroutin 85
          	// 1.goroutin 86
          	// 1.goroutin 87
          	// 1.goroutin 88
          	// 2.goroutin 69
          	// 3.goroutin 82
          	// 3.goroutin 90
          	// 3.goroutin 92
          	// 3.goroutin 93
          	// 3.goroutin 94
          	// 1.goroutin 89
          	// 1.goroutin 96
          	// 2.goroutin 91
          	// 2.goroutin 98
          	// 2.goroutin 99
          	// End 2.goroutin
          	// 1.goroutin 97
          	// End 1.goroutin
          	// 3.goroutin 95
          	// End 3.goroutin
          }
          

          チャネル + go routin + for

          package main
          
          import "fmt"
          
          func main() {
              ch1 := make(chan int, 3)
          	ch1 <- 1
          	ch1 <- 2
          	ch1 <- 3
          	close(ch1)
          	for i := range ch1 {
          		fmt.Println(i)
          	}
          
          	// 1
          	// 2
          	// 3
          }
          

          チャンネル + select その1

      package main
      
      import "fmt"
      
      func main() {
      	ch1 := make(chan int, 2)
      	ch2 := make(chan string, 2)
      
      	ch2 <- "A"
      
      	select {
      	case v1 := <-ch1:
      		fmt.Println(v1 + 1000)
      	case v2 := <-ch2:
      		fmt.Println(v2 + "!?")
      	}
      	// A!?
      }
      

      その2

      func main() {
      	ch1 := make(chan int, 2)
      	ch2 := make(chan string, 2)
      
      	ch2 <- "A"
      	ch1 <- 1
      	ch2 <- "B"
      	ch1 <- 2
      
      	select {
      	case v1 := <-ch1:
      		fmt.Println(v1 + 1000)
      	case v2 := <-ch2:
      		fmt.Println(v2 + "!?")
      	}
      	// ランダムになる
      	// kanehiroyuu@MacBook-Pro-2 golang-webgosql % go run channelSelect.go
      	// A!?
      	// kanehiroyuu@MacBook-Pro-2 golang-webgosql % go run channelSelect.go
      	// A!?
      	// kanehiroyuu@MacBook-Pro-2 golang-webgosql % go run channelSelect.go
      	// 1001
      	// kanehiroyuu@MacBook-Pro-2 golang-webgosql % go run channelSelect.go
      	// 1001
      	// kanehiroyuu@MacBook-Pro-2 golang-webgosql % go run channelSelect.go
      	// A!?
      }
      

      その3

      package main
      
      import "fmt"
      
      func main() {
      	ch3 := make(chan int,)
      	ch4 := make(chan int)
      	ch5 := make(chan int)
      
      	// reciever
      	go func() {
      		for {
      			i := <-ch3
      			ch4 <- i * 2
      		}
      	}()
      
      	go func() {
      		for {
      			i2 := <-ch4
      			ch5 <- i2 -1
      		}
      	}()
      
      	n := 0
      L:
      	for {
      		select {
      		case ch3 <- n:
      			n++
      		case i3 := <-ch5:
      			fmt.Println("recieved", i3)
      	    default:
      		    if n > 100 {
      			    break L
      			}
      		}
      	}
      }
      
      // kanehiroyuu@MacBook-Pro-2 golang-webgosql % go run channelSelect2.go
      // recieved -1
      // recieved 1
      // recieved 3
      // recieved 5
      // recieved 7
      // recieved 9
      // recieved 11
      // recieved 13
      // recieved 15
      // ...
      // recieved 183
      // recieved 185
      // recieved 187
      // recieved 189
      // recieved 191
      // recieved 193
      // recieved 195
      // recieved 197
      
    • ポインタ
package main

import "fmt"

func Double(i int) {
	i = i * 2
}

func Doublev2(i *int) {
	*i = *i * 2
}

func Doublev3(s []int) {
	for i, v := range s {
		s[i] = v * 2
	}
}

func main() {
	var n int = 100
	fmt.Println(n) // 100
	fmt.Println(&n) // 0xc00012a008

	Double(n)
	fmt.Println(n) // 100

	var p *int = &n // &変数 ... ポインタ
	fmt.Println(p) // 0xc000132008
	fmt.Println(*p) // 100 ... *をつけると実体

	*p = 300 // *pで実体を指定して代入
	fmt.Println(n) // 300
	n = 200
	fmt.Println(*p) // 200

	Doublev2(&n)
	fmt.Println(n) // 400

	// スライスは参照型なので関数先で自動的に値が参照渡しされてる
	var sl []int = []int{1, 2, 3}
	Doublev3(sl)
	fmt.Println(sl) // [2 4 6]
}
    • CRUD操作 … 掲示板アプリなどで
    • JSON操作
    • フレームワーク
      Echoの可能性が高い

      新卒2年目がGo言語に挑戦してみた!


      フレームワークなしって可能性もある

    • Redisにレスポンスキャッシュ, 更新時にキャッシュクリア & キャッシュ
    • init() … main()より先に呼ばれる関数
package main

import (
	"fmt"
)

func init() {
	fmt.Println("init()")
}

func main() {
	fmt.Println("main()")
	// init()
	// main()
}
  • ジョブ・キュー

 

ミドルウェア側のチューニング

  • 画像やCSSといった静的ファイルの圧縮
  • メモリの最適化
  • プロセス、CPUといったパラメータチューニング
  • MySQLのINDEXを貼る

 

 

 

Nginx

ルールが参照系だけの場合

  • 可能な限りHTTPレスポンスはNginx側でキャッシュする
    キャッシュ is キング。
  • ログインが存在するアプリの場合
    ・ページキャッシュ
     ・セッションキーがある場合はキャッシュしないようにする
     ・おそらくルール上利用は難しい
    ・オブジェクトキャッシュ
    ・RedisによるNoSQL実装をする必要がある
  • http2の利用
    ・listen 443 ssl http2;
    ・listen 80 http2;
  • CPU設定 autoで自動設定
    worker_processes
    auto;

 

  • https://worklog.be/archives/3222#cache_pathconf
  • https://www.linuxcapable.com/set-up-nginx-fastcgi-cache-on-ubuntu-20-04/
user www www;
pid /var/run/nginx.pid;
 
## auto を指定すれば最大限利用できる CPU コア数を勝手に設定してくれる
## 指定したいならサーバの CPU コア数以下で設定する
worker_processes auto;
worker_rlimit_nofile 4096;
 
events {
    use epoll;
    multi_accept on;
    worker_connections 1024;
}
 
http {
 
    include mime.types;
    default_type text/plain;
 
    charset            utf-8;
    sendfile           on;
    tcp_nopush         on;
    tcp_nodelay        on;
    server_tokens      off;
    keepalive_requests 100;
    keepalive_timeout  3;
 
    server_names_hash_bucket_size 64;
    types_hash_max_size 2048;
    client_body_buffer_size 64k;
    client_body_temp_path /home/www/tmp/client_body_temp 1 2;
 
    ## gzip圧縮を有効化
    gzip            on;
    gzip_vary       on;
    gzip_proxied    any;
    gzip_comp_level 6;
    gzip_types      text/plain text/css text/xml text/javascript
                    application/json application/javascript application/x-javascript
                    application/xml application/rss+xml application/atom+xml
                    image/svg+xml;
 
    ## SSL周り
    ssl_session_timeout 30m;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_tickets off;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256;
 
    ## fastcgi
    fastcgi_buffers         8 64k;
    fastcgi_buffer_size     64k;
    fastcgi_connect_timeout 60;
    fastcgi_send_timeout    60;
    fastcgi_read_timeout    300;
 
    ## proxy (WordPressだけだったらここは不要)
    proxy_connect_timeout 60;
    proxy_send_timeout    60;
    proxy_read_timeout    120;
    proxy_http_version    1.1;
    proxy_cache_bypass    $http_upgrade;
    proxy_set_header      Upgrade            $http_upgrade;
    proxy_set_header      Connection         "upgrade";
    proxy_set_header      Host               $host;
    proxy_set_header      X-Real-IP          $remote_addr;
    proxy_set_header      X-Forwarded-Host   $host;
    proxy_set_header      X-Forwarded-Server $host;
    proxy_set_header      X-Forwarded-For    $proxy_add_x_forwarded_for;
    proxy_set_header      X-Forwarded-Proto  $scheme;
    proxy_set_header      X-Forwarded-Port   $server_port;
    proxy_temp_path       /home/www/tmp;
 
    ## cache_pathについては別ファイルで設定する
    include conf.d/cache_path.conf;
 
 
## デフォルトのサーバ
server {
 
    listen *:80 default_server;
    root   /home/www/htdocs;
 
    access_log /var/log/nginx-access.log combined;
    error_log  /var/log/nginx-error.log warn;
 
    index index.html;
    include conf.d/common.conf;
 
}
 
    ## バーチャルドメインの設定
    include conf.d/virtual.conf;
 
}

 

 

MySQL

  • INDEXを貼る
    ・WHERE = {キー}
    ・ORDER BY {キー}
    このキーに対してINDEXを貼る
  • EXPLAINによるALL解析EXPLAIN SELECT  xxxx

 

mysql > EXPLAIN select * from sampledb.sampletable ;

typeにALLやindexがあったらINDEXを貼った方が良い。

indexの場合は、

typeがrefになるようにwhereの位置など変更してINDEXが効くようにクエリを改良する。

ただし、

一覧など全データを取ってきてという処理であれば、ALLは仕様がない場合もある。

 

  • innodb_buffer_pool_size … GOの処理に割り当てる以外のメモリの8割はここに充てる
  • query_cache_size=64M

 

 

 

Amazonおすすめ

iPad 9世代 2021年最新作

iPad 9世代出たから買い替え。安いぞ!🐱 初めてならiPad。Kindleを外で見るならiPad mini。ほとんどの人には通常のiPadをおすすめします><

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)