Akatsukiのインターンシップに参加してきました

9月9日から9月30日までAkatsukiのサマーインターンシップに参加してきました。

取り組んだこと

取り組んだことは以下の2つになります.

N+1問題の解消

開発されているアプリケーションで、N+1が発生していました。インターンの課題として、N+1問題の解消をまず最初に取り組みました。 N+1問題に関しては、他のブログでわかりやすく解説されています。

pikawaka.com

N+1問題が実際にどこで起きているかを、ログから探しました。 以下のようなログを発見して、実際にN+1が起きている箇所を特定しました。

SELECT * FROM deck WHERE user.num = 0
SELECT * FROM deck WHERE user.num = 1
SELECT * FROM deck WHERE user.num = 2
.....

次に、ログに記録されていたSQLを実行している関数を特定して、その部分の修正を行いました。
N+1問題の対処として、includeを使うことにより対処されている記事が多いですが、今回はActiverecord-Importを利用しました。

github.com

また、キャッシュをうまく使うことにより、データフローをよくしました。 実際にN+1問題を解消することにより、以下の表に示すようにSQLの平均呼び出し回数を削減することができました。

N+1解消前 N+1解消後
Segment % Time Avg Calls(per txn) Avg Time(ms) % Time Avg Calls(per txn) Avg Time(ms)
find 4.9 18.6 24.3 2.5 4.53 12.5
select 4.4 12.0 21.8 0.1 0.258 0.447

アプリケーションの平均実行時間もN+1問題を解消することにより、520msから465msに短縮することができました。

f:id:yotiyotiaruku:20200930152349p:plain
アプリの平均実行時間 N+1解消前
f:id:yotiyotiaruku:20200930152352p:plain
アプリの平均実行時間 N+1解消後

AWSの新しいインスタンスタイプの検証

N+1問題の解消に取り組み時間が余っていたので,AWSの新しいインスタンスタイプの検証もさせて頂きました. インターンシップで参加させていただいた部署では,EC2のc5インスタンスを使っています. 現在は,c5インスタンスより新しい世代としてc5aインスタンスが登場しています.

aws.amazon.com

新しいインスタンスであるc5aはc5に比べて10%ほど値段が安くなっています. 新しいインスタンスに移行することができれば,EC2のコストも削減することができます. 実際に移行できるかを確かめるために,c5インスタンスとc5aインスタンスの比較を行いました.

インスタンスの比較としては,インスタンスにデプロイしたWebアプリケーションに対して負荷試験を行いました. 負荷試験を行った際に,CPU,メモリ使用率に変化があるかや平均レスポンスに差があるかを測定しました. 負荷試験の結果を以下の表に示します. f:id:yotiyotiaruku:20200930182310p:plain

負荷試験の結果が示す通り,CPU使用率がc5インスタンスに比べて高くなっています. リクエストもc5インスタンスに比べて捌けていません. 比較結果からc5インスタンスからc5aインスタンスにそのままインスタンスの変更はできませんが,構成を変更することにより対処できるのではないかということが分かりました.

インターンシップに参加して

サーバサイドの本格的な実装を行ったことはなかったのですが,メンターや社員の方にサポートをしていただいて楽しく業務に取り組むことができました. コロナの関係で物理的な出社は一回もせずにインターンシップが終わってしまいましたが,Zoomなどでコミュニケーションを取ることで円滑にインターンシップに参加できたかなと思います.

また,自分の課題に関してもたくさん見つけることができたので,その部分を解消していきたいと思います.

FortigateのEMAC-VLANを試す

FortigateのEnhanced MAC VLANs(EMAC-VLAN)を試してみました.

help.fortinet.com

Enhanced MAC VLANsを使った動機

自宅のインターネットでは,ISPからのDHCP(Dynamic Host Configuration Protocol)かStaticでグローバルIPアドレスをインターフェースに割り振ることにより,インターネットへとつなぐことができます.

LANコンセントは一つしかないため,DHCPを使用した場合は,固定ではないグローバルIPアドレスを使う必要がありますし,StaticなグローバルIPアドレスを使うとDHCP側のグローバルIPアドレスを使うことができません.

そこで,仮想的に複数のインターフェースを構成できるEMAC-VLANを使ってみました.

検証環境

  • Fortigate 90d
    • FortiOS v6.0.9 build0335 (GA)

EMAC-VLANの作成

まず,FortigateのGUIにログインをします. 次に,Network -> Interfacesを選択します.

f:id:yotiyotiaruku:20200606103035p:plain
Interfaces画面

次に,上の[Create New]ボタンを[Interface]を選択します.
選択すると,Interfaceの作成画面が表示されます.
この時に,Typeの部分でEMAC VLANを選択して,Addressing modeをDHCPにします.
物理的なInterfaceと紐づける部分は,wan1を選択します.

