Nine MVP's Blog

16/05/2011

ASP.NET 4.0 : High Scalable ASP.NET Session and Cache with Windows Server AppFabric Caching vol.2

Filed under: ASP.NET, Core System — Tags: , — Nine MVP @ 1:58 am
ตอนที่ 1 (Part 1)
ตอนที่ 2 (Part 2)

 

Programming Level:

  • Intermediate

Computer Skills:

  1. ASP.NET 4.0
  2. C#

Development Tool and Library

  1. OS: Windows 7 or Windows Server 2008 or later
  2. Visual Studio 2010 or later
  3. Windows Server AppFabric Caching (download for x86, for x64)
  4. ASP.NET 4 Providers for Windows Server AppFabric Caching (download)

Agenda

  • Introduce
  • Basic of ASP.NET Session and Cache
  • Sample ASP.NET Web Application with InProc Mode
  • Case Study: Problem of ASP.NET Web Application with InProc Mode
  • Solution: Implement Cache Server
  • Create and Setting AppFabric Cache for ASP.NET Web Application
  • Using AppFabric Cache within ASP.NET Web Application
  • Test Run ASP.NET Web Application and Monitoring Cache
  • Conclusion

Introduce

จากตอนที่แล้วผมได้กล่าวถึง Session State ใน Mode ต่าง ๆ  โดยเราจะมาทำความเข้าใจเกี่ยวกับหน่วยความจำภายในของ ASP.NET กัน และดูตัวอย่างเว็บที่ใช้งาน Session และ Cache ของ ASP.NET ด้วยค่าเริ่มต้นของ web.config

ต่อด้วยทำความรู้จักกับปัญหาของ ASP.NET Web Application ที่ออกแบบไว้โดยสถาปัตยกรรมแบบง่ายๆ ที่มีข้อจำกัดในหลาย ๆ ด้าน รวมไปถึงผลกระทบอื่น ๆ ซึ่งเราจะมาแก้ปัญหาเหล่านี้ด้วยการใช้ AppFabric Caching มาช่วยในการแก้ปัญหา

 

ASP.NET Session and Cache

เรามาทำความรู้จักกับหน่วยความจำที่ของ ASP.NET คร่าว ๆ กันก่อนครับ

Session

System.Web.HttpContext.Current.Session หรือ Session เป็นหน่วยความจำที่สามารถโปรแกรมเมอร์สามารถเก็บข้อมูลของ user แต่ละคนโดยแยกจากกัน ไม่สามารถใช้ร่วมกันได้ ซึ่งเซสชั่นจะยังมีอายุคงอยู่จนกว่าจะ timeout หรือสั่งทำลายโดยโปรแกรม

Session[“SessionName”] = null;

Session.Remove(“session name”);

Session.Abandon();

Cache มี 3 ชนิดครับ

Data Caching เป็น Programmatically สามารถเรียกใช้โดยอ้างถึง HttpContext.Current.Cache หรือ Cache ซึ่งเป็นหน่วยความจำที่เก็บข้อมูลคล้ายกับเซสชั่น แต่แคชสามารถแชร์กันใช้งานกันภายใน Web Application โดยทุกเซสชั่นสามารถเข้าถึงข้อมูลของแคชได้ สามารถจัดเก็บได้โดยโปรแกรมเมอร์เอง และการสร้างแคชจะต้องกำหนดอายุุของแคชเสมอ

var expiredDT = DateTime.Now.AddMinutes(10);
Cache.Insert("AllCustomers",custs, null, expiredDT, TimeSpan.Zero, CacheItemPriority.Default, null);

Output Caching เป็น Automatic Cache ของ Page โปรแกรมเมอร์ไม่สามารถสั่งเก็บค่าหรือเรียกมาใช้งานได้ การเก็บแคชจะกระทำโดย ASP.NET โดยเก็บข้อมูลตามค่า Vary Option ที่ตั้งไว้ และจะทำลายแคชตามอายุที่กำหนดไว้ โดยสามารถกำหนด directive tag ใน aspx page ไว้ประมาณนี้

