Presentation laddar. Vänta.

Presentation laddar. Vänta.

Välkommen till Sommarkollo 2007 2006. Windows Communication Foundation André Henriksson, Johan Lindfors.

Liknande presentationer


En presentation över ämnet: "Välkommen till Sommarkollo 2007 2006. Windows Communication Foundation André Henriksson, Johan Lindfors."— Presentationens avskrift:

1 Välkommen till Sommarkollo

2 Windows Communication Foundation André Henriksson, Johan Lindfors

3 Agenda Programmeringsmodellen Olika typer av ”hosting” Skalbarhet, prestanda Versionshantering Arkitekturen i WCF Säkerhet och tillförlitlighet Andra ämnen Enterprise Library Service Factory

4 Agenda Programmeringsmodellen Olika typer av ”hosting” Skalbarhet, prestanda Versionshantering Arkitekturen i WCF Säkerhet och tillförlitlighet Andra ämnen Enterprise Library Service Factory

5 WCF byggstenar Förenar teknikerna för distribuerad kommunikation ”On-machine”, ”Cross-machine”, ”Cross-Internet” Brett stöd för WS-* specifikationerna Kompatibelt med existerande tekniker från Microsoft Förenklar utvecklingen av löst kopplade tjänster Konfigurationsbaserad kommunikation Enhetlig Interoperabilitet Tjänsteorienterat

6 Klient Tjänst Klienter och tjänster

7 Klient Tjänst “Endpoints” Endpoint Endpoints exponerar funktionalitet

8 Klient Tjänst Adress, Bindning, Kontrakt A BC CBA CBA CBA Endpoints exponerar funktionalitet Adress beskriver VART! Bindning beskriver HUR! Kontrakt beskriver VAD!

9 WSDL Klient Tjänst Metadata A BC CBA CBA CBA Endpoints exponerar funktionalitet Adress beskriver VART! Bindning beskriver HUR! Kontrakt beskriver VAD! WSDL beskriver ”endpoints”

10 WSDL Klient Tjänst Uppträdanden Uppträdanden beskriver exempelvis Instansiering och aktivering Sessionshantering Transaktioner A BC CBA CBA CBA UUU

11 WCF på en enda bild “ServiceContract” “DataContract” “Service-type” Uppträdanden Address + bindning + kontrakt = “Endpoint” “ServiceHost” [ServiceContract] public interface IMyService { [OperationContract] void MyOperation(Request request); } public class MyService : IMyService { public void MyOperation(Request request) { } } [DataContract] public class Request { [DataMember] string data; } [ServiceBehavior( InstanceContextMode=InstanceContextMode.Single)]

12 Tjänst och klient

13 [ServiceContract] Överrensstämmer med elementet i WSDL “Name” – namn på kontraktet (typ-namn) “Namespace” – namnrymd för tjänstens metoder “Session“ – stöd för kanaler med tillstånd “CallbackContract” – typ på retur-kontrakt (vid kanaler med duplex) [ServiceContract(Name=”BankingServicesContract ”, Namespace=”www.bank.se”)] public interface IMyService { [OperationContract] string TransferMoney(string credAcc, string debAcc, double amount); }

14 WCF och WSDL WSDL kontrakt genereras i flera filer Använder Scheman separeras alltid från tjänsten

15 Duplex [ServiceContract] [ServiceContract(Session = true, CallbackContract = typeof(IOrderEntryCallback))] public interface IOrderEntry { [OperationContract(IsOneWay = true)] void PlaceOrder(PurchaseOrder order); } [ServiceContract] public interface IOrderEntryCallback { [OperationContract(IsOneWay = true)] void PlaceOrderCompleted( PurchaseOrderStatus orderStatus); }

16 [OperationContract] “Name” – externt namn på metoden “IsOneWay” – beskriver om metoden returnerar ett meddelande eller inte “Action” – “SOAP action” (“Name”) “ReplyAction” – “SOAP return action” [ServiceContract(Name=”BankingServicesContract ”, Namespace=”www.bank.se”)] public interface IMyService { [OperationContract(Name=”Transfer”, IsOneWay=true)]] string TransferMoney(string credAcc, string debAcc, double amount); }

