Windows Azure Tips from Prospex

システム開発 × インフラ構築・運用 × グラフィックデザイン = プロスペックス

セッションごにょごにょしたくなった

clock January 9, 2012 23:53 by author Ito

こんばんは。

今夜は Azure のセッションについて調べてみた。
調べていて、良いまとめサイトがあったので紹介します。

ブチザッキ - {2011/08/23}   Windows AzureのWeb Roleでセッションを共有する
http://buchizo.wordpress.com/2011/08/23/windows-azure%E3%81%AEweb-role%E3%81%A7%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E5%85%B1%E6%9C%89%E3%81%99%E3%82%8B/

では今夜はこのへんで…

 

ごめんなさい。

以上の記事に書かれていることで、だいたいのセッションの問題は解決すると思いうけど、
あるものを使うだけでは面白くないため、今回から自前でセッション管理してみようとおもいます。

まず、簡単なカスタムセッションを作ってみます。
SessionStateStoreProviderBase クラスを継承して作っていくようです。
http://msdn.microsoft.com/ja-jp/library/ms178587%28v=VS.90%29.aspx

サンプルはMSDNにもあるのでそれをみつつ…
http://msdn.microsoft.com/ja-jp/library/ms178588%28v=VS.90%29.aspx
http://msdn.microsoft.com/ja-jp/library/ms178589%28v=VS.90%29.aspx

public class TestSessionStateProvider : System.Web.SessionState.SessionStateStoreProviderBase {

        private int Timeout {
            get { return 20; }
        }

        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) {
            base.Initialize(name, config);
        }
        public override void InitializeRequest(HttpContext context) {
        }

        public override void EndRequest(HttpContext context) {
        }

        public override void Dispose() {
        }

        public override System.Web.SessionState.SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out System.Web.SessionState.SessionStateActions actions) {
            return GetSessionData(true, context, id, out locked, out lockAge, out lockId, out actions);
        }

        public override System.Web.SessionState.SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out System.Web.SessionState.SessionStateActions actions) {
           return GetSessionData(false, context, id, out locked, out lockAge, out lockId, out actions);
        }

        public override void SetAndReleaseItemExclusive(HttpContext context, string id, System.Web.SessionState.SessionStateStoreData item, object lockId, bool newItem) {
            UpdateSessionData(context, id, item, lockId, newItem);
        }

        public override void ReleaseItemExclusive(HttpContext context, string id, object lockId) {
            // 実装は後ほど
        }

        public override void RemoveItem(HttpContext context, string id, object lockId, System.Web.SessionState.SessionStateStoreData item) {
            // 実装は後ほど
        }

        public override void CreateUninitializedItem(HttpContext context, string id, int timeout) {
            // 実装は後ほど
        }

        public override System.Web.SessionState.SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout) {
            return new SessionStateStoreData(new SessionStateItemCollection(),
                                             SessionStateUtility.GetSessionStaticObjects(context),
                                             timeout);
        }

        public override bool SetItemExpireCallback(System.Web.SessionState.SessionStateItemExpireCallback expireCallback) {
            // 実装は後ほど
            return false;
        }

        public override void ResetItemTimeout(HttpContext context, string id) {
            // 実装は後ほど
        }

        private SessionStateStoreData GetSessionData(bool lockSession, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out System.Web.SessionState.SessionStateActions actions) {
            // 今回は、HttpContext.Application にセッション情報を保存する

            SessionStateStoreData sessionState;

            Dictionary<string, byte[]> sessionData
                = (Dictionary<string, byte[]>)HttpContext.Current.Application["session"];

            // id のセッションがあるか
            if ( sessionData != null && sessionData.ContainsKey(id) ) {
                // セッションを復元

                using ( var stream = new MemoryStream(sessionData[id]) ) {
                    using ( var reader = new BinaryReader(stream) ) {

                        sessionState = new SessionStateStoreData(SessionStateItemCollection.Deserialize(reader),
                                                         SessionStateUtility.GetSessionStaticObjects(context),
                                                         this.Timeout);
                    }
                }

            } else {
                // 新規にセッションを作成
                sessionState = CreateNewStoreData(context, this.Timeout);
            }
           
            locked = false;
            lockId = null;
            lockAge = new TimeSpan(0, this.Timeout, 0);
            actions = SessionStateActions.None;

            return sessionState;
        }

        private void UpdateSessionData(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) {
            // HttpContext.Application に保存されているセッション情報を復元する

            Dictionary<string, byte[]> sessionData
                = (Dictionary<string, byte[]>)HttpContext.Current.Application["session"];
            if ( sessionData == null ) {
                sessionData = new Dictionary<string, byte[]>();
            }

            using ( var stream = new MemoryStream() ) {
                using ( var writer = new BinaryWriter(stream) ) {
                    var sessionItem = (SessionStateItemCollection)item.Items;
                    sessionItem.Serialize(writer);
                }

                sessionData[id] = stream.GetBuffer();
            }

            HttpContext.Current.Application["session"] = sessionData;
        }

    }

