ニクニクドットミー

カッコいいおっさんを目指すエンジニアの厳かなブログ

Goでtoml.DecodeFileしたときにハマったことメモ

182b65b9 539c 4d24 9b1f ee4a1a8756f1 TOMLという設定ファイルの為のミニ言語があり、それをGoで試してみた所、うまく読み込まれずにハマってしまったので、メモ。

config_test.go


package main

import (
    "github.com/BurntSushi/toml"
    "testing"
    "fmt"
)

type ConfToml struct {
    Keys SectionKeys `toml:"keys"`
}

type SectionKeys struct {
    Consumer_key string `toml:"consumer_key"`
    access_token string `toml:"access_token"`
}

// config の read
func readSettingsConfig(path string, config *ConfToml) {
    _, err := toml.DecodeFile(path, config)
    if err != nil {
        panic(err)
    }
}

func Test_readSettingsConfg(t *testing.T) {
    var conftoml ConfToml

    _, err := toml.DecodeFile("config.toml", &conftoml) 
    if err != nil {
        panic(err)
    }
    
    fmt.Println(conftoml.Keys)

    // Printlnする為に、あえてerrorにしている。
    if conftoml.Keys.Consumer_key != "aab" {
        t.Error("Not Match")
    }
    if conftoml.Keys.Consumer_key != "bbb" {
        t.Error("Not Match")
    }

}

config.toml


[keys]
consumer_key = "aaa"
access_token = "bbb"

実行結果


{aaa }
--- FAIL: Test_readSettingsConfg (0.00s)
        config_test.go:38: Not Match
        config_test.go:41: Not Match
FAIL
FAIL    command-line-arguments  0.005s

この太字にしたところがポイントで、これはtomlファイルを読み込んだ構造体をPrintlnしているのですが、aaaという値だけ格納されている状態です。 本来ならば、{aaa bbb}となるはずです。


type SectionKeys struct {
    Consumer_key string `toml:"consumer_key"`
    access_token string `toml:"access_token"`
}

このSectionKesyという構造体のフィールド名が小文字と大文字で違っているのが原因です。 どうやらDecodeFileはフィールド名が小文字だと値が設定されないようです。 ※Access_tokenと大文字で設定すると正しく値は設定されました。

恐らくですが、github.com/BurntSushi/tomlパッケージ外の構造体へのアクセス権限がない(エクスポートできない)のが原因かと思っています。 値が設定されず、やだな〜やだな〜こわいなーこわいな〜とハマっておりました。

謝った認識かもしれませんので、ご指導ご鞭撻のほどよろしくお願いします。

参考サイト

【個人メモ】設定ファイルフォーマットにはTOMLがいいのかも Go言語での構造体実装パターン

【AWS】ElastiCacheRedisをMulti-AZ構成にするとAOFの設定ができないっぽい?

Redis 今日はElastiCacheRedisを触ることが多かったので、本日二回目のElastiCacheのメモ。

ElastiCacheRedisがMulti-AZ対応したので、Multi-AZ構成でクラスタを作成していたのですが、 なんとParameterGroupでappendonly yesにしたgroupを設定するとエラーとなってしまうのです!ドン!(多分だけど。。。)


Cannot have redis persistence(appendonly) and Multi-AZ both on

ちなみにこんなエラー。

どうやら同じエラーになった方がいたようで、こちらの記事を参考にさせて頂きました。 [AWS]マルチAZなElastiCache Redisの永続性についてメモ

実は今年の一月ぐらいに他のインスタンスで同じMulti-AZ構成にしたクラスタがあったのですが、そちらはなんとAOFの設定が出来ているのです!(さらに深まる謎)

結局のところ

埒が明かないので、AOFの設定無しのParameterGroupを設定したところ、クラスタの作成が問題なく出来ました。 参考にさせて頂いた記事にありましたが、Multi-AZではインスタンスが死んだら、そのインスタンスは破棄するので、AOFを残す意味がないから?という仮説を立てられておりました。 自分もその意見には納得です。

だれかご存知の方いますかーーーーー?