<%@ OutputCache Duration="30" Location="Any" VaryByParam="none" %>

Fragment Caching เป็น Automatic Cache ของ user control มีลักษณะเหมือนกับ Output Caching แต่จะจัดเก็บแคชของบางส่วนใน Page เช่น user control เป็นต้น การใช้งานก็สามารถเพิ่ม directive tag ในหน้า ascx ดังนี้

<%@ OutputCache Duration="30" Location="Any" VaryByParam="none" %>

ข้อมูลที่จะสามารถเก็บไว้ใน Session และ Cache ได้คือข้อมูลที่สามารถ Serializable ได้เท่านั้น เช่น Primitive data type, POCO, XML เป็นต้น

เราก็ได้รู้จักกับ Session, Cache กันไปแล้ว ต่อไปเราจะไปดูการเรียกใช้งานในเว็บโปรแกรมกันครับ

 

ตัวอย่าง: ASP.NET Web Application with InProc Mode (Default Mode)

Download Code Sample Here

InProc Mode จะเป็นการเก็บข้อมูลเซสชั่นและแคชทั้งหมดเอาที่หน่วยความจำของเครื่อง Web Server โดยตัวอย่างเว็บนี้จะมีหน้า default.aspx เป็นส่วนที่ใช้ทำการทดสอบครับ ซึ่งจะมีการเรียกใช้งานหน่วยความจำของ ASP.NET ทั้ง Session, Cache Data, OutputCache ตามปกติดังนี้

image

image

ในส่วนที่ 1 ไว้สำหรับทดสอบ OutputCache ของ Page ซึ่งผมได้วาง @ OutputCahce เอาไว้ในหน้า default.aspx

<%@ OutputCache Duration="1" Location="Any" VaryByParam="none" %>

ปล. เอา tag ออกเพื่อทดสอบกรณีที่ไม่ใช้ OutputCache หรือกำหนดค่า 1 จะใกล้เคียงกับไม่เก็บแคช

GetDate Button
  1. protected void btnGetDate_Click(object sender, EventArgs e)
  2. {
  3.     lblShowDate.Text =  DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss");
  4. }

ทดสอบ 1 Duration=1 เมื่อกด Get Date Time button เพื่อดึงเวลาจะเห็นว่าเวลาจะเปลี่ยนแปลงตลอดทุกครั้งที่กดปุ่มเนื่องจาก กำหนดค่าไว้ต่ำสุดที่ 1 วินาที (แต่ถ้าไวพอ 1วิ กด2คลิ๊ก ก็ไม่เปลี่ยนจ้า)

ทดสอบ 2 Duration=15 ASP.NET จะเก็บแคชของหน้านั้นเอาไว้ 15 วินาทีโดยไม่ต้องกลับไปทำงานใน CodeBehind เพื่อโหลดข้อมูลกลับมาใหม่ สังเกตุได้ว่าเวลาจะไม่เปลี่ยนไปจนกว่าจะครบ 15 วินาที

ส่วนที่ 2 จะ load data มาจาก database และนำไปเก็บ ไว้ใน Session และ Cache

Load Data Button
  1. protected void btnLoadDataToSession_Click(object sender, EventArgs e)
  2. {
  3.     using( var db = new NorthwindEntities())
  4.     {
  5.         db.ContextOptions.LazyLoadingEnabled = false;
  6.         var custs = db.Customers.ToList();
  7.         var orders = db.Orders.ToList();
  8.        
  9.         // Stored to Session
  10.         // System.Web.HttpContext.Current.Session
  11.         Session["AllCustomers"] = custs;
  12.         Session["AllOrders"] = orders;
  13.  
  14.         // Stored to Cache
  15.         // System.Web.HttpContext.Current.Cache
  16.         var expiredDT = DateTime.Now.AddMinutes(10);
  17.         Cache.Insert("AllCustomers",custs, null,
  18.             expiredDT, TimeSpan.Zero, CacheItemPriority.Default, null);
  19.         Cache.Insert("AllOrders", orders, null,
  20.             expiredDT, TimeSpan.Zero, CacheItemPriority.Default, null);
  21.  
  22.         DropDownList1.Items.Clear();
  23.         DropDownList1.DataSource = Session.Keys;
  24.         DropDownList1.DataBind();
  25.         DropDownList1.Items.Insert(0, "");
  26.         DropDownList1.SelectedIndex = 0;
  27.  
  28.         DropDownList2.Items.Clear();
  29.         DropDownList2.DataSource = Cache.GetEnumerator().ForLinq().Select(pair => pair.Key);
  30.         DropDownList2.DataBind();
  31.         DropDownList2.Items.Insert(0, "");
  32.         DropDownList2.SelectedIndex = 0;
  33.  
  34.  
  35.     }
  36. }

