Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A gondosan megtervezett RESTful webes API meghatározza az ügyfélalkalmazások számára elérhető erőforrásokat, kapcsolatokat és navigációs sémákat. A webes API-k megvalósításakor és központi telepítésekor a webes API-t futtató környezet fizikai követelményeit és a webes API felépítését kell figyelembe vennie az adatok logikai szerkezete helyett. Ez az útmutató a webes API implementálásának és közzétételének ajánlott eljárásaira összpontosít, hogy elérhetővé tegye az ügyfélalkalmazások számára. A webes API-tervezéssel kapcsolatos részletes információkért tekintse meg a webes API-tervezést.
Kérelmek feldolgozása
A kéréseket kezelő kód megvalósításakor vegye figyelembe az alábbi szempontokat:
A GET, PUT, DELETE, HEAD és PATCH műveleteknek idempotensnek kell lenniük
A kérelmeket megvalósító kódnak nem lehetnek mellékhatásai. Ha egy kérést megismétel ugyanazon az erőforráson, a kérésnek ugyanazt az állapotot kell eredményeznie. Ha például több DELETE-kérést küld ugyanarra az URI-ra, annak ugyanannak a hatásnak kell lennie, bár a válaszüzenetekben szereplő HTTP-állapotkód eltérő lehet. Lehetséges, hogy az első törlési kérelem a 204 (nincs tartalom) állapotkódot, a további törlési kérelmek pedig a 404 (nem található) állapotkódot adják vissza.
Megjegyzés
A megvalósítással kapcsolatos útmutatásért lásd: Idempotens fogyasztói minta. A gyakorlatban először határozza meg, hogy egy művelet természetes idempotens-e, és ha nem, alkalmazza a mesterséges idempotenciát a feldolgozott üzenetazonosítók nyomon követésével és az ismétlődő elemek proaktív vagy újraaktív kezelésével.
Az új erőforrásokat létrehozó POST műveleteknek nem lehetnek független mellékhatásai
Ha egy POST-kérelem egy új erőforrás létrehozására szolgál, a kérés hatását az új erőforrásra kell korlátozni (és esetleg bármely közvetlenül kapcsolódó erőforrásra, ha valamilyen kapcsolat van benne). Egy e-kereskedelmi rendszerben például az ügyfél számára új rendelést létrehozó POST-kérések is módosíthatják a készletszinteket, és számlázási adatokat hozhatnak létre, de nem módosíthatják a rendeléshez közvetlenül nem kapcsolódó információkat, és nem befolyásolhatják a rendszer általános állapotát.
Kerülje el a bőbeszédű POST, PUT és DELETE műveletek megvalósítását
Ne tervezzen API-t csevegőműveletek alapján. Minden kéréshez protokoll, hálózat és számítási többletterhelés tartozik. Ha például egy nagyobb kötegelt kérés helyett 100 kisebb kérést hajt végre, az többletterhelést okoz az ügyfélben, a hálózaton és az erőforrás-kiszolgálón. Amikor csak lehetséges, az egyes erőforrások helyett http-igetámogatást biztosítson az erőforráscsoportokhoz.
- A gyűjtemények GET kérése egyszerre több erőforrást is lekérhet.
- A POST-kérések több új erőforrás adatait is tartalmazhatják, és mindet hozzáadhatják ugyanahhoz a gyűjteményhez.
- A PUT-kérések a gyűjtemény teljes erőforráskészletét lecserélhetik.
- A DELETE-kérések eltávolíthatnak egy teljes gyűjteményt.
Az ASP.NET, webes API 2-ben található Open Data Protocol (OData) támogatás lehetővé teszi a kérések kötegelését. Az ügyfélalkalmazások több webes API-kérést is csomagolhatnak, és egyetlen HTTP-kérésben küldhetik el őket a kiszolgálónak, és egyetlen HTTP-választ kaphatnak, amely tartalmazza az egyes kérésekre adott válaszokat. További információ: Batch engedélyezése a Webes API OData szolgáltatásban.
Kövesse a HTTP-specifikációkat válasz küldésekor
A webes API-nak olyan üzeneteket kell visszaadnia, amelyek tartalmazzák a megfelelő HTTP-állapotkódot, amelyek alapján az ügyfél el tudja dönteni, hogyan kezelje az eredményt. Emellett tartalmazniuk kell még a megfelelő HTTP-fejléceket, hogy az ügyfél értse az eredmény jellegét, valamint egy megfelelően formázott törzset, amely alapján az ügyfél elemezheti az eredményt.
Például a POST műveletnek a 201 (Létrehozva) állapotkódot kell visszaadnia, a válaszüzenetnek pedig bele kell foglalnia kell az újonnan létrehozott erőforrás URI-jét a válaszüzenet Location fejlécébe.
A tartalomegyeztetés támogatása
A válaszüzenet törzse különböző formátumú adatokat tartalmazhat. Egy HTTP GET-kérés például JSON- vagy XML-formátumban is visszaadhat adatokat. Az ügyfél által küldött kérés tartalmazhat egy Accept fejlécet, amelyben megadja, hogy milyen adatformátumokat tud kezelni. Ezek a formátumok médiatípusként vannak megadva. Például egy olyan ügyfél, amely get kérelmet ad ki, amely lekéri a képet, megadhat egy Accept fejlécet, amely felsorolja az ügyfél által kezelhető médiatípusokat, például image/jpeg, image/gif, image/png. Amikor a webes API visszaadja az eredményt, az adatokat a felsorolt médiatípusok egyikével kell formáznia, és meg kell adnia a formátumot a válasz Content-Type fejlécében.
Ha az ügyfél nem ad meg Elfogadás fejlécet, a válasz törzséhez használjon ésszerű alapértelmezett formátumot. Példaként az ASP.NET, webes API keretrendszer alapértelmezés szerint JSON-ra van bekapcsolva a szövegalapú adatok esetében.
Adjon meg hivatkozásokat a HATEOAS stílusú navigáció és az erőforrás-felderítés támogatásához
A HATEOAS módszer lehetővé teszi az ügyfelek számára, hogy egy kezdeti kiindulási pontról navigáljanak és derítsék fel az erőforrásokat. Ez URI-ket tartalmazó hivatkozásokkal történik. Amikor egy ügyfél kiad egy HTTP GET kérést egy erőforrás beszerzéséhez, akkor a válasznak tartalmaznia olyan URI-kat kell tartalmaznia, amelyekkel az ügyfélalkalmazás gyorsan megtalálhat bármilyen közvetlenül kapcsolódó erőforrást. Egy e-kereskedelmi megoldást támogató webes API-ban például az ügyfél számos megrendelést adhat le. Amikor egy ügyfélalkalmazás lekéri az ügyfél adatait, a válasznak olyan hivatkozásokat kell tartalmaznia, amelyek alapján az ügyfélalkalmazás el tudja küldeni a HTTP GET kéréseket a rendelés lekéréséhez. Emellett a HATEOAS stílusú hivatkozásoknak le kell írniuk a többi olyan műveletet (például POST, PUT és DELETE), amelyeket az egyes csatolt erőforrások támogatnak a megfelelő URI-val együtt az egyes kérések végrehajtásához. Ezt a megközelítést részletesebben az API-tervezésben ismertetjük.
Jelenleg nincsenek a HATEOAS megvalósítására vonatkozó szabványok, de a következő példa bemutat egy lehetséges módszert. Ebben a példában egy HTTP GET kérés, amely megkeresi az ügyfél adatait, egy olyan választ ad vissza, amely hateoAS-hivatkozásokat tartalmaz, amelyek az adott ügyfél megrendelésére hivatkoznak:
GET https://adventure-works.com/customers/2 HTTP/1.1
Accept: text/json
...
HTTP/1.1 200 OK
...
Content-Type: application/json; charset=utf-8
...
Content-Length: ...
{"CustomerID":2,"CustomerName":"Bert","Links":[
{"rel":"self",
"href":"https://adventure-works.com/customers/2",
"action":"GET",
"types":["text/xml","application/json"]},
{"rel":"self",
"href":"https://adventure-works.com/customers/2",
"action":"PUT",
"types":["application/x-www-form-urlencoded"]},
{"rel":"self",
"href":"https://adventure-works.com/customers/2",
"action":"DELETE",
"types":[]},
{"rel":"orders",
"href":"https://adventure-works.com/customers/2/orders",
"action":"GET",
"types":["text/xml","application/json"]},
{"rel":"orders",
"href":"https://adventure-works.com/customers/2/orders",
"action":"POST",
"types":["application/x-www-form-urlencoded"]}
]}
Ebben a példában a felhasználói adatokat a Customer osztály jelöli a következő kódrészletben. A HATEOAS-hivatkozásokat a Links gyűjteménytulajdonság tartalmazza:
public class Customer
{
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public List<Link> Links { get; set; }
...
}
public class Link
{
public string Rel { get; set; }
public string Href { get; set; }
public string Action { get; set; }
public string [] Types { get; set; }
}
A HTTP GET művelet lekérdezi a felhasználói adatokat a tárolóból, és létrehoz egy Customer objektumot, majd feltölti a Links gyűjteményt. Az eredményt egy JSON-válaszüzenet formájában adja vissza a rendszer. Minden hivatkozás a következő mezőket tartalmazza:
- A visszaadott objektum és a hivatkozás által leírt objektum közötti kapcsolat (
Rel) Ebben az esetbenselfazt jelzi, hogy a hivatkozás maga az objektumra mutató hivatkozás (hasonló athissok objektumorientált nyelv mutatóihoz), ésordersa kapcsolódó rendelési adatokat tartalmazó gyűjtemény neve. - A hivatkozás által leírt objektum hiperhivatkozása (
Href) egy URI formájában. - Az URI felé küldhető HTTP-kérelem típusa (
Action). - Azon adatok formátuma (
Types), amelyeket meg kell adni a HTTP-kérelemben, vagy amelyeket a válasz visszaadhat, a kérelem típusától függően.
A példa HTTP-válaszban található HATEOAS-hivatkozások azt jelzik, hogy egy ügyfélalkalmazás a következő műveleteket hajthatja végre:
- Egy HTTP GET kérelem a
https://adventure-works.com/customers/2URI felé, amely (újra) lekéri az ügyfél adatait. Ezek az adatok XML vagy JSON formátumban adhatók vissza. - Egy HTTP PUT kérelem a
https://adventure-works.com/customers/2URI felé, amely módosítja az ügyfél adatait. Az új adatokat a kérésüzenetben x-www-form-urlencoded formátumban kell megadni. - Egy HTTP DELETE kérelem a
https://adventure-works.com/customers/2URI felé, amely törli az ügyfelet. A kérés nem vár további információkat, és nem ad vissza adatokat a válaszüzenet törzsében. - Egy HTTP GET kérelem a
https://adventure-works.com/customers/2/ordersURI felé, amely lekéri az ügyfél összes rendelését. Ezek az adatok XML vagy JSON formátumban adhatók vissza. - HTTP POST-kérés az URI-hoz
https://adventure-works.com/customers/2/orders, hogy hozzon létre egy új rendelést az ügyfél számára. Az adatokat a kérésüzenetben x-www-form-urlencoded formátumban kell megadni.
Kivételek kezelése
Ha egy művelet nem kezelt kivételt jelez, vegye figyelembe a következő szempontokat.
Kivételek rögzítése és jelentéssel bíró válasz visszaadása az ügyfeleknek
A HTTP-műveleteket megvalósító kódnak átfogó kivételkezelést kell biztosítania ahelyett, hogy engedné a nem kezelt kivételek propagálását a keretrendszerbe. Ha egy kivétel megakadályozza a művelet sikeres elvégzését, a kivétel visszaadható a válaszüzenetben, de ez esetben jelentéssel bíró leírást is kell adnia a kivételt okozó hibáról. A kivételnek tartalmaznia kell a megfelelő HTTP-állapotkódot is ahelyett, hogy minden helyzetben az 500-at adja vissza. Ha például egy felhasználó kérés egy olyan frissítést vált ki, amely megsért egy korlátozást (például megkísérel törölni egy nyitott rendelésekkel rendelkező ügyfelet), akkor a 409 (Ütközés) állapotkódot kell visszaadni, valamint az üzenet törzsében jelezni kell ütközés okát. Ha valamilyen más körülmény akadályozza a kérés teljesítését, akkor a 400 (Hibás kérelem) állapotkód is visszaadható. A HTTP-állapotkódok teljes listáját a W3C webhelyén található Állapotkód-definíciók lapon találja.
A kódpélda rögzíti a különböző körülményeket, és megfelelő választ ad vissza.
[HttpDelete]
[Route("customers/{id:int}")]
public IHttpActionResult DeleteCustomer(int id)
{
try
{
// Find the customer to be deleted in the repository
var customerToDelete = repository.GetCustomer(id);
// If there is no such customer, return an error response
// with status code 404 (Not Found)
if (customerToDelete == null)
{
return NotFound();
}
// Remove the customer from the repository
// The DeleteCustomer method returns true if the customer
// was successfully deleted
if (repository.DeleteCustomer(id))
{
// Return a response message with status code 204 (No Content)
// To indicate that the operation was successful
return StatusCode(HttpStatusCode.NoContent);
}
else
{
// Otherwise return a 400 (Bad Request) error response
return BadRequest(Strings.CustomerNotDeleted);
}
}
catch
{
// If an uncaught exception occurs, return an error response
// with status code 500 (Internal Server Error)
return InternalServerError();
}
}
Tipp.
Ne tartalmazzon olyan információkat, amelyek hasznosak lehetnek az API-ba behatolni próbáló támadók számára.
Sok webkiszolgáló maga rögzíti a hibák körülményeit, mielőtt a hibák elérnék a webes API-t. Ha például egy webhelyen hitelesítés van konfigurálva, és a felhasználó nem adja meg a megfelelő hitelesítési adatokat, a webkiszolgálónak a 401 (Nem engedélyezett) állapotkódot kell visszaadnia. Az ügyfél hitelesítése után a kód a saját ellenőrzéseivel győződhet meg róla, hogy az ügyfélnek hozzáféréssel kell rendelkeznie a kért erőforráshoz. Ha a hitelesítés sikertelen, a 403 (Tiltott) állapotkódot kell visszaadni.
A kivételek egységes kezelése és a hibákkal kapcsolatos adatok naplózása
A kivételek egységes kezelése érdekében érdemes egy globális hibakezelési stratégiát bevezetnie a teljes webes API-n. Olyan hibanaplózást is be kell építenie, amely rögzíti az egyes kivételek teljes részleteit; ez a hibanapló részletes információkat tartalmazhat, feltéve, hogy azokat nem teszik elérhetővé az interneten keresztül az ügyfelek számára.
Az ügyféloldali és kiszolgálóoldali hibák megkülönböztetése
A HTTP-protokoll megkülönbözteti az ügyfélalkalmazás által okozott (HTTP 4xx állapotkódú) és a kiszolgáló hibái miatt előforduló (HTTP 5xx állapotkódú) hibákat. Ügyeljen arra, hogy a hibákkal kapcsolatos válaszüzenetekben betartsa ezt a konvenciót.
Ügyféloldali adatelérés optimalizálása
Az elosztott környezetekben, például amelyekben egy webkiszolgáló és ügyfélalkalmazások találhatók, az egyik elsődleges hibaforrás a hálózat. Ez jelentős szűk keresztmetszeteket okozhat, különösen akkor, ha egy ügyfélalkalmazás gyakran küld kérelmeket vagy fogad adatokat. Ezért törekedni kell a hálózaton keresztül zajló forgalom minimalizálására. Az adatok lekérését és karbantartását kezelő kód megvalósításakor vegye figyelembe az alábbi szempontokat:
Ügyféloldali gyorsítótárazás támogatása
A HTTP 1.1 protokoll támogatja a gyorsítótárazást az ügyfeleken és köztes kiszolgálókon, ahol a Cache-Control fejléc használatával irányítják a kérelmek gyorsítótárazását. Amikor egy ügyfélalkalmazás egy HTTP GET kérést küld a webes API-nak, a válasz tartalmazhat egy Cache-Control fejlécet, amely jelzi, hogy a válasz törzsében található adatok biztonságosan gyorsítótárazhatók-e az ügyfélnél vagy egy köztes kiszolgálón, amelyen a kérelem áthaladt, valamint megadja, hogy az adatok mennyi idő után járnak le és válnak elavulttá.
A következő példa bemutat egy HTTP GET kérelmet és a rá adott választ, amely tartalmaz egy Cache-Control fejlécet:
GET https://adventure-works.com/orders/2 HTTP/1.1
HTTP/1.1 200 OK
...
Cache-Control: max-age=600, private
Content-Type: text/json; charset=utf-8
Content-Length: ...
{"orderID":2,"productID":4,"quantity":2,"orderValue":10.00}
Ebben a példában a Cache-Control fejléc azt határozza meg, hogy a visszaadott adatok 600 másodperc után lejárjanak, és csak egyetlen ügyfél számára alkalmasak, és nem tárolhatók más ügyfelek által használt megosztott gyorsítótárban (privát). A Cache-Control fejléc a private helyett megadhat public (nyilvános) beállítást is, amely esetben az adatok tárolhatók egy megosztott gyorsítótárban, vagy megadhatja a no-store (nincs tárolás) értéket, amely esetben az adatok nem gyorsítótárazhatók az ügyfélben. Az alábbi példakód bemutatja, hogyan hozható létre egy Cache-Control fejléc a válaszüzenetben:
public class OrdersController : ApiController
{
...
[Route("api/orders/{id:int:min(0)}")]
[HttpGet]
public IHttpActionResult FindOrderByID(int id)
{
// Find the matching order
Order order = ...;
...
// Create a Cache-Control header for the response
var cacheControlHeader = new CacheControlHeaderValue();
cacheControlHeader.Private = true;
cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);
...
// Return a response message containing the order and the cache control header
OkResultWithCaching<Order> response = new OkResultWithCaching<Order>(order, this)
{
CacheControlHeader = cacheControlHeader
};
return response;
}
...
}
Ez a kód egy egyéni IHttpActionResult osztályt használ.OkResultWithCaching Ez az osztály lehetővé teszi a vezérlőnek a gyorsítótárfejléc tartalmának beállítását:
public class OkResultWithCaching<T> : OkNegotiatedContentResult<T>
{
public OkResultWithCaching(T content, ApiController controller)
: base(content, controller) { }
public OkResultWithCaching(T content, IContentNegotiator contentNegotiator, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
: base(content, contentNegotiator, request, formatters) { }
public CacheControlHeaderValue CacheControlHeader { get; set; }
public EntityTagHeaderValue ETag { get; set; }
public override async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response;
try
{
response = await base.ExecuteAsync(cancellationToken);
response.Headers.CacheControl = this.CacheControlHeader;
response.Headers.ETag = ETag;
}
catch (OperationCanceledException)
{
response = new HttpResponseMessage(HttpStatusCode.Conflict) {ReasonPhrase = "Operation was cancelled"};
}
return response;
}
}
Megjegyzés
Az HTTP protokoll a no-cache direktívát is meghatározza a Cache-Control fejléchez. Meglehetősen zavaró módon ez az irányelv nem azt jelenti, hogy "ne gyorsítótárazz", hanem "a gyorsítótárazott adatok újraértékelése a kiszolgálóval annak visszaadása előtt"; az adatok továbbra is gyorsítótárazhatók, de a rendszer minden alkalommal ellenőrzi, hogy az adatok továbbra is aktuálisak-e.
A gyorsítótár kezelése az ügyfélalkalmazás vagy a köztes kiszolgáló feladata, de ha megfelelően van megvalósítva, akkor a használatával sávszélesség takarítható meg és növelhető a teljesítmény, mivel nincs szükség a már beszerzett adatok újbóli lekérésére.
A Cache-Control fejléc max-age (maximális kor) értéke csak tájékoztató jellegű, és nem garantálja, hogy a vonatkozó adatok időközben nem változnak. A webes API-nak a max-age-t megfelelő értékre kell állítania, az adatok várható változékonysága alapján. Ha ez az időszak lejár, az ügyfélnek törölnie kell az objektumot a gyorsítótárból.
Megjegyzés
A legtöbb modern böngésző támogatja az ügyféloldali gyorsítótárazást azáltal, hogy az ismertetett módon gyorsítótár-vezérlő fejléceket ad hozzá a kérelmekhez, és megvizsgálja az eredmények fejlécét. Néhány régebbi böngésző azonban nem gyorsítótárazza a lekérdezési sztringet tartalmazó URL-címből visszaadott értékeket. Ez általában nem jelent problémát az olyan egyéni ügyfélalkalmazások esetében, amelyek az itt tárgyalt protokoll alapján implementálják a saját gyorsítótár-kezelési stratégiájukat.
Egyes régebbi proxyk ugyanígy viselkednek, és lehetséges, hogy nem gyorsítótárazzák a lekérdezési sztringekat tartalmazó URL-címeken alapuló kérelmeket. Ez az olyan egyedi ügyfélalkalmazások számára jelenthet problémát, amelyek egy ilyen proxyn keresztül csatlakoznak egy webkiszolgálóhoz.
A lekérdezés feldolgozásának optimalizálása ETagek megadásával
Amikor egy ügyfélalkalmazás lekéri az objektumot, a válaszüzenet egy entitáscímkét (ETag) is tartalmazhat. Az ETag egy átlátszatlan karakterlánc, amely egy erőforrás verzióját jelzi; minden alkalommal, amikor egy erőforrás változik, az ETag is módosul. Az ügyfélalkalmazásnak az adat részeként tárolnia kell az ETag-et. Az alábbi példakód bemutatja, hogyan lehet hozzáadni egy ETaget egy HTTP GET kérelemre adott válaszhoz. Ez a GetHashCode kód egy objektum metódusával hoz létre egy numerikus értéket, amely azonosítja az objektumot (szükség esetén felülbírálhatja ezt a módszert, és létrehozhat saját kivonatot egy olyan algoritmus használatával, mint az MD5):
public class OrdersController : ApiController
{
...
public IHttpActionResult FindOrderByID(int id)
{
// Find the matching order
Order order = ...;
...
var hashedOrder = order.GetHashCode();
string hashedOrderEtag = $"\"{hashedOrder}\"";
var eTag = new EntityTagHeaderValue(hashedOrderEtag);
// Return a response message containing the order and the cache control header
OkResultWithCaching<Order> response = new OkResultWithCaching<Order>(order, this)
{
...,
ETag = eTag
};
return response;
}
...
}
A webes API által közzétett válaszüzenet így néz ki:
HTTP/1.1 200 OK
...
Cache-Control: max-age=600, private
Content-Type: text/json; charset=utf-8
ETag: "2147483648"
Content-Length: ...
{"orderID":2,"productID":4,"quantity":2,"orderValue":10.00}
Tipp.
Biztonsági okokból ne engedélyezze a bizalmas vagy hitelesített (HTTPS) kapcsolaton keresztül visszaküldött adatok gyorsítótárazását.
Egy ügyfélalkalmazás egy újabb GET kéréssel bármikor újra lekérheti ugyanazt az erőforrást, és ha az erőforrás változott (ha más az ETagje), akkor a gyorsítótárazott verziót el kell távolítani, és az új verziót kell hozzáadni a gyorsítótárhoz. Ha egy erőforrás nagy méretű, és az ügyfélnek való visszaküldése jelentős sávszélességet igényel, akkor nem hatékony több kérelmet küldeni ugyanannak az adatnak a lekérése céljából. A HTTP-protokoll ennek elkerülése érdekében a következő folyamatot határozza meg a GET kérelmek optimalizálásához, amelyet a webes API-knak támogatniuk kell:
Az ügyfél létrehoz egy GET kérelmet, amely az erőforrás jelenleg gyorsítótárazott verziójának ETagjét tartalmazza, és egy If-None-Match HTTP-fejlécben hivatkozik rá:
GET https://adventure-works.com/orders/2 HTTP/1.1 If-None-Match: "2147483648"A webes API GET művelete lekéri a kért adatok jelenlegi ETag címkéjét (2. rendelés a fenti példában), és összehasonlítja az értéket az If-None-Match fejlécben találhatóval.
Ha a kért adatok jelenlegi ETagje megegyezik a kérés által megadott ETaggel, akkor az erőforrás nem változott, és a webes API-nak a HTTP-válaszban egy üres üzenettörzset és a 304 (Nem módosított) állapotkódot kell visszaadnia.
Ha a kért adatok jelenlegi ETagje nem egyezik a kérés által megadott ETaggel, akkor az adatok megváltoztak, és a webes API-nak HTTP-választ kell adnia az üzenet törzsében lévő új adatokkal és egy 200-es állapotkóddal (OK).
Ha a kért adatok már nem léteznek, akkor a webes API-nak egy 404 (Nem található) állapotkódú HTTP-választ kell visszaadnia.
Az ügyfél az állapotkódot használja a gyorsítótár karbantartásához. Ha az adatok nem változtak (304-es állapotkód), akkor az objektum a gyorsítótárban maradhat, és ügyfélalkalmazás tovább használhatja az objektum jelenlegi verzióját. Ha az adatok megváltoztak (200-as állapotkód), akkor a gyorsítótárazott objektumot el kell távolítani, és egy újat kell beszúrni helyette. Ha az adatok már nem érhetők el (404-es állapotkód), akkor az objektumot el kell távolítani a gyorsítótárból.
Megjegyzés
Ha a válasz fejléce a no-store Cache-Control fejlécet tartalmazza, akkor az objektumot mindenképp el kell távolítani a gyorsítótárból, a HTTP-állapotkódtól függetlenül.
Az alábbi kód az FindOrderByID If-None-Match fejléc támogatásához kiterjesztett metódust mutatja be. Megfigyelheti, hogy ha a If-None-Match fejléc hiányzik, mindig a megadott rendelés kerül lekérésre.
public class OrdersController : ApiController
{
[Route("api/orders/{id:int:min(0)}")]
[HttpGet]
public IHttpActionResult FindOrderByID(int id)
{
try
{
// Find the matching order
Order order = ...;
// If there is no such order then return NotFound
if (order == null)
{
return NotFound();
}
// Generate the ETag for the order
var hashedOrder = order.GetHashCode();
string hashedOrderEtag = $"\"{hashedOrder}\"";
// Create the Cache-Control and ETag headers for the response
IHttpActionResult response;
var cacheControlHeader = new CacheControlHeaderValue();
cacheControlHeader.Public = true;
cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);
var eTag = new EntityTagHeaderValue(hashedOrderEtag);
// Retrieve the If-None-Match header from the request (if it exists)
var nonMatchEtags = Request.Headers.IfNoneMatch;
// If there is an ETag in the If-None-Match header and
// this ETag matches that of the order just retrieved,
// then create a Not Modified response message
if (nonMatchEtags.Count > 0 &&
String.CompareOrdinal(nonMatchEtags.First().Tag, hashedOrderEtag) == 0)
{
response = new EmptyResultWithCaching()
{
StatusCode = HttpStatusCode.NotModified,
CacheControlHeader = cacheControlHeader,
ETag = eTag
};
}
// Otherwise create a response message that contains the order details
else
{
response = new OkResultWithCaching<Order>(order, this)
{
CacheControlHeader = cacheControlHeader,
ETag = eTag
};
}
return response;
}
catch
{
return InternalServerError();
}
}
...
}
Ebben a példában egy IHttpActionResult nevű másik egyéni EmptyResultWithCaching osztály is található. Ez az osztály burkolóként szolgál egy HttpResponseMessage olyan objektum köré, amely nem tartalmaz választörzset:
public class EmptyResultWithCaching : IHttpActionResult
{
public CacheControlHeaderValue CacheControlHeader { get; set; }
public EntityTagHeaderValue ETag { get; set; }
public HttpStatusCode StatusCode { get; set; }
public Uri Location { get; set; }
public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response = new HttpResponseMessage(StatusCode);
response.Headers.CacheControl = this.CacheControlHeader;
response.Headers.ETag = this.ETag;
response.Headers.Location = this.Location;
return response;
}
}
Tipp.
Ebben a példában az adatok ETagje az alapul szolgáló adatforrásból lekért adatok kivonatolásával jön létre. Ha az ETag más módon is kiszámítható, akkor a folyamat tovább optimalizálható, és az adatokat csak akkor kell lekérni az adatforrásból, ha változtak. Ez a módszer különösen hasznos, ha az adatok mérete nagy, vagy az adatforrás elérése jelentős késést eredményezhet (például ha az adatforrás egy távoli adatbázis).
ETagek használatával támogassa az optimista egyetértést
A korábban gyorsítótárazott adatok frissítésének engedélyezéséhez a HTTP-protokoll támogat egy optimista párhuzamossági stratégiát. Ha egy erőforrás lekérése és gyorsítótárazása után az ügyfélalkalmazás később PUT vagy DELETE kérést küld az erőforrás módosítására vagy eltávolítására, tartalmaznia kell egy If-Match fejlécet, amely az ETagre hivatkozik. A webes API ezen információk alapján határozza meg, hogy az erőforrást a lekérése óta módosította-e egy másik felhasználó, majd az alábbiak szerint visszaküldi a megfelelő választ az ügyfélalkalmazásnak:
Az ügyfél létrehoz egy PUT kérelmet, amely tartalmazza az erőforrás új adatait és az erőforrás jelenleg gyorsítótárazott verziójának ETagjét, amelyre egy If-Match HTTP-fejléc hivatkozik. A következő példa egy rendelést frissítő PUT kérelmet mutat be:
PUT https://adventure-works.com/orders/1 HTTP/1.1 If-Match: "2282343857" Content-Type: application/x-www-form-urlencoded Content-Length: ... productID=3&quantity=5&orderValue=250A webes API PUT művelete lekéri a kért adatok jelenlegi ETag címkéjét (1. rendelés a fenti példában), és összehasonlítja az értéket az If-Match fejlécben találhatóval.
Ha a kért adatok aktuális ETagje megegyezik a kérés által biztosított ETaggel, az erőforrás nem változott, és a webes API-nak végre kell hajtania a frissítést, és ha sikeres, a 204-es HTTP-állapotkóddal (tartalom nélkül) küld üzenetet. A válasz tartalmazhatja az erőforrás frissített verziójának Cache-Control és ETag fejléceit. A válasznak mindig tartalmaznia kell a Location fejlécet, amely az újonnan frissített erőforrás URI-jére hivatkozik.
Ha a kért adatok jelenlegi ETagje nem egyezik a kérés által megadott ETaggel, akkor az adatokat egy másik felhasználó módosította a lekérés óta, és a webes API-nak egy üres üzenettörzset és egy 412-es állapotkódot tartalmazó HTTP-választ kell visszaadnia (az előfeltétel sikertelen).
Ha a frissítendő erőforrás már nem létezik, akkor a webes API-nak egy 404 (Nem található) állapotkódú HTTP-választ kell visszaadnia.
Az ügyfél az állapotkóddal és a válaszfejlécekkel tartja karban a gyorsítótárat. Ha az adatok frissültek (állapotkód: 204), akkor az objektum gyorsítótárazva maradhat, feltéve, hogy a Cache-Control fejléc nem tiltja a tárolást, de az ETag-et frissíteni kell. Ha az adatokat egy másik felhasználó módosította (állapotkód: 412), vagy nem található (állapotkód: 404), akkor a gyorsítótárazott objektumot el kell vetni.
A következő példakód az Orders vezérlő PUT műveletének megvalósítását mutatja be:
public class OrdersController : ApiController
{
[HttpPut]
[Route("api/orders/{id:int}")]
public IHttpActionResult UpdateExistingOrder(int id, DTOOrder order)
{
try
{
var baseUri = Constants.GetUriFromConfig();
var orderToUpdate = this.ordersRepository.GetOrder(id);
if (orderToUpdate == null)
{
return NotFound();
}
var hashedOrder = orderToUpdate.GetHashCode();
string hashedOrderEtag = $"\"{hashedOrder}\"";
// Retrieve the If-Match header from the request (if it exists)
var matchEtags = Request.Headers.IfMatch;
// If there is an ETag in the If-Match header and
// this ETag matches that of the order just retrieved,
// or if there is no ETag, then update the Order
if (((matchEtags.Count > 0 &&
String.CompareOrdinal(matchEtags.First().Tag, hashedOrderEtag) == 0)) ||
matchEtags.Count == 0)
{
// Modify the order
orderToUpdate.OrderValue = order.OrderValue;
orderToUpdate.ProductID = order.ProductID;
orderToUpdate.Quantity = order.Quantity;
// Save the order back to the data store
// ...
// Create the No Content response with Cache-Control, ETag, and Location headers
var cacheControlHeader = new CacheControlHeaderValue();
cacheControlHeader.Private = true;
cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);
hashedOrder = order.GetHashCode();
hashedOrderEtag = $"\"{hashedOrder}\"";
var eTag = new EntityTagHeaderValue(hashedOrderEtag);
var location = new Uri($"{baseUri}/{Constants.ORDERS}/{id}");
var response = new EmptyResultWithCaching()
{
StatusCode = HttpStatusCode.NoContent,
CacheControlHeader = cacheControlHeader,
ETag = eTag,
Location = location
};
return response;
}
// Otherwise return a Precondition Failed response
return StatusCode(HttpStatusCode.PreconditionFailed);
}
catch
{
return InternalServerError();
}
}
...
}
Tipp.
A If-Match fejléc használata nem kötelező, és ha nincs megadva, a webes API mindig megpróbálja frissíteni a megadott sorrendet, esetleg vakon felülírja egy másik felhasználó által végrehajtott frissítést. Az elveszett frissítések miatti problémák elkerüléséhez mindig adjon meg egy If-Match fejlécet.
Nagyméretű kérelmek és válaszok kezelése
Időnként egy ügyfélalkalmazásnak olyan kéréseket kell kiadnia, amelyek több megabájtos (vagy nagyobb) méretű adatokat küldenek vagy fogadnak. Ha az ügyfélalkalmazás ekkora mennyiségű adat átvitelére várakozik, előfordulhat, hogy nem válaszol. Ha jelentős mennyiségű adatot tartalmazó kérelmeket kezel, vegye figyelembe a következő szempontokat:
Nagyméretű objektumokat tartalmazó kérelmek és válaszok optimalizálása
Egyes erőforrások lehetnek nagy objektumok, vagy nagy mezők, például grafikus képek vagy más típusú bináris adatok. A webes API-nak támogatnia kell a streamelést az ilyen erőforrások fel- és letöltésének optimalizálásához.
A HTTP-protokoll biztosítja a darabolásos átvitel kódolási mechanizmusát, amellyel a nagyméretű adatobjektumok visszastreamelhetők egy ügyfélhez. Amikor az ügyfél elküld egy nagy objektumra vonatkozó HTTP GET kérést, a webes API képes a választ darabonkénti adattömbök formájában visszaküldeni egy HTTP-kapcsolaton keresztül. Előfordulhat, hogy a válaszban szereplő adatok hossza kezdetben nem ismert (előállításra kerülhet), ezért a webes API-t üzemeltető kiszolgálónak minden egyes adattömbbel egy válaszüzenetet kell küldenie, amely az Transfer-Encoding: Chunked fejlécet adja meg a Tartalom-hossz fejléc helyett. Az ügyfélalkalmazás egymás után kaphatja meg az egyes adattömböket, amelyekből felépíti a teljes választ. Az adatok átvitele akkor ér véget, amikor a kiszolgáló visszaküld egy nulla méretű végső tömböt.
Egyetlen kérelem is eredményezhet egy olyan nagyméretű objektumot, amely jelentős erőforrásokat használ fel. Ha a streamelési folyamat során a webes API megállapítja, hogy a kérésben szereplő adatok mennyisége túllépett néhány elfogadható korlátot, megszakíthatja a műveletet, és egy 413-es állapotkódú válaszüzenetet küld (túl nagy kérelem entitás).
A hálózaton keresztül továbbított nagyméretű objektumok mérete HTTP-tömörítéssel minimalizálható. Ez a módszer segít csökkenteni a hálózati forgalmat és a kapcsolódó hálózati késést, viszont az ügyfélnek és a webes API-t futtató kiszolgálónak egyaránt további feldolgozást kell végeznie. Például egy olyan ügyfélalkalmazás, amely tömörített adatokat vár, tartalmazhat egy Accept-Encoding: gzip kérésfejlécet (más adattömörítési algoritmusok is megadhatóak). Ha a kiszolgáló támogatja a tömörítést, az üzenet törzsében gzip formátumban tárolt tartalommal és a Content-Encoding: gzip válaszfejlécmel kell válaszolnia.
A tömörítés kombinálható a streameléssel: a streamelés előtt tömörítse az adatokat, és adja meg a gzip tartalomkódolást és a darabolt átviteli kódolást az üzenetfejlécekben. Egyes webkiszolgálók, például az Internet Information Server, konfigurálhatók HTTP-válaszok automatikus tömörítésére, függetlenül attól, hogy a webes API tömöríti-e az adatokat.
Részleges válaszok implementálása olyan ügyfelek esetében, amelyek nem támogatják az aszinkron műveleteket
Az aszinkron streamelés alternatívájaként az ügyfélalkalmazás explicit módon megadhatja, hogy a nagy objektumok esetében tömbökben kéri az adatokat. Ezeket a tömböket részleges válaszoknak hívják. Az ügyfélalkalmazás egy HTTP HEAD kérést küld az objektum adatainak lekéréséhez. Ha a webes API támogatja a részleges válaszokat, válaszüzenettel kell válaszolnia a HEAD-kérésre, amely egy fejlécet és egy Accept-Ranges fejlécet tartalmazContent-Length, amely az objektum teljes méretét jelzi, de az üzenet törzsének üresnek kell lennie. Az ügyfélalkalmazás ezen információk alapján hoz létre több GET kérést, amelyekben megadja a fogadni kívánt bájttartományt. A webes API-nak HTTP állapotkód 206 (Részleges tartalom) válaszüzenetet kell visszaadnia, egy Content-Length fejlécet, amely megadja a válaszüzenet törzsében szereplő adatok tényleges mennyiségét, valamint egy Content-Range fejlécet, amely jelzi, hogy az adat melyik részét képviseli az objektum, például bájtok 4000 és 8000 között.
A HTTP HEAD-kérelmeket és a részleges válaszokat az API-tervezés részletesebben ismerteti.
Kerülje a szükségtelen 100-Continue állapotüzenetek küldését az ügyfélalkalmazásban
Egy olyan ügyfélalkalmazás, amely nagy mennyiségű adatot fog küldeni egy kiszolgálónak, először eldöntheti, hogy a kiszolgáló valóban hajlandó-e elfogadni a kérést. Mielőtt az ügyfélalkalmazás elküldi az adatokat, elküldhet egy HTTP-kérést, amely üres üzenettörzset és egy Expect: 100-Continue fejlécet tartalmaz, amely azt jelzi, hogy a Content-Length fejléc az adatok méretét mutatja. Ha a kiszolgáló hajlandó kezelni a kérést, akkor a válaszüzenetében a 100 (Folytatás) HTTP-állapotkódot kell megadnia. Az ügyfélalkalmazás ezután folytathatja és elküldheti a teljes kérést, beleértve az üzenet törzsében lévő adatokat is.
Ha Internet Information Services (IIS) használatával üzemeltet egy szolgáltatást, a HTTP.sys illesztőprogram automatikusan észleli és kezeli a Várt: 100-Folytatás fejléceket, mielőtt kéréseket ad át a webalkalmazásnak. Ez azt jelenti, hogy az alkalmazás kódjában valószínűleg nem lesznek láthatók ezek a fejlécek, és feltételezhető, hogy az IIS már kiszűrte az olyan üzeneteket, amelyeket nem megfelelőnek vagy túl nagynak talált.
Ha ügyfélalkalmazásokat hoz létre a .NET-keretrendszer használatával, akkor az összes POST és PUT üzenet először a Várt: 100-Folytatás fejlécekkel küld üzeneteket alapértelmezés szerint. A kiszolgálóoldalhoz hasonlóan a folyamatot is transzparens módon kezeli a .NET-keretrendszer. Ez a folyamat azonban minden POST és PUT kérést eredményez, ami két oda-visszautat okoz a kiszolgálóra, még kisebb kérések esetén is. Ha az alkalmazás nem küld nagy mennyiségű adatot tartalmazó kéréseket, letilthatja ezt a funkciót az ServicePointManager osztály használatával, hogy objektumokat hozzon létre ServicePoint az ügyfélalkalmazásban. A ServicePoint objektum a kiszolgálón lévő erőforrásokat azonosító URI-k séma- és gazdagéptöredékei alapján kezeli az ügyfél által a kiszolgálóval létrehozott kapcsolatokat. Ezután a Expect100Continue objektum ServicePoint tulajdonságát false (hamis) értékre állíthatja. Az ügyfél által az objektum sémájának és gazdagéptöredékeinek megfelelő URI-val elküldött további POST- és PUT-kérések Expect: 100-Continue fejlécek nélkül kerülnek elküldésre. A következő kód bemutatja, hogyan konfigurálható egy ServicePoint objektum, hogy az összes, http sémához és www.contoso.com gazdagéphez tartozó URI-knek küldött kérést konfigurálja.
Uri uri = new Uri("https://www.contoso.com/");
ServicePoint sp = ServicePointManager.FindServicePoint(uri);
sp.Expect100Continue = false;
Az osztály statikus Expect100Continue tulajdonságát úgy is beállíthatja ServicePointManager , hogy a tulajdonság alapértelmezett értékét adja meg az összes később létrehozott ServicePoint-objektumhoz .
Olyan kérések lapozásának támogatása, amelyek nagy számú objektumot adhatnak vissza
Ha egy gyűjtemény sok erőforrást tartalmaz, egy GET kérés eljuttatása a megfelelő URI-hez jelentős mértékű feldolgozást igényelhet a webes API-t üzemeltető kiszolgálón, ami hatással lehet a teljesítményre és nagy mennyiségű hálózati forgalommal járhat, ez pedig a késések növekedéséhez vezet.
Az ilyen esetek kezeléséhez a webes API-nak támogatnia kell az olyan lekérdezési sztringekat, amelyek lehetővé teszik, hogy az ügyfélalkalmazás pontosítsa a kérelmeket, vagy könnyebben kezelhető, különálló blokkokra (vagy lapokra) tagolva kérje le az adatokat. Az alábbi kód a GetAllOrders vezérlőben található Orders metódust mutatja be. Ez a metódus a rendelések részleteit kéri le. Ha a metódus korlátozás nélküli lenne, előfordulhat, hogy nagy mennyiségű adatot adna vissza. A limit és az offset paraméter célja, hogy az adatok mennyiségét egy kisebb részhalmazra csökkentse, ebben az esetben alapértelmezés szerint csak az első 10 rendelésre:
public class OrdersController : ApiController
{
...
[Route("api/orders")]
[HttpGet]
public IEnumerable<Order> GetAllOrders(int limit=10, int offset=0)
{
// Find the number of orders specified by the limit parameter
// starting with the order specified by the offset parameter
var orders = ...
return orders;
}
...
}
Egy ügyfélalkalmazás kiadhat olyan kérelmet, amely 30 rendelést kér le a https://www.adventure-works.com/api/orders?limit=30&offset=50 URI használatával 50-es eltolástól kezdve.
Tipp.
Ne engedélyezze az ügyfélalkalmazásoknak olyan lekérdezési sztringek megadását, amelyek 2000 karakternél hosszabb URI-t eredményeznek. Sok webes ügyfél és kiszolgáló nem tudja kezelni az ilyen hosszú URI-kat.
A válaszképesség, a skálázhatóság és a rendelkezésre állás fenntartása
Ugyanezt a webes API-t számos, a világ bármely pontján futó ügyfélalkalmazás használhatja. Fontos, hogy a webes API úgy legyen megvalósítva, hogy válaszképes legyen nagy mértékű terhelés alatt is, hogy skálázható legyen a nagymértékben ingadozó számítási feladatok kezeléséhez, és hogy garantáltan rendelkezésre álljon az üzleti szempontból kulcsfontosságú műveleteket végző ügyfelek számára. Mindezen követelmények teljesítése érdekében vegye figyelembe a következő szempontokat:
A hosszan futó kérelmek aszinkron támogatásának biztosítása
Az olyan kérelmeket, amelyek feldolgozása hosszú időbe telhet, a kérelmet küldő ügyfél blokkolása nélkül kell feldolgozni. A webes API elvégezhet néhány kezdeti ellenőrzést a kérelem érvényesítéséhez, elindíthat egy külön feladatot a munka elvégzéséhez, majd visszaadhat egy 202 (Elfogadva) HTTP-kódú válaszüzenetet. A feladat futhat aszinkron módon a webes API feldolgozófolyamatának részeként, vagy kiszervezhető egy háttérfeladatba. A HTTP-szemantika és a megvalósítás teljes útmutatóját az Aszinkron Request-Reply minta ismerteti.
A webes API-nak emellett biztosítania kell egy mechanizmust, amely visszaadja a feldolgozás eredményét az ügyfélalkalmazásnak. Ennek érdekében megadhat az ügyfélalkalmazásoknak egy lekérdezési mechanizmust, amellyel időnként lekérdezhetik, hogy a feldolgozás befejeződött-e, és lekérhetik az eredményt, vagy engedélyezhetjük, hogy a webes API egy értesítést küldjön a művelet befejezése után.
Egyszerűen megvalósíthat egy lekérdezési mechanizmust, ha a következőképpen megad egy virtuális erőforrásként szolgáló lekérdezési URI-t:
- Az ügyfélalkalmazás elküldi a kezdeti kérelmet a webes API-nak.
- A webes API egy Azure Table Storage vagy Azure Managed Redis táblában tárolja a kéréssel kapcsolatos információkat, és létrehoz egy egyedi kulcsot ehhez a bejegyzéshez, esetleg globálisan egyedi azonosító (GUID) formájában. Másik lehetőségként a kéréssel és az egyedi kulccsal kapcsolatos információkat tartalmazó üzenet elküldhető Azure Service Bus is.
- A webes API a feldolgozást külön feladatként vagy egy olyan tárral kezdeményezi, mint a Hangfire. A webes API a táblában a feladat állapotát Fut értékre állítja.
- Ha Azure Service Bus használ, az üzenetfeldolgozás az API-tól elkülönítve történik, esetleg Azure Functions vagy AKS használatával.
- A webes API egy 202-es (elfogadott) HTTP-állapotkódú válaszüzenetet és egy URI-t ad vissza, amely tartalmazza a létrehozott egyedi kulcsot – például a /polling/{guid}.
- Amikor a feladat befejeződött, a webes API az eredményeket a táblában tárolja, és a tevékenység állapotát befejezettre állítja. Ha a feladat meghiúsul, a webes API a hibával kapcsolatos információkat is tárolhatja, és a sikertelen állapotot állíthatja be.
- Érdemes újrapróbálkozási technikákat alkalmazni az esetleges átmeneti hibák megoldásához.
- A feladat futása közben az ügyfél továbbra is végezhet saját feldolgozást. Rendszeresen küldhet kérést a korábban kapott URI címre.
- Az URI webes API lekérdezi a tábla megfelelő feladatának állapotát, és egy 200-es (OK) HTTP-állapotkódot tartalmazó válaszüzenetet ad vissza, amely tartalmazza ezt az állapotot (Futtatás, Befejezett vagy Sikertelen). Ha a feladat befejeződött vagy meghiúsult, a válaszüzenet tartalmazhatja a feldolgozás eredményét vagy a sikertelenség okával kapcsolatban elérhető információkat is.
- Ha a hosszú ideig futó folyamat köztesebb állapotokkal rendelkezik, jobb, ha olyan kódtárat használ, amely támogatja a sagamintát, például az NServiceBust vagy a MassTransitet.
Az értesítések megvalósításának lehetőségei a következők:
- Értesítési központ használata aszinkron válaszok leküldéséhez az ügyfélalkalmazásokhoz. További információ: Send értesítések adott felhasználóknak a Azure Notification Hubs használatával.
- A Comet modell használata egy állandó hálózati kapcsolat fenntartásához az ügyfél és a webes API-t üzemeltető kiszolgáló között, és a kapcsolat használata a kiszolgálóról az ügyfélhez visszaküldött üzenetek leküldéséhez. Az MSDN magazincikke Egyszerű üstökösalkalmazás létrehozása a Microsoft .NET-keretrendszerben egy példamegoldást ír le.
- A SignalR használatával valós időben küldhet le adatokat a webkiszolgálóról az ügyfélre egy állandó hálózati kapcsolaton keresztül. A SignalR nuGet-csomagként érhető el ASP.NET webalkalmazásokhoz. További információt a ASP.NET SignalR webhelyén talál.
Biztosítsd, hogy minden kérelem állapot nélküli legyen
Minden egyes kérelmet atominak kell tekinteni. Egy ügyfélalkalmazás különböző időpontokban elküldött kérelmei között nem állhatnak fenn függőségek. Ez a megközelítés támogatja a méretezhetőséget. A webszolgáltatás példányai több kiszolgálón is üzembe helyezhetők. Az ügyfélkérések bármelyik példányra irányíthatók, és az eredményeknek mindig ugyanazoknak kell lenniük. Emellett hasonló okból javítja a rendelkezésre állást; ha a webkiszolgáló sikertelen kérései átirányíthatók egy másik példányra (Azure Traffic Manager használatával), miközben a kiszolgáló újraindul, és nincs hatással az ügyfélalkalmazásokra.
Ügyfelek nyomon követése és szabályozás implementálása a DoS-támadások esélyének csökkentése érdekében
Ha egy adott ügyfél egy adott időszakon belül nagy számú kérést küld, az monopolizálhatja a szolgáltatást, és hatással lehet más ügyfelek teljesítményére. Ennek elkerülése érdekében a webes API monitorozhatja az ügyfélalkalmazások hívásait. Ez az összes bejövő kérelem IP-címének rögzítésével vagy az összes hitelesített hozzáférés naplózásával is történhet. Ezen adatok alapján korlátozható az erőforrásokhoz való hozzáférés. Ha egy ügyfél túllép egy adott korlátozását, a webes API visszaadhat egy válaszüzenetet az 503 (A szolgáltatás nem érhető el) állapotkóddal és egy Retry-After fejléccel, amelyben megadja, hogy az ügyfél mikor küldheti el a következő kérelmet anélkül, hogy a rendszer elutasítaná. Ez a stratégia segíthet csökkenteni annak esélyét, hogy egy ügyfélcsoport szolgáltatásmegtagadási (DoS) támadást indítson, mely a rendszert akadályozza. További információkért tekintse meg a fojtási mintát.
Állandó HTTP-kapcsolatok gondos kezelése
A HTTP-protokoll támogatja az állandó HTTP-kapcsolatokat, ahol elérhetők. A HTTP 1.0 specifikáció hozzáadta a Connection:Keep-Alive fejlécet, amely lehetővé teszi, hogy az ügyfélalkalmazás jelezze a kiszolgálónak, hogy ugyanazt a kapcsolatot használhatja a következő kérések küldésére az újak megnyitása helyett. A kapcsolat automatikusan lezáródik, ha az ügyfél nem használja újra a kapcsolatot a gazdagép által meghatározott időtartamon belül. Ez a viselkedés az alapértelmezett a HTTP 1.1-ben, ahogyan azt Azure szolgáltatások használják, így nem kell Keep-Alive fejléceket belefoglalni az üzenetekbe.
A kapcsolat nyitva tartása segíthet növelni a válaszkészséget a késés és a hálózati torlódás csökkentésével, de gyengítheti a skálázhatóságot, mivel a szükségtelen kapcsolatok felesleges nyitva tartása korlátozza a további ügyfelek csatlakozási lehetőségeit. Emellett ha az ügyfélalkalmazás mobileszközön fut, csökkentheti az eszköz akkumulátor-élettartamát is: ha az alkalmazás csak alkalmanként kérelmeket küld a kiszolgáló felé, a kapcsolat nyitva tartása gyorsabban lemerítheti az akkumulátort. Annak érdekében, hogy egy kapcsolat ne legyen állandó a HTTP 1.1-ben, az ügyfél tartalmazhat egy Connection: close fejlécet, amely üzeneteket tartalmaz az alapértelmezett viselkedés felülbírálásához. Hasonlóképpen, ha egy kiszolgáló sok ügyfelet kezel, a válaszüzenetek fejlécét is belefoglalhatja Connection: close a kapcsolat bezárásához és a kiszolgáló erőforrásainak mentéséhez.
Megjegyzés
Az állandó HTTP-kapcsolatok választható funkciók, amelyekkel csökkentheti a hálózati terhelést, ha elkerüli a kommunikációs csatorna ismételt létrehozását. A webes API és az ügyfélalkalmazás azonban nem függhet az állandó HTTP-kapcsolat elérhetőségétől. Ne használjon állandó HTTP-kapcsolatokat a Comet-stílusú értesítési rendszerek implementálásához. Használjon inkább csatlakozókat, vagy WebSocketeket (ha elérhetők) az átviteli vezérlő protokoll rétegében. Keep-Alive fejlécek hasznossága korlátozott, ha egy ügyfélalkalmazás proxyn keresztül kommunikál a kiszolgálóval. Csak az ügyfél és a proxy közötti kapcsolat marad állandó.
Webes API-k közzététele és kezelése
Ahhoz, hogy egy webes API elérhető legyen az ügyfélalkalmazások számára, a webes API-t telepíteni kell egy gazdakörnyezetben. Ez a környezet általában webkiszolgáló, bár más típusú gazdafolyamat lehet. A webes API-k közzétételekor vegye figyelembe a következő szempontokat:
- Minden kérelmet hitelesíteni és engedélyezni kell, és be kell tartatni a megfelelő szintű hozzáférés-vezérlést.
- A kereskedelmi webes API-k válaszidejére különböző minőségi garanciák vonatkozhatnak. Fontos gondoskodni arról, hogy a hoszt környezet méretezhető legyen, ha a terhelés idővel jelentősen változhat.
- Lehetséges, hogy bevételszerzési célokra kell mérni a kérelmeket.
- Lehetséges, hogy a webes API felé irányuló forgalmat korlátozni kell, valamint a kvótájukat felhasználó adott ügyfelekre vonatkozó szabályozást kell bevezetni.
- A szabályozási követelmények előírhatják az összes kérelem és válasz naplózását.
- A rendelkezésre állás biztosítása érdekében szükség lehet a webes API-t üzemeltető kiszolgáló állapotának figyelésére, és szükség esetén újra kell indítani.
Hasznos lehet ezeket a problémákat elkülöníteni a webes API megvalósításával kapcsolatos technikai problémáktól. Emiatt érdemes lehet létrehozni egy előtérrendszert, amely külön folyamatként fut, és a webes API-hoz irányítja a kérelmeket. Az előtérrendszer felügyeleti műveleteket biztosíthat, és továbbíthatja az érvényesített kéréseket a webes API felé. Az előtérrendszer használata számos funkcionális előnnyel is jár, többek között:
- Több webes API integrációs pontjaként szolgál.
- különböző technológiák használatával átalakítja az üzeneteket és lefordítja a kommunikációs protokollokat az ügyfelek számára.
- Gyorsítótárazza a kérelmeket és válaszokat a webes API-t futtató kiszolgáló terhelésének csökkentése érdekében.
Webes API tesztelése
A webes API-kat ugyanolyan alaposan kell tesztelni, mint minden más szoftvert. Érdemes lehet egységteszteket létrehozni a funkció ellenőrzéséhez.
A webes API természete további követelményeket támaszt annak ellenőrzéséhez, hogy megfelelően működik-e. Fordítson különös figyelmet a következőkre:
Ellenőrizze az összes útvonalat, hogy a megfelelő műveleteket hívják-e meg. Különösen figyeljen a váratlanul visszaadott 405 (Nem engedélyezett metódus) HTTP-állapotkódra, mivel ez azt jelezheti, hogy egy útvonal és a rajta keresztül elküldhető HTTP-metódusok (GET, POST, PUT, DELETE) nem egyeznek.
HTTP-kérések küldése olyan útvonalakra, amelyek nem támogatják őket, például POST-kérés küldése egy adott erőforrásnak (a POST-kéréseket csak erőforráscsoportoknak kell elküldeni). Ezekben az esetekben az egyetlen érvényes válasz a 405 (Nem engedélyezett) állapotkód lehet.
Ellenőrizze, hogy az összes útvonal megfelelően védett-e, és megtörténnek-e a megfelelő hitelesítési és engedélyezési ellenőrzések.
Megjegyzés
A biztonság bizonyos aspektusai, például a felhasználói hitelesítés valószínűleg nem a webes API, hanem a gazdakörnyezet feladata, de az üzembe helyezési folyamat részeként biztonsági teszteket is be kell vonni.
Tesztelje az egyes műveletek kivételkezelését, és ellenőrizze, hogy a műveletek megfelelő és jelentéssel bíró HTTP-válaszokat adnak-e vissza az ügyfélalkalmazásnak.
Ellenőrizze, hogy a kérelem- és válaszüzenetek szabályosak-e. Ha például egy HTTP POST kérelem x-www-form-urlencoded formátumban tartalmazza egy új erőforrás adatait, győződjön meg arról, hogy a vonatkozó művelet megfelelően elemzi az adatokat, létrehozza az erőforrásokat, és visszaad egy választ, amely tartalmazza az új erőforrás részleteit, köztük a megfelelő Location fejlécet.
Ellenőrizze az összes hivatkozást és URI-t a válaszüzenetekben. Egy HTTP POST-üzenetnek például az újonnan létrehozott erőforrás URI-ját kell visszaadnia. Minden HATEOAS-hivatkozásnak érvényesnek kell lennie.
Győződjön meg arról, hogy a minden művelet a megfelelő állapotkódokat adja vissza a különböző bemeneti kombinációkra. Példa:
- Ha egy lekérdezés sikeres, a 200 (OK) állapotkódot kell visszaadnia.
- Ha egy erőforrás nem található, a műveletnek a 404-ben megadott HTTP-állapotkódot kell visszaadnia (nem található).
- Ha az ügyfél elküld egy kérelmet, amely sikeresen töröl egy erőforrást, a 204 (Nincs tartalom) állapotkódnak kell megjelennie.
- Ha az ügyfél egy új erőforrást létrehozó kérést küld, az állapotkódnak 201 (Létrehozva) kell lennie.
Figyeljen az 5xx tartományba eső váratlan állapotkódokra. Ezekkel az üzenetekkel a gazdakiszolgáló általában azt jelzi, hogy nem tudott teljesíteni egy érvényes kérelmet.
Tesztelje az ügyfélalkalmazás által megadható különböző fejléc-kombinációkat, és győződjön meg arról, hogy a webes API a várt információt adja vissza a válaszüzenetekben.
Tesztelje a lekérdezési sztringekat. Ha egy műveletnek választható paraméterei is lehetnek (például tördelési kérések), tesztelje a paraméterek különböző kombinációit és sorrendjeit.
Ellenőrizze, hogy az aszinkron műveletek sikeresen befejeződnek-e. Ha a webes API támogatja a nagy bináris objektumokat (például video- vagy hangfájlokat) visszaküldött kérések streamelését, győződjön meg arról, hogy az ügyfélkérések nem lesznek blokkolva az adatok streamelése közben. Ha a webes API hosszú ideig futó adatmódosítási műveletek lekérdezését valósítja meg, ellenőrizze, hogy a műveletek helyesen jelentik-e az állapotukat a folytatás során.
Emellett hozzon létre és futtasson teljesítményteszteket, amelyekkel ellenőrizheti, hogy a webes API kielégítően működik-e nagy terhelés alatt. Webes teljesítmény- és terheléstesztelési projektet Visual Studio Ultimate használatával hozhat létre.
Azure API Management használata
Azure érdemes lehet Azure API Management használatával közzétenni és kezelni egy webes API-t. Ezzel az eszközzel létrehozhat egy olyan szolgáltatást, amely egy vagy több webes API előtér-szolgáltatásaként funkcionál. A szolgáltatás maga egy méretezhető webszolgáltatás, amelyet a Azure portál használatával hozhat létre és konfigurálhat. A szolgáltatással a következőképpen tehet közzé és felügyelhet egy webes API-t:
Helyezze üzembe a webes API-t egy üzemeltetési platformon, például Azure App Service, Azure Container Apps, Azure Kubernetes Service (AKS) vagy Azure Virtual Machines.
Csatlakoztassa az API Management szolgáltatást a webes API-hoz. A felügyeleti API URL-címére küldött kérelmeket a webes API-ban lévő URI-kre képezi le a rendszer. Egy API Management szolgáltatás több webes API-hoz is irányíthatja a kérelmeket. Ezáltal több webes API-t összesíthet egyetlen felügyeleti szolgáltatásban. Hasonlóképp egy webes API-ra több API Management szolgáltatás is hivatkozhat, ha a különböző alkalmazások számára elérhető funkciókat korlátozni vagy particionálni kell.
Megjegyzés
A HTTP GET-kérelmekre adott válasz részeként létrehozott HATEOAS-hivatkozásokban az URI-knak az API felügyeleti szolgáltatás URL-címére kell hivatkoznia, nem pedig a webes API-t üzemeltető webkiszolgálóra.
Minden webes API-hoz adja meg a közzétett HTTP-műveleteket, valamint a műveletek által bemenetként felhasználható opcionális paramétereket. Azt is beállíthatja, hogy az API Management szolgáltatás gyorsítótárazza-e a webes API-tól kapott választ, így optimalizálhatja az ugyanazon adatokra irányuló ismétlődő kérelmeket. Rögzítse az egyes műveletek által adható HTTP-válaszok részleteit. Ezek az információk a fejlesztők dokumentációjának létrehozására szolgálnak, ezért fontos, hogy pontosak és teljesek legyenek.
A műveleteket manuálisan is definiálhatja a Azure portál által biztosított varázslókkal, vagy importálhatja őket egy WADL vagy Swagger formátumú definíciókat tartalmazó fájlból.
Konfigurálja az API Management szolgáltatás és a webes API-t üzemeltető webkiszolgáló közötti kommunikáció biztonsági beállításait. Az API management szolgáltatás jelenleg támogatja az alapszintű hitelesítést és a kölcsönös hitelesítést tanúsítványok használatával, valamint az Open Authorization (OAuth) 2.0-s felhasználói hitelesítést.
Hozzon létre egy terméket. A termék közzétételi egység; hozzá kell adnia azokat a webes API-kat, amelyeket korábban csatlakoztatott a kezelési szolgáltatáshoz. A termék közzététele után a webes API-k elérhetővé válnak a fejlesztők számára.
Megjegyzés
A termék közzététele előtt megadhatja azokat a felhasználói csoportokat, amelyek hozzáférhetnek a termékhez, és felhasználókat adhat hozzá ezekhez a csoportokhoz. Ezzel szabályozható, hogy a webes API-t mely fejlesztők és alkalmazások használhatják. Ha egy webes API jóváhagyást igényel, a fejlesztőknek el kell küldeniük egy kérést a termék rendszergazdájának, mielőtt hozzáférnének. A rendszergazda engedélyezheti vagy megtagadhatja a fejlesztő hozzáférését. A már meglévő fejlesztők is blokkolhatók, ha változnak a körülmények.
Konfiguráljon szabályzatokat minden webes API-hoz. A szabályzatok meghatározzák például, hogy a tartományok közötti hívások engedélyezettek-e, hogy hogyan zajlik az ügyfelek hitelesítése, hogy az XML és JSON formátumok közötti átalakítás transzparens módon történik-e, hogy egy adott IP-címtartomány hívásai korlátozva legyenek-e, hogy a hívások sebessége korlátozott legyen-e, valamint a használati kvótákat. A szabályzatok alkalmazhatók globálisan az egész termékre, a termékben lévő adott webes API-ra, vagy a webes API-k egyes műveleteire.
További információkért tekintse meg az API Management dokumentációját.
Tipp.
Azure biztosítja a Azure Traffic Manager, amely lehetővé teszi a feladatátvétel és a terheléselosztás implementálását, valamint a késés csökkentését a különböző földrajzi helyeken üzemeltetett webhelyek több példányában. A Azure Traffic Manager az API Management Szolgáltatással együtt használhatja; az API Management Service a kéréseket egy webhely példányaihoz irányíthatja a Azure Traffic Manager keresztül. További információ: Traffic Manager útválasztási módszerek.
Ebben a struktúrában, ha egyéni DNS-neveket használ a webhelyekhez, minden webhelyhez konfigurálnia kell a megfelelő CNAME rekordot, hogy a Azure Traffic Manager webhely DNS-nevére mutasson.
Ügyféloldali fejlesztők támogatása
Az ügyfélalkalmazások fejlesztőinek általában információkra van szükségük a webes API elérésével kapcsolatban. Emellett dokumentációra is szükségük van a paraméterekről, adattípusokról, visszatérési típusokról és visszatérési kódokról, amelyek leírják a webszolgáltatás és az ügyfélalkalmazás között küldött különböző kérelmeket és válaszokat.
A webes API-k REST-műveleteinek dokumentálása
A Azure API Management szolgáltatás tartalmaz egy fejlesztői portált, amely leírja a webes API által közzétett REST-műveleteket. A közzétett termékek megjelennek a portálon. A fejlesztők ezen a portálon regisztrálhatnak hozzáférésért, majd a rendszergazda jóváhagyhatja vagy visszautasítja a kérelmüket. Ha a fejlesztőt jóváhagyják, egy előfizetési kulcsot kapnak, amellyel hitelesíthetik az általuk fejlesztett ügyfélalkalmazások hívásait. Ezt a kulcsot minden webes API-híváshoz meg kell adni.
A portál a következőket is tartalmazza:
- A termék dokumentációja, a termék által elérhetővé tett műveletek listája, a szükséges paraméterek és a különböző visszaadható válaszok. A webes API közzétételére vonatkozó, a Microsoft Azure API Management Szolgáltatások használatával készült szakaszban található lista 3. lépésében megadott adatok alapján generálódnak ezek az információk.
- Kódrészletek, amelyek bemutatják, hogyan hívhat meg műveleteket több nyelvről, például JavaScript, C#, Java, Ruby, Python és PHP.
- Egy fejlesztői konzol, amely lehetővé teszi a fejlesztőknek a termékműveletek HTTP-kérelmek küldésével való tesztelését, valamint az eredmények megtekintését.
- Egy oldal, ahol a fejlesztők jelenthetik a talált hibákat és problémákat.
A Azure portál lehetővé teszi a fejlesztői portál testreszabását, hogy a cég arculatának megfelelően módosítsa a stílust és az elrendezést.
Ügyféloldali SDK megvalósítása
Ha olyan ügyfélalkalmazást hoz létre, amely REST-kérelmek meghívásával ér el egy webes API-t, nagy mennyiségű kódot kell írni az egyes kérelmek létrehozásához, megfelelő formázásához és a webszolgáltatást futtató kiszolgálóra való elküldéséhez, valamint a válasz elemzéséhez, a kérelem sikerességének vagy sikertelenségének megállapításához és a visszaadott adatok kinyeréséhez. Ha el kívánja szigetelni az ügyfélalkalmazást ezektől a problémáktól, megadhat egy SDK-t, amely becsomagolja a REST-felületet, és egy jobban használható metódusgyűjteménybe foglalja ezeket a részleteket. Az ügyfélalkalmazások felhasználhatják ezeket a metódusokat, amelyek transzparens módon átalakítják a hívásokat REST-kérelmekké, majd a válaszokat visszaalakítják a metódusok által visszaadott értékekké. Ez egy gyakori technika, amelyet számos szolgáltatás, köztük a Azure SDK is implementál.
Egy ügyféloldali SDK létrehozása jelentős vállalkozás, mivel egységes megvalósítást és alapos tesztelést igényel. Azonban a folyamat nagy része gépesíthető, és sok beszállító kínál olyan eszközöket, amelyekkel számos feladat automatizálható.
Webes API monitorozása
Attól függően, hogy a webes API hogyan lett közzétéve és üzembe helyezve, monitorozhatja az API-t közvetlenül, vagy felhasználási és állapotadatokat gyűjthet az API Management szolgáltatáson áthaladó forgalom elemzésével.
Webes API közvetlen monitorozása
A Azure Monitor OpenTelemetry Distro segítségével gyűjtse össze a rendelkezésre állási, teljesítmény- és használati adatokat a webes API-ból, és küldje el az Application Insightsnak. A disztribúció nyomon követi és rögzíti a kérelmekre és válaszokra vonatkozó információkat a webes API felhőben való üzembe helyezésekor. Amikor egy Azure webhelyen helyezi üzembe a webes API-t, a rendszer megvizsgálja az összes forgalmat, és a következő statisztikákat gyűjti össze:
- kiszolgáló válaszideje,
- kiszolgáló kérelmeinek száma és az egyes kérelmek részletei,
- a leglassabb kérelmek átlagos válaszidő alapján,
- a sikertelen kérelmek részletei,
- a különböző böngészők és felhasználói ügynökök által kezdeményezett munkamenetek száma,
- a leggyakrabban megtekintett lapok (ez nem elsősorban a webes API-khoz, hanem a webalkalmazásokhoz hasznos).
- a webes API-hoz hozzáférő különböző felhasználói szerepkörök.
Ezeket az adatokat valós időben tekintheti meg a Azure portálon. Olyan webes teszteket is létrehozhat, amelyek a webes API állapotát figyelik. A webes teszt rendszeres kérést küld egy adott URI-nak a webes API-ban, és rögzíti a választ. Megadhatja a sikeres válasz definícióját (például a 200-as HTTP-állapotkódot), és ha a kérés nem adja vissza ezt a választ, gondoskodhat arról, hogy a rendszer riasztást küldjön egy rendszergazdának. Szükség esetén a rendszergazda újraindíthatja a webes API-t futtató kiszolgálót, ha meghibásodott.
További információért lásd: Enable Azure Monitor OpenTelemetry for .NET, Node.js, Python és Java alkalmazásokhoz.
Webes API monitorozása az API Management szolgáltatáson keresztül
Ha a webes API-t az API Management szolgáltatással tette közzé, a Azure portál API Management lapja tartalmaz egy irányítópultot, amely lehetővé teszi a szolgáltatás általános teljesítményének megtekintését. Az Elemzés oldalon részletes elemzések találhatók a termék használatáról. Ez az oldal a következő lapokat tartalmazza:
- Használat Ez a lap információkat közöl az API-hívások számáról és az ezek kezeléséhez igénybe vett sávszélességről. A használati adatok szűrhetők termék, API és művelet szerint.
- Egészség Ezen a lapon megtekinthetők az API-kérelmek eredményei (a visszaadott HTTP-állapotkódok), a gyorsítótárazási szabályzat hatékonysága, az API válaszideje és a szolgáltatás válaszideje. Az állapotadatok szintén szűrhetők termék, API és művelet szerint.
- Tevékenység. Ez a lap szöveges összegzést tartalmaz a sikeres, sikertelen és blokkolt hívásokról, az átlagos válaszidőről, valamint az egyes termékek, webes API-k és műveletek válaszidejéről. Emellett az oldal az egyes fejlesztők által indított hívások számát is felsorolja.
- Áttekintés – Ez a lap a teljesítményadatok összegzését tartalmazza, beleértve a legtöbb API-hívást indító fejlesztőket, és az e hívásokat fogadó termékeket, webes API-kat és műveleteket.
Ezen adatok alapján lehet megállapítani, hogy egy adott webes API vagy művelet szűk keresztmetszetet okoz-e, majd szükség esetén skálázhatja a gazdakörnyezetet további kiszolgálókkal. Emellett az is megállapítható, ha egy vagy több alkalmazás aránytalanul nagy mennyiségű erőforrást használ, majd a megfelelő szabályzatokkal kvóták állíthatók be és korlátozható a hívások gyakorisága.
Megjegyzés
A közzétett termékek részleteinek módosításai azonnal hatályba lépnek. Például egy webes API-hoz hozzáadhat vagy eltávolíthat egy műveletet anélkül, hogy újra közzé kellene tennie a webes API-t tartalmazó terméket.
Következő lépések
- ASP.NET, webes API OData példákat és további információkat tartalmaz az OData webes API ASP.NET használatával történő implementálásáról.
- A Web API és a Web API OData csoportos támogatásának bemutatása leírja, hogyan lehet csoportos műveleteket megvalósítani egy webes API-ban az OData használatával.
- Az idempotens fogyasztói minta implementálási útmutatást nyújt a feldolgozott üzenetazonosítók nyomon követéséhez és a duplikált kézbesítés kezeléséhez.
- A W3C webhelyén található állapotkód-definíciók a HTTP-állapotkódok teljes listáját és leírását tartalmazzák.
- A Háttérfeladatok WebJobs-feladatokkal való futtatásáról szóló cikk útmutatást és példákat tartalmaz a háttérbeli műveletek WebJobs használatával való végrehajtásához.
- Azure Notification Hubs értesíti a felhasználókat bemutatja, hogyan lehet Azure Notification Hub használatával aszinkron válaszokat küldeni az ügyfélalkalmazásokba.
- Az API Management leírja, hogyan lehet közzétenni egy terméket, amely felügyelt és biztonságos hozzáférést biztosít egy webes API-hoz.
- Azure API Management REST API-referencia azt ismerteti, hogyan hozhat létre egyéni felügyeleti alkalmazásokat az API Management REST API használatával.
- Traffic Manager útválasztási módszerei összefoglalja, hogyan használható Azure Traffic Manager a kérések terheléselosztására egy webes API-t futtató webhely több példányában.
- Enable Azure Monitor OpenTelemetry részletes információkat nyújt arról, hogy a Azure Monitor OpenTelemetria-disztribúciót úgy konfigurálja, hogy telemetriát küldjön az Application Insightsnak.