追記 2015/02/18 この件についてAWSに問い合わせしたところ早速回答がきました! Multi-AZ構成でAOF設定は出来ない仕様 さらに英語のみですが、ドキュメントに記載されているとのこと。  - Best Practices for Implementing Amazon ElastiCache / Mitigating Out-of-Disk-Space Issues When Using AOF  http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/BestPractices.html#BestPractices.FaultTolerance

Enabling Redis Multi-AZ as a Better Approach to Fault Tolerance  If you are enabling AOF to protect against data loss, consider using a replication group with Multi-AZ enabled instead of AOF. In any Redis replication group, if a replica fails, it is automatically replaced and synchronized with the primary cluster. If Multi-AZ is enabled on a Redis replication group and the primary fails, it fails over to a read replica. This functionality is much faster than rebuilding the primary from an AOF file. For maximum fault tolerance, even against a hardware fault in an underlying physical server, launch your primary and replica clusters in different Availability Zones. Because there is no need for AOF in this scenario, you do not risk running out of disk space. AOF ですがローカルディスクに書き込みを行う都合上、物理的な障害には対応できません。また、ディスクに書き込みを行う都合上、更新が非常に多いとローカルディスクを使い切り書き込みができなくなる事例も報告されております。この影響を回避するため、ベストプラクティスとしては AOF ではなく Multi-AZ 構成によって耐障害性を考慮頂くことをお勧めしております。 Multi-AZ 構成により十分な耐障害性が確保できることから、ElastiCache の仕様としては AOF との併用ができないような仕様となっております。

やはりMulti-AZになったことでAOFファイルつくる必要がないという判断のようです。

早急に連絡くれたサポートに感謝!

【AWS】S3のrdbファイルからElastiCache Redisを作成する時の些細な注意点

Redis S3にアップしたrdbファイルからElastiCacheを作成することってよくありますよね。ありますよね。

僕は今回初めて対応しましたが、たった些細な設定が漏れていた為、大ハマりしました。お世話になりました。

ドキュメント

バックアップと復元の管理 (Redis)