17 Synkront Asynkront [ServiceContract] public interface IMath { [OperationContract] int Add(int I, int j); } [OperationContract] [ServiceContract] public interface IMath { [OperationContract(AsyncPattern = true)] IAsyncResult BeginAdd( int i, int j, AsyncCallback cb, object o); int EndAdd(IAsyncResult result); }

18 Nivåer av programmering Använd olika abstraktionsnivåer Definera operationer med parametrar Definera operationer med typade meddelanden Definera operationer med otypade meddelanden string TransferMoney(string credAcc, string debAcc, double amount); TransferMoneyResponse TransferMoney(TransferMoneyRequest request); Message TransferMoney(Message request);

19 [DataContract] Kompatibilitet baseras på schema och inte på typer Explicit definition på vad som tillhör kontraktet [DataContract(Name="Account")] class CheckingAccount { [DataMember] private string Customer; [DataMember(Name="Number")] private string Registration; private string InternalID; } [DataContract(Name=“Account”)] class SavingsAccount { [DataMember(Name=“Customer”)] private string Client; [DataMember(Name=“Number”)] private string AccountNr; }

20 [MessageContract] Modellera själv meddelanden i SOAP Definera element för “header” och “body” Kan användas för att skicka “meta-information” erikven 100 A B [MessageContract] class TransferMoneyRequest { [MessageHeader] private string requestor; [MessageBodyMember] public string CreditAccount; [MessageBodyMember] public string DebitAccount; [MessageBodyMember] public double Amount; } [MessageContract] class TransferMoneyResponse { [MessageBodyMember] private string Result; public TransferMoneyResponse(Mess … }

21 Felhantering Automatisk hantering vid utveckling

22 [FaultContract] [DataContract] class MyFault { [DataMember] public string Reason = null; } [ServiceContract] public interface IOrderEntry { [OperationContract] [FaultContract(typeof(MyFault))] PurchaseOrder GetOrder(String orderId); } public class OrderEntry: IOrderEntry { public PurchaseOrder GetOrder(string orderId) { try{…} catch(Exception exception) { MyFault theFault = new MyFault(); theFault.Reason = “Some Reason”; throw new FaultException (theFault); } }

23 På klienten [DataContract(Name="MyFault")] public class ClientFault { [DataMember] string Reason = null; }... try { PurchaseOrder order = Service.GetOrder(orderId); } catch (FaultException clientFault) { Console.WriteLine(clientFault.Detail.Reason); } [FaultContract]

24 Bindningar En bindning består av Transport + ”Encoding” + Protokoll Tre sätt att konfigurera Använd en standard Anpassa en standard Skapa en skräddarsydd

25 Bindningar Interoperabiliet Säkerhet Session Transaktioner Duplex BasicHttpBindingBP 1.1T | S WsHttpBindingWST | SXX WsDualHttpBindingWSSXXX NetTcpBinding.NETT | SXXX NetNamedPipeBinding.NETTXXX NetMsmqBinding.NETT | SX CustomBinding***** T = SSL/TLS | S = WS-Security | O = “One-Way Only”

26 Bindningar: Standard OBS: Liten bokstav på bindning i konfiguration

27 Bindningar: Anpassa

28 .PerCall En instans per anrop.PerSession En instans per session.Single En instans per tjänst Instansiering [ServiceContract] public interface IEcho{ … } [ServiceBehavior(InstanceContextMode= InstanceContextMode.Single)] internal class MyService: IEcho { … }

29 SessionId = null Client 1 SessionId = null Client 2 ServiceHost Service New Instansiering:.PerCall

30 .Single Med ytterligare konstruktorer Instansiering [ServiceContract] public interface IEcho{... } [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] internal class MyService: IEcho { private string myData = null; private MyService(){} internal MyService(string startUpData){ this.myData=startUpData; }... } public class MyHost { MyService service = new MyService(“The initial data”); using(ServiceHost host = new ServiceHost(service)) {... } }

31 Instansiering:.Single SessionId = "1" Client 1 SessionId = "1" SessionId = "2" Client 2 ServiceHost Service New The singleton could do it's own session/state mgt.

32 .PerSession Instansiering [ServiceContract] [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] public class Math { private long sum = 0; [OperationContract] public int Add(int i, int j) { this.sum = this.sum + i + j; return i + j; } [OperationContract] public long GetTotal() { return this.sum; } [OperationContract] [OperationBehavior(ReleaseInstanceMode = ReleaseInstanceMode.AfterCall)] public void Clear() { this.sum = 0; } }

33 Instansiering:.PerSession SessionId = "1" Client 1 SessionId = "1" SessionId = "2" Client 2 ServiceHost Service SessionId=1 New Service SessionId=2 New

34 Hantera sessioner [ServiceContract(Session=true)] public interface IMath { [OperationContract( /* IsInitiating=true, IsTerminating=false */)] void Clear(); [OperationContract( IsInitiating=false /* IsTerminating=false */)] void Add(int value); [OperationContract( IsInitiating=false, IsTerminating=true)] int GetFinalSum(); } “Slå på” session “Default” värden Får inte starta en ny session Terminerar sessionen

35 Kontrollerar trådsäkerhet Single (som är grundinställning) Multiple Reentrant Inte relevant för instansering per anrop “Concurrency” [ServiceContract] public interface IEchoContract {... } [ServiceBehavior(ConcurrencyMode= ConcurrencyMode.Multiple)] public class EchoService: IEchoContract {... }

36 Kan användas för att begränsa last Samtidiga anrop, instanser, kopplingar “Throttling” [ServiceBehavior( ConcurrencyMode = ConcurrencyMode.Multiple)] public class MyService {... }

37 Med kod, metod 1 One-off “In-line Proxy” Klienter using System.ServiceModel; namespace MyNamespace { public interface IEcho { string Echo(string input); } public class Program { public static void Main(string[] arguments) { IEcho proxy = new ChannelFactory ("EchoService").CreateChannel(); Console.WriteLine(proxy.Echo(”Ping")); ((IChannel)proxy).Close(); }

38 Med kod, metod 2 Återanvändbar “klass-proxy” Klienter using System.ServiceModel; [ServiceContract] public interface IEchoService { [OperationContract] string Echo(string input); } internal class EchoServiceClient: ClientBase, IEchoService { public EchoServiceClient(string configurationName) :base(configurationName) { } string IEchoService.Echo(string input) { return this.InnerProxy.Echo(input); } public class Program { public static void Main(string[] arguments) { EchoServiceClient client = new EchoServiceClient("EchoService"); ((IEchoServiceClient)client).Echo("Hello, World!"); client.Close(); }

39 Konfigurationen Klienter

40 Generera klienten

41 Agenda Programmeringsmodellen Olika typer av ”hosting” Skalbarhet, prestanda Versionshantering Arkitekturen i WCF Säkerhet och tillförlitlighet Andra ämnen Enterprise Library Service Factory

42 I egna applikationer Hosting [ServiceContract] public interface ILenderService {...} internal class LenderService: ILenderService {...} public class Program { static void Main(string[] args) { using (ServiceHost host = ServiceHost( typeof(LenderService))) { host.Open(); Console.WriteLine(”Host is active."); Console.ReadLine(); host.Close(); } Kan generera ”exceptions”

43 I hanterad ”Windows Service” Processens livslängd kontrolleras av OS Inbyggd “Service Control Manager” Hosting public partial class MyNTService : ServiceBase { private ServiceHost host = null; public MyNTService() { InitializeComponent(); } protected override void OnStart(string[] args) { this.host = new ServiceHost( typeof(LenderService)); host.Open(); } protected override void OnStop() { host.Close(); }

44 IIS < 7.0 Bara över HTTP Med WPAS HTTP, TCP, NamedPipes using System.ServiceModel; namespace MyNamespace { [ServiceContract] public interface ILender {…} internal class LenderService: ILender {…} } Hosting ServiceHost Language=“C#” Service=“MyNamespace.LenderService” %>

45 Olika sätt att ”hosta”

46 Jämförelse av prestanda Undersökning gjordes i vintras Servern konfigurerads antingen för 1 eller 4 processorer 4 klienter lastade servern (CPU gick på 100%) us/library/bb aspx

47 Prestanda (vs ASMX) Över http Över https <48% <26% <36% <13%

48 Prestanda (vs WSE) Med en processor Med fyra processorer <277% <248%

49 Prestanda (vs COM+) Med en processor Med fyra processorer <149%, OBS långsammare vid primitiva meddelanden <104%

50 Med en processor Med fyra processorer Prestanda (vs.NET Remoting) <30% <38%

51 Agenda Programmeringsmodellen Olika typer av ”hosting” Skalbarhet, prestanda Versionshantering Arkitekturen i WCF Säkerhet och tillförlitlighet Andra ämnen Enterprise Library Service Factory

52 Beslutsträd - versionshantering Ny operation? Ändra en operation Ändra ett datakontrakt Ny medlem? Radera operation? Ändra bindning? Arv av service-kontrakt Lägg till ny ”valfri” medlem Nästa version av ”DataContract” i nästa version av namnrymd Nästa version av ”ServiceContract” i nästa version av namnrymd Lägg till ny ”endpoint” Eventuellt ta bort gammal ”endpoint” J N JJ J N N N N J J

53 [ServiceContract] public interface IMyService { [OperationContract] void MyOperation(Request request); } public class MyService : IMyDerivedService {... } [ServiceContract] public interface IMyDerivedService : IMyService { [OperationContract] void MyNewOperation(NewRequest request); } Versionshantering Derivera “ServiceContract”

54 Beslutsträd - versionshantering Ny operation? Ändra en operation Ändra ett datakontrakt Ny medlem? Radera operation? Ändra bindning? Arv av service-kontrakt Lägg till ny ”valfri” medlem Nästa version av ”DataContract” i nästa version av namnrymd Nästa version av ”ServiceContract” i nästa version av namnrymd Lägg till ny ”endpoint” Eventuellt ta bort gammal ”endpoint” J N JJ J N N N N J J

55 Lägg till valfri medlem i “DataContract” [DataContract] public class MyDataContract { [DataMember(IsRequired = true)] public string MyOriginalMember; [DataMember(IsRequired = false)] public string MyNewMember; private ExtensionDataObject extensionData; public ExtensionDataObject ExtensionData { get { return this.extensionData; } set { this.extensionData = value; } } } Versionshantering : IExtensibleDataObject

56 Beslutsträd - versionshantering Ny operation? Ändra en operation Ändra ett datakontrakt Ny medlem? Radera operation? Ändra bindning? Arv av service-kontrakt Lägg till ny ”valfri” medlem Nästa version av ”DataContract” i nästa version av namnrymd Nästa version av ”ServiceContract” i nästa version av namnrymd Lägg till ny ”endpoint” Eventuellt ta bort gammal ”endpoint” J N JJ J N N N N J J

57 [DataContract] public class RetiredEndpointFault { [DataMember] public string NewEndpointMetadata; } [ServiceContract] public interface IMyServiceContract { [OperationContract(IsOneWay=true)] void MyMethod(MyDataContract input); [FaultContract(typeof(RetiredEndpointFault))] [OperationContract(Action="*",ReplyAction="*")] Message MyDefaultMethod(Message input); } Versionshantering För att kunna radera “Endpoints” Lägg till en ”Default” operation Definera ett ”FaultContract” för ”pensionerad endpoint” för ”Default”-operationen

58 Versionshantering

59 Agenda Programmeringsmodellen Olika typer av ”hosting” Skalbarhet, prestanda Versionshantering Arkitekturen i WCF Säkerhet och tillförlitlighet Andra ämnen Enterprise Library Service Factory

60 Arkitekturen i WCF Kontrakt Klient-kod parametrar Klient-kod parametrar Typad proxy ”Channel” ”Transport Channel” byte[] ”Transport Channel” byte[] ”Encoder” Kontrakt Servicetyp parametrar Servicetyp parametrar ”Dispatcher” ”Channel” ”Transport Channel” byte[] ”Transport Channel” byte[] ”Encoder” ”WSDL Exporter” Adderas genom att addera nya uppträdanden Skräddarsydd kanal Skräddarsydd transport Skräddarsydd kodning ”Parameter Inspector” ”Message Formatter” ”Message Inspector” ”Operation Invoker” ”Operation Selector” Adderas med nya bindnings-element

61 Anpassning

62 Agenda Programmeringsmodellen Olika typer av ”hosting” Skalbarhet, prestanda Versionshantering Arkitekturen i WCF Säkerhet och tillförlitlighet Andra ämnen Enterprise Library Service Factory

63 Säkerhet och WCF Säkerheten i WCF erbjuder två saker Säker överföring av meddelanden mellan entiteter Begränsa åtkomst till resurser från entiteter Entitet Person, företag, applikation Resurs Fil, tjänst, operation

64 Säkerhet för meddelanden Konfidentiell Integritet Autentisering Auktorisering Loggning

65 Säkerhetsmodellen i WCF Baseras på vitsord och utsagor Kan erbjuda önskade krav på säkerhet Säkert som grundinställning Utom vid interoperabilitet BasicHttpBinding Konsekvent mellan inställningar (bindningar) Konsekvent mellan vitsord

66 Säkerhet på transportnivå Säkerhetskraven erbjuds på transportlagret Fördelar Bra prestanda Vanlig implementation Små förändringar Nackdelar Begränsad uppsättning utsagor Ingen säkerhet utanför “tråden”

67 Säkerhet på transportnivå

68 Säkerhet på meddelanden Säkerhetskraven erbjuds på meddelandelagret Fördelar Stöd för fler typer av utsagor Utbyggbart Säkerhet från “början till slut” Nackdelar Standards och användning konsolideras fortfarande Viss påverkan på prestandan

69 Säkerhet på meddelandenivå

70 “Mixed Mode” Kompromiss mellan säkerhet på transport- och meddelande-nivån Transportnivån erbjuder integritet och konfidentiallitet Fördelar för prestandan Meddelandenivån hanterar utsagor Rika “vitsord”, utbyggbart

71 “Mixed Mode”

72 Användarnamn/lösenord Konfigureras på klientsidan Console.WriteLine(" Enter username[domain\\user]:"); string username = Console.ReadLine(); Console.WriteLine(" Enter password:"); string password = Console.ReadLine(); CalculatorProxy wsProxy = new CalculatorProxy(); wsProxy.ClientCredentials.UserName.UserName = username; wsProxy.ClientCredentials.UserName.Password = password;

73 “Impersonation” Servern kan iklä sig rollen av klienten [OperationBehavior( Impersonation=ImpersonationOption.Required)] public double Sub(int a, int b) { return a - b; } public double Add(int a, int b) { using (ServiceSecurityContext.Current. WindowsIdentity.Impersonate()) { return a + b; }

74 “PrincipalPermission” Använda säkerhetsmodellen i Windows och.NET Framework [PrincipalPermission(SecurityAction.Demand, Role="Builtin\\Administrators")] public double Mul(int a, int b) { return a * b; }

75 En hel del säkerhet

76 Tillförlitlighet Kan konfigureras på: netTcpBinding (av) wsHttpBinding (av) wsDualHttpBinding (alltid på)

77 Köer Förbättrar tillgängligheten Döljer åtkomst till tjänst eller nätverk Stöd för utskalning Flera läsare från en kö Erbjuder lastbalansering Buffrar meddelanden för senare hantering Är en av byggstenarna för kompenserande aktiviteter

78 Hur köer fungerar! Meddelande KlientTjänst “Dead Letter Queue” “Queue” “Poison Queue” “Queue”

79 “Queue Endpoint”

80 Transaktioner Atomiska eller kompenserande Välj mellan koppling eller komplexitet Atomiska transaktioner Enklare att utveckla Negativ påverkan på prestandan “Tightare”-koppling Kompenserande aktivitet Mer komplex att utveckla Bättre prestanda “Lösare”-koppling

81 Transaktioner [ServiceContract] public interface IMyContract { [OperationContract] [TransactionFlow(TransactionFlowOption.Required)] bool Transfer1(Account from, Account to, decimal amount); [OperationContract] [TransactionFlow(TransactionFlowOption.NotAllowed)] bool Transfer2(Account from, Account to, decimal amount); } Delta i en transaktion

82 Transaktioner public class MyService: IMyContract { [OperationBehavior( TransactionScopeRequired = true, TransactionAutoComplete = true)] public bool Transfer1( Account from, Account to, decimal amount) {... } [OperationBehavior( TransactionScopeRequired = true, TransactionAutoComplete = false)] public bool Transfer2( Account from, Account to, decimal amount) {... OperationContext.Current.SetTransactionComplete(); } Utvecklaren av tjänsten

83 Transaktioner Kontroll av transaktioner Administratören av tjänsten

84 Transaktioner using (TransactionScope scope = new TransactionScope()) { proxyOne.Transfer1(AccountOne, AccountTwo, amount); proxyTwo.Transfer1(AccountThree,AccountFour,amount); UpdateLocalCache(AccountOne, AccountTwo, amount); scope.Complete(); } Använda transaktioner Klientsidan

85 Agenda Programmeringsmodellen Olika typer av ”hosting” Skalbarhet, prestanda Versionshantering Arkitekturen i WCF Säkerhet och tillförlitlighet Andra ämnen Enterprise Library Service Factory

86 Enterprise Library 3.1 “Exception Handling Application Block” “ExceptionShieldingBehavior” Anropar “Exception Handling Application Block” för att skydda fel från anroparen “Logging Application Block” Kan konfigureras för att hantera WCF händelser “XmlTraceListener” kan generera format för diagnostik-verktygen för WCF “Validation Application Block” “ValidationBehavior” kan validera datakontrakt

87 Enterprise Library

88 WCF Service Factory Tillägg till Visual Studio Riktlinjer och rekommendationer Recept för nästa steg Stöd för ASMX eller WCF Referens- implementation Artiklar och dokumentation Guidance Packages Recept, mallar och guider Rekommendation Designmönster Hittas under utveckling Demonstreras med kod Beskrivs som lösning på problem Demonstreras som tillägg till Visual Studio Dokumenteras som processer

89 WCF Service Factory

90

91

92 Presentationen kommer att läggas upp på: 2006

93 using System.Web.Services; public class AccountingOperation { public string AccountName; public long Amount; } public class Accounting { [WebMethod(TransactionOption=TransactionOption.RequiresNew)] public int AddEntry(AccountingOperation debit, AccountingOperation credit) { // Add entry to internal accounting book // return id. } } using System.ServiceModel; [ServiceContract(FormatMode=ContractFormatMode.XmlSerializer)] [OperationContract] [OperationBehavior(AutoEnlistTransaction=true)] // ASMX till WCF

94 public class Accounting : ServicedComponent { public void AddCreditEntry(string creditAccount, int creditAmount) { } using System.EnterpriseServices; [ComponentAccessControl] [SecureMethod] [Transaction(TransactionOption.Required)] [SecurityRole("Manager")] using System.ServiceModel; [ServiceContract] [OperationContract] [OperationBehavior(AutoEnlistTransaction=true)] [PrincipalPermission(SecurityAction.Demand, Role="Managers")] // COM+ till WCF

95 using Microsoft.Web.Services3; [WebService] class HelloWorld { [WebMethod] public string Hello (string text) { MessageSignature signature = (MessageSignature) RequestSoapContext.Current.Security.Elements[0]; if (!signature.SigningToken.Principal.IsInRole ("BUILTIN\Administrators")) throw new AuthorizationException("Access denied"); return String.Format("Hello, {0}", text); } } // Konfigurationsförändringar krävs också [OperationContract] [PrincipalPermission(SecurityAction.Demand, null, "BUILTIN\Administrators")] using System.ServiceModel; [ServiceContract] // WSE till WCF

96 class MyQService { public void ReceiveOrders() { MessageQueue Queue = new XmlMessageFormatter formatter = new XmlMessageFormatter( new Type[] { typeof(System.Data.DataSet)}); Queue.Formatter = formatter; System.Messaging.Message msg = null; while((msg= Queue.Receive()) != null) { DataSet booklist = (DataSet) msg.Body; ProcessOrders(booklist); } } Public void ProcessOrder(DataSet BookList) {... } } using System.Messaging; using System.ServiceModel; [ServiceContract] [OperationContract(IsOneWay = true)] // MSMQ till WCF

97 using System.Runtime.Remoting; [Serializable] public class AccountingOperation { public string AccountName; public long Amount; } public class Accounting { public int AddEntry(AccountingOperation debit, AccountingOperation credit) { // Add entry to internal accounting book // return id. } } using System.ServiceModel; [ServiceContract] [OperationContract] : MarshalByRefObject //.NET Remoting till WCF

98 Resurser Webbsidor Bloggar Böcker och tidskrifter Programming ”Indigo” MSDN Magazine

99


Ladda ner ppt "Välkommen till Sommarkollo 2007 2006. Windows Communication Foundation André Henriksson, Johan Lindfors."

Liknande presentationer


Google-annonser