ただ HttpContext.Application に保存するだけのものです。
(InProc セッションの超劣化版)

これから少しずつまともに使えるものにしていこう。



ストレージにRESTでアクセス

clock July 12, 2011 22:20 by author Ito

Azure のストレージは、REST API が用意されているみたい。
http://msdn.microsoft.com/en-us/library/dd179355.aspx

そこで、直接このAPI達を使ってみて、Azure ストレージをちょっとだけ詳しくなろうと試みてみた…

まずは何も考えずに、blob の List Containers API の URL をブラウザでアクセス。

 

まあ予想通りエラーです。

さきほどの MSDN を眺めてみると…下のほうにサンプルが…

 GET http://myaccount.blob.core.windows.net/?comp=list&maxresults=3 HTTP/1.1
x-ms-version: 2009-09-19
x-ms-date: Sun, 27 Sep 2009 22:08:44 GMT
Authorization: SharedKey myaccount:CY1OP3O3jGFpYFbTCBimLn0Xov0vt0khH/D5Gy0fXvg=

とりあえず、サンプルを今回アクセスするストレージに合うように書き換えて、
Authorization はよくわからんので消して、TCP 送信ソフトで送信してみた。

あれ…リクエストが返ってこない…

それから1時間格闘の末、HTTPヘッダの最後に空行を入れないといけない駄目という事がわかった…
(うち、ネットワーク弱いな…)

ということで、以下のリクエストを投げてみる。(****はストレージアカウント名)

[HTTP リクエスト]

GET http://****.blob.core.windows.net/?comp=list&maxresults=3 HTTP/1.1
x-ms-version: 2009-09-19
x-ms-date: Tue, 12 Jul 2011 13:10:38 GMT
<空行>

なんか返ってきた!

HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
Date: Tue, 12 Jul 2011 13:40:02 GMT
Connection: close
Content-Length: 334

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Bad Request</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Bad Request - Invalid Hostname</h2>
<hr><p>HTTP Error 400. The request hostname is invalid.</p>
</BODY></HTML>

あれ? HTTP/1.1 400 Bad Request ってなんだ…

無効なホスト名って言われてる…

さらに30分…
どうやら、HTTP/1.1 では、Host ヘッダが必要みたい。

で Host ヘッダをつけて送信。

[HTTP リクエスト]

GET http://****.blob.core.windows.net/?comp=list&maxresults=3 HTTP/1.1
Host: ****.blob.core.windows.net
x-ms-version: 2009-09-19
x-ms-date: Tue, 12 Jul 2011 13:10:38 GMT

[レスポンス]

HTTP/1.1 404 The specified resource does not exist.
Content-Length: 223
Content-Type: application/xml
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 8c77457c-e991-4c54-9b27-5d30eb854811
x-ms-version: 2009-09-19
Date: Tue, 12 Jul 2011 13:44:34 GMT

<?xml version="1.0" encoding="utf-8"?><Error><Code>ResourceNotFound</Code><Message>The specified resource does not exist.
RequestId:8c77457c-e991-4c54-9b27-5d30eb854811
Time:2011-07-12T13:44:34.9547433Z</Message></Error>

ブラウザでアクセスしたときと同じ内容だ!

これでブラウザに並んだぜ。

で、消してた Authorization ヘッダをつけてみるが…

Authorization: SharedKey myaccount:CY1OP3O3jGFpYFbTCBimLn0Xov0vt0khH/D5Gy0fXvg=

myaccount 部分はストレージアカウント名で良いとして…
CY1OP3O3jGFpYFbTCBimLn0Xov0vt0khH/D5Gy0fXvg= の部分はどうすればいいんだ?

そこでいろいろと調べてみたら、参考になりそうなサイトを見つけた。

■てすとぶろぐ さん
 ・Azure Storage 関係の REST API で利用する Authorization ヘッダ
  
http://blogahf.blogspot.com/2011/05/azure-storage-rest-api-authorization.html
 ・Azure Storage REST API の Authorization ヘッダ・改訂版
  
http://blogahf.blogspot.com/2011/05/azure-storage-rest-api-authorization_25.html

■REST API でBlob 操作 - Azureの小ネタ
  
http://d.hatena.ne.jp/StateMachine/20110405/1302014188