RDB ファイルへの読み込みアクセスを ElastiCache に許可 次のステップでは、Amazon S3 にコピーしておいたスナップショットファイルへの読み込みアクセスを ElastiCache に許可します。 Amazon S3 にコピーしておいたスナップショットへの読み込みアクセスを ElastiCache に許可するには AWS Management Console にサインインして Amazon S3 コンソールを開きます(https://console.aws.amazon.com/s3)。 [All Buckets] をクリックし、RDB ファイルを含む Amazon S3 バケットの名前をクリックします。 RDB ファイルを含むフォルダの名前をクリックします。 RDB ファイルの名前をクリックし、[Actions] ドロップダウンメニューをクリックして [Properties] を選択します。 [Permissions] をクリックして [Add more permissions] をクリックします。 [Grantee] ボックスに、E メールアドレスaws-scs-s3-readonly@amazon.comを入力します。 [Open/Download] をクリックし、[Save] をクリックします。 Note aws-scs-s3-readonly@amazon.com アカウントは、Amazon S3 から Redis スナップショットデータをアップロードするお客様だけが使用します。

aws-scs-s3-readonly@amazon.comを許可

はい。これを許可してなかったので、No permission to access S3ってエラーになってましたとさ。

ドキュメント大事。

(ってかこれハマる人結構いるんじゃね)

GOTRACEBACKのメモ

182b65b9 539c 4d24 9b1f ee4a1a8756f1

GOTRACEBACKという環境変数があり、それを設定することによって、go runしたときのプログラムのトレースバックが変わるようです。

The GOTRACEBACK variable controls the amount of output generated when a Go program fails due to an unrecovered panic or an unexpected runtime condition. By default, a failure prints a stack trace for every extant goroutine, eliding functions internal to the run-time system, and then exits with exit code 2. If GOTRACEBACK=0, the per-goroutine stack traces are omitted entirely. If GOTRACEBACK=1, the default behavior is used. If GOTRACEBACK=2, the per-goroutine stack traces include run-time functions. If GOTRACEBACK=crash, the per-goroutine stack traces include run-time functions, and if possible the program crashes in an operating-specific manner instead of exiting. For example, on Unix systems, the program raises SIGABRT to trigger a core dump.

Google先生で翻訳したところ、

GOTRACEBACK = 0は、単位のゴルーチンスタックトレースが完全に省略している場合は終了コード2で終了します。

GOTRACEBACK = 1の場合、デフォルトの動作が使用されます。

GOTRACEBACK = 2場合は、単位のゴルーチンスタックトレースは、実行時の機能が含まれます。

以下のサンプルコードで試してみました。


package main


import (
        "log"
        "runtime"
)

func main(){
        log.Println(runtime.NumGoroutine()) //動いているゴルーチンの数
        select{}
}

GOTRACEBACK=0


[root@localhost vagrant]# GOTRACEBACK=0 go run sample.go
2015/02/12 13:39:00 4
fatal error: all goroutines are asleep - deadlock!
exit status 2

終了ステータスコードとエラーメッセージが出力されます。

GOTRACEBACK=1


[root@localhost vagrant]# GOTRACEBACK=1 go run sample.go
2015/02/12 13:40:02 4
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [select (no cases)]:
main.main()
    /vagrant/sample.go:11 +0xd5
exit status 2

終了ステータスコードとどの行でエラーになったか出力されます。

GOTRACEBACK=2


[root@localhost vagrant]# GOTRACEBACK=2 go run sample.go
2015/02/12 13:40:17 4
fatal error: all goroutines are asleep - deadlock!

runtime stack:
runtime.throw(0x54f7e3)
    /usr/local/go/src/runtime/panic.go:491 +0xad fp=0x7fff416d3b58 sp=0x7fff416d3b28
checkdead()
    /usr/local/go/src/runtime/proc.c:2854 +0x1f8 fp=0x7fff416d3ba8 sp=0x7fff416d3b58
mput(0x551e40)
    /usr/local/go/src/runtime/proc.c:3175 +0x47 fp=0x7fff416d3bb0 sp=0x7fff416d3ba8
stopm()
    /usr/local/go/src/runtime/proc.c:1176 +0xea fp=0x7fff416d3bd0 sp=0x7fff416d3bb0
findrunnable(0xc208012000)
    /usr/local/go/src/runtime/proc.c:1487 +0x562 fp=0x7fff416d3c08 sp=0x7fff416d3bd0
schedule()
    /usr/local/go/src/runtime/proc.c:1575 +0x151 fp=0x7fff416d3c38 sp=0x7fff416d3c08
runtime.park_m(0xc2080006c0)
    /usr/local/go/src/runtime/proc.c:1654 +0x113 fp=0x7fff416d3c60 sp=0x7fff416d3c38
runtime.mcall(0x42d204)
    /usr/local/go/src/runtime/asm_amd64.s:186 +0x5a fp=0x7fff416d3c70 sp=0x7fff416d3c60

goroutine 1 [select (no cases)]:
runtime.gopark(0x0, 0x0, 0x4ef830, 0x11)
    /usr/local/go/src/runtime/proc.go:130 +0x105 fp=0xc20802df08 sp=0xc20802ded8
runtime.block()
    /usr/local/go/src/runtime/select.go:176 +0x46 fp=0xc20802df30 sp=0xc20802df08
main.main()
    /vagrant/sample.go:11 +0xd5 fp=0xc20802df98 sp=0xc20802df30
runtime.main()
    /usr/local/go/src/runtime/proc.go:63 +0xf3 fp=0xc20802dfe0 sp=0xc20802df98
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc20802dfe8 sp=0xc20802dfe0

goroutine 2 [force gc (idle)]:
runtime.gopark(0x42edb0, 0x5516e0, 0x4e49d0, 0xf)
    /usr/local/go/src/runtime/proc.go:130 +0x105 fp=0xc20801a798 sp=0xc20801a768
runtime.goparkunlock(0x5516e0, 0x4e49d0, 0xf)
    /usr/local/go/src/runtime/proc.go:136 +0x48 fp=0xc20801a7c0 sp=0xc20801a798
runtime.forcegchelper()
    /usr/local/go/src/runtime/proc.go:99 +0xce fp=0xc20801a7e0 sp=0xc20801a7c0
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc20801a7e8 sp=0xc20801a7e0
created by runtime.init·4
    /usr/local/go/src/runtime/proc.go:87 +0x25

goroutine 3 [GC sweep wait]:
runtime.gopark(0x42edb0, 0x558978, 0x4e21f0, 0xd)
    /usr/local/go/src/runtime/proc.go:130 +0x105 fp=0xc20801df98 sp=0xc20801df68
runtime.goparkunlock(0x558978, 0x4e21f0, 0xd)
    /usr/local/go/src/runtime/proc.go:136 +0x48 fp=0xc20801dfc0 sp=0xc20801df98
runtime.bgsweep()
    /usr/local/go/src/runtime/mgc0.go:98 +0xbc fp=0xc20801dfe0 sp=0xc20801dfc0
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc20801dfe8 sp=0xc20801dfe0
created by gc
    /usr/local/go/src/runtime/mgc0.c:1383

goroutine 4 [finalizer wait]:
runtime.gopark(0x42edb0, 0x558970, 0x4e4550, 0xe)
    /usr/local/go/src/runtime/proc.go:130 +0x105 fp=0xc208019730 sp=0xc208019700
runtime.goparkunlock(0x558970, 0x4e4550, 0xe)
    /usr/local/go/src/runtime/proc.go:136 +0x48 fp=0xc208019758 sp=0xc208019730
runtime.runfinq()
    /usr/local/go/src/runtime/malloc.go:727 +0xba fp=0xc2080197e0 sp=0xc208019758
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc2080197e8 sp=0xc2080197e0
created by runtime.createfing
    /usr/local/go/src/runtime/malloc.go:707 +0x5e
exit status 2

長いです。終了ステータスコードと他に動いてるゴルーチンが出力されます。

こう思った

GOTRACEBACK=2で他のゴルーチンがわかるのは便利かも。 なぜall goroutines are asleep - deadlock!となるのかは謎。。。

GoをCentOS-6.5に入れてみた!

182b65b9 539c 4d24 9b1f ee4a1a8756f1 Goで生きていくと決めて数時間経ちました。皆さんいかがお過ごしでしょうか。

つい先日行われたdotssummit 2015でたくさんのスタートアップ企業がプレゼンを行いました。

多くのスタートアップが、Goへ舵を切り始めているのが印象的でした。

  1. パフォーマンスがいい
  2. 単一バイナリなので管理が楽
  3. 並立処理が簡単

gunosyではappサーバはGoで動いていて、ピーク時のレスポンスタイムは30msだそうです。はやい。

メルカリは部分的にGoを使っていて、発表者の久保さん@cubicdaiyaのGo使いぶりが凄まじく、「めっちゃかっこいいな」と思い、Goで生きて行こうと決めたのでした。なので、数時間というか2日くらい経ってます。

Go自体はMacに入れていたのですが、昨日Vagrant Cloudを試していて作ったCentOS-6.5の環境があるので、そちらに改めて入れてみました。

Goのダウンロード


cd /usr/local/src

wget --no-check-certificate https://storage.googleapis.com/golang/go1.4.1.linux-amd64.tar.gz

tar zxvf go1.4.1.linux-amd64.tar.gz

でGoがダウンロード出来ましたので、PATHが通っている所に設置します。 シンボリックリンクを張ってみました。


ln -s /usr/local/src/go/bin/go /usr/bin/go

GOPATH,GOROOTを設定

.bash_profileに以下を書きます。


export GOROOT=/usr/local/src/go
export GOPATH=$HOME/go/bin
export GOPATH=$HOME/go
export PATH=$PATH:$GOROOT
export PATH=$PATH:$GOPATH
export PATH=$PATH:$GOPATH/bin

※追記 GOPATHの指定が誤っていました。binまで付けてしまうとgo getした際に/bin/bin/とbin以下にさらにbinディレクトリを作ってしまう為、PATHが通らなくなってしまいます。 GOROOTはGoを設置してるディレクトリを指定します。 GOPATHはgo getしたときに格納されるディレクトリになります。

ちなみにGOPATHを設定しないまま、go getすると怒られます。

package github.com/cubicdaiya/nginx-build: cannot download, $GOPATH not set. For more details see: go help gopath

GOPATHについて詳しく説明してくれている記事がありましたので、引用。

GOPATH には2つ役割があります。 ビルド時のインポートパスとして、GOPATH に指定したすべてのディレクトリを参照する(コロン区切り) go get コマンドで外部パッケージを読み込んだ時、 GOPATH の先頭のディレクトリにダウンロードする そして、公式ドキュメントにもありますが、Goで自分のプロジェクトを書く時にも、このGOPATHの下で書くのが良いとされています。 例えば、自分が githubソースコードを管理していて、ユーザー名が foo、リポジトリが bar だったら $GOPATH/src/github.com/foo/bar というディレクトリを作ってそこで作業します。

ここまでくればGoは動くはずです。


$ go version
go version go1.4.1 linux/amd64

go getしてみる

せっかくなので、go getしてモジュールを手に入れましょう。 dotssummitで衝撃だった@cubicdaiyaさんのnginx-buildを入れてみます。 nginx-buildでnginxをビルドしよう


go get -u github.com/cubicdaiya/nginx-build

mkdir -p ~/opt/nginx
nginx-build -d ~/opt/nginx
cd ~/opt/nginx/1.7.9/nginx-1.7.9
sudo make install
objs/nginx -v

無事インストールされました! ※途中make installする必要がありました。

参考

これからGoを始める人のためのTips集

こう思った

Goの時代が来てます。Goはバイナリを配るだけですぐ使えるので、インフラエンジニアにもってこいな言語です。 ポインタの概念があるので、そこはしっかり覚えないといけませんが、その分効率的なプログラムが書けると思います。 Goで生きて行けるようにがんばるゾ!

Vagrant Cloudからbox追加する

Vagrant

Vagrant Cloudというboxが集まっている?サイトがvagrant 1.5の公開と合わせて出ていたようです。

自分が気づいたのは最近のことで、ちょっと使ってみたいと思います。

Vagrant Cloudを使うにあたってユーザー登録が必要なので、済ませておきましょう。

vagrant loginを実行する


~/l/v/nginx-lab ❯❯❯ vagrant -v
Vagrant 1.7.2

versionは1.5以降であればOK!


~/l/v/nginx-lab ❯❯❯ vagrant plugin list
vagrant-share (1.1.3, system)

pluginはshareがデフォルトで入っているようです。


~/l/v/nginx-lab ❯❯❯ vagrant login
In a moment we will ask for your username and password to HashiCorp's
Atlas. After authenticating, we will store an access token locally on
disk. Your login details will be transmitted over a secure connection, and
are never stored on disk locally.

If you do not have an Atlas account, sign up at
https://atlas.hashicorp.com.

Atlas Username: maaaato
Password (will be hidden):
You are now logged in.

Vagrant Cloudに登録したユーザ情報を入力。 login成功!

vagrant cloudからbox追加


~/l/v/nginx-lab ❯❯❯ vagrant box add chef/centos-6.5
==> box: Loading metadata for box 'chef/centos-6.5'
    box: URL: https://atlas.hashicorp.com/chef/centos-6.5
This box can work with multiple providers! The providers that it
can work with are listed below. Please review the list and choose
the provider you will be working with.

1) virtualbox
2) vmware_desktop