line 3-7 ทำการดึงข้อมูลของ Customer, Order ขึ้นมาทั้งหมด

line 11-12 เก็บข้อมูล Customer, Order ลงใน Session ทั้งสองตัว

line 16-20 เก็บข้อมูล Customer, Order ลงใน Cache และกำหนดอายุของแคชไว้ที่ 10 นาที

line 22-32 ทำการผูกคีย์ของ Session และ Cache กับ Dropdownlist ทั้ง 2 เพื่อเอาไว้ใช้ในการดึงข้อมูล

และเราจะทำการดักจับไอเท็มของ Session และ Cache ไว้เพื่อทดสอบ scope การใช้งาน ว่าแตกต่างกันอย่างไร

Page Load Event
  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3.     if (!IsPostBack)
  4.     {
  5.         DropDownList1.Items.Clear();
  6.         DropDownList1.DataSource = Session.Keys;
  7.         DropDownList1.DataBind();
  8.         DropDownList1.Items.Insert(0, "");
  9.         DropDownList1.SelectedIndex = 0;
  10.  
  11.         DropDownList2.Items.Clear();
  12.         DropDownList2.DataSource = Cache.GetEnumerator().ForLinq().Select(pair => pair.Key);
  13.         DropDownList2.DataBind();
  14.         DropDownList2.Items.Insert(0, "");
  15.         DropDownList2.SelectedIndex = 0;
  16.     }
  17. }

ส่วนที่ 3 ใน dropdownlist ทั้งสองจะมี Key ที่ใช้ในการดึงข้อมูลออกมาจาก Session และ Cache เพื่อที่จะเลือกและผูกข้อมูลเข้ากับ DataGrid เพื่อแสดงผล เมื่อเลือก item ใน dropdownlist จะ postback กลับไปเพื่อดึงข้อมูลจาก session, cache ที่ต้องการ

Dropdown IndexChanged Code
  1. // Get Data From Session
  2. protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
  3. {
  4.     List<Order> orders = null;
  5.     List<Customer> custs = null;
  6.     if (!string.IsNullOrEmpty(DropDownList1.SelectedValue))
  7.     {
  8.         if (DropDownList1.SelectedValue == "AllCustomers")
  9.         {
  10.             custs = Session[DropDownList1.SelectedValue] as List<Customer>;
  11.             GridView1.DataSource = custs;
  12.             GridView1.DataBind();
  13.         }
  14.         else if (DropDownList1.SelectedValue == "AllOrders")
  15.         {
  16.             orders = Session[DropDownList1.SelectedValue] as List<Order>;
  17.             GridView1.DataSource = orders;
  18.             GridView1.DataBind();
  19.         }
  20.     }
  21. }
  22.  
  23. //Get Data From Cache
  24. protected void DropDownList2_SelectedIndexChanged(object sender, EventArgs e)
  25. {
  26.     List<Order> orders = null;
  27.     List<Customer> custs = null;
  28.     if (!string.IsNullOrEmpty(DropDownList2.SelectedValue))
  29.     {
  30.         if (DropDownList2.SelectedValue == "AllCustomers")
  31.         {
  32.             custs = Cache.Get(DropDownList2.SelectedValue) as List<Customer>;
  33.             GridView1.DataSource = custs;
  34.             GridView1.DataBind();
  35.         }
  36.         else if (DropDownList1.SelectedValue == "AllOrders")
  37.         {
  38.             orders = Cache.Get(DropDownList2.SelectedValue) as List<Order>;
  39.             GridView1.DataSource = orders;
  40.             GridView1.DataBind();
  41.         }
  42.     }
  43. }