どうやら、HTTPヘッダの内容に、SHA256ハッシュとBASE64で認証キーを作り、
それを指定するようだ…

で、頑張って作成してアクセス…

[HTTPリクエスト]

GET http://****.blob.core.windows.net/?comp=list&maxresults=3 HTTP/1.1
Host: ****.blob.core.windows.net
x-ms-version: 2009-09-19
x-ms-date: Tue, 12 Jul 2011 13:10:38 GMT
Authorization: SharedKeyLite ****: 7XJc+dO+3uN+ZynDbxRTK4bC4N7UIPhXgN/wedHv50E=

[レスポンス]

HTTP/1.1 400 Authentication information is not given in the correct format. Check the value of Authorization header.
Content-Length: 297
Content-Type: application/xml
Server: Microsoft-HTTPAPI/2.0
x-ms-request-id: e2116cae-c135-497d-8113-dfa7b72c943f
Date: Tue, 12 Jul 2011 13:58:20 GMT

<?xml version="1.0" encoding="utf-8"?><Error><Code>InvalidAuthenticationInfo</Code><Message>Authentication information is not given in the correct format. Check the value of Authorization header.
RequestId:e2116cae-c135-497d-8113-dfa7b72c943f
Time:2011-07-12T13:58:20.3896662Z</Message></Error>

なんか認証キーが違う言われた…

認証キーはプログラム組んで作成させないと難しそうだ…

次回は、認証キーを作るプログラム作りで行こう。

 



Web Role のIISを自動設定する

clock June 6, 2011 21:35 by author Sekine

前回の記事:Web Role をデプロイすると何が起こっているのか では、

Web Role 上のアプリケーションが、IIS上でどこのディレクトリ、設定で

動作しているのかを、VM上で確認した。


その後、MVCアプリケーションのViewsフォルダの物理位置を他のフォルダへ移動し、

Viewsフォルダは、仮想パスとして、移動した先のフォルダを設定した。

前回、これ等はVM上にリモートデスクトップで入って手作業で変更したので、

手間が掛かり、クラウドとして運用を考えた場合はダメダメ過ぎる。

但し、MVC動作として、Azure上でも問題無く動作出来る事が分かった事は、

収穫に値するでしょう(当たり前の事なんだけどね)。



今回は、ファイルコピー、仮想フォルダ設定を自動化させる為のモジュールを生成します。

デプロイ後に、VMへリモートデスクトップで更に設定・・というのは当然ナシ!



本題の前に、Startupタスクについて軽く説明します。

Web Role のプロジェクトで、OS設定をする方法は、幾く通りか方法があります。

ざっと思いつくのは、

・Windows サービスを入れちゃう(サービス作って、sc.exeで入れ込むとか)

・プログラム作ってゴニョゴニョするw

どちらも、Startupタスクで実行させる事は共通です。

※あるOSSで、RoleEntryPointで何かの設定をしているコードを見かけてるので、
RoleEntryPointでもゴニョゴニョ出来るかもしれません。


Windows Azure での、Startupタスクの使用方法は、

ServiceDefinition.csdef に
<Startup>
    <Task commandLine="実行させたいバッチファイル.cmd"  />
</Startup>

簡単に言えばこれだけ。他のオプションもあります。

例えば、実行させたいバッチを、startup.cmd としましょう。

Webプロジェクト内に、startup.cmdというテキストファイルを用意し、

中身は、**.exe でも call でも、普通に行いたいバッチを書きます。

.cmdとしましたが、.batでも良いし、.vbsとしてVBスクリプトを記述しても良いです。

デプロイを行った瞬間に、そのバッチが動くというのが、Startupタスク です。



それでは、本題に。

IISの設定を行うには、いろいろ方法があります。

設定するアプリケーションを作成するか、vbs設定、PowerShellスクリプト設定など。


私は、スクリプトはあまり得意ではないので、アプリケーションを作成します。

更に、ここで利用するモジュールは、

Microsoft.Web.Administration.dll です。

このファイルは、IISをインストールしたWindowsなら、

<システムフォルダ>\inetsrv の中に見つかるはずです。


では、IISを設定するアプリケーションを作成します。

※ デプロイするWeb Role のプロジェクト名と、ローカルストレージ名が決定している事!

プロジェクト名は、startupInfrastructure (任意)とします。

プロジェクトは、C#、コンソールアプリケーション、.NET Framework 4

コンソールでのデフォルトのフレームワークは、.NET Framework 4 Client Profile ですが、

Microsoft.Web.Administration で利用する名前空間がみつからないので、

.NET Framework 4 とします。



プログラムの流れは、

・IISサイトの確認

・ローカルストレージフォルダの確認

・フォルダ作成、ファイルコピー

・フォルダ・ファイルのアクセス制限の設定

・仮想ディレクトリの設定

となります。


また、Startupタスクの動作は、バックグラウンドとして動作させ、

この、IIS設定アプリケーションでは、設定できるまでリトライループを掛けます。

これは、Startupタスクの動きを確認すると分かるのですが、

通常(フォアグランド)で動作させると、Startupタスクのバッチが完了してから、

IIS上へデプロイされるので、IISの設定が出来ないからです。

バックグラウンド動作であれば、バッチ起動と同時にデプロイされるので、

設定ができますが、両方が一緒に動作するので、

デプロイ設定されるまで、Waitをかけたループを行います。



プロジェクトの先頭は、

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Security.Principal;
using System.Security.AccessControl;
using Microsoft.Web.Administration;

namespace startupInfrastructure
{
    class Program
    {
        private const string LOCAL_RESOURCE_ROOT = @"C:\Resources\Directory";

        private static string webProjectName = "MvcApplication1";
        private static string storageName = "WebContentsStorage";

        static void Main(string[] args)
        {

こんな感じで始まります。

webProjectName、storageNameは、WebRoleに合わせてください。


では、IISサイトの確認のメソッド

IISSiteCheck(webProjectName); の様に呼ぶ

public static void IISSiteCheck(string siteName)
{
    while (true)
    {
        bool isLoop = true;
        try
        {
            ServerManager serverManager = new ServerManager();
            foreach (Site site in serverManager.Sites)
            {
                if (site.Name.StartsWith(siteName))
                {
                    isLoop = false;
                    break;
                }
            }
        }
        catch
        {
            isLoop = true;
        }

        if (isLoop)
        {
            Thread.Sleep(1000);
        }
        else
        {
            break;
        }
    }
}

ServerManagerクラスは、Microsoft.Web.Administration 内のクラスです。

IISのサイト一覧に、Web Role のプロジェクト名が現れたら、ループを抜けます。

スマートでは無いですが、Startupタスクで行うとこのようになるのは仕方がないようです。



ローカルストレージフォルダの確認
string localResourceRootPath = 
    GetLocalStorageDirectory(webProjectName, storageName); の様に呼ぶ

public static string GetLocalStorageDirectory(string projectName, string storageName)
{
    string result = string.Empty;

    while (string.IsNullOrEmpty(result))
    {
        try
        {
            string[] directorys = Directory.GetDirectories(LOCAL_RESOURCE_ROOT);
            foreach (string s in directorys)
            {
                int find = s.IndexOf(string.Format(".{0}.{1}", projectName, storageName));
                if (find >= 0)
                {
                    result = s;
                }
            }
        }
        catch
        {
        }

        if (string.IsNullOrEmpty(result))
        {
            Thread.Sleep(1000);
        }
    }

    return result;
}



ローカルストレージにフォルダ作成

以下のような感じで、ローカルストレージ内に、Viewsフォルダを作成する。

string path = Path.Combine(localResourceRootPath, “Views”);
Directory.CreateDirectory(path);

FileSystemAccessRule rule = new FileSystemAccessRule(
    new NTAccount(“Everyone”),
    FileSystemRights.Modify,
    InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit,
    PropagationFlags.None,
    AccessControlType.Allow);

DirectorySecurity security = Directory.GetAccessControl(path);
security.SetAccessRule(rule);
Directory.SetAccessControl(path, security);


次にIISのフォルダを設定します。

ServerManager serverManager = new ServerManager();

Application webApplication = null;
VirtualDirectory appDirectory = null;
VirtualDirectory viewsDirectory = null;

foreach (Site site in serverManager.Sites)
{
    if (site.Name.StartsWith(webProjectName))
    {
        foreach (Application app in site.Applications)
        {
            if (app.Path == "/")
            {
                webApplication = app;

                foreach (VirtualDirectory virtualDirectory in app.VirtualDirectories)
                {
                    if (virtualDirectory.Path.ToLower() == "/")
                    {
                        appDirectory = virtualDirectory;
                        continue;
                    }

                    if (virtualDirectory.Path.ToLower() == "/views")
                    {
                        viewsDirectory = virtualDirectory;
                        continue;
                    }
                }

                break;
            }
        }

        break;
    }
}

string server_rootDirectoryPath = appDirectory.PhysicalPath;
string server_viewsDirectoryPath = Path.Combine(server_rootDirectoryPath, "Views");
if (Directory.Exists(server_viewsDirectoryPath))

    // 実ディレクトリから、ローカルストレージへフォルダ階層毎にコピーする。 
    // コピーしたフォルダ・ファイルのアクセス制限も設定します。:ソースコードは割愛します。
}

if (viewsDirectory == null)
{
    webApplication.VirtualDirectories.Add("/Views", localResourceViewsPath);
}
else
{
    viewsDirectory.PhysicalPath = localResourceViewsPath;
}

serverManager.CommitChanges();


上記の、VirtualDirectory変数には、対象とするIISのフォルダ情報が入ります。

仮想ディレクトリの情報は、PhysicalPathメンバで設定します。


以上で、設定プログラムは完了。

Azureパッケージに入れるため、Web Role アプリケーションからプロジェクト参照します。

また、App.configは、startupInfrastructure.exe.configとして存在する必要があるので、

Web Roleプロジェクトに、startupInfrastructure.exe.configを作成し、

App.configの内容を転記しておきます。

Microsoft.Web.Administration.dll は、出力ディレクトリにコピーされるようにしてください。

startup.cmdの内容は、
----
@echo off

startupInfrastructure.exe
----

これだけ。

Startupタスクの定義は、
<Startup>
  <Task commandLine="startup.cmd" executionContext="elevated" taskType="background" />
</Startup>

となります。

適切に設定されていれば、デプロイ完了と同時に、

Viewsフォルダがローカルストレージに配置され、仮想ディレクトリとして参照されます。


関根:



Web Role をデプロイすると何が起こっているのか

clock May 10, 2011 22:29 by author Sekine

Windows Azure 上でのローカルファイルのコンテンツを操作したくなった。

基本的にAzure上では、ファイル操作が自由に出来るのは

ローカルストレージ領域のものに対してという事になっているのだが、

単にそれは、初期のファイルアクセス権がそうさせている。


何はともあれ、具体的にリモートデスクトップで

何が起こっているのか確認してみた。


リモートデスクトップをするためには、デプロイするパッケージが必要なので、

まずは、Visual Studio で簡単なWeb Role を作成する。


※SDK 1.4 がインストールされているものとする。

プロジェクトの作成
C#、Cloud Windows Azure Project を選択、

image

MVC 2 Web Role を追加。

単体テストプロジェクトは作成しない。


プロジェクトが開いたら、ローカルストレージを領域を1つ追加する

image

Web Role をダブルクリックし、プロパティを表示

image

Local Storage で、”Add Local Storage”

名前は、LocalStorageDatas にした。


プログラムは、何も書かずにこれだけの設定で、Azure用にパッケージを作ります。

image

リモートデスクトップが有効なパッケージの設定をします。

image


.\bin 配下、Debug\Publishにパッケージが出来ます。
ServiceConfiguration.cscfg
WindowsAzureProject1.cspkg


このパッケージをAzure へデプロイします。

image


しばらくすると、デプロイ完了。

image

インスタンスを選択すると、右上のリモートデスクトップのリンクが有効になってます。

image

クリックして、RDP接続ログインします。


サーバーマネージャを開き、デプロイされたIIS上のWebサイトを確認
image

Eドライブの、.\siteroot\0 という所にWebサイトが配置されています。

image


作成したローカルストレージのルートフォルダは、・・・

Cドライブです。

image

C:\Resources\Directory\7d42203ef8c144cc880b0fb178b73fb4.MvcWebRole1.LocalStorageDatas

C:\Resources\Directory\[自動的に割り振られた文字].[Webアプリケーション名].[ストレージ名]

という名前ルールになってます。


ファイルのアクセス権はどうなっているのか?

の前に、実行ユーザーは誰なのか?Webサイトのアプリケーションプールは、

image

憶測不能・・?な自動に振られた名前がつけられて、

image

ビルトインの、NetworkServiceユーザーで動いています。


ファイルのACLは?

Webサイトの、E:\siteroot/0 配下

image IUSR もいますが、権限は同じでした。



ローカルストレージは、特殊権限として付与され、

権限を見ると、Fullでは無いにしても、Fullに近い権限を持っています。

image



フォルダの構成は分かった。

では、必ず毎回そうなのかというと?

Webサイトが置かれるドライブレターは、いろいろ試したところ変更されました。

RDP接続したまま、パッケージを上書きしてデプロイを行った時に、EドライブがFドライブに変更されました。


ローカルストレージに関しては、同じ構成のままでした。

任意に振られるフォルダ接頭句に関しては、確証はもてないので、

C:\Resources\Directory\[自動的に割り振られた文字].[Webアプリケーション名].[ストレージ名]

というルールは覚えておかないとね。




さてさて、折角なので、

というか本当にやりたい事の検証はここから



ローカルストレージに、MVC の View部分になるViewsをフォルダごとコピーします。

image

最初に有ったWebサイトのViewsフォルダーを削除

= E:\sitesroot\0\Views は、フォルダーごとバッサリ削除

IIS マネージャ上で、元々Viewsが有った位置に、

Viewsの仮想ディレクトリを作成、場所はローカルストレージ位置のフォルダーを指定

image

意味わかりますね?


では、アクセス

image

・・・エラーに出会えました


仕方が無いので、作成した Views フォルダーのACLをいじります。

乱暴ですが、Everyone を 追加。権限は変更で!


再びアクセス

image


表示できました。


これで、WebアプリケーションからViewテンプレートを直接変更する事が出来るような

アプリケーションを作る事ができます。



Windows Azure SDK.1.3 から StartupTask が使えるようになりました。


次回は、今回のようなViewsをローカルストレージにコピー、

Viewsの仮想ディレクトリ設定など、IISを設定するプログラムと、

それらを、StartupTask で行う方法を示します。


関根:



データバインドって、言ってみるとクセになりそう

clock March 10, 2011 22:28 by author fujii

みんな楽しくやってるだろうか?

そんな寂しい時は、声を出して言ってみよう。

「データバインド」

ということで、今日は「データバインド」して帰ります。

先週作ったプロジェクトに「WebForm2.aspx」を追加。

image

おもむろに「GridView」を張り付ける。

image 

「WebForm2.aspx」、コードはこれだけで……

   1: <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="WebForm2.aspx.vb" Inherits="WebRole1.WebForm2" %>
   2:  
   3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   4:  
   5: <html xmlns="http://www.w3.org/1999/xhtml">
   6: <head runat="server">
   7:     <title></title>
   8: </head>
   9: <body>
  10:     <form id="form1" runat="server">
  11:     <div>
  12:         <asp:GridView ID="GridView1" runat="server" />
  13:     </div>
  14:     </form>
  15: </body>
  16: </html>

 

「WebForm2.vb」はこれだけ。

   1: Imports Microsoft.WindowsAzure
   2: Imports Microsoft.WindowsAzure.StorageClient
   3: Imports Microsoft.WindowsAzure.ServiceRuntime
   4:  
   5: Public Class WebForm2
   6:     Inherits System.Web.UI.Page
   7:  
   8:     Private account As CloudStorageAccount = CloudStorageAccount.Parse( _
   9:       RoleEnvironment.GetConfigurationSettingValue("StorageConnection"))
  10:  
  11:     Private table As CloudTableClient = account.CreateCloudTableClient()
  12:     Private tsc As TableServiceContext
  13:  
  14:     Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  15:  
  16:         tsc = table.GetDataServiceContext()
  17:         table.CreateTableIfNotExist("PostCode")
  18:  
  19:         Dim query = tsc.CreateQuery(Of Class1)("PostCode")
  20:  
  21:         GridView1.DataSource = query
  22:         GridView1.DataBind()
  23:  
  24:     End Sub
  25:  
  26: End Class

今週のポイントは、「Dim query = tsc.CreateQuery(Of Class1)("PostCode")」のみ。

ちなみに、「Class1.vb」は先週と同じ。

   1: Public Class Class1
   2:     Inherits Microsoft.WindowsAzure.StorageClient.TableServiceEntity
   3:  
   4:     Public Property Time As Date
   5:     Public Property TodofukenKana As String
   6:     Public Property KushichosonKana As String
   7:     Public Property JushoKana As String
   8:     Public Property Todofuken As String
   9:     Public Property Kushichoson As String
  10:     Public Property Jusho As String
  11:  
  12:  
  13:     Public Sub New(ByVal partitionKey As String, ByVal rowKey As String, ByVal time As Date, _
  14:                    ByVal todofukenKana As String, ByVal kushichosonKana As String, ByVal jushoKana As String, _
  15:                    ByVal todofuken As String, ByVal kushichoson As String, ByVal jusho As String)
  16:  
  17:         Me.PartitionKey = partitionKey
  18:         Me.RowKey = rowKey
  19:  
  20:         Me.Time = time
  21:         Me.TodofukenKana = todofukenKana
  22:         Me.KushichosonKana = kushichosonKana
  23:         Me.JushoKana = jushoKana
  24:         Me.Todofuken = todofuken
  25:         Me.Kushichoson = kushichoson
  26:         Me.Jusho = jusho
  27:  
  28:     End Sub
  29:  
  30:     Public Sub New()
  31:  
  32:     End Sub
  33:  
  34: End Class

デバッグで実行。

image

データを投入し……

image 

手打ちで「WebForm2.aspx」へ。

image

で、例外がスローされました。

image 

今日は「データバインド」の日なので、こんな例外は無視。

「WorkerRole」は今日の主役じゃないし……

「CreateTableIfNotExist」は、「Try」するといいかも。

で、もう一回実行すると……

image 

「データバインド」

すっきりしたので、帰ろうかと思ったが……

やはり、デプロイしないと本物の「データバインド」ではない。

いつも通り、ストレージを作成し……

image

名前は「gridview」にした。

今思うと、「databind」にすれば良かったが、どうでもいい。

いつも通り、「access key」を張り付ける。

image 

image

image

発行して……

image

「Hosted Service」を作る。

名前は「gridview」にした。

今思うと……それはいい。

image

で、作ったはいいが……

image 

「WorkerRole」の「Status」が「Ready」になったり「Busy」になったりと、落ち着かない。

image

一回止めたけど、ダメ。

image 

「WebRole」は動くが……

image

「WorkerRole」が安定しないので、ボタンを押してもキューばかりが溜まっていく。

データの投入ができなければ、「データバインド」は成立しない。

image

「gridview」……名前が悪い。

ならばと思い、もう一個「Hosted Service」を作る。

名前は念願の「databind」だ。

「region」は「Anywhere US」にしてみた。

image

できた。

なんか、先に作った「gridview」は赤字になっとる。

image

で、うまくいったかというと、これがうまくいかない。

image

今日は「データバインド」の日なので、原因はおいおい調査するとしよう。

今日のところは最後の手段……

調子の悪い「WorkerRole」はあきらめ、

「WebRole」で書き込むまでよ。

image

健闘むなしく、タイムアウトになるものの……

image

154行作ってくれました。

image

それでは一緒に……

image

「データバインド」

後味悪いけど、「データバインド」

本物の「データバインド」は厳しい……

やはり、例外処理は入れといた方が良かったのか?

「データバインド」

声に出すと、すっきりしたので、帰ります。



AzureをPowerShellで管理

clock February 28, 2011 22:58 by author Tanaka

本日はAzureでPowerShellをつかってみる。
以下のネタは実用性があまりないですが・・・

■Windows 7ならデフォルトでPowerShellを標準搭載しているから、
以下のURLからCmdLetsをダウンロードしてインストールする 

http://archive.msdn.microsoft.com/azurecmdlets

■Management CmdLetsでAzureの管理をするには 
以下の情報が必要  

1.サービス名 → http://azurecmdlettest.cloudapp.net/というプロダクションがあったらazurecmdlettestの部分 
2.サブスクリプションID → Azureの管理画面から確認できる 
3.アカウント証明書 → ローカル、Azure上に配置する必要がある。  

※アカウント証明書を作成して配置する方法
(以下の参考URLではコマンドラインツールを使用して、あらかじめアップロードが可能な状態の証明書の作成方法が書いてある。)
http://www.atmarkit.co.jp/fdotnet/special/azuresdk13_02/azuresdk13_02_01.html

■実用性はあまりないが、プロダクション環境からサービスを削除してみる。 

ProductionRemove.ps1というファイル名にしてみた。

以下内容
$name = "azurecmdlettest"
$sub = "<サブスクリプションID>"  
$cert = Get-Item cert:\CurrentUser\My\"<証明書の拇印>"  

Add-PSSnapin AzureManagementToolsSnapIn  
Get-HostedService -ServiceName $name -certificate $cert -SubscriptionID $sub |  
Remove-Deployment -Slot Production |  
Get-OperationStatus -WaitToComplete  

※証明書の拇印は以下のコマンドで確認できる。  
PS C:\> Get-Item cert:\CurrentUser\My\*  

azurecmdlettestは確かに削除できた。



Visual Studio 2010 から Web ロールを発行する

clock February 21, 2011 12:57 by author Ando

 

Visual Studio から Azureアプリケーションを直接発行することが可能です。
Azure ポータルも新しくなった事ですし、その手順を整理しておきたいと思います。

今回は、Visual Studio の「新しいプロジェクト」で作成した ASP.NET Web Form のシンプルなWebロールを発行してみます。

image

まず、最初に注意したいのが、ソリューションエクスプローラの Azure プロジェクトを右クリックすると表示される「発行」を使うという事です。
(「ビルド」メニューの「発行」ではなくて)

image

そうすると下のダイアログボックスが表示されます。

image

デフォルトでは、「資格情報」に何もセットされていませんので、ドロップダウンリストから「追加」を選択します。
すると、以下のダイアログボックスが表示されます。

image

「1. 認証のために、資格情報を作成するか既存の資格情報を選択します」が空欄になっていますが、リストに自分のWindowsユーザー名の資格情報がありましたので、それを選択しました。

「表示」ボタンを押すと、証明書の有効期限が2110年までになっていますので、問題なさそうです。

その後、「完全パスのコピー」をクリックしてから、「Windows Azure ポータル」リンクをクリックします。

image

Azure ポータルが表示されたら、左側ナビゲーション メニューの「Hosted Services, Storage Accounts & CDN」をクリックし、その上部のメニューから、「Management Certificates」を選択します。

image

左上の「Add Certificate」をクリックすると、次の画面が表示されますので「Browse」ボタンを押し、クリップボードから証明書のパスを貼り付けます。

image image

そして、「Done」をクリックします。

image

証明書が追加されました。

image

右下に表示されている、「Subscription ID」をコピーして、Visual Studio のダイアログに貼り付けます。

image

ところが、エラーメッセージが表示されてしまいました。

image image

どうやら、事前に「配置先となる配置環境」を作っておく必要があるようです。

そこで、「Windows Azure ポータル」の画面に戻り、「New Hosted Service」をクリック。
いくつかの必要な項目を入力し、「OK」します。

※ ここでは「Do not deploy」を選択しました。Visual Studio から deploy しようとしてるからです。

image

そして、Visual Studio で再度「発行」を試みます。

今度は「配置先となる配置環境」に先ほど用意したものが表示されました。

Production と Staging を選ぶことができますが、ここでは Staging を選択します。

image

「OK」をクリックすると、Visual Studio のステータスバーの表示が状況に応じて変更されてゆきます。
「ビルドを開始しました」 … 「○○○に対する △△△ の配置」 …

その間、自動的に「Windows Azure ポータル」の画面が全面に表示され、発行の様子を確認することができます。

発行には数分を要しますので、しばらく待ちます。

image

無事に発行ができました。

(課金される前に、削除しておこう。)

■ 参考情報

http://d.hatena.ne.jp/haru-tama/20100609

http://d.hatena.ne.jp/waritohutsu/20110123/1295770096



早くAzureに浸りたい

clock February 10, 2011 21:26 by author Ito

いつになったらAzure触れるんだろ…

みんなAzureやらGoogleAppsEngineやら調べている中、うちはまだ普通のASP.NETで開発してます…

今までロックやらトランザクションやら書いていますが、まともなテストプログラム作っていないので、机上の空論になりかねないです。

 

さて、前回「キューでトランザクション処理実現できるんじゃね?」と書いた直後に、KVSの最大の利点を忘れていました。

スケールアウト!

ストレージテーブルでデータをうまく設計すれば、Webロール増やすだけで負荷分散!なんてことができるけど、
ストレージに書き込むためのキュー・トランザクション管理するワーカーロールが一つだと、現状のRDBMSとあまりかわらないじゃん…

まあ、ワーカーロール増やせばいいんだが、うまくいくんかな…

さて、振出しに戻った…



Visual Studio 変換ウィザードへようこそ

clock February 8, 2011 23:09 by author fujii

歓迎されるのは気持ちがいいものだが、

「Visual Studio 変換ウィザードへようこそ」って言われても……More...



ほんとにmutexでいけるんか?

clock February 1, 2011 21:08 by author Ito

前回、テーブルレコードをmutexでロックすれば排他制御できるんじゃね?と書いたけど…ほんとにできるんか。
mutexてマシン内で唯一になるが、azureの複数ロール環境じゃどうなるんだろ?

考えていても進まないので、実際やってみるか…ということでプログラム書いてます。

まず、開発環境でWebロール2つ用意してためしてみる。…うん、ロックされている。
でも所詮開発環境。たぶんこいつのmutexはローカルマシンの.netのmutex使ってるだけだと思うので、ロックされて当たり前じゃね?
ではデプロイ…

デプロイ環境なんて用意してねぇよ。

うちはまだ にはなっていないのだ。自腹怖いし時間がないし…

複数ロールのmutex(ロック処理)ってできるのか?と毎度のgoogle先生に聞いてみた。
http://social.msdn.microsoft.com/Forums/en/windowsazure/thread/ed5d6306-6e2b-4867-8e1d-425962a5f900

英語やないか………

Microsoftさんが言うには、「今はないけど、これから用意するかも。そんな要望が上がってきてるから。」とのこと。

まあ、デプロイできないから…mutexのテスト終了。


パフォーマンス的にどうなのかわからないが、テーブルストレージのトランザクション処理…キュー使えば普通に行けそうな予感。

更新コマンドをキューに貯めて、FlushかComitかUpdateかしらないが、そんなメソッド作って呼ぶと、裏にいるワーカーロールがキューの内容を実行してくれる。

なんか行けそうな気がした。

時間出来たら試してみるかな……いつになるんだろ……



Sign In