Enter your choice: 1
==> box: Adding box 'chef/centos-6.5' (v1.0.0) for provider: virtualbox
    box: Downloading: https://vagrantcloud.com/chef/boxes/centos-6.5/versions/1.0.0/providers/virtualbox.box
==> box: Successfully added box 'chef/centos-6.5' (v1.0.0) for 'virtualbox'!


~/l/v/nginx-lab ❯❯❯ vagrant box list                                                                                                                                               ⏎
chef/centos-6.5 (virtualbox, 1.0.0)

vagrantの起動

Vagrant initしていればVagrantfileがあるので、以下の様に修正。


config.vm.box = "chef/centos-6.5"


~/l/v/nginx-lab ❯❯❯ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'chef/centos-6.5'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'chef/centos-6.5' is up to date...
==> default: Setting the name of the VM: nginx-lab_default_1423404350975_49918
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 => 2222 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Connection timeout. Retrying...
    default:
    default: Vagrant insecure key detected. Vagrant will automatically replace
    default: this with a newly generated keypair for better security.
    default:
    default: Inserting generated public key within guest...
    default: Removing insecure key from the guest if its present...
    default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: Mounting shared folders...
    default: /vagrant => /Users/masayuki.nakano/lab/vagrant-project/nginx-lab

Checking if box 'chef/centos-6.5' is up to date...

vagrant cloud上のboxに変更があったら取り込んでくれるみたいです。


~/l/v/nginx-lab ❯❯❯ vagrant ssh
Last login: Fri Mar  7 16:57:20 2014 from 10.0.2.2
[vagrant@localhost ~]$

無事sshで接続できました!

注意点

vagrant 1.5からbox追加の仕様が変わりました。


vagrant box add <box-name> <url>
vagrant box add centos-6.5 chef/centos-6.5


vagrant box add <box-name>
vagrant box add --name sl6-64 http://lyte.id.au/vagrant/sl6-64-lyte.box

参考

vagrantのboxをvagrant cloudからもらってくる

こう思った

Vagrant Cloudでbox追加が楽になったと感じました。 一方でユーザ登録はちょっとめんどいなと感じますが、vagrant cloud上にあるboxの信頼性が上がったのかなと思います。 (変なboxが上がっていないという意味で)

apache preforkパラメータについてのメモ

Apache log

前回、apacheのMaxRequestsPerChildを検証してみたというタイトルで、MaxRequestsPerChildを軽く試してみました。

他にもいくつかパラメータがありましたので、それらの意味をメモっておきます。


<IfModule prefork.c>
StartServers       5
MinSpareServers    5
MaxSpareServers    5
ServerLimit        5
MaxClients         5
MaxRequestsPerChild  5
</IfModule>



パラメータ 説明 補足
StartServers 起動時に生成される子サーバプロセスの数 StartServers ディレクティブは、 起動時に生成される子サーバプロセスの数を設定します。 プロセス数は負荷に応じて動的に制御されますので、 通常はこの値を調整する理由はあまりないでしょう。
MinSpareServers 待機時の最小子プロセス数 子プロセスがMinSpareServersより少なくなったら、この値まで子プロセスを上げます
MaxSpareServers 待機時の最大子プロセス数 子プロセスがMaxSpareServersより大きくなったら、この値まで子プロセスを下げます
ServerLimit 設定可能なサーバプロセス数の上限 MaxClientsを256以上に設定したい場合はServerLimitも設定する必要があります。また、 MaxClientsの上に書かないと効きません
prefork MPM の場合は、このディレクティブは Apache プロセス稼働中における MaxClients に設定可能な上限値を設定することになります
MaxClients リクエストに応答するために作成される 子プロセスの最大個数 MaxClients ディレクティブは、 応答することのできる同時リクエスト数を設定します。 MaxClients 制限数を越えるコネクションは通常、 ListenBacklog ディレクティブで設定した数までキューに入ります。 他のリクエストの最後まで達して子プロセスが空くと、 次のコネクションに応答します。
スレッドを用いないサーバ (すなわち prefork) では、MaxClients は、リクエストに応答するために起動される 子プロセスの最大数となります。 デフォルト値は 256 で、これを増加させたい場合は、 ServerLimit の値も増加させる必要があります

※いまの設定値はダミーで設定してます。 またこれらのパラメータの値は揃えた方がいいです。 理由は、forkは重い処理なので、出来るだけforkさせない為です。 とても分かりやすく説明してくれている記事がありましたので、記載しておきます。 プロのサーバ管理者がApacheのStartServers, (Min|Max)SpareServers, MaxClientsを同じにする理由

こう思った

前回はMaxRequestsPerChildを調べましたが、他にもたくさんあったので、調べてみました。 基本はすべての値(RequestsPerChild以外)は揃えるのがベターのようです。 WEBサービスボトルネックなるのはDBが多いと思うので、apacheのチューニングはあまり無いような気がしてます。 でもチューニングできるとカッコイイと思うので、する機会あればしてみたいと思います。

参考 ・httpd.confについて調べたのでまとめたよ