line 8-18 เป็นการดึงค่าโดยใช้ key AllCustomers, AllOrders ไปดึงค่าที่เก็บอยู่ใน Session และผูกข้อมูลเข้ากับ Gridview เพื่อแสดงค่า

line 30-40 เป็นการดึงค่าโดยใช้ key AllCustomers, AllOrders ไปดึงค่าที่เก็บอยู่ใน Cache และผูกข้อมูลเข้ากับ Gridview เพื่อแสดงค่า

และสุุดท้ายก็จะเป็น web.config ที่เป็น ASP.NET4 ของเว็บนี้ครับ (โล่งๆ ไม่มีอะไรเลย)

web.config
  1. <?xml version="1.0"?>
  2. <configuration>
  3.   <connectionStrings>
  4.     <add name="NorthwindEntities" connectionString="metadata=res://*/NorthwindDB.csdl|res://*/NorthwindDB.ssdl|
  5.          res://*/NorthwindDB.msl;provider=System.Data.SqlClient;provider connection string=&quot;
  6.          data source=.;initial catalog=Northwind;integrated security=True;multipleactiveresultsets=True;App=EntityFramework&quot;"
  7.          providerName="System.Data.EntityClient" />
  8.   </connectionStrings>
  9.  
  10.   <system.web>
  11.     <compilation debug="true" targetFramework="4.0" />
  12.   </system.web>
  13.  
  14.   <system.webServer>
  15.      <modules runAllManagedModulesForAllRequests="true"/>
  16.   </system.webServer>
  17. </configuration>

 

Case Study : ตัวอย่างปัญหาจากตัวอย่างเว็บด้านบน (Problem of ASP.NET Session and Cache with InProc Mode)

ในกรณีตัวอย่างนี้ ตัว web application วิเคราะห์และทดสอบการจำเป็นในการใช้ Session, Cache, OutputPage  ในส่วนที่เหมาะสมของเว็บแล้ว แต่ว่ายังใช้หน่วยความจำของ Web Server ในการเก็บข้อมูลเหล่านั้นตรง ๆ ก็คือ Session = InProc Mode และ default Cache Provider ที่มีมาให้นั่นเอง

เมื่อเราพัฒนาเว็บแอ๊พพลิเคชั่นผ่านการทดสอบในส่วนของบิสซิเนสเรียบร้อยแล้ว ก็จะทำเทสในเรื่อง Load Test เพื่อหาค่าความสามารถในการรองรับ concurrent user ที่จะเข้ามาใช้งานระบบ ซึ่งในตัวอย่างได้สมมติเอาว่าผ่านการทำ load test มาแล้ว ซึ่งทั้งระบบ Web Server และ Database นั้น รองรับจำนวน user อยู่ที่ 200 concurrent โดยใช้งานปกติจะมีจำนวน concurrent ประมาณ 80-150 คน

image

เมื่อถึงเวลาหนึ่งทางกิจการได้เติบโตขึ้น ทำให้จำนวนผู้เข้าใช้งานเว็บมีจำนวนมากขึ้นเป็นลำดับ ซึ่งอาจจะเป็นช่วงเวลาเช่นช่วงเที่ยง เย็น และวันหยุด พบว่าหลายครั้งที่ Web Server Down เพราะต้องบริการข้อมูลยูสเซอร์ที่เข้าใช้งานพร้อมกันจำนวน 300 user concurrents ซึ่งเกินจากที่ระบบจะรองรับได้ ดังภาพด้านล่าง

image

ผลคือระบบล่ม ทุกอย่างจะเริ่มต้นได้ใหม่ก็จนกว่าจะ restart Web Site/Database กันใหม่ แบบนี้ทำให้ธุรกิจเสียหายแน่ ๆ ครับ

ปัญหาและสาเหตุมีดังนี้

