tekitoumemo’s diary

C#、.NET系の技術ブログを書いています。みんなの洋楽ランキングを運営しています。

.NET Coreで最新バージョンのC#を扱う

https://honeycombsoft.com/Content/Images/Articles/Content//40cc3e52-745d-48b8-8a09-02c21efc36e5.png

.Net Coreでは何も指定しないとC#7.0しか使えません。こんなエラーが出ます。

Feature '新機能' is not available in C# 7.0. Please use language version 7.1 or greater.
7.1以上にあげなさい

7.1以上にあげる場合はcsprojに以下を記載します。

<LangVersion>7.1</LangVersion>

常に最新にしたい場合は「Latest」を指定。現在は7.3です。

<LangVersion>Latest</LangVersion>

C#は言語のバージョンによる影響が少ないので「Latest」で十分運用出来ると思います。非同期Main使えんなーと思ったらこれだったのね。

Azure App Serviceでgit submoduleが動くか

GithubからAzure App Serviceにデプロイする場合、ボタンポチポチで出来るのですがAzure App Service on LinuxだとちょっとKuduを弄らなければいけなかったので、同じようにgit submoduleもデプロイ時に取得してきてくれるのか確認してみました(Jenkinsとかちょっと工夫が必要なのでめんどい)。

git submoduleとは

外部の git リポジトリを、自分の git リポジトリのサブディレクトリとして扱える仕組みです。外部のリポジトリのブランチ単位でなく、コミット単位(CommitID)で管理するので初めて利用する人はちょっと手こずりますが理解出来ると結構便利な機能です。ちなみにsvn:externalsと同じように扱うと地獄なので、変更の少ないライブラリに利用するといいかもしれません。
Git - Submodules

git submoduleを用意する

配置したいディレクトリでsubmoduleを追加します。

git submodule add {url}

そしてgithubにpushすると以下のような感じになります。「@」の後ろはコミット番号になりますのでブランチは関係ありません。ちなみにDapperSlackOffは、Dapperの拡張ライブラリ(僕が作った)なので頻繁に変更するものではありません。DapperSlackOffはもうちょい安定したらブログに書きます。
submodule
f:id:tekitoumemo:20181125210550p:plain

デプロイする

デプロイ方法は前回書いた記事を参考にしてください。Windowsの場合は、スクリプトとアプリケーション設定がいりません。
tekitoumemo.hatenablog.com

結果

余裕でデプロイ出来た、動作も問題なし。
f:id:tekitoumemo:20181125211104p:plain

結論

Azure便利。submoduleは極力使わないが鉄。

Rechartsを使ってみたけどグラフの使い方って難しい。。

https://saitoxu.io/images/2018/02-28-ogp.png

みんなの洋楽ランキングでランキングのグラフを作りたいと思ったのでRechartsに挑戦したけど、結局断念する結果となりそうです。いろんな要因があったので、使い方を含めここで説明しようかと思います。

ランキング形式に向いていない!(っぽい)

ランキングは10位→1位と数が小さくなるほどグラフが上に上がり、通常のグラフは数が大きくなるほとグラフが上に上がります(以下の画像参照)。

ランキング
https://1.bp.blogspot.com/-7yWQqujkWiM/VJ6qx16El5I/AAAAAAAACos/jceIrn_QXs4/s1600/010.jpg
通常のグラフ
f:id:tekitoumemo:20181120235614p:plain

Rechartsでランキング形式にするには非常にめんどくさく、ごまかしながら実装する手法が必要のようです。Reactで実装したのですが、ざっと以下のようになりました。

import React, { Component } from "react"
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip } from "recharts"

export class ChartRanking extends Component {
  render() {
    const data = [
      { name: '', 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10 },
      { name: "a", uv: 1 },
      { name: "b", uv: 3 },
      { name: "c", uv: 2 },
      { name: "d", uv: 4 },
      { name: "e", uv: 3 },
      { name: "f", uv: 2 },
      { name: "g", uv: 4 },
      { name: "h", uv: 5 }
    ]
    return (
      <div className="App">
        <LineChart width={600} height={500} data={data}>
          <XAxis dataKey="name" angle={90} height={90} textAnchor='start'/>
          <YAxis type="category" interval={0} />
          <CartesianGrid strokeDasharray="3 3" />
          <Tooltip />
          <Line dataKey="10" stroke="#ffffff" style={{ display: "none" }} />
          <Line dataKey="9" stroke="#ffffff" style={{ display: "none" }} />
          <Line dataKey="8" stroke="#ffffff" style={{ display: "none" }} />
          <Line dataKey="7" stroke="#ffffff" style={{ display: "none" }} />
          <Line dataKey="6" stroke="#ffffff" style={{ display: "none" }} />
          <Line dataKey="5" stroke="#ffffff" style={{ display: "none" }} />
          <Line dataKey="4" stroke="#ffffff" style={{ display: "none" }} />
          <Line dataKey="3" stroke="#ffffff" style={{ display: "none" }} />
          <Line dataKey="2" stroke="#ffffff" style={{ display: "none" }} />
          <Line dataKey="1" stroke="#ffffff" style={{ display: "none" }} />
          <Line dataKey="uv" stroke="#8884d8" />
        </LineChart>
      </div>
    )
  }
}
微妙①

かなりごまかしごまかしで実装する必要があります。
これとか↓

{ name: '', 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10 },
...
<Line dataKey="10" stroke="#ffffff" style={{ display: "none" }} />
<Line dataKey="9" stroke="#ffffff" style={{ display: "none" }} />

詳しい説明はココに書いてあります。

微妙②

データの定義順序に依存しないためにダミーを入れてるので1列目が空白になっちゃう。
f:id:tekitoumemo:20181121001458p:plain

微妙③

これはRecharts関係ないですが、X軸が増えるとサイズが大きくなります。スマホだと横スクロールは微妙なので何列にするか制限かける必要があり非常に微妙です。

その他、Quitaに書いてなかったこと

ラベルの開始位置?

textAnchor='start'

f:id:tekitoumemo:20181121001901p:plain

textAnchor='end'

f:id:tekitoumemo:20181121001941p:plain

Y軸の間隔調整

// 数値が大きいほど間隔が大きくなる
interval={0}

結構機能は揃っているので、深掘りすればいい感じになるのかも知れませんがそこまでする必要がない理由が出てきました。

ランキングにグラフは不要

折れ線グラフは時間の経過に応じて変化する情報を見るものですが、ランキングは時間の変化によって読みとれる情報がほとんどないことがわかりました。例えば3位から1位に変化した場合に順位が上がったの要因が想像出来ません。それだとユーザーからみてなんとなくヒットしたんだろうなー程度の間隔で終わってしまうことが想像出来ました。

スマホには向かない

先ほども述べましたが、X軸が増えると横幅が大きくなります。そのために数を制限してグラフを作っても正しいデータじゃないのであまり意味がないと判断しました。ちなみに洋楽はトップ10に20周ランクインする曲が普通にあるのでX軸が増える可能性が高いのです。以下のようなスマホでグラフを実装してるアプリがありますが、やっぱりデータから読みとれる情報が少ないとあまり意味がなさないですね。
f:id:tekitoumemo:20181121004945p:plain
アップルのヘルスケアアプリですが、数値が低いとサポッたか体調が悪かったかなど読み取れます。

別にグラフじゃなくていいんじゃないかな

某ブログでエクセルで作ったグラフを乗っけているマニアの人がいて、いいなぁ〜と思いましたがユーザーからするとマニアックな情報なんてそうそう必要ないんじゃないかと思いました。みんなの洋楽ランキングの記事を見てくれた曲がどれだけヒットしているか知ってほしいので、グラフじゃなく数値で示せればある程度はいいのでは?と思いました。Spotifyのpopularityって項目はアーティストがどれだけ知名度があるか示している項目で100に近づけばだいたい知ってるよって指標になっています。あと、どれだけヒットしているか知ってほしい理由として注目されているものほど興味がわくという研究結果が出ている(どっかの記事でみた)ので他のページも見てくれるだろうと思っています。


なんかキュレーションサイトって簡単そうに見えて結構難しいんだなーと実感しました。

Azure SQL Databaseのスケールアップする方法

f:id:tekitoumemo:20181117225845p:plain
Azure SQL Databaseを調べると以下のような記事が出てきました。

docs.microsoft.com
qiita.com

えっ?ボタンポチポチでスケールアップ出来ないの!?

いやPaas使う意味!それどころかクラウド使う意味ねぇ!と思ったのでAzureいじったら簡単にスケールアップ出来ましたので、載せときます。

SQLデータベースの[設定]をクリック

f:id:tekitoumemo:20181117224121p:plain

こんな画面が出てくるので適当なプランでスケールアップするだけです。
f:id:tekitoumemo:20181117224221p:plain

これだけ、ちょー楽。

軽くプランについて

正直ここら辺は全く知らないけど、とりあえず2つの指標によって値段が変わります。ここで出てくるDTUとは以下の通りです。

DTUとは、SQL Database のデータベースの処理性能を表す単位であり、SQL Databaseにおける各サービスレベルの性能を表す為の指標の1つです。
DTUはベンチマークテストにより、弊社が独自で決めており、具体的には、各サービスレベルのCPU、メモリ、およびディスクの読み書きを組み合わせた測定に基づいて算出しております。

B1プラン

1DTU + 2Gまでで月600円ちょい
正直僕の運用しているみんなの洋楽ランキングレベルだと余裕です。たまに100%になってるのは夜間バッチで1500件ぐらいGRUD掛けてます。
f:id:tekitoumemo:20181117225231p:plain

Sプラン

100DTU(多分)+250Gまで
DTUによりけりだけど250Gの10DTUで2000円弱ぐらい。それなりのサービスで運用出来るだろう。

Pプラン

4000DTU+4Tまで
これ使うようになったら起業しましょう。

インフラは全然わからないし、やる気がしないのでPaasに全振りでお任せしたいのでスケールアップを調べました。Azureは簡単でかゆいところに手がとどくので使いやすいですね。でももっと楽に出来るサービス期待してる!

App Service on Linuxに移行が完了しました

https://i1.wp.com/itnerd.space/wp-content/uploads/2016/11/2016-11-02-14_18_26-Presentation1-PowerPoint.png?resize=624%2C254

みんなの洋楽ランキングをApp Service on Linuxに完全移行しました。やり方は以前書いた記事通りです。
tekitoumemo.hatenablog.com
ちょっと変えた点と言えばnodeのモジュールをGithubに入れたくなかったのでシェルスクリプトにnpm installを追加したぐらいです。

ここでは移行のときにやったことを書いておこうと思います。ただ、サービスを20〜30分停止してしまったのでちょっと微妙っていうのと個人サービスだから1時間ぐらいサービス止めてもいいやぐらいに考えてたので結構グダグダです。

deploy.shをちょっと変更する

App Service on Linuxではslnファイルが使えないので複数のプロジェクトがある場合はシェルスクリプトでデプロイする必要があります。僕の場合はReact使ってるのでnodeのモジュールをインストール必要があったので以下を加えました。

npm i src/
exitWithMessageOnError "npm install failed"

App Service on Linuxにデプロイする

まずデプロイしておきましょう。ドメインの移行してもサービスが動かなかったら話になりません。僕はGithubのmasterブランチにプッシュされたらデプロイする設定にしています。
f:id:tekitoumemo:20181104155948p:plain
デプロイオプションが11/26に終了するみたいです。その代わりデプロイセンターを使えとなっています。以下のメッセージが表示されていました。

Deployment Options will be leaving the App Service Menu on November 26th, 2018. Click here to try out our new Deployment Center feature replacing it.
(デプロイメントオプションは、2018年11月26日にApp Serviceメニューを終了します。新しいデプロイメントセンター機能を置き換えるには、ここをクリックしてください。)

ドメインを外す

まずはドメインを外しました。本当はドメイン外しちゃいけないのかもしれませんが、DNSレコード設定していなくてもApp Service on Linuxに設定出来ちゃったので意味不明でした。ドメイン外してApp Service on Linuxに設定するとちゃんと出来ました。
f:id:tekitoumemo:20181104155150p:plain
3点リーダーを押すと「削除」って出てくるので押下するとドメインが外されます。WindowsのAppServiceはドメインを外してしまったのでこれはApp Service on Linuxの画面ですが基本同じです。

SSL外す

次にSSLを外しました。これしないとApp Service on Linux側のSSLで「SSLがついてるからオーバーロードしますなんちゃら」って警告が出ます。
f:id:tekitoumemo:20181104155528p:plain
タブからpfxかcerが選べるのでお好きな方を。これも3点リーダーから「削除」を押下すると削除されます。

App Service on LinuxドメインSSLを設定する

以下の流れと全く一緒です。お名前.COMのDNSレコードは約10分ぐらい反映するのに時間がかかった気がします。
tekitoumemo.hatenablog.com

これでちゃんと動作するはずです。余談ですが、Let’s Encryptで期限が近づいていないのに再取得するといつもと違うメッセージが出ました。こちらは以下の記事を参考にしてください。
tekitoumemo.hatenablog.com

まだ移行してから1日も経っていないのですが、変わったところを書きます。

App Service on Linuxの無料試用期間が無期限!?

Azureのプランを作るたびに1ヶ月無料になります。つまり、1ヶ月以上使い続けなければずっと無料。作って削除して作って削除しての繰り返しだったら無料試用期間があるうちはずっと無料っぽいです。ちなみにB1プラン(安いやつやん)のみです。

メモリ使用量が10%弱変わった?

Windowsサーバーだと50%台だったのですが、Linuxサーバーだと60%台に上がりました。
Windowsサーバー
f:id:tekitoumemo:20181104161120p:plain
Linuxサーバー
f:id:tekitoumemo:20181104161207p:plain
まぁ60%なら全然許容範囲ですが、ちょっと気になります。しばやんさんが以下のようなことを書いてたのですが、いまいち理由がわからないです。

明らかにコンテナの起動時間が遅いので最低でも B2 / S2 を選ぶべきです。

App Service on Linux を本番環境で運用する際の注意点 - しばやん雑記

とにかく安くなったってのが大きいです。Windowsサーバーでやる必要がなければ、Linuxにした方が確実におトクですし、B2インスタンスWindowsのB1インスタンスとほぼ同じ値段ってのが良いですね(盛りました1500円ぐらい違います。)今だと1ヶ月無料なので検証出来るのは助かりました。

Let’s Encryptは期限切れが近づかないと更新出来ない

更新出来るんですけどね、証明書を作ろうとすると

「What would you like to do?(キミ何したいん?)」

って言われます(つらい)。そのメッセージがこれ

saito@saito-Aspire-one-1-131:~$ sudo certbot-auto certonly --server https://acme-v02.api.letsencrypt.org/directory --manual --preferred-challenges dns-01 --domain mygkrnk.com
[sudo] saito のパスワード: 
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Cert not yet due for renewal

You have an existing certificate that has exactly the same domains or certificate name you requested and isn't close to expiry.
(ref: /etc/letsencrypt/renewal/mygkrnk.com-0001.conf)

What would you like to do?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Keep the existing certificate for now
2: Renew & replace the cert (limit ~5 per 7 days)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1
Keeping the existing certificate

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Certificate not yet due for renewal; no action taken.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

証明を更新することも出来るっぽいけど、やる必要ないならやらなくていいよねーって感じっす。
更新したい人は2番を選択すればいいっぽいっす。

2: Renew & replace the cert (limit ~5 per 7 days)

.net coreでHttpClient

https://4.bp.blogspot.com/-iQ7CUthzPg8/UdYhKuwNgrI/AAAAAAAAV5k/o0tEGbK-PwI/s400/tatemono_koujou.png

HttpClientFactoryについて

めっちゃ内容薄い、他のブログ見た方が良いかも

HttpClientがとりあえずひどい作りなので、HttpClientFactoryってものがあります。HttpClientのひどい設計をカバーしたものがHttpClientFactoryです。名前もひどいもんですね。

HttpClientの何がダメなのか?

「ソケット枯渇して色々バグあるよー」ってやつです。詳しくは以下を見てください。
www.infoq.com
docs.microsoft.com
.Net Frameworkではシングルトンにして対応する必要がありました。知らなかったけど

HttpClientFactoryを使うとどうなのか?

「ソケット枯渇しないしバグもないよ!」ってやつです。詳しくは以下を見てください。
.NETのHttpClientの修正

使い方

nuget

dotnet add package Microsoft.Extensions.Http --version 2.1.1

最新が14日前でそろそろ2.2.0がリリースされると思います。

DI

public void ConfigureServices(IServiceCollection services)
{
    // これ
    services.AddHttpClient();
           
    services.AddMvc();
}
これ

Constructor Injection

public class HomeController : Controller
    {
        private readonly IHttpClientFactory _httpClientFactory;

        public HomeController(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }
}

使いたいところで注入。

GETする

var client = _httpClientFactory.CreateClient();
var result = await client.GetStringAsync({URL});

clientはHttpClientなのでいつも通りに使えばおっけいです。

そもそもHttpClientを普通に使えないのが謎ですが、まぁこんなライブラリもありますって内容でした。