f:id:yotiyotiaruku:20200606103455p:plain
EMAC-VLAN

正常に仮想的なInterfaceが作成されると以下の画像のように,wan1の下にemac-wanが作られます. f:id:yotiyotiaruku:20200606103806p:plain また,emac-wanをダブルクリックすることにより,ISPからDHCPが払い出されているかを確認できます. f:id:yotiyotiaruku:20200606103947p:plain

WANの設定

次に物理的なインターフェースであるWAN1にIPアドレスを設定します.
こちらは,固定のグローバルIPアドレスを使用したいので,ManualでグローバルIPアドレスを設定します.(大半の方はPPPoEだと思います)

SD-WANの設定

上記の設定で,固定のグローバルIPアドレスISPからDHCP経由でプライベートIPアドレスを取得することができます.
このままでは,固定のグローバルIPアドレスからしかインターネットにアクセスしないため,SD-WAN機能を利用して,振り分けを行います.

Network->SD-WANを選択します.
SD-WANを有効化し,SD-WAN Interface Membersに EMAC-VLANで作成したインターフェースとwan1を追加します.

f:id:yotiyotiaruku:20200606104822p:plain
SD-WAN

最後に,SD-WAN Rulesの設定をします. SD-WAN Rulesにルールを追加することにより,特定のInterfaceからの通信をemac-wanのみに流すといった設定ができます. 今回はinternal2のポートから来たトラヒックemac-wanに流す設定を追加します. f:id:yotiyotiaruku:20200606105126p:plain

これで,通信ごとに違う経路でインターネットにアクセスすることができます. 以下の画像に違うインターフェースでグローバルIPアドレスを取得した結果です.

f:id:yotiyotiaruku:20200606105706p:plain
各インターフェースごとのグローバルIPの結果

最後に

今回のEMAC-VLANを使うと,複数個のグローバルIPアドレスを使うことができます.
ISPの規約によっては,禁止されているところもあると思うので自己責任でお願いします. また,今回のブログ記事の内容が規約違反するなどあれば,ご連絡をいただければ幸いです.

イトーキ スチールラックを購入

4月入り新居に引っ越しをして,本棚が必要になったのでスチールラックを購入しました.
購入した商品は,イトーキの軽量タイプRR型シリーズ ERR-143340-W7になります.

購入したサイトは,kagg.jp です.
オフィスチェアなどを以前にも購入させていただいており,サポートも充実しているのでおすすめのサイトです.

www.kagg.jp

購入から設置まで

購入してから,3週間で発送になり,作業員の方が来られて設置までをやってもらいました. f:id:yotiyotiaruku:20200606095711p:plain

使用感

以前は木製の本棚を使っていてぐらつきも結構あったのに対して,スチールラックはがっしりしているという印象があります.
規格としても,150Kg/段なので,本とかパソコンを適当においても十分耐えられるのではないかと思います.
本はなぜか倒れないのですが,本用の仕切りは欲しいなと探しています. あと,UTMなどを下の段にまとめてるのですが,寝る際にアクセスランプなどが結構まぶしいので試行錯誤をしています.

NASを40GbEに対応させる

導入目的

NASからサーバにISOをダウンロードしてくると行った際に非常に時間がかかっていました. NASとサーバ間を高速化するためです.

使用した機材

使用した機材は以下のものになります.

  • Synology RS3618xs(NAS)
    • Mellanox Connect-x3
  • サーバ
  • LinkX™Ethernet Direct Attached Copper ケーブル (MC2210130-002)

NASにHCA(Host Channel Adapter)をインストールさせたあと,DACケーブルを使いサーバとNASをつなぎました.

InfinibandをEthernetに切り替える

購入してきたままのMellanox Connect-x3ではInfinibandしか使うことができないため,Portの設定をInfinibandからEthernetに切り替えます. 以下のブログを参考にさせていただきました. 家庭向け(仮) 40GbE NIC 導入方法 この切替はNASの端末で行うのは難しいため,別の端末を利用して行いました(NASでもシェルを使うことはできますが,パッケージマネージャがなかったため)

次に切り替えたHCAをNASにインストールします.使用していたNASは拡張用のPCIeに刺すだけで認識されました.

速度テスト

NASにHCAをインストールしてNAS側から認識されているかを確認します.

$ sudo ethtool [interfaceの名前]

Settings for eth4:
        Supported ports: [ FIBRE ]
        Supported link modes:   1000baseKX/Full 
                                10000baseKX4/Full
                                10000baseKR/Full
                                40000baseCR4/Full
                                40000baseSR4/Full
                                56000baseCR4/Full
                                56000baseSR4/Full
        Supported pause frame use: Symmetric Receive-only
        Supports auto-negotiation: Yes
        Advertised link modes:  1000baseKX/Full
                                10000baseKX4/Full
                                10000baseKR/Full
                                40000baseCR4/Full
                                40000baseSR4/Full
        Advertised pause frame use: Symmetric
        Advertised auto-negotiation: Yes
        Link partner advertised link modes:  40000baseCR4/Full
        Link partner advertised pause frame use: No
        Link partner advertised auto-negotiation: Yes
        Speed: 40000Mb/s
        Duplex: Full
        Port: Direct Attach Copper
        PHYAD: 0
        Transceiver: internal
        Auto-negotiation: on
        Supports Wake-on: d
        Wake-on: d
        Current message level: 0x00000014 (20)
                               link ifdown
        Link detected: yes

認識されているのが確認されたので,DACケーブルを使いサーバとNASを接続します. (今回した使用したHCAは規格としてはQSFPでありQSFP+と互換があるのかを調べてみましたが,資料は見つけれませんでした.QSFP+と接続したところ,リンクアップをしたので恐らく対応していると思います)

接続後にIPアドレスを設定して,疎通性があるか確認します.

$ sudo ip address add  [ip address] dev [interface name]
$ ping [target ip address]

NASにiperf3をインストールしてiperf3サーバを立ち上げます.

$ iperf3 -s

Server側からNASのiperf3サーバにアクセスします

$ iperf3  -c [NASのIP address]
Connecting to host 192.168.100.5, port 5201
[  4] local 192.168.100.7 port 49768 connected to 192.168.100.5 port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-1.00   sec  2.47 GBytes  21.2 Gbits/sec    0    933 KBytes
[  4]   1.00-2.00   sec  2.87 GBytes  24.6 Gbits/sec    0    933 KBytes       
[  4]   2.00-3.00   sec  2.87 GBytes  24.7 Gbits/sec    0    933 KBytes       
[  4]   3.00-4.00   sec  2.87 GBytes  24.7 Gbits/sec    0    933 KBytes       
[  4]   4.00-5.00   sec  2.88 GBytes  24.7 Gbits/sec    0    933 KBytes       
[  4]   5.00-6.00   sec  2.87 GBytes  24.6 Gbits/sec    0    933 KBytes       
[  4]   6.00-7.00   sec  2.88 GBytes  24.8 Gbits/sec    0    933 KBytes       
[  4]   7.00-8.00   sec  2.87 GBytes  24.6 Gbits/sec    0    933 KBytes       
[  4]   8.00-9.00   sec  2.88 GBytes  24.7 Gbits/sec    0    933 KBytes       
[  4]   9.00-10.00  sec  2.88 GBytes  24.7 Gbits/sec    0    933 KBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.00  sec  28.3 GBytes  24.3 Gbits/sec    0             sender
[  4]   0.00-10.00  sec  28.3 GBytes  24.3 Gbits/sec                  receive

20Gbit/sec以上でており,サーバとNAS間のファイル転送が高速化できました.

PJLinkを使いプロジェクターを操作する

Ricohのプロジェクターを操作する

研究室で使用しているRicohのプロジェクターを手元から操作をしたかったので,そのような規格がないか探していました.Ricohのプロジェクターで対応している規格は複数個あったのですが,一番ドキュメントが充実していたPJLinkという規格を使用して操作をしてみました.

PJLinkの仕組み

以下に図がPJLinkの一通りの流れになります(https://pjlink.jbmia.or.jp/data/5-1_PJLink_20131210.pdfから引用).

  1. TCPでコネクションを確立する.
  2. プロジェクタからネゴシエーションのためのコードを受け取る.
  3. クライアント側からコマンドを送信する.
  4. 30秒以内であれば,何回もコマンドを送信できる. https://pjlink.jbmia.or.jp/data/5-1_PJLink_20131210.pdfから引用

公式からPJLinkを試すためのソフトが公開されていますが,今回はGUIからではなくCLIから操作を行いたいので,RustでCLIツールを作りました.

use std::io::{Error, Read, Write};
use std::net::{TcpListener, TcpStream, Shutdown};
use std::str::from_utf8;
use std::net::ToSocketAddrs;
use structopt::{clap, StructOpt};

#[derive(StructOpt, Debug)]
#[structopt(name = "joseph")]
#[structopt(setting(clap::AppSettings::ColoredHelp))]
struct Opt {
    #[structopt(name = "CMD")]
    command: String,

    #[structopt(name = "parrameter")]
    transmission: String,
}


fn main() {
    //command argument
    let opt = Opt::from_args();
    //println!("{:#?}", &opt);
    
    let command = &opt.command;
    let transmission_parameters = &opt.transmission;
    println!("{} {}", command, transmission_parameters);

    match TcpStream::connect("[プロジェクターのIP]:4352") {
        Ok(mut stream) => {
            println!("Successfully connected to server");
            let mut data = [0 as u8; 9];
            
            stream.read_exact(&mut data);
            let negotiation = from_utf8(&data).unwrap();
            println!("{}", negotiation);
            send_command(stream, command, transmission_parameters);
        },
        Err(e) => {
            println!("Failed to connect: {}", e);
        }
    }
}

fn send_command(mut stream: TcpStream, command: &str, transmission_parameters: &str) {
    let command_header = "%1";
    let separater = " ";
    let terminal_symbol = "\r";
    let send_command = command_header.to_owned() + command + separater + transmission_parameters + terminal_symbol;
    println!("{}", send_command);
    let mut recv_data = [0 as u8; 9];
    stream.write(send_command.as_bytes()).unwrap();
    // recv_data 
    stream.read_exact(&mut recv_data);
    let result = from_utf8(&recv_data).unwrap();
    println!("{}", result);
}

コマンドの構造

PJLinkでのプロジェクターに送信するコマンドについて,示します.

ヘッダークラス コマンド本体 セパレータ 送信パラメータ 終端(CR)
2バイト 4バイト 1バイト 128バイト以内 1バイト

コマンドの例を示します.

ヘッダークラス コマンド本体 セパレータ 送信パラメータ 終端(CR)
%1 POWR 1 \r

コマンド一覧

以下のコマンドは実際にプロジェクターに送信して実行がされたものになります.(ヘッダークラスと終端記号は除く) 機種によってはコマンドのパラメータが違うと思うので,実際にパラメータを送信して確認してみてください.

コマンド パラメータ 期待される結果
POWR 0 電源オフ
POWR 1 電源オン
POWR ? 電源状態問合せ
INPT 31 HDMI入力に切り替わる
INPT 41 USB入力
INPT 51 ネットワーク経由入力
INPT 53 Miracast入力
NAME ? プロジェクタ名の問い合わせ

参考資料

PjLink仕様書

NTT セキュアプラットフォーム研究所のインターンシップに参加してきました

TL;DR

NTT セキュアプラットフォーム研究所のインターンシップに参加してきました。 f:id:yotiyotiaruku:20190421084346j:plain

参加するまで

書類選考→参加決定という流れでした。提出した書類では現在取り組んでいる研究テーマや応募理由を書いて出しました。 自分が取り組みたいテーマを選択できる形式だったのですが、修士以上でないと参加できないテーマがありさすが研究所だなと感じました。
書類を提出してから、1ヶ月後ぐらいに合格の通知をいただき非常に嬉しかったのを覚えています。

取り組んだこと

2月4日から3月1日の4週間ほど参加させていただきました。
取り組んだ内容としては「監査ログを用いたサイバー攻撃の全容解明技術の実装と評価」を行いました。 詳しいことはあまり書けないですが、論文を読んで実装して評価を行うことを1ヶ月を通して取り組んでいました。

感想

  • 優秀な研究者の方が周りに居られるなかで、一ヶ月研究をさせていただけて非常に勉強になりました。
  • メンターさんからも非常に丁寧に研究のやり方や様々なことを教えて頂けて、圧倒的に成長をすることができたインターンシップでした。
  • 企業での研究ということもあり、実際の現場で応用できるように研究をされていたことも印象的でした。

最後になりましたが、メンターさんを始め研究所の皆様、本当にありがとうございました。

(公開をしてはいけない部分などあれば、ご連絡ください。)

カヤックのインターンシップに参加しました

初めに

インターンシップの記事を書くのが大変遅くなってしまいましたが、8月6日から10日までの5日間カヤックインターンシップに参加させていただきました。 配属先としてはインフラチームに配属させていただき、インフラのことをやっていました。

f:id:yotiyotiaruku:20181216195929j:plain
カヤック

参加するまで

選考としては、作ったもの選考を選択しました。人事面接、エンジニア面接、役員面接と3回面談があり、インターンでも丁寧に選考されるんだなという印象でした。 配属される部署などはある程度自分で選択できることができて非常にありがたかったです。カヤックさんはISUCONが強いイメージがあったので、インフラ部署を希望して参加させて頂きました。

インターンシップ

インターンシップでは、Chefを使ってサーバに対してメトリクスを取るエージェントをインストールする作業と社内ISUCONをやらせていただきました。 Chefを使った作業では、あまり触れていなかったChefの使い方であったり、どのようにコードを書けばいいのかをコードレビューしていただけ非常に勉強になりました。 社内ISUCONでは、業務時間1日を使い高速化を行いつつ、どうすれば高速化できるかを教えていただけて、本当に楽しかったです。

最後に

自分のコードの書き方やインフラに関する知識などが圧倒的に足りていないことを実感でき、とても楽しかったです。 藤原さんを始め、インフラ部の社員さんやお昼を一緒に食べに行った皆様、本当にありがとうございました。

f:id:yotiyotiaruku:20181216195927j:plainf:id:yotiyotiaruku:20181216195923j:plain