Client : เนื่อง user แต่ละคนจะต้องสร้าง session ขึ้นเป็นของตัวเอง และการกดเพื่อสร้าง request กลับไปที่ web server ทุกครั้ง และจำเป็นจะต้องเข้าเว็บเซอร์เวอร์เดิมทุกรีเควส หากเว็บเซอร์เวอร์ตัวนั้นล่มไป เซสชั่นทุกอย่างก็จะหายไปหมดเช่นกัน

Web Server : มีการเก็บ Session, Cache แยกจากกันในแต่ละเว็บเซอร์เวอร์ ซึ่งไม่สามารถที่จะแชร์ข้ามเครื่องกันได้ ทำให้ข้อมูลบางตัวที่ควรจะแชร์กันได้ต้องถูกสร้างขึ้นใหม่ทุกครั้งที่มี user เข้ามาใช้งาน

Database : มีการใช้งาน Disk อย่างหนัก เพราะทุก request ที่ส่งเข้ามาเกือบทั้งหมดจะต้องเข้าถึงข้อมูลตลอดเวลา

ก่อนที่เราจะเลือกทางแก้ปัญหาโดยการลงทุนเพิ่ม Web Server, Upgrade Database Server เหล่านั้น หากพิจารณากันให้ดี  ปัญหาที่สำคัญก็คือ

1. เกิดข้อจำกัดของ Web Server ในส่วนของ Memory สำหรับเก็บข้อมูลพวก Session, Cache โดยแยกไปตามขนาดของ RAM ที่ติดตั้งในแต่ไว้ใน Server

2. เกิดข้อจำกัดของ User Process ในการทำงาน โดยจะทำงานได้เพียงบน Web Server ตัวเดียวเท่านั้น

3. มีการเข้าถึง Database ตลอดเวลาเพื่อดึงข้อมูลที่ซ้ำๆกันทุกครั้ง ที่ผู้ใช้ร้องขอบริการเดิม ๆ

4. Web Server ใน Farm ทุกตัวควรจะเห็น Session ของ User คนเดิม เมื่อเกิดปัญหากรณี Web Server ตัวใด ๆ ที่ User ใช้งานอยู่เกิดล่ม ก็สามารถที่จะยังทำงานต่อด้วย web server ตัวอื่นได้ทัทีโดยข้อมูลปัจจุบันยังคงอยู่

ซึ่งปัญหาเหล่านี้แก้ได้ครับ

 

Solution : Implement Cache Server (AppFabric Caching)

จากตอนที่ 1 นั้นผมได้แนะนำตัว AppFabric Cache Service ไปแล้ว ซึ่งเราจะนำเข้ามาใช้แก้ไขปัญหาที่เกิดขึ้นข้างต้น โดยก่อนที่จะเข้าถึง Database เราก็วาง Cache Server เอาไว้ให้เป็นตัวบริการเก็บข้อมูลทั้ง Session, Cache ตามรูปดังนี้

image

จากโมเดลด้านบนนี้ เราใช้ Cache Server มาวางโดยเอาไว้แก้ไขปัญหาของ Web Server ดังนี้

1. เพิ่มขนาดของ Cache บน Web Server  โดยขนาดจะขึ้นอยู่กับหน่วยความจำของ Cache Server

2. เอาไว้เก็บ User Session แทนการเก็บบน Web Server ป้องกันปัญหากรณี web server ที่ user ใช้งานอยู่ขณะนั้นเกิดปัญหา ทำให้ Web Server อีกตัวสามารถทำงานแทน web server ตัวที่ล่มไปได้ทันที

3. เป็นข้อมูลที่ถูกเรีกยใช้บ่อย และข้อมูลนั้น อาจจะเป็น Static Data หรือมีการเปลี่ยนแปลงของข้อมูลน้อย  ลดภาระของ Database ในการดึงข้อมูลส่งให้ Web Server บ่อย ๆ

ต่อไปเข้าสู่ขั้นตอนการสร้างและนำ AppFabric Cache ไปใช้ใน ASP.NET กันครับ

 

Create and Setting AppFabric Cache for ASP.NET Web Application

