2012年12月23日日曜日

負荷対策・負荷分散の勉強会に行ってきた

2012年12月20日(木) に渋谷 ヒカリエで行われた負荷分散の勉強会に行って来ました。
そのメモです。

勉強会の募集ページはこちら。
好評で超満員だったので、第2回が開催されるそうです。
【負荷対策・負荷分散】勉強会!! ~原因究明から、対処法、実例発表まで~ ロードバランサ、DBチューニング、NoSQLと幅広くお話します!

以下メモ。
----------------------------------------

自社のサービスで、リスティング広告のレポートをまとめるのが主な負荷。
サーバの基本構成は。CentOS + Apache + PHP + MySQL。
そこに追加するのが、Memcached。


----------------------------------------

■MySQL
MyISAM でやってたけど、テーブル単位でロックされるから管理画面の表示ができない!
→InnoDB に変更して解消。なお、InnoDB は行単位でロックする仕組み。

でも、InnoDB には罠が!
ログファイルが膨大になって、レコードを DELETE してもログが更新されない。
→ ibdata をテーブル単位にして解消。
=> innodb_file_per_table

さらに、ログファイルのサイズやログのファイル数を設定して使いやすく。
→ innodb_log_file_size = 1364M
→ 
innodb_log_files_in_group = 3

なぜ、ログファイルが膨大になって問題になったのか。
ログは30日分を insert or update していた。
でも、update するにも一回 select してみないとあるかどうか分からない。
→ じゃあ、全部 DELETE して 全部 INSERT したらいいよ!
→ SQL増えた!ログも増えた!ログが!!

insert or update を判断する MySQL の便利な機能があるよ
=> INSERT ... ON DUPLICATE KEY UPDATE
指定された PrimaryKey があれば、UPDATE。なければ INSERT をしてくれる。

インデックスをはろう!はるとすごい速度が上がる!
はっただけで満足せずに、
・良く Where で使うワードを調査
・遅いクエリが無いか slow-query-log で確認
・インデックスがきちんと使われているか explain で検証
を忘れずに。

発行するSQLにコメントを付けてデバッグしやすくしてみる。
コメントに、どのサーバから来てどのセッションで実行された SQL なのかを残すと、show processlist や slow-query-log でわかりやすくなるよ。
ただし、コメントが毎回違うからクエリキャッシュ出来ない。
※これは素晴らしいアイディア!気付かなかった!

無理に正規化しない。
JOIN すると遅くなることもあるので、それだったら欲しい情報が全て1レコードにあったほうがいい。


----------------------------------------

■Memcached
導入に手間がかかるけど、静的でかつ頻繁にデータが変わらない SELECT 結果なら、毎回クエリを実行するのではなく、Memcached にキャッシュさせておいた方がいい。
メモリ上に展開されるので、HDD へのアクセスが発生する方法より格段に速くなる。
----------------------------------------

■PHP
フレームワークや、大量のソースを読み込む必要がある PHP を使ったサービスなら、アクセラレーターは導入した方がいい。
PHP は、実行する時にバックでコンパイルしている。
コンパイルするファイルが多ければ多いほど処理完了までに時間がかかる。
アクセラレーターはコンパイル結果をキャッシュしておくものなので、表示までの速度が速くなる。

改善のための解析用にログを残すのも大切。
どのページ(URL)で、誰が、どのくらいのメモリーを使って、何秒で表示まで終了したかを記録すると、わかりやすいよ。
----------------------------------------

■いろいろパワーアップするために
HDD より高速化したいので、Fusion-io が気になる。
DB に SSD を使ってみたけど、書き込み制限ですぐにダメになってしまった。

MySQL5.6 は、まだ正式リリースではないのだけど、InnoDB まわりが進化しているので早く実戦投入したい!

2012年12月21日金曜日

Linux サーバ上でエンコードされたメールを PHP でデコードして確認する方法



Postfix 設定に失敗して、送信されるはずだったメールがローカルユーザと勘違いされ、
でもローカルユーザにそんなやつはいないから root 宛に転送されていた。
mail コマンドで確認したら、メールの内容が残ってた!助かった!でも文字化けしてる…

=E3=81=93=E3=81=AE=E3=83=A1=E3=83=BC=E3=83=AB=E3=81=AF=E3=80=81 ...


http://d.hatena.ne.jp/minesouta/touch/searchdiary?word=*%5BPerl%5D&of=10
これは文字化け?いいえ、Quoted Printable です。
エンコードされているんですよ。
Perl でデコード出来ます。


http://www.plus-a.net/tools/text_tool/
試しにデコードをしてみよう。
お!読める文字になった!


http://pentan.info/php/quoted_printable.html
php でも Quoted Printable 文字列の変換することができるんですよ。
quoted_printable_decode っていう関数があるんです。


php がインストールされているからデコードできそうだ!
早速やってみよう!


メールが記録されているファイルを確認
# less /var/spool/mail/root


あったあった!
これらを別のファイルに書き出す
# cp /var/spool/mail/root /root/mails.txt


書きだしたファイルをデコードして別に保存する
# php -r "echo quoted_printable_decode( file_get_contents('mails.txt') );" > decode_mails.txt


サーバからダウンロードしてきて確認。
subject に余計な文字が紛れていて、所々おかしいけど、これで読めるようになった!


2012年11月25日日曜日

vim : netrw の note が出て困る


最近、windows で vim を使い始めました。
NetBeans だと、自動で補完されるので忘れっぽい私にはとても助かっていたのですが、毎日2回は反応しなくなるという困ったちゃん。
そこで、社内の Vimmer から色々頂いて vim に挑戦したわけです。

しかし、vim を使っていると次のような注意書きが毎回出てきて、ちょっと困ってました。

**note** (netrw) consider setting g:netrw_localcopycmd<copy> to something that works


検索したら、対処法が見つかったのでやってみます。




vim ~/.vimrc

" ファイルの最後に以下を追加しました。
let g:netrw_localcopycmd=''


これで、エラーが出なくなりました。

ちなみに、netrw は ファイルブラウザ。:Explore コマンドのやつです。

Netrwを使いこなす
http://d.hatena.ne.jp/hagure_beans/20100603/1275591475


2012年11月12日月曜日

mysql に 4バイトutf8 の文字を入れたい

MySQL に iOS の絵文字など、4バイトUTF-8 の文字を入れると、そこで途切れるという現象がありました。
残念ながら発生したサーバの MySQL バージョンは5.1系でバージョンアップせずに対応したのですが、最近構築したサービスイン前のサーバは5.5系だったので設定してみました。


■設定内容
1. 文字コードを utf8 → utf8mb4 に変更
2. skip-character-set-client-handshake を設定


■詳細
1. 文字コードを utf8 → utf8mb4 に変更

MySQLの UTF-8 は4バイトに対応していません。
ですが、絵文字や中国漢字、日本語でも特殊漢字などは4バイトが含まれています。

詳しくはこちら↓
iOS の絵文字(4bytes UTF-8)が入った文字列を MySQL に INSERT/UPDATE すると絵文字以降の文字がぶった切られる件

------------

2. skip-character-set-client-handshake を設定

mysql.cnf の character-set-server を変更しただけでは、PHP で取得した時の文字コードがビルドした時のものが使用されます。
そうすると、MySQLのエラーが出てしまうのです。

General error: 1267 Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation ...

これを、ビルドした情報ではなく、MySQL サーバの文字コードで取得するには次のオプションを使います。

skip-character-set-client-handshake

詳しくはこちら↓
PHPとMySQLの個人的まとめ


■変更内容
# vi my.cnf

[client]
-- default-character-set = utf8
++ default-character-set = utf8mb4

[mysqld]
-- character-set-server = utf8
++ character-set-server = utf8mb4
++ skip-character-set-client-handshake


■phpから文字コードを見るコード

<?php

$mysql_host = 'localhost';
$mysql_user = 'root';
$mysql_pw   = '';
$mysql_db   = 'mysql';

$conn = mysqli_connect($mysql_host, $mysql_user, $mysql_pw, $mysql_db);

$sql = "SHOW VARIABLES LIKE 'char%'";
$result = mysqli_query($conn, $sql);

while ($data = mysqli_fetch_array($result, MYSQLI_NUM)) {
    echo str_pad($data[0], 24) ." | ". $data[1]."\n";
}

?>
-------------

以下、実行結果です。

character_set_client     | utf8mb4
character_set_connection | utf8mb4
character_set_database   | utf8mb4
character_set_filesystem | binary
character_set_results    | utf8mb4
character_set_server     | utf8mb4
character_set_system     | utf8
character_sets_dir       | /usr/local/mysql/share/charsets/

2012年10月29日月曜日

新しいサービスの提案:写真に署名を入れるサービス


ちょっと思いついたのでメモしておきます。
今はアイディアレベルですので、作ってやるぜ!という方、アイディア頂き!という方、どうぞ宜しくお願いします。
こここうするとイイヨ!とか、同じサービスあるよ!とかでも構いません。
ご連絡は @netsket_koshiba まで。

このアイディアで(・∀・)ニヤニヤ出来たら、お酒1杯ご馳走してもらえれば(ゴニョゴニョ…



■どんなサービス?
SNSやブログにアップする写真に、サイトURLやアカウント名などの定型文(署名)を入れて返却するサービス。


■どうして?
お気に入りのブロガーさんが写真をSNSにアップした所、勝手に使われてしまって困っているとつぶやいていたから。(複数)


■どうする?
入れたい文字と写真を選んで送信。
文字入れした写真をダウンロード。


■どうやって儲ける?
定型文の登録、アップできる写真数の制限解除が出来るアカウント作成。
月の利用料ではなくデポジット制。
アカウント削除時にデポジットが残っていたら返却。

2012年9月24日月曜日

qpstudy 2012.09 秋なのに怖い話 〜障害発生編〜 に行ってきた



9月22日に行われた「qpstudy 2012.09 秋なのに怖い話 〜障害発生編〜」に行って来ました。
参加された皆様におかれましては、参加のためにeverevo(イベレボ)の負荷テストにご協力頂きまして、誠にありがとうございました。
懇親会LTでグダグダなご挨拶でしたが、皆様にお礼ができて良かったです。


さて、本編です。夏は終わりますが障害に関する怖い話です。
背筋が凍る話があったり、爆笑が起こったりと、いつもながらに楽しい勉強会でした。
今回の進め方は、登壇者が怖い話をして、「どうしたら良かったか」というのを参加者に答えてもらうという形式だったのですが、とても良いですね!勉強になりました!


以下、勉強になった点をずらずらと。

・負荷テストは機能単位で行うのも大切。模擬障害とか。
・サーバ構成図とシステム構成図の2つは必要。2つ揃ってサービス構成図。
・障害の多いサーバには大抵お札が貼ってある。
・障害調査は下から。泥棒もタンスは下から。ハード→設定→ミドル→アプリ→ユーザー。
・動いている時はミドルorアプリor設定orユーザー。
・死んでる時はハードorDC。
・DCが原因という障害は結構ある。
・優秀すぎると命狙われる、きけんなしょくぎょう。



懇親会も盛り上がりましたね。
いつもはLTの時談笑もされていたのですが、今回はほぼ全員が懇親会LTを見聞きしてました。
個人的には、終了間際の魔法の言葉からBLへの話と、
はせごーさんの「夕飯どうしようと思ってTL見てたらqpstudyやってて、懇親会空いてたから来たんだ」という話が楽しかったですw


主催のリーダー、スタッフの皆様、参加された皆様、ありがとうございました!
またお会いしましょう!

2012年8月29日水曜日

mod_evasive で画像をチェックしない方法

セキュリティ対策として、mod_evasiveを入れたのはちょっと前。
画像のロードが多いサイトだったので、DoSアタックと勘違いされてアラートメールがぞくぞくと…

通常、mod_evasiveはIPアドレスしかwhitelistに登録できません。
そこで、コンパイル前のソースを書き換えて特定の条件ではスルーするようにします。



------------------------------



[mod_evasive20.c]

- #define MAILER  "/bin/mail %s"
+ #define MAILER  "/bin/mail -s 'DoS Alert! from your-service.com' %s"


static int access_checker(request_rec *r)
{
int ret = OK;

+    /* IGNORE_DOS */
+    if (apr_table_get(r->subprocess_env, "IGNORE_DOS") != NULL)
+      return OK;


※apr_table_get(r->subprocess_env, "IGNORE_DOS") でIGNORE_DOSが有効になっているか確認します。
※apache1.3 を使っている方はいないと思いますが、もし使ってたらap_table_getに直してください。
------------------------------

[modevasive.conf]

+ SetEnvIf Request_URI "\.(gif|jpg|png)$" IGNORE_DOS


※URIに特定の拡張子が含まれていたらIGNORE_DOSが有効になります。

------------------------------


なお、mod_evasive20.c を書き換えた後は、apxsでコンパイルしてApacheの再起動を行います。

# apxs -ica mod_evasive20.c
# apachectl configtest
# apachectl graceful


以上!



※参考URL※

ap_table と apr_table の違い



2012年8月10日金曜日

Fedora8 で php をインストール

今時Fedora8は無いだろうとあちこちから言われそうですが…

たまたま昔テスト用の環境に作ったものが残っていたので使っていましたが、phpのバージョンが古くエラーが出てしまいました。
OSのバージョンアップでも良いのですが、phpだけアップグレード出来ればと思いまして…(^_^;)


phpはyumでインストールしていました。
なのでyumで5.3をインストールしようとしましたがバージョンがありません。(当たり前
remiを使ってインストールするようです。



wget http://rpms.famillecollet.com/remi-release-8.rpm
rpm -ivh remi-release-8.rpm
yum install --enablerepo remi php

2012年8月7日火曜日

ec2-bundle-vol で鍵ファイルが削除される


ec2 tools を更新したインスタンスでAMIを取得し、そのAMIを起動した時の事です。
元のインスタンスでは動いていた ec2 tools のコマンドでエラーが発生する(;´Д`)
理由は、秘密鍵等々が無いから。



どうやらver.1.4.0.0以降ではこれらのファイルが削除されるのがデフォルトのようです。
以下、「--manual」より。

The recursive copying process copies directories from the volume into the image.
The special directories:

- '/dev'
- '/media'
- '/mnt'
- '/proc'
- '/sys'

are always excluded.

Files matching the following regular expressions:

- '*/#*#'
- '*/.#*'
- '*.sw'
- '*.swo'
- '*.swp'
- '*~'
- '*.pem'
- '*.priv'
- '*id_rsa*'
- '*id_dsa*'
- '*.gpg'
- '*.jks'
- '*/.ssh/authorized_keys'
- '*/.bash_history'

are excluded by default on Linux. Individual files that match these patterns may be
included by specifying the '--include' option.



ちなみに、これまで使っていたver.1.3-53773では削除されません。
マニュアルにも載っていません。うぐぅ…
仕方がないので、必要なものだけは「--include」で指定しました。

2012年7月18日水曜日

EBS が attaching から attached にならない


EC2にて、EBSを何度かattach/detachしている際に、
ステータスがattachingのまま変化せず、インスタンス側に接続されない事がありました。


■原因
attachしようとしていたデバイスが既に使用(mount)されていたから。

今回は、detachが成功していたのでそのままattachしてしまったのですが、インスタンス側でデバイス(/dev/sdg)がmountされたままでした。
なので、attach出来ずattachingから進まなかったのです。。。




■対応方法
1.mountされていないか確認し、もしされていたらumountする
2.未使用のデバイスを使用する(sdf - sdpの中から選択)
3.インスタンスを再起動する

umount で -l を使う前に fuser で確認


umountしようとしたら device is busy とエラーが出ること、ありませんか?

どこかで使われてるよ!って言われているのですが、心当たりが全くないので強制的にumountしたくなります。
その気持ちを抑えて、一度使われているプロセスを確認しましょう。


# fuser -muv <umountしようとしているディレクトリ>



このプロセスなら消しても大丈夫と確認した上で、強制umountします。

# umount -l <ディレクトリ>



このオプション、シェル上だと使えませんでした。。。

2012年7月12日木曜日

https接続できるGitサーバを立てるならgit-http-backendを使おう


Gitサーバに接続する方法は3つあります。
・SSH
・git
・https


httpsで接続できるようにするには、WebDAVが一般的だったようですが、
どうにも接続が出来ずにいたら「git-http-backend」を使うといいよという情報を発見!



CentOS5で、Trac と git の連携 より
正確なソースがよくわからないけど、どうやら WebDAV だと、push がサポートされないっぽい。最近は、git-http-backend を使うらしい。なので、こいつを使うことに。


gitリポジトリをホストするのにWebDAV使わないほうがいい より
共有gitリポジトリをホストする方法をググると、WebDAVを使ったやり方が結構出てくる。このやり方には明確なデメリットしか無いにもかかわらず、WebDAVを使ってホストする方法を紹介するページでは触れられていないことが多い。(中略)もうWebDAVを導入してしまって構成変えるのも面倒くさい場合は、Smart HTTPを導入することでWebDAVによるホストの欠点を完全に隠すことができる。速度もssh経由に劣らないし、サーバサイドフックも起動する。



「git-http-backend」を使ったら超カンタンにhttpsなGitサーバが出来上がりましたよっと。

2012年7月10日火曜日

symfonyでカラムの更新を判断する


phpで、条件によってあるカラムを変更する、という処理を行う関数があるとします。
この時、戻り値で変更があったかどうかsymfonyなら分かるんです!



ざっくり、こんな感じ。

function change() {
  if ($this->name === 'test') {
    $this->name = 'hoge';
  }

  return $this;
}


// $user->name = 'test'

$user->change();
$lastModified = $user->getLastModified(); // $lastModifiedは配列

if (isset($lastModified['name']) {
  echo 'change!';
}


symfony使いなら知ってるよ( ´_ゝ`) かもしれないけど、初めて知ったので(^_^;)

2012年6月14日木曜日

[追記アリ]AWSのELBでHealthyHostCountが0になる


某サービスで時たまELBのヘルスチェックに失敗し、HealthyHostCountが1を下回る事がありました。
AutoScalingの設定もしていますが、in/outの時以外でも発生し、
CPU使用率が30%だったとしても発生しました。

原因がわからず、AutoScalingのしきい値を一時的に変更してみたりもしましたが、一向に改善せず。。。


そういえば、ヘルスチェックの設定項目にtimeoutがあったよな、と言うことで許可をもらい設定を変更しました。
初期値の5から少しあげた10に変更。

変更後1日立ちましたが、これまで日に1回は発生していた問題が発生していません。やった!
このまま問題が解決してくれれば・・・


あと、twitterで教えてもらった事があるので箇条書きにします。

■AWSのELBとApacheを使う際の注意点
・Timeoutは120以上が推奨
・ApacheのKeepAliveは有効にすべし。ELBとの接続効率があがる。

thanks for @iara !


【追記(2012-06-15)】
中の人より、詳しい説明を頂きました。
荒木さんありがとうございます!!

debiancdn : Amazon ELBをうまくつかうには、KeepAliveを有効にしよう。Timeoutは60秒よりだいぶ長くしよう。その背景。



2012年5月23日水曜日

href=# の時、ページトップに戻らないようにする


jqueryを修正していてハマったのでメモです。


■ハマった内容
<a href="#">をクリックすると、スクロールしていたとしてもページのトップに戻ってしまう。

リンクをクリックした後、htmlをappendする処理。
そこから動きたくないのに、どうしてもトップに戻ってしまってイラッっと…



■対応方法
$('a[href="#"]').click( function() {
// 処理
return false;
});

2012年4月20日金曜日

mysql5.1でslow_queryを有効にする


バージョンが変わって設定方法も変わったようなのでメモ。

my.cnfの[mysqld]に以下を追加します。

slow_query_log=1
slow_query_log_file=mysql-slow.log
long_query_time=3

追加したらmysqlを再起動します。


slow_query_log=ONでも可って書いてあったのでONで試しましたがOFFのままでした。
なので、slow_query_log=1にしましょう。

2012年4月18日水曜日

DoS対策で使えるiptablesのhitcountは最大値=20だった!

iptablesでDoS対策する方法に、hitcountを使って接続回数を制限するものがあります。
sshだったりhttpだったり、ポート別・IPアドレス別に制限がかかるのです。

sshの場合は60秒間で5回など、hitcountが少なくて良いのですが、
httpの場合は画像のロードなどもあるので、10回より多めにしておきたいところです。

さぁ試してみよう!


--seconds 30 --hitcount 50 に設定して、100回接続してみました。
しかしどうでしょう。全てOKになってしまいました。
数値を小さくすると効果が出ているのですが、数値を変えて試すと20以上は全てOKでした。
どうやらhitcountの最大値は20だったようです。
※ここまで検証で試しました。
※この事は普通に英語サイトで記述されています。orz


じゃ、対応してみようか


hitcountの最大値はデフォルトで20です。
設定ファイルを確認してみましょう。

# cat /sys/module/ipt_recent/parameters/ip_pkt_list_tot 
20



このままでは --hitcount 50 としても全く効きません。
なので、基本的な設定を変更します。


# vi /etc/modprode.conf
以下を追加します。

options ipt_recent ip_pkt_list_tot=50


設定を反映しましょう。

/-- CentOS5の場合 [ここから] --/

# service iptables stop
# rmmod ipt_recent
# modprode ipt_recent

/-- CentOS5の場合 [ここまで] --/


# service iptables restart




設定の反映が完了しました。
設定ファイルを確認してみましょう。

# cat /sys/module/ipt_recent/parameters/ip_pkt_list_tot 
50 <- 変わった!?



この設定が有効かどうかは、50回以上自動アクセスするテストプログラムを稼働させて、パケットがrejectされているか見てみましょう。
今回はmod_evasiveに付いてきたtest.plを書き換えて実行してみました。
便利ですね、このテストプログラム。



【参考URL】
hitcountの最大値について:

ip_pkt_list_totについて:

modprode.confの設定が反映されない時はmodplodeをreloadしてみよう:

2012年4月13日金曜日

EBSのスナップショット

AWSのEC2のサービスに、EBSがあります。
このEBSはスナップショット機能を使ってバックアップしているのですが、管理画面から見るとEBSのサイズで表示されているので、常にフルバックアップをしているものと思っていました。。。

実は、最初に取得したスナップショット以降は、差分を作成しているんだそうです。

仮想サーバーEC2 & EBS詳細 -ほぼ週刊AWSマイスターシリーズ
EBSのスナップショット作成機能の仕組みについて


なので、スナップショットの利用料金も差分の分のみ。
※利用料金をよくよく見たらそうなってました(汗

isStatusCode以外でstatusを確認する方法

symfonyのfunctional testでstatusをチェックする時はisStatusCodeを使います。
けど、今のステータスによって処理を変えたいので、次のものを使ってみます。


$status = $browsser->getResponse()->getStatusCode();



2012年4月5日木曜日

古いCentOSでyumすると404になる

CentOS4が稼働している仮想環境でyumをしようとしたら404・・・・・・orz
古すぎですねすいません。

CentOS4系はサポート終了のため、ミラーサイトから削除されたそうです。
それでも4系を使いたい場合は以下のサイトに替えましょう。




ただし、$releasever だけではディレクトリが見れない時があります。
そんな時は、$releasever.9と、コンマ以降を付け足してください。

そんな事する前に、OSアップグレードしろって話ですが…

2012年3月30日金曜日

PDO::FETCH_COLUMN


使い方):
$r = $q->execute()->fetchAll(PDO::FETCH_COLUMN, 9);

意味):
SELECTされたカラム9番目を$rに代入。
ちなみに、カラムは0番目から数え始める。

windowsでgrepみたいな事をする


コマンドプロンプトで以下を実行。

cd ディレクトリ
findstr /S 検索文字 *


参考サイト:http://www.mapee.jp/wlh/windowsgrep.html

2012年3月12日月曜日

mysqlのバイナリログを日時指定で削除する


mysqlに[PURGE MASTER LOGS]というコマンドがあります。
マスタログを削除するものです。
このあとに[TO "バイナリログ名"]を入れると、そのログの前までを削除します。
これは良く使っていました。

ログファイル名ではなく、日時指定をすることもできます。

[PURGE MASTER LOGS BEFORE 'YYYY-mm-dd HH:ii:ss']

指定した日時より前のログが含まれるバイナリログが削除されます。
ただし、ログの途中が指定された場合は削除されません。



例えば、以下のバイナリログが残っているとします。

mysql-bin.0000001 (2012-03-01 - 2012-03-05のログ)
mysql-bin.0000002 (2012-03-05 - 2012-03-10のログ)



mysql> PURGE MASTER LOGS BEFORE '2012-03-06 00:00:00';
→mysql-bin.0000001が削除されます


mysql> PURGE MASTER LOGS BEFORE '2012-03-04 00:00:00';
→ログは削除されません

2012年2月20日月曜日

【休憩】肉球クッキーの作り方

バレンタインが終わって、来月はホワイトデーですね。
お返しに肉球クッキーなんてどうでしょう(*^_^*)
肉球じゃなく、ハートでも可愛いですよ。

※注意!ざっくり適当レシピです。詳しいクッキーの作り方は他のレシピをご参照ください(^_^;)


◆材料
・お好きなクッキー生地
・チョコレート
・生クリームor牛乳



◆作り方
1.クッキー生地を小さじ1程とり、丸めます。

2.丸めたら手のひらで潰します。
ちょっと厚めにしましょう。

3.人差し指、小指を使って肉球の形を付けます。
クッキー生地を指で押して、肉球型の凹みを付けます。
押す時は可愛い肉球をイメージして!
失敗したら丸めてもう一度!

4.オーブンで焼きます。

5.チョコを溶かします。
クッキーを焼いている間にチョコを湯煎で溶かします。
チョコ40gと牛乳大さじ1を耐熱容器に入れ、お湯を張った鍋に浮かべます。
熱すぎるとチョコが分離するので、熱くなったらお湯から外します。

6.焼きあがったクッキーにチョコを垂らします。
スプーンでゆっくり、ちょっとずつ。。。
可愛い肉球をイメージして。。。
凹みが可愛くなくても、チョコで修正!

7.冷やして完成!!!














◆コツ
とにかく可愛い肉球をイメージすること!
イメージ通りになるように慎重に作業すること。

php+GDでテキスト画象を作ると色が変わる?

画象の仕様をきちんと理解している人なら悩まなかったはず…
ちょっと悩んだ部分があったので、自分に向けて解説してみようと思います。


◆問題◆
php+GDを使って、文字を青(#00f)書き込んだ画象を作る。
とあるバナーと、その文字画像を合体させてgif保存する。
保存後の画象を見ると、文字色が青から灰色(#ccf)になっている。
その他の画象では問題なかった。




◆原因◆
問題が発生したのはjpegをgifにしたもの。
gifは256色。対してjpegは1670万色。
高画質を低画質にしたために色数が減り、変色してしまった。

pngは元から低画質の画象を使っていたので、今回の問題に直面しなかった。




◆対策◆
先にgif以外の画象をgifに変換する。
そのあとで文字画像と合体させる。