お楽しみはこれからだ!
2015年4月13日月曜日
2014年5月22日木曜日
Amazon RDS for SQLServerはミラーリングだった
ディスクのスナップショットでしょー。データ欠落することもあるんだろーなー。なんて適当なこと言ってマジすいません。
インスタンス立てて確認しました。マジ、ミラーリングでした。調子乗ってすいませんでした。データベース作ってしばらくすると、見慣れたあの表示。
作りたては、まだミラーリング準備中なんだろね。確認してないけど。
テーブル作ってテストデータ100万レコード作成中にいきなり!
この見慣れた「プリンシパル、同期済み」が出てきた。
あー。ちゃんとミラーリングやー。相方のサーバー名も違うやつだし、ウィットネスもいた。
なのに接続先は固定でfailover partner指定とかないんだぜ!そこはエンドポイントが受け付けて、そこから先にうまいこと繋げてるんだろね。
ここから先はビールでマッチョなお方、おねげーします。
2014年5月21日水曜日
URLRewriteでほとんどすべてCDNに向ける
HTMLの書き換えルールをURLRewriteでセットすれば、環境設定だけでCDN向けたりできるよー、っていうのを書いたのはいつの話だろう...。
URLRewrite+CloudFrontでパフォーマンスを取り戻す http://takepara.blogspot.jp/2011/12/urlrewritecloudfront.html
いまや、猫も杓子もCDN使うじゃないですか。
CloudFront/KeyCDNもHTTP Methodうまいこと処理できるようになってるから、オリジンにガッツリかぶせて(サイトの公開URLをCDNに向けてすべてのリクエストをCF経由オリジン行き)しまうっていうアプローチもありですし。
とはいえ、トラフィックあれだしー、証明書もなんだしー、お金かかるっしーなっしー、だとやっぱりURLRewriteですよね。
でもね、前のエントリの方法だと、SRC属性がちゃんと"/"で始まってることを条件にしてたんです。そうは問屋が卸さない書き方をすることもあるですよね。ルール厳しいと比較的低コストで最適化できるからいいのにー、という理屈は通りませんよ。
なので、こうなったらIMG/SCRIPT/LINKガッツリ全部書き換えてやる!でも、絶対参照やスキーム相対でホスト名込のものはそのまま残す。
前回の方法はSRC属性(ターゲットPATH)のみのパターンマッチでやってたけど、今回はリクエストURLも参照することでより広範囲に適用。もちろんパターンマッチはするんだけど、それはホスト名指定を救いたいから、という意味で、特定パスのマッチとはちょっとアプローチが違います。
考えられる組み合わせとして、リクエストURLが"/"で終わってるか、終わってないか。ターゲットPATHが"/"で始まってるか、始まってないか。の、組み合わせで4パターン。だけどターゲットPATHが"/"で始まってる絶対パス指定はリクエストURLにかかわらず、絶対パスなので実質3パターン。
- リクエストURLが"/"で終わってない
http://localhost/rewrite - リクエストURLが"/"で終わってる
http://localhost/rewrite/
- ターゲットPATHが"/"で始まってない
<img src="images/logo.gif" />
<img src="./images/logo.gif" />
<img src="../rewrite/images/logo.gif" /> - ターゲットPATHが"/"で始まってる
<img src="/rewrite/images/logo.gif" /> - 例外的にhttp/httpsで始まってるものと、"//"のスキーム相対で始まってるもの
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.1.min.js"></script>
なので、3パターンの組み合わせに対して、Rewriteするルールを作成すれば、ターゲットPATHそのものに対するパターンマッチを行う必要がなくなる(特定のパスを指してるものだけをCDNに向けるようなRewriteをしない)ので、コーダーの書き方に依存したRewriteにならないはず。
これらのコンテンツがRewriteで正しく表示されるように考えたルールが↓これ(CDNのホスト名はlocalhost扱い)。
<?xml version="1.0"?>
<configuration>
<system.webServer>
<rewrite>
<outboundRules>
<rule name="HttpCdnPathAbsolute" preCondition="html" enabled="true">
<match filterByTags="Img, Link, Script" pattern="^/[^/]+(.*)$" />
<action type="Rewrite" value="//localhost{R:0}" />
<conditions>
<add input="{HTTPS}" pattern="off" />
</conditions>
</rule>
<rule name="HttpCdnPathRelativeSlashEnd" preCondition="html" enabled="true">
<match filterByTags="Img, Link, Script" pattern="^((?!/.*)(?!//.*)(?!http.*)(?!https.*))(.*)$" />
<action type="Rewrite" value="//localhost{PATH_INFO}{R:0}" />
<conditions>
<add input="{HTTPS}" pattern="off" />
<add input="{REQUEST_URI}" pattern="/$" />
</conditions>
</rule>
<rule name="HttpCdnPathRelativeUnslashEnd" preCondition="html" enabled="true">
<match filterByTags="Img, Link, Script" pattern="^((?!/.*)(?!//.*)(?!http.*)(?!https.*))(.*)$" />
<action type="Rewrite" value="//localhost{PATH_INFO}/../{R:0}" />
<conditions>
<add input="{HTTPS}" pattern="off" />
<add input="{REQUEST_URI}" pattern="[^/]$" />
</conditions>
</rule>
<preConditions>
<preCondition name="html">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="text/html" />
<add input="{RESPONSE_STATUS}" pattern="^[45].*$" negate="true" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
↑これはHTTPの時だけCDNにっていう設定なのでconditionsにHTTPSが”off”って入ってる。HTTPSも同じホストに書き換えていいなら、そこ削除で。HTTPSの時は違うホスト名にしたい場合、同じ組み合わせをもういっちょHTTPS用に登録してね。
何もしなかった時のレンダリング結果
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Rewrite Test</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="./jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="../rewrite/jquery-1.10.1.min.js"></script>
</head>
<body>
<img src="/rewrite/images/logo.gif" /><br />
<img src="images/logo.gif" /><br />
<img src="./images/logo.gif" /><br />
<img src="../rewrite/images/logo.gif" /><br />
</body>
</html>
フォルダ構成としては
/rewrite
/rewrite/index.cshtml
/rewrite/images
/rewrite/images/logo.gif
これをイメージ。
リクエストURLが"/"で終わってない時のレンダリング結果
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Rewrite Test</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="//localhost/rewrite/index.cshtml/../jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="//localhost/rewrite/index.cshtml/.././jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="//localhost/rewrite/index.cshtml/../../rewrite/jquery-1.10.1.min.js"></script>
</head>
<body>
<img src="//localhost/rewrite/images/logo.gif" /><br />
<img src="//localhost/rewrite/index.cshtml/../images/logo.gif" /><br />
<img src="//localhost/rewrite/index.cshtml/.././images/logo.gif" /><br />
<img src="//localhost/rewrite/index.cshtml/../../rewrite/images/logo.gif" /><br />
</body>
</html>
リクエストURLが"/"で終わった時のレンダリング結果
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Rewrite Test</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="//localhost/rewrite/jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="//localhost/rewrite/./jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="//localhost/rewrite/../rewrite/jquery-1.10.1.min.js"></script>
</head>
<body>
<img src="//localhost/rewrite/images/logo.gif" /><br />
<img src="//localhost/rewrite/images/logo.gif" /><br />
<img src="//localhost/rewrite/./images/logo.gif" /><br />
<img src="//localhost/rewrite/../rewrite/images/logo.gif" /><br />
</body>
</html>
リクエストURLが"http://localhost/rewrite/index.cshtml/"となってる時のレンダリング結果
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Rewrite Test</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="//localhost/rewrite/index.cshtml/jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="//localhost/rewrite/index.cshtml/./jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="//localhost/rewrite/index.cshtml/../rewrite/jquery-1.10.1.min.js"></script>
</head>
<body>
<img src="//localhost/rewrite/images/logo.gif" /><br />
<img src="//localhost/rewrite/index.cshtml/images/logo.gif" /><br />
<img src="//localhost/rewrite/index.cshtml/./images/logo.gif" /><br />
<img src="//localhost/rewrite/index.cshtml/../rewrite/images/logo.gif" /><br />
</body>
</html>
明らかに参照パスがおかしい(階層が一個浅い)んだけど、この場合も救いたいとなるとかなりヘビー。なんでかというと、階層構造を無視してる指定になってるから。 現状ではこういうリクエスト時に末尾の"/"を削除したURL(canonical url)にリダイレクトするようにすればうまくいくぜ!たぶん。きっと。
2014年5月14日水曜日
KRuntimeとかMVCとかちょっと触ってみた
もうみんな、ASP.NET vNEXTっていうか、.NETでの開発方法の変更が気になって仕方ないすね。
ここまで変えてくるのかよ!っていうくらい感動的。.NET初めて出てきた時くらいのワクワクですねー。
とりあえず、KVMつかってみよー。
https://github.com/aspnet/home
に書かれてること素直にやるだけす。
cloneしてkvmsetup。
PowerShellでもCmdでも。それぞれ別々にね。
kvm install なんちゃらかんちゃらで .kreにランタイムをごっそり。MyGet。
で、Samples/ConsoleAppでkvm restore。これで、一個上のpackagesに色々ごっそり。MyGet。
あとはもうk run。
すげー!Hello World。binがないー!!し、Tempにcscなら吐き出すはずのものがないー!
あ、SET KRE_TRACE=1ね。
klr.exeさんよー!中でRoslynだねー。
KRuntime structure
https://github.com/aspnet/Home/wiki/KRuntime-structure
次。HelloWeb。k runじゃなくてk web。
StaticFilesモジュール。いや、StaticFileMiddleware。これもpackagesにMicrosoft.AspNet.StaticFiles.dllとしてMyGet。
Task Invoke(HttpContext context)なんだけど、そうでしたっけ?
Task Invoke(IDictionary
次。HelloMvc。
同じですね。k webですね。
うほ。うごきよる。しかもRazorリポジトリにごっそり入ってるから、移行中なんだね。すげーなー。
Microsoft.AspNet.Mvc.Razorのソースみたら、ICompilationServiceの実装がRoslynCompirationService。BuildManager使わないんじゃん!kprojって拡張子気になるけどおいとこ。やべー。興奮してきた。Razorはまだcshtmlしか実装してないみたい。vbhtmlのコードがなかった。
Microsoft.AspNet.Mvcがどこまで移行してるのか、試しに、HomeControllerとIndex.cshtmlをいじってみたよ。
Controllers/HomeController.cs
Views/Home/Index.cshtml
ModelBindするかなー。って程度の確認ですけどね。
するがな!
すごいがな!
ブルブルしてきた。超ブルブルしてきたSystem.Web完全に分離できてるー。かっけー。そんなの当分先になると思ってたのにー。MVC6でも参照なくすんかいー。
ちょっと、こう、やべし。超楽しい。どこかのLINQの人じゃないけど、超楽しい。
まだIISで動かしてない(KLR上で動かすだけだからビルドじゃなくて実行しただけ)から、Heliosだとどんなbinになるのか気になるしー。App_CodeとかASP.NETでのシステムフォルダの扱い(app_globalresourcesとかさー)がどこまで行けるようになるのかなー。たまらん!
ん?
the assemblies never exist on the disk.
んん!?
・No-compile developer experience
って書いてるね...。まじか。ビビった。
2014年5月9日金曜日
スレッドスロットルなんか普通しなくてもいいのにね
個別アプリケーションごとにVMがあったりとかー、そういうんだと、そんな時は maxConcurrentThreadsPerCPU とかでー、でしょうか。あ、maxWorkerThreads とかでも。
なんでそんなことが必要なんですか。そもそもCPU Throttlingでいいじゃないですかー。と、いうのもあるんですけど、そもそもマシンパワーのあまりない環境とかだと、返事が返ってこないです。解決方法はいろいろあるなかで、強制的にリクエストをキューから取り出さなきゃいいじゃないと思った結果がSetMaxThreads。
private int ThreadPoolThrottle
{
get
{
return int.Parse(ConfigurationManager.AppSettings["ThreadPoolThrottle"] ?? "0");
}
}
{
// 重いテンプレートの場合これ。
int workers;
int completions;
System.Threading.ThreadPool.GetMaxThreads(out workers, out completions);
System.Threading.ThreadPool.SetMaxThreads(ThreadPoolThrottle, completions);
}
2014年5月1日木曜日
CSVを今っぽく
一般的には","カンマで区切るんだと思います。
でも、ダブルクォート使いたいしー、っていうんで"TAB"タブ区切りにしちゃったり。
さらに、用途によっては改行入らないから、ダブルクォート内での改行処理とかなくてもいいよー、っていうのがよくあるパターンかなー、と思ったりもします。
簡単に整理すると
- カラム区切りはタブ
- カラム内に改行はない
- レコードの区切りは改行
- 1行目はカラム名を指定するヘッダ
- 2行目以降がレコード
このくらいの緩いルールで実装するっていうのを前提にしてみようと思います。
ところで、CSVって1行目からデータ派?それとも1行目はヘッダー派?ヘッダーが入ったらCSVじゃないよー、とかっていう原理主義もあろうかと思うけど、そこは気にせずにぜひ。1カラム目がHならヘッダーレコード、Dならデータレコード、とかっていう構造をもつものはそもそもそれに適したJSONやXMLがいいので、その話も今回はないってことにしてください。
前置きなげー!
本題は、CSVを可変長カラムにするほうがみんな幸せなんじゃない?っていうのとModel Validationで検証するほうが何かと楽ちんじゃない?です。
可変長カラムっていうのはどういうことかっつーと、そもそもCSVで取り込むデータを何らかのPOCOに入れて保持するっていうのを前提に、そのあとデータストアに反映するとか、そのあとの処理に流す、っていうふうに考えると、POCOならコンストラクタで初期値セットするなり、何もしなかったら型の初期値が入ってるから、そのままの値を次の処理に渡せばよろしい、っていう使い方でよければ、そもそもCSV内にそのカラムなくてもいいよね!
で、Model Validationって言ってるのは、POCOにデータいったん入れるんなら、そのタイミングでDataAnnotations使って、モデル検証しちゃえばいいよね!
ビジネスルールを適用して、さらなる検証を行いたい(特定のIDがデータストアに存在するのかとか、外部サービスに依存してるものはModel Validationで行わない)場合は、さらに上位のレイヤで処理すれば、いろいろ疎結合だし、テストも楽ちんでしょーがー。使いまわせるしね。
そんなのそうしてますから!っていういまどきの方々は面白くない話なんですけど、身近なところでは、そーなんだー、という話にもなったので。
なんで、CSVを固定カラムじゃないほうがいいと思ったのか、っていうのは(一般的じゃない理由かもしれないけど)データストアの拡張とか、処理の拡張に対して、CSVフォーマットが紐づいててほしくない、影響範囲に含めたくないから。っていうのと、マルチテナント展開するシステムだと、外部で生成されるCSVを、自システムに取り込む、っていうフローがほとんどだけど、機能拡張のたびに外部での生成方法変えて、とは言いずらい。し、言ってたらペースが外部に依存して、すごく遅くなるから。
CSV作る人(そこをシステム化してるかどうかはあまり重要じゃないですね)と、そのCSVを自システムに処理させる、っていう業務を、いろんな意味で疎結合。の、イメージす。
んー、うまく言えてないすね。さーせん。ようするにフォーマットが疎じゃないと不便だったから、です。んじゃ、CSVにするなよ!みたいなね。でも、Excelでデータつくるじゃん!
ここまでで、もうイメージできた人も多いと思うけど、せっかくなので、コードでどう表現するのかを書いてみます。
これってコードにすると、
var columns = line.Split(splitChar);
とか、ですね。
1行目ならそこにはカラム名(これの一覧はPOCOにセットするために保持しとく)が入ってて、1行目以降ならそれはデータ。っていうのを、上位層で判定。
これで、レコードをカラムに分割できました。
今度はカラム名の一覧と、モデルクラス(ジェネリックでしょうね)のプロパティをマッピング。
var properties = TypeDescriptor.GetProperties(type);
これで一応POCOのプロパティ一覧(PropertyDescriptorCollection)は取得できましょう。キャッシュするかどうかはお好きに。
あとは、もう単純にくるくるループ回していけば、いいですよね!PropertyDescriptorがあれば、Converter.ConvertFromStringでプロパティにセットできるか判定もね。
後は、DataAnnotationsを指定してるかもしれないから、Validator.TryValidateObjectで、モデル検証。
public static IList
{
var lineNumber = 0;
var mappings = new ColumnMapping[] { };
var result = new List
foreach (var line in LoadLine(text))
{
var rowErrors = new List
var columns = ParserHelper.SplitLine(line, SplitChar);
lineNumber++;
if (lineNumber == 1)
{
// 1行目のヘッダからマッピングカラム判定
mappings = GenerateColmunMappings
continue;
}
var model = new T() { IsValid = false, LineNumber = lineNumber - 1 };
result.Add(model);
// マッピングと数が一致してない行はエラー
if (columns.Length != mappings.Length)
{
rowErrors.Add("ヘッダのカラム数と一致しません");
continue;
}
// カラム値をマッピング
foreach (var map in mappings)
{
var value = columns[map.Index];
// 無効カラムはスキップ
if (!map.IsValid)
continue;
// 値の正規化
value = ParserHelper.NormalizeString(map.PropertyDescriptor, value);
// 値の型変換可能かチェック
if (!ParserHelper.IsValidValue(map.PropertyDescriptor, value))
{
rowErrors.Add("カラムの型が適切ではありません(" + map.HeaderName + ")");
}
else
{
map.PropertyDescriptor.SetValue(model, ParserHelper.ConvertFromString(map.PropertyDescriptor, value));
}
}
// DataAnnotationでモデル検証
var validationResults = new List
ModelValidator.Validation(model, validationResults);
rowErrors.AddRange(validationResults.Select(vr => vr.ErrorMessage));
model.IsValid = !validationResults.Any();
if (!model.IsValid)
{
model.ErrorMessage = string.Join("\n", validationResults.Select(vr => vr.ErrorMessage));
}
// なんかやりたかったらどうぞ
if (action != null)
{
action(model);
}
}
return result;
}
で、これのいいところはヘッダにカラム名してして、その名前をキーにプロパティにセットするから、CSVのフォーマットとして並び順が全く重要じゃなくなる。悪いところ?まぁ、いいや。いいように考えましょう。
あと、今回のコードではPOCO中心でCSVファイルのカラム有無を判定するような処理いれてないす。POCOの値だけを頼りにカラムの更新を判断して処理する場合、たとえばデータストアに反映するなんてときに特定カラムのみ更新する、とか、値をNullにするのか無指定なのか判断できないとちょっと不便かもー?
takepara/ModernCsv
あと、他にも変な機能もあるけど、興味があるなら...。
2014年4月28日月曜日
Amazon VPCをYAMAHA RTX-1200で落ち着かせる
Amazon Virtual Private Cloud (Amazon VPC) 設定例
グローバルではどうか知らないですけど、国内ならYAMAHAルーター使ってるひと、結構いると思うんですよね。安いですし。
んで、RTX1200使って接続させるんです。設定自体は簡単だし。
が、これが、なかなか曲者で。
気づきはVPCからオンプレのDB接続に失敗して、処理が正常終了しないことが、たまにある、です。
そもそも、ちゃんと検証して、どういうことが起きるのか確認しときなさい、っていうのはもうそりゃそうですよね。
ちなみにDB接続をリトライする処理を入れる、じゃ問題は解決しないんすよね。
結論から言うと「VPNアップダウン繰り返すなら、SAキープアライブにIPSec DPD使わずにICMP Echo使いましょう」です。
IPsec DPD
18.19 IKE キープアライブ機能の設定
いずれもIKEの生存確認のための機能だけど、AWSやらYAMAHAに問い合わせしたり、ログから判断した結果、DPDだとレスポンスが返ってこないことが、結構あってDOWN/UPを繰り返す。そのタイミングでアプリケーションからみたConnection Poolは、切れてないと思ってるから接続を使いまわそうとする。けど、実質再接続されちゃってるもんだから、データは到達しない。
と、いう状況なので、アプリケーションから対処しようとするなら、接続がロストしたと判定した場合はClearAllPoolでプールを全部クリアしたのちの再接続、という処理にしましょう。この辺TDS ProxyのSQL Databaseでの挙動とは違う(そこから先が切り替わったから再接続、って意味では同じだけど、直接の接続先が変わるわけではない)ので対応方法も違うことになりましょう。
SqlConnection.ClearAllPools Method (System.Data.SqlClient)
と、いっても、既存システムをそのままクラウドに持っていきたいのにソースいじるの?っていうのはちょっと納得できないすよね。もちろん、そういう風に最初から作っておけば、いいんですけど、それはまぁ、ねー。
どういう挙動をしていたか、ルーターのsyslogを監視してたら、一日のうち何度もDOWN/UPを繰り返してるんです。なんで、繰り返すんだろー、と思って、syslog debug onで様子見。完全に不定期。規則性が見つからない状況で繰り返すんですけど、どうもキープアライブのところで、返事が返ってきてないことがちょくちょくあってシーケンスエラーが出てる。2本あるトンネルのうち、片方だけ。
標準のコンフィグ設定で指定されてるトンネルを入れ替えて様子みてると、入れ替え前と同じトンネルにつながってるほうだけ相変わらず変な挙動。
ふむ。いろいろ試してみたんすよね。コンフィグ変えたり(mssとかさー)。でも、少し落ち着いたかな、と思いきやすぐまたDOWN/UP。なんど解決したと夢見たことか。
それもあれですよね、SAの有効期限がISAKMPとIPSec別々に指定してて方や初期値で8時間のままだったりして、なんか、うまく動いてるように見えただけ、的な?こちらの設定都合じゃないところでDPDの返事がないから、関係ないのにね。
どうにもこうにもキープアライブ怪しい、って思ってたところAWSのサポートから、ICMP Echoにしてみてください、って返事が来た。理由を教えてほしい、ルーター側の問題なのかAWSの実装なのか知りたいから、っていうと「わかりません」ですって。そういうこともありますよね。
YAMAHAにも同じ問い合わせしたんだけど、返ってきた答えは「わかりません」でした。
これね、しょうがないかな、とは思うんですよね。組み合わせすべてテストするなんて、現実的じゃないしね。
接続の向きはいいとして(VPN通さないようにして、接続テストプログラム動かしても再現しない、っていう検証後の話です)、IPSecでのセッション管理について詳しくないですけど、鍵とセッションは紐づいてるんでしょーね。それなら、IPSec再接続後には、その上位も再接続しなさい、の理屈が通るもんね。
dotnetConf2015 Japan
https://github.com/takepara/MvcVpl ↑こちらにいろいろ置いときました。 参加してくださった方々の温かい対応に感謝感謝です。
-
Working with SSL at Development Time is easier with IISExpress - Scott Hanselman Hanselmanさんのエントリに書かれてる通りデス! IIS ExpressでSSLを有効にしたデバッグだと無効...
-
How to iterate through objects in ViewData via javascript on the page/view? - Stack Overflow この質問の回答としては、ページにscriptタグを書き、その中でJavaScriptを書き...
-
すでにコロケーションサービスを利用したりして、データセンターには自前のサーバーがいて。でも、今のデータセンターの利用を拡張していったり、するのもどうかなー、資産化するのもなー。という時にはパブリッククラウドにVPN接続させて、オンプレミスとのハイブリッド。 ハイブリッドクラウド...