ต่อไปเราจะทำการสร้างแคชดาต้าเบส และตั้งค่าเอาไว้ใช้งานกับ asp.net web application ของเราครับ

โดยจะสร้างแคชเอาไว้ 2 ตัวโดยให้ชือ่ว่า ASPNETSessionCache เอาไว้เก็บข้อมูลที่เป็นเซสชั่นและ ASPNETOutputCache เอาไว้เก็บข้อมูลแคช ทำตามขึ้นตอนดังนี้

1. เรียกหน้าต่าง Caching Administration Windows Powershell ออกมาใช้งาน

2. พิมพ์

Use-CacheCluster

3. สั่งสตาร์ท service ด้วยคำสั่ง

Start-CacheCluster

4. เพิ่ม user สำหรับเข้าใช้งานแคช ให้ Add Current user สำหรับ Debug

เลือก 1 ชุดคำสั่งตาม windows ที่ใช้ครับ

– กรณีใช้ service account  (all windows edition)

Grant-CacheAllowedClientAccount –Account “ComputerName\UserName”

– กรณีใช้ Network Server Account (win03, win03r2, win08, vista)

grant-cacheallowedclientaccount -Account "NETWORK SERVICE"

– ใช้ ASPNET User account ใน Windows 7/WS08R2:

grant-cacheallowedclientaccount -Account "IIS AppPool\ASP.NET v4.0"

5. สร้างแคชสำหรับ asp.net ไว้เก็บเซสชั่นชื่อ ASPNETSessionCache และ ASPNETOutputCache

New-Cache –CacheName ASPNETSessionCache –Eviction None –TimeToLive 60

New-Cache –CacheName ASPNETOutputCache –Eviction None –TimeToLive 60

6. เรียกดู Cache DB ที่สร้างไว้ทั้งสองก้อนว่าสำเร็จหรือไม่ด้วยคำสั่ง

Get-Cache

image

7. ตรวจสอบดูว่าแคชทั้ง 2 ว่าตั้งค่าไว้อย่างไรบ้าง

Get-CacheConfig ASPNETSessionCache

Get-CacheConfig ASPNETOutputCache

image

7. ตรวจสอบค่า Staticstics ว่ามีสถานะปัจจุบันอย่างไรบ้าง

Get-CacheStatistics ASPNETSessionCache

Get-CacheStatistics ASPNETOutputCache

image

แค่นี้ AppFabric Cache ก็พร้อมใช้งานแล้วครับ ต่อไปเราจะไปดูการตั้งค่าและเรียกใช้งานภายใน asp.net กัน

 

Using AppFabric Cache within ASP.NET Web Application

Download Code Sample Here

ในขั้นตอนนี้เราจะย้าย Session และ Cache จากหน่วยความจำภายในเครื่องไปเก็บไว้ใน AppFabric Cache

การเรียกใช้ AppFabric Cache ภายใน Web Application นั้น ในตอนนี้ผมขอเลือกใช้ Library ตัวนึงซึ่งมีความสามารถเยอะกว่า Cache Client ที่ไมโครซอฟต์มีมาให้ตั้งแต่ติดตั้ง AppFabric

การนำไปใช้งานนั้นมี 2 วิธีคือ ทำผ่าน web.config และ เขียนโค้ด

ในขั้นตอนแรก  ดาวน์โหลด ASP.NET 4 Providers for AppFabric Caching จาก CodePlex มาใช้งาน ให้ unzip ออกและมองหา “Microsoft.Web.DistributedCache.dll” โดยตัวนี้จะเป็น Custom Provider ที่เรียกใช้ Microsoft.ApplicationServer.Caching.Client.dll ของ AppFabric อีกทีนึง

Setting Method 1: Edit web.config

เปิด Web Application ขึ้นมาแก้ไข web.config ดังนี้

– เพิ่มค่า configSection สำหรับ Cache Client ของ Microsoft เพื่อให้รู้จัก dataCachcClient Section

web.config: configSections
  1. <section name="dataCacheClient"
  2.     type="Microsoft.ApplicationServer.Caching.DataCacheClientSection,
  3.         Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0,
  4.         Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  5.     allowLocation="true"
  6.     allowDefinition="Everywhere"/>

