PLISE STAFF'S BLOG

株式会社PLISEのスタッフブログです。

10月スタッフ会合を行いました。

こんにちは、先月ぶりです。

今月もスタッフ会合が開かれました。

 

今月のワークショップは、

「 システムエンジニアなら必ず知っておきたい、楽しいトラブル対応

                       経験から学ぶ障害対応術 」

です!

 

なんと楽しそうなテーマなのでしょう!

始める前からワクワクして、眠ることのできない夜が続きそうです。

 

 

障害とは、ここではもちろんシステム障害のことを指し、情報システムが何かしらの不具合により本来の機能が利用できなくなることです。

例えば、インターネットショッピングをしようと思い、普段利用しているWEBサイトにアクセスを試みたが、"ページが見つかりません"と表示される・・・

こんな経験が少なからずあると思います。

 

そして今回のワークショップは障害対応術です。

つまり、こういった障害が発生しないためにどう対処するか。

また、障害が発生してしまった場合にどう対処するかをワークショップ形式で学びました。

 

f:id:plise:20151117163035j:plain

 

ワークショップを終えると、今回は4チームに分かれて演習を行いました。

 

あなたたちのチームはあるA社のショッピングサイトを作成しました。
運用をA社が行い、システム保守をチームで担当しています。
ショッピングサイトには、一般の会員がアクセスするフロントページと、
会員や商品を管理する管理者ページがあります。
クラウドサービスを利用しており、1台のWebサーバーと、1台のデータベースサーバーで動いています。
使用ミドルウェアApacheTomcat、データベースはOracleです。各サーバーにはSSHでログインすることができます。
社内にはほぼ同環境のテスト環境を用意しています。
2ヶ月前にサイトをオープンし、3日前とその1週間前に、プログラムに機能追加をおこなっています。

 

- 演習1

ある日、フロントページのある商品のページにアクセスが出来ないとの問い合わせを、A社から電話で受けました。
あなたは早速SSHでサーバーにログインし、状況の把握に取りかかりました。

  1. 電話で伝えるべきこと、聞いておいた方がよいことは何でしょうか
  2. 状況の確認をするために何を調べればよいでしょうか?疑わしいところはどこでしょうか?
  3. 原因について、いくつか仮説を立ててみてください。

 

演習が始まると、早速チーム毎に分かれて話し合いです。

時間内に全ての意見を書ききれないほどに案が飛び交いました。

 

  1. 特定の商品の情報。どの状況で発生したか。閲覧環境。
  2. ログの確認。再現可能かどうか。3日前、10日前に変更したプログラムが怪しい。クラウドサーバーが怪しい。
  3. 特定の商品に特殊な文字が組み込まれていた。プログラムにバグを埋め込んだ。ブラウザ。クラウドサーバーの仕様変更。

等々・・・

 

ここに挙げたのは一例で、1チームだけでもかなりの量となりました。

 

4チーム合わせると・・・システム障害は考慮しなければならないことが多くて楽しいですね!はぁ・・・

 

演習の様子①

f:id:plise:20151117163137j:plain

 

f:id:plise:20151117163124j:plain

 

- 演習2

調査を進めたところ、障害の原因が分かりました。
3日前に修正を行ったプログラムにバグがありました。
・不正な値が商品データに追加されてしまった。
・その商品データのページを開いた場合エラーが発生する

  1. 至急やらなくてはならないことは何でしょう
  2. 原因解決のためにやらなければいけないことは何でしょう
  3. 修正を行う際に確認しなければならないことは何があるでしょうか。
  4. 同じ障害・バグを発生させないために、今後どのようなことが必要でしょうか。

 

  1. 運用担当のA社への謝罪。特定のデータの削除(削除する前に全体のバックアップ)。一般ユーザーに向けたHPに謝罪/障害報告。
  2. バグ修正(不正な値が入らないようにバリデーション)。
  3. 今回のバグを修正する際に別のバグを埋め込んでいないか。テスト機で動作確認。
  4. 単体テスト/結合テストの強化。社内共有。

 

どのチームにも、"謝罪"の項目がありました。

顧客や取引先との信頼関係を築くためにも謝罪は大切ですね! 

他にも、連絡/報告を確実にといった趣旨の項目も多く挙げられました。

 

 

演習の様子②

f:id:plise:20151117163053j:plain

 

 

f:id:plise:20151117163109j:plain

 

 ここまでで今回の演習は終了です。

 私たちは、開発が終わるとプロジェクトが終わったかのように思っていますが、システム保守も含めて一つのプロジェクトです。システム開発で得られた信頼・利益を守るためにも、確かな障害対応術を身に着けるべきだと強く感じさせられました!

 

トラブル対応について"楽しく"学べました!ありがとうございました!

 

8月スタッフ会合を行いました

こんにちは!

8月もスタッフ会合を行いました。

今回のワークショップは・・・・・

 

お休みです

 

というのも、大きなお仕事が決まり、そのことについての説明があったからです!

 

今回のこの大きなプロジェクトのメンバーは、学生がプロジェクトへの意気込みを添えて応募し、参加するという形で決まります。

7月にプライマリ(研修)を終えた1、2年生も大勢が参加したいと言っていました。

 

会合の後に懇親会を行うのですが、そこで今回のお仕事の気合い入れをケーキでしました。

 

f:id:plise:20150904192225j:plain

 

f:id:plise:20150909010301j:plain

 

これからも良いものを作っていけるように、頑張っていきます!!

 

では、今回はこのあたりで失礼します

9月のスタッフ会合ではまたワークショップを行う予定なので、またその様子を報告します!

7月スタッフ会合を行いました。

こんにちは、1ヶ月ぶりです。
今月も、スタッフ会合が開かれました。

今月のワークショップは「実践的SQLパフォーマンスチューニング」です。
SQLとは、データベースから目的のデータを取得する目的で使う言語のことです。
しかし、誤った書き方をしてしまうと、動作が極端に遅くなってしまいます。

そこで、SQLのパフォーマンスチューニングです!

SQLの書き方を見直すことで、元の数倍の速度で処理ができるようになることもあります。
以前、会社のとある案件で、SQLを見直したら動作が数十倍速くなったこともあるそうです。

では今回のワークショップです!

ワークショップ担当の社員から、とあるSQL文が渡されました。
このSQLはパフォーマンスがとても悪いそうです。
これを、複数のチームに別れてパフォーマンスチューニングしていきます。

渡されたSQLに、

  • インデックスを張る
  • 1対多の関係をできるだけ排除する ⇒ INNER JOIN文をEXISTSに置き換える(場合による)
  • 不要な重複を作らない

といった処理をしていきます。

時間が限られているため、どれを優先して行うかも勝負の鍵を握ります!

インデックスとは、索引みたいなもので、

  • データを絞り込むために使用する列
  • 表の結合条件の列
  • データの並び替えやグループ分けで使用する列

に張ると処理が高速になります。

これらを含めて作業開始です・・・!
まずどの作業をするかチーム内で話し合いました。
まず始めに、渡されたSQLの実行に掛かる時間を調べました。

EXPLAIN ANALYZE 
SELECT DISTINCT
  u.name 
FROM
  users AS u 
  LEFT JOIN orders AS o 
    ON u.id = o.user_id 
  LEFT JOIN order_details AS od 
    ON od.order_id = o.id 
  LEFT JOIN order_addresses AS oa 
    ON oa.order_id = o.id 
WHERE
  oa.address LIKE '会津若松%' 
  AND o.order_date > '2012-01-01' 
  AND od.price > 50000 
ORDER BY
  u.name

実行するSQL文の前にEXPLAIN ANALYZEを付けると実行時間や、コストを表示することができます。
初期のSQL文の実行速度は、約20000ms(20秒)でした。

さて、ここからチューニング開始です!
ある人は先にインデックスを貼ろう!と言ったり、また別の人は先にINNER JOINをEXISTSに置き換えようと言ったり・・・。

f:id:plise:20150804170409j:plain

私たちのチームはdistinctで重複してるレコードを排除することから始めました。
SELECT句にdistinctを付けて・・・あれ、あまり早くならない。
少ししか効果がないと言っていたのでこんなものなのかな?

次にインデックスを貼る事にしました。
検索条件に使うname, address, order_dateに貼って・・・
CREATE INDEX インデックス名 ON テーブル名(カラム名)
おお、中々早くなった。

f:id:plise:20150804173010j:plain

最後にEXISTSで副問い合わせ。
私達のチームはここで苦戦。あれ、そもそもEXISTSって何だ・・・という状態に^^;
インターネットで調べつつ何とか完成はできたものの、WHERE句で各IDを結びつけるのを忘れていて全く別の処理に・・・。
それぞれのチームの結果はこうなりました!

  • team A ("Total runtime: 207.238 ms")
CREATE INDEX index_order_details ON order_details(order_id); 
CREATE INDEX index_order_addresses ON order_addresses(order_id); 
CREATE INDEX index_orders ON orders(user_id);

SELECT
  u.* 
FROM
  users AS u 
WHERE
  EXISTS ( 
    SELECT
      o 
    FROM
      orders AS o 
    WHERE
      u.id = o.user_id 
      AND o.order_date > '2012-01-01' 
      AND EXISTS ( 
        SELECT
          od 
        FROM
          order_details AS od 
        WHERE
          od.order_id = o.id 
          AND od.price > 50000
      ) 
      AND EXISTS ( 
        SELECT
          oa 
        FROM
          order_addresses AS oa 
        WHERE
          oa.order_id = o.id 
          AND oa.address LIKE '会津若松%'
      )
  ) 
ORDER BY
  u.name; 

  • team B (exists内でuserとひもづいていないため、SQL間違い)
CREATE INDEX username ON users(name); 
CREATE INDEX order_address ON order_addresses(address); 
CREATE INDEX order_date ON orders(order_date); 
CREATE INDEX order_details_price ON order_details(price);

SELECT DISTINCT
  u.id
  , u.name 
FROM
  users AS u 
  LEFT JOIN orders as o 
    ON u.id = o.user_id 
WHERE
  o.order_date > '2012-01-01' 
  AND EXISTS ( 
    SELECT
      * 
    FROM
      order_details 
    WHERE
      price > 50000 
      AND EXISTS ( 
        SELECT
          * 
        FROM
          order_addresses 
        WHERE
          address LIKE '会津若松%'
      )
  ) 
ORDER BY
  u.name; 

  • team C ("Total runtime: 498.736 ms")
select
  u.id
  , u.name 
from
  users as u 
where
  exists ( 
    select
      null 
    from
      ( 
        select
          o.user_id 
        from
          orders as o 
        where
          exists ( 
            select
              null 
            from
              order_details as od 
            where
              od.price > 50000 
              and od.order_id = o.id
          ) 
          and exists ( 
            select
              null 
            from
              order_addresses as oa 
            where
              oa.address like '会津若松%' 
              and oa.order_id = o.id
          ) 
          and o.order_date > '2012-01-01'
      ) as k 
    where
      k.user_id = u.id
  ) 
order by
  u.name; 
  • team D ("Total runtime: 209.447 ms")
select
  u.* 
from
  users as u 
  left join orders as o 
    ON u.id = o.user_id 
where
  exists ( 
    select
      * 
    from
      order_addresses as oa 
    where
      oa.order_id = u.id 
      and oa.address like '会津若松%'
  ) 
  and exists ( 
    select
      * 
    from
      order_details as od 
    where
      od.order_id = u.id 
      and od.price > 50000
  ) 
  and exists ( 
    select
      * 
    from
      orders as o 
    where
      u.id = o.user_id 
      and o.order_date > '2012-01-01'
  ) 
group by
  u.id 
having
  count(u.id) > 1 
order by
  u.name; 
  • team E (exists内でuserとひもづいていないため、SQL間違い)
select
  u.id
  , u.name 
from
  users as u 
where
  exists ( 
    select
      null 
    from
      ( 
        select
          o.user_id 
        from
          orders as o 
        where
          exists ( 
            select
              null 
            from
              order_details as od 
            where
              od.price > 50000 
              and od.order_id = o.id
          ) 
          and exists ( 
            select
              null 
            from
              order_addresses as oa 
            where
              oa.address like '会津若松%' 
              and oa.order_id = o.id
          ) 
          and o.order_date > '2012-01-01'
      ) as k 
    where
      k.user_id = u.id
  ) 
order by
  u.name; 

回答("Total runtime: 199.284 ms")

create index order_user_id_index ON orders(user_id); 
create index oder_order_date_index ON orders(order_date); 
create index od_order_id_index ON order_details(order_id);
create index od_price_index on order_details(price); 
create index oa_order_index on order_addresses(order_id); 
create index oa_address_index on order_addresses(address); 
create index user_name_index on users(name);

select
  u.id, u.name 
from
  users as u 
where
  EXISTS ( 
    select
      * 
    from
      orders o 
    where
      u.id = o.user_id 
      and o.order_date > '2012-01-01' 
      and EXISTS ( 
        select
          * 
        from
          order_details od 
        where
          o.id = od.order_id 
          and od.price > 50000
      ) 
      and EXISTS ( 
        select
          * 
        from
          order_addresses oa 
        where
          o.id = oa.order_id 
          and oa.address like '会津若松%'
      )
  ) 
order by
  u.name

20秒が0.2秒になりました。
ハードウェアのコストを掛けずにパフォーマンスが改善される・・・SQLパフォーマンスチューニング素晴らしい!
業務にも活かしたいと思います!ありがとうございました!

6月スタッフ会合を行いました

こんにちは

先日、毎月恒例のスタッフ会合を行いました。

今回のワークショップでは、「犬でも出来るアプリケションサーバー構築」ということでサーバーの構築を行いました。

 

サーバーという単語は皆さん、聞いたことがあるのではないでしょうか?

コンピュータネットワークにおいて、他のコンピュータに対し、自身の持っているデータなどを提供するコンピュータ、または、その機能を持つソフトウェアのことです。

簡単にいうと、コンピュータ同士の間の通信の橋渡しをするものです。

 

今回はVM(バーチャルマシン、仮想マシン)上にサーバーを構築しました。

4〜5人のグループに分かれて作業を行いました。

どのグループも手順書に従ってVMの作成、CentoOS7というOSのインストールまでは順調に行うことができました。

 

ここから今回の課題に入っていきます。

 

はじめにfirewallの起動状態の確認をします。

firewallとはあるコンピュータやネットワークと外部の境界に設置され、外部の攻撃から内部を保護するためのツールです。

ある特定のコンピュータネットワークとその外部との通信を制御し、内部のコンピュータネットワークの安全を維持します。

 

次にapacheのインストールをします。

apacheとは世界中で使われているWebサーバーアプリケーションです。

 

apacheのインストールが完了したら、バージョン、起動の確認を行います。

その後、設定ファイルの場所を確認したら、apacheの設定を確かめ、どこにHTMLファイルを置けばhttp://xxx.xxx.xxx.xxx/index.htmlxxx.xxx.xxx.xxxにはIPアドレスが入ります)でアクセスできるかを確認し、index.htmlを作成します。

 

最後に動作確認します。

ブラウザを立ち上げ、アクセスすると!

 

・・・・・・あれ?動かないorz

 

ここから表示されない原因を探しました。

原因はfirewallのHTTPポートが開いていないこと。

HTTPポートを開け、もう1度アクセスすると・・・

 

無事、Webページが表示されました!

 

f:id:plise:20150703232828j:plain

f:id:plise:20150703232904j:plain

f:id:plise:20150703232914j:plain

今回、体験するまで、サーバー構築は難しいイメージがありましたが、実際にやってみて面白かったです。

これを機にサーバーの勉強をはじめるスタッフもいました^^

 

では、今回はこのあたりで失礼しま〜すノシ

5月スタッフ会合を行いました

5月15日にスタッフ会合を行いました。

スタッフ会合は月に1度行っていて、活動の報告や社員とスタッフの親睦会などを行っています。

 

今日はスタッフ会合で行った社員によるワークショップの様子を紹介していきたいと思います!

今回のスタッフ会合では『システム概念図を作成するワークショップ』を行いました。

 

 システム概念図とは、システムの仕組みがどういった動きをするかを大まかに分かりやすく、具体的なイメージが掴めるように図で表したものです。

 

スタッフを5グループに分けて、システム概念図の作成をしました。

演習問題にはお客様が欲しいと思った背景と基本的な要件だけが記述されており、システムをイメージしてシステム概念図を設計しなくてはいけません。

この要件を実現するにはどういった機能が必要か、この機能を使うのは誰かなどといったことを考えながら設計していきます。

この作業が想像していた以上に難しい!!

どのグループも協力しながら、一生懸命に取り組んでいました。 

f:id:plise:20150522210919j:plain

 

f:id:plise:20150522211102j:plain

 

f:id:plise:20150522210241j:plain

(↑ 内容は企業秘密のため、申し訳ありませんが伏せさせて戴きます。)

 

私たちがこのシステム概念図を作るのに30分かかっても完成できなかったの対し、社員はお客様とのミーティング時にお客様の目の前で話を聞きながらシステム概念図を作成していくとのことでした。

システム概念図を早くかつ分かりやすく作成できるようになるためにこれから練習していきたいと思います! 

新スタッフ歓迎会を行いました!

新スタッフの歓迎会を行いました!

今年度は新たに学部1, 2年生12名がスタッフに加わりました。

歓迎会には新スタッフの他に社員やPLISE運営メンバーが参加しました。ピザを食べながら会話してスタッフ、社員の交流を深めました。

f:id:plise:20150423223500j:plain

f:id:plise:20150423223000j:plain

  ↑ ロクロの受け継ぎwww

 

新スタッフは今週からプログラミング教育Primaryが始まっています。

新スタッフの皆さん、Primary頑張ってください!!