– เพิ่ม dataCacheClient Section เพื่อกำหนดที่อยู่ของ AppFabric Host และ Port

web.config: dataCacheClient
  1. <dataCacheClient>
  2.   <hosts>
  3.     <host name="Nine-NB" cachePort="22233" />
  4.   </hosts>
  5. </dataCacheClient>

– ตั้งค่าการใช้ Cache ของ ASP.NET ไปที่ AppFabric โดยกำหนดเพิ่มเติมใน <system.web>

web.config: <sessionState>
  1. <sessionState mode="Custom" customProvider="DistributedSessionAspSessionProvider">
  2.   <providers>
  3.     <!– specify the named cache for session data –>
  4.     <!–<add name="AppFabricCacheSessionStoreProvider"
  5.       type="Microsoft.ApplicationServer.Caching.DataCacheSessionStoreProvider"
  6.       cacheName="ASPNETSession"
  7.       sharedId="ASPNETSession"/>–>
  8.     <add name="DistributedSessionAspSessionProvider"
  9.          type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider,
  10.          Microsoft.Web.DistributedCache"
  11.         cacheName="ASPNETSessionCache"
  12.           applicationName="ASPNETWeb"
  13.           useBlobMode="false" />
  14.   </providers>
  15. </sessionState>

line 8  ตั้งค่าชื่อของ provider ที่เราต้องการจะเพิ่มเติม

line 9 กำหนด type ของ dll ที่เรานำมาใช้

line11-13  เป็นการะบุ Cache โดยอ้างถึง ASPNETSession ที่สร้างไว้ใน AppFabric Cache, กำหนด ApplicationName ที่จะเข้าใช้แคชก้อนดังกล่าว และระบุไม่ใช่ Blob Mode

line – 1 กำหนด mode=”Custom” และเลือกใช้ customProivder=”DistributedSessionAspSessionProvider” ตามที่ได้ตั้งค่าไว้

– ตั้งค่าการใช้ Page Output Cache ของ ASP.NET ไปที่ AppFabric โดยกำหนดเพิ่มเติมใน <system.web>

web.config: <caching>
  1. <caching>
  2.   <outputCache defaultProvider="DistributedCache">
  3.     <providers>
  4.       <add name="DistributedCache"
  5.            type="Microsoft.Web.DistributedCache.DistributedCacheOutputCacheProvider,
  6.            Microsoft.Web.DistributedCache" cacheName="ASPNETOutputCache" applicationName ="ASPNETWeb" />
  7.     </providers>
  8.   </outputCache>
  9. </caching>

line 4 กำหนดชื่อของ Cache ที่เราใช้อ้างอิง

line 5 ใส่ type ของ dll ที่จะใช้ในการทำ page output cache

line 6 cacheName กำหนดให้ใช้แคชที่ชื่อ ASPNEToutputCache และกำหนดชื่อ applicationName เป็น ASPNETWeb

line 1 ที่ defaultProvider กำหนดให้ใช้ DistributedCache name ที่เราได้สร้างไว้

Setting Method 2: Cache with Programmatically

เพิ่มโค้ดใน Global.asax.cs ดังนี้

Code Snippet
  1. void Application_Start(object sender, EventArgs e)
  2. {
  3.     DistributedCacheSessionStateStoreProvider.CacheConnecting += DistributedCacheSessionStateStoreProvider_CacheConnecting;
  4.     DistributedCacheOutputCacheProvider.CacheConnecting += DistributedCacheOutputCacheProvider_CacheConnecting;
  5. }
  6.  
  7. void DistributedCacheOutputCacheProvider_CacheConnecting(object sender, CacheConnectingEventArgs e)
  8. {
  9.     e.CacheFactoryConfiguration = new DataCacheFactoryConfiguration()
  10.             {
  11.                 Servers = new DataCacheServerEndpoint[] {new DataCacheServerEndpoint("Nine-NB", 22233)}
  12.             };
  13.     e.CacheName = "ASPNETOutputCache";
  14. }
  15.  
  16. void DistributedCacheSessionStateStoreProvider_CacheConnecting(object sender, CacheConnectingEventArgs e)
  17. {
  18.     e.CacheFactoryConfiguration = new DataCacheFactoryConfiguration()
  19.         {
  20.             Servers = new DataCacheServerEndpoint[] { new DataCacheServerEndpoint("Nine-NB", 22233) }
  21.         };
  22.     e.CacheName = "ASPNETSessionCache";
  23. }

line 3-4 ทำการผูก event ให้ CacheSession และ OutputCache Provider เมื่อมีการร้องขอให้ทำการ connect ไปยัง Cache Server ก็ให้ไปทำ event Connecting ทั้งสอง

line 7-14 เป็น event ของ Output Cache โดยทำการ add host, port number และกำหนดชื่อของ Cache Name ที่จะใช้

line 16-23 เป็น event ของ Cache Session โดยทำการ add host, port number และกำหนดชื่อของ Cache Name ที่จะใช้

 

Test Run ASP.NET Web Application and Monitoring Cache

เริ่มแรกให้ทำการตรวจสอบว่า Cache ของ ASPNETSessionCache และ ASPNETOutputCache นั้นยังมีสถานะก่อนใช้งานเป็นดังนี้

image

ยังไม่มีการเก็บข้อมูลใด ๆ ลงใน Cache ทั้งสองก้อน    จากนั้นเราจะทำการ Run Web Site ด้วย Visual Studio 2010 ด้วยการกด F5 ได้ผลขึ้นดังนี้

image

เนื่องจากมี page output cache เกิดขึ้น ดงันั้นเราจะไปตรวจสอบที่ ASPNETOutputCache จะพบได้ว่ามีการเก็บ object ลงไปใน Cache เพิ่มดังนี้

image

ที่เห็นนี้จะเป็น Automatic Cache และ Session สำหรับ System ในการทำงานของ ASP.NET Web Application ซึ่งจะเกิดขึ้นทุกครั้งที่ User เข้ามาทำงานในหน้า Default.aspx

ต่อไปเราจะทำการ เก็บค่าลง Session และ Cache ด้วยการกด button ในหัวข้อที่ 2 Load Data

เมื่อ response กลับมา ลองไปคลิ๊กที่ downdown ทั้งสองจะพบว่ามี key ของทั้ง Session และ Cache ที่เราเก็บค่าไว้ใน AppFabric Caching นั่นเอง

ทีนี้เรากลับไปดูความเปลี่ยนแปลงที่เกิดขึ้นใน Cache ทั้งสองตัวกันครับ

image

ก็จะพบว่ามีจำนวนของ Item ที่เก็บเพิ่มขึ้นอันเนื่องมาจากการเก็บข้อมูลลงไปนั่นเอง

 

Conclusion

หวังว่าพอจะมองเห็นประโยชน์จากดีไซน์นี้ หากต้องการที่จะ scale ระบบ web server ให้ทำงานได้สมบูรณ์และมีประสิทธิภาพสูงสุดนั้น บทความนี้ก็เป็นอีกหนึ่งแนวทางในการนำไปสู่ผลสำเร็จนั้นครับ

ในตอนต่อไป ผมจะพูดถึงการนำ AppFabric Caching ไปใช้ใน MVC, EF, NHibernate เท่าที่จะพอนึกออกครับ และหากมีโอกาสผมจะทำการทดสอบในส่วนของการทำ Cache Cluster, Fault Torrelance Testing, Performance Tesing ต่อไปด้วยครับ


Download Code Sample Here

Chalermpon Areepong Nine (นาย)

Microsoft MVP Thailand ASP.NET

email : nine_biz-talk.net at hotmail dot com

2 Comments »

  1. ลงชื่อรอติดตามผลงานตอนหน้าครับ ^^

    Comment by มด ย่อง — 01/05/2012 @ 3:42 pm

    • ขอบคุณครับ ใกล้ถึงคิวแล้วครับ

      Comment by Nine MVP ASP.NET — 03/05/2012 @ 5:00 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: