Nếu các ứng dụng REST được coi là không trạng thái, làm thế nào để bạn quản lý các phiên?


536

Tôi cần làm rõ một số. Tôi đã đọc về REST và xây dựng các ứng dụng RESTful. Theo wikipedia, bản thân REST được định nghĩa là Chuyển giao trạng thái đại diện . Do đó, tôi không hiểu tất cả các gobbledeygook không quốc tịch này mà mọi người cứ phun ra.

Từ wikipedia:

Tại bất kỳ thời điểm cụ thể nào, khách hàng có thể chuyển đổi giữa các trạng thái ứng dụng hoặc "nghỉ ngơi". Một máy khách ở trạng thái nghỉ có thể tương tác với người dùng của nó, nhưng không tạo ra tải và không tiêu thụ bộ nhớ trên mỗi máy khách trên bộ máy chủ hoặc trên mạng.

Có phải họ chỉ nói không sử dụng kho dữ liệu cấp phiên / ứng dụng ???

Tôi nhận được một mục tiêu của REST là làm cho truy cập URI nhất quán và khả dụng, thay vì ẩn các yêu cầu phân trang trong các bài đăng, làm cho số trang của yêu cầu trở thành một phần của URI GET. Có nghĩa với tôi. Nhưng có vẻ như nó chỉ quá nhiệt tình nói rằng không nên lưu trữ dữ liệu trên mỗi máy khách (dữ liệu phiên).

Điều gì sẽ xảy ra nếu tôi có một hàng tin nhắn và người dùng của tôi muốn đọc tin nhắn, nhưng khi anh ta đọc chúng, muốn chặn một số tin nhắn người gửi đến trong suốt thời gian của phiên? Sẽ không có ý nghĩa gì khi lưu trữ cái này ở một nơi bên phía máy chủ và máy chủ chỉ gửi tin nhắn (hoặc ID tin nhắn) mà người dùng không bị chặn?

Tôi có thực sự phải gửi toàn bộ danh sách người gửi tin nhắn để chặn mỗi lần tôi yêu cầu danh sách tin nhắn mới không? Danh sách tin nhắn phù hợp với tôi sẽ không / thậm chí không phải là tài nguyên có sẵn công khai ở nơi đầu tiên ..

Một lần nữa, chỉ cần cố gắng để hiểu điều này. Ai đó hãy làm rõ.


Cập nhật:

Tôi đã tìm thấy một câu hỏi tràn ngăn xếp có câu trả lời không hoàn toàn giúp tôi tìm ra cách đó: Cách quản lý trạng thái trong REST nói rằng trạng thái máy khách quan trọng nên được chuyển theo mọi yêu cầu .... Ugg .. có vẻ như rất nhiều chi phí ... Điều này có đúng không ??


2
@ S.Lott: Tôi không nghĩ đó là cố ý gây hiểu lầm. Tôi nghĩ đó là một sự hiểu lầm vì thuật ngữ khó hiểu.
CHỈ CẦN HOẠT ĐỘNG CỦA TÔI

2
@ CHỈ CẦN HOẠT ĐỘNG CỦA TÔI: Đoán thú vị. Bản thân tôi không thể tin được một điều như vậy, vì rõ ràng từ "không trạng thái" đó có nghĩa là bản thân giao thức REST là không trạng thái; trong đó không nói gì về trạng thái ứng dụng cơ bản và cập nhật nó với các yêu cầu PUT, POST và DELETE.
S.Lott

@ S.Lott: Bản thân giao thức HTTP là không trạng thái. Từ những gì chúng ta đã thảo luận dưới đây, REST là một quan điểm về cách xây dựng ứng dụng của bạn trong khi không có máy chủ web xử lý trạng thái phiên (trái ngược với các loại trạng thái khác trong những thứ như DB). Tôi thậm chí không nghĩ REST một giao thức, mà là quan điểm về cách sử dụng giao thức HTTP. Tôi nghĩ rằng các bạn đã xóa nó rằng đó là về cách xây dựng ứng dụng của bạn để mở rộng quy mô bằng cách để phía khách hàng lưu trữ tất cả dữ liệu phiên cụ thể của khách hàng và làm cho các truy cập URI trở nên bình thường nhất có thể, trừ khi họ không nên. Có lẽ không ... :(
Zak

1
"Có lẽ không .." Điều đó có nghĩa là gì? Bạn có một câu hỏi mới? Hãy tìm kiếm SO cho nó. Nếu nó không tồn tại ở đây, thì hãy hỏi nó.
S.Lott

Có ai đã đọc Webber, Parastatidis và Robinson's ReST in Practice (hoặc nhìn thấy ví dụ restbucks của họ) chưa? Các câu trả lời dưới đây có ý nghĩa, nhưng chắc chắn các đơn đặt hàng cà phê trong ví dụ restbucks là trạng thái của một khách hàng? Số lượng đơn đặt hàng quy mô với số lượng khách hàng. Đâu là ranh giới giữa trạng thái máy khách và tài nguyên?
Rikki

Câu trả lời:


340

Không trạng thái có nghĩa là mọi yêu cầu HTTP xảy ra trong sự cô lập hoàn toàn. Khi máy khách thực hiện một yêu cầu HTTP, nó bao gồm tất cả các thông tin cần thiết để máy chủ thực hiện yêu cầu đó. Máy chủ không bao giờ dựa vào thông tin từ các yêu cầu trước đó. Nếu thông tin đó là quan trọng, khách hàng sẽ phải gửi lại trong yêu cầu tiếp theo. Không quốc tịch cũng mang lại những tính năng mới. Việc phân phối một ứng dụng phi trạng thái trên các máy chủ cân bằng tải sẽ dễ dàng hơn. Một ứng dụng phi trạng thái cũng dễ dàng để lưu trữ.

Thực tế có hai loại nhà nước. Trạng thái ứng dụng sống trên máy khách và Trạng thái tài nguyên sống trên máy chủ.

Một dịch vụ web chỉ cần quan tâm đến trạng thái ứng dụng của bạn khi bạn thực sự đưa ra yêu cầu. Thời gian còn lại, nó thậm chí không biết bạn tồn tại. Điều này có nghĩa là bất cứ khi nào khách hàng đưa ra yêu cầu, nó phải bao gồm tất cả các trạng thái ứng dụng mà máy chủ sẽ cần xử lý nó.

Trạng thái tài nguyên là giống nhau cho mọi khách hàng và vị trí thích hợp của nó là trên máy chủ. Khi bạn tải ảnh lên máy chủ, bạn tạo một tài nguyên mới: ảnh mới có URI riêng và có thể là mục tiêu của các yêu cầu trong tương lai. Bạn có thể tìm nạp, sửa đổi và xóa tài nguyên này thông qua HTTP.

Hy vọng điều này sẽ giúp phân biệt ý nghĩa của trạng thái không quốc tịch và các trạng thái khác nhau.


4
Điều này có nghĩa là mỗi khi một yêu cầu được gửi, khách hàng nên gửi người dùng / mật khẩu của mình để xác thực? Bởi vì tôi đoán việc lưu trữ một phiên, ngay cả khi nó nằm trên một db không có sql được chia sẻ giữa tất cả các máy chủ, không phải là không trạng thái, hay là vậy?
Carlos Navarro Astiasarán

1
@ CarlosNavarroAstiasarán có nhiều kỹ thuật khác nhau để xử lý xác thực không trạng thái. Google JWT chẳng hạn.
địa lý

1
@geoidesic: "Vì mã thông báo web JSON là không trạng thái, không có cách nào để vô hiệu hóa chúng mà không lưu trữ trạng thái máy chủ, do đó đánh bại lợi thế của mã thông báo không trạng thái." WIkipedia
ulationkh

@ulationkh Đó là sự trình bày sai lệch về những gì bạn có thể làm với các mã thông báo. Việc lưu trữ ID được phê duyệt cùng với mã thông báo khá đơn giản và chỉ chấp nhận mã thông báo có ID được phê duyệt làm khiếu nại. Không quốc tịch không có nghĩa là bạn không thể một cái gì đó trong cơ sở dữ liệu. Về cơ bản, bạn lưu trữ một ID trong cơ sở dữ liệu phải khớp với cùng một ID trong mã thông báo. Để thu hồi mã thông báo, bạn xóa ID khỏi cơ sở dữ liệu. Không có trạng thái được ghi nhớ trong chính dịch vụ. Hoặc thậm chí tốt hơn là bạn lưu trữ khóa ký với người dùng trong cơ sở dữ liệu và thu hồi khóa.
Andrew T Finnell

@AndrewTFinnell: Nếu bạn phải lưu ID đã được phê duyệt trên máy chủ, thì nó phải được lưu trữ trên tất cả các máy chủ tiềm năng có thể xử lý đăng nhập REST, có thể liên quan đến rất nhiều trạng thái máy chủ trên kiến ​​trúc máy chủ web song song.
uctkh

491

Giải thích cơ bản là:

Không có trạng thái phiên khách trên máy chủ.

Theo trạng thái không trạng thái, điều đó có nghĩa là máy chủ không lưu trữ bất kỳ trạng thái nào về phiên máy khách ở phía máy chủ.

Các khách được lưu trữ trên máy khách. Máy chủ không trạng thái có nghĩa là mọi máy chủ có thể phục vụ bất kỳ máy khách nào vào bất kỳ lúc nào, không có mối quan hệ phiên hoặc phiên dính . Thông tin phiên có liên quan được lưu trữ trên máy khách và được chuyển đến máy chủ khi cần.

Điều đó không loại trừ các dịch vụ khác mà máy chủ web nói đến để duy trì trạng thái về các đối tượng kinh doanh như giỏ hàng, không chỉ về trạng thái ứng dụng / phiên hiện tại của khách hàng.

Các bao giờ nên lưu trữ trạng thái ứng dụng của máy khách trên máy chủ mà được chuyển từ máy khách đến mọi nơi cần đến.

Đó là nơi ST trong REST xuất phát, Chuyển trạng thái . Bạn chuyển trạng thái xung quanh thay vì có máy chủ lưu trữ nó. Đây là cách duy nhất để mở rộng quy mô cho hàng triệu người dùng đồng thời. Nếu không vì lý do nào khác vì hàng triệu phiên là hàng triệu phiên.

Tải trọng của quản lý phiên được khấu hao trên tất cả các máy khách, các máy khách lưu trữ trạng thái phiên của chúng và các máy chủ có thể phục vụ nhiều đơn đặt hàng lớn hơn hoặc nhiều hơn theo cách không trạng thái.

Ngay cả đối với một dịch vụ mà bạn nghĩ sẽ chỉ cần trong số 10 ngàn người dùng đồng thời, bạn vẫn nên làm cho dịch vụ của mình không trạng thái. Hàng chục ngàn vẫn là hàng chục ngàn và sẽ có chi phí thời gian và không gian liên quan đến nó.

Statless là cách giao thức HTTP và web nói chung được thiết kế để hoạt động và là một triển khai đơn giản hơn và bạn có một đường dẫn mã duy nhất thay vì một loạt logic phía máy chủ để duy trì một loạt trạng thái phiên.

Có một số nguyên tắc thực hiện rất cơ bản:

Đây là những nguyên tắc không triển khai, cách bạn đáp ứng những nguyên tắc này có thể khác nhau.

Tóm lại, năm nguyên tắc chính là:

  1. Cung cấp cho mọi thứ của người Viking một ID
  2. Liên kết mọi thứ với nhau
  3. Sử dụng các phương pháp tiêu chuẩn
  4. Tài nguyên với nhiều đại diện
  5. Giao tiếp không quốc tịch

Không có gì về xác thực hoặc ủy quyền trong luận án REST .

Bởi vì không có gì khác với việc xác thực một yêu cầu là RESTful từ một yêu cầu không có. Xác thực không liên quan đến cuộc thảo luận RESTful.

Giải thích cách tạo một ứng dụng không trạng thái cho các yêu cầu cụ thể của bạn, là quá rộng đối với StackOverflow.

Việc triển khai Xác thực và Ủy quyền khi liên quan đến REST thậm chí còn quá rộng - các cách tiếp cận rộng rãi và khác nhau để triển khai được giải thích rất chi tiết trên internet nói chung.

Nhận xét yêu cầu trợ giúp / thông tin về điều này sẽ / nên được gắn cờ là Không còn cần thiết .


22
Đó dường như là một tuyên bố khá táo bạo rằng đó là cách duy nhất để mở rộng quy mô cho hàng triệu người dùng. Tại sao các phiên phía máy chủ không thể chỉ là một dịch vụ khác?
Zak

27
@Zak: Bởi vì hàng triệu phiên là hàng triệu phiên. Vấn đề là để tránh chi phí quản lý phiên này.
S.Lott

91
đó không phải là sự táo bạo mà đó là trải nghiệm

21
Không có gì trong câu trả lời của tôi ngụ ý một giải pháp dựa trên quyền truy cập cơ sở dữ liệu theo mọi yêu cầu, nếu bạn nghĩ rằng nó không phải là một phần thất bại trong việc hiểu xác thực và ủy quyền ở quy mô đó. Việc xác thực có thể được ẩn trong trạng thái, bạn có nghĩ rằng facebook thực hiện "quyền truy cập cơ sở dữ liệu" theo mọi yêu cầu của API REST không? Hoặc Google cho vấn đề đó? gợi ý: không

6
Vì vậy, nếu tôi lưu trữ trạng thái người dùng trong bộ nhớ cache phân tán nói memcache và tất cả máy chủ web của tôi bây giờ không cần lưu trữ bất kỳ trạng thái nào ngoài việc đi và lấy trạng thái từ memcache, tôi có thể xem xét ứng dụng này không trạng thái không?
Jaskey

76

Có phải họ chỉ nói không sử dụng kho dữ liệu cấp phiên / ứng dụng ???

Không. Họ không nói điều đó một cách tầm thường.

Họ đang nói không định nghĩa một "phiên". Đừng đăng nhập. Đừng đăng xuất. Cung cấp thông tin đăng nhập với yêu cầu. Mỗi yêu cầu đứng một mình.

Bạn vẫn có cửa hàng dữ liệu. Bạn vẫn có xác thực và ủy quyền. Bạn chỉ không lãng phí thời gian để thiết lập phiên và duy trì trạng thái phiên.

Vấn đề là mỗi yêu cầu (a) hoàn toàn độc lập và (b) có thể được đưa vào một trang trại máy chủ song song khổng lồ mà không cần bất kỳ công việc thực tế nào. Apache hoặc Squid có thể vượt qua các yêu cầu RESTful một cách mù quáng và thành công.

Điều gì sẽ xảy ra nếu tôi có một hàng tin nhắn và người dùng của tôi muốn đọc tin nhắn, nhưng khi anh ta đọc chúng, muốn chặn một số tin nhắn người gửi đến trong suốt thời gian của phiên?

Nếu người dùng muốn có một bộ lọc, thì chỉ cần cung cấp bộ lọc cho mỗi yêu cầu.

Sẽ không có nghĩa gì khi ... máy chủ chỉ gửi tin nhắn (hoặc ID tin nhắn) mà người dùng không bị chặn?

Đúng. Cung cấp bộ lọc trong yêu cầu URI RESTful.

Tôi có thực sự phải gửi toàn bộ danh sách người gửi tin nhắn để chặn mỗi lần tôi yêu cầu danh sách tin nhắn mới không?

Đúng. "Danh sách người gửi tin nhắn để chặn" này có thể lớn đến mức nào? Một danh sách ngắn của PK?

Một yêu cầu NHẬN có thể rất lớn. Nếu cần, bạn có thể thử yêu cầu POST mặc dù nghe có vẻ giống như một loại truy vấn.


28
"Đừng đăng nhập. Đừng đăng xuất. Cung cấp thông tin đăng nhập với yêu cầu." Tôi luôn thấy các câu trả lời như thế này trong các câu hỏi về cách duy trì trạng thái không trạng thái trong API REST mà không có bất kỳ chi tiết nào về nơi / cách người ta nên lưu trữ các thông tin đăng nhập đó trên máy khách. Chắc chắn chúng ta không nên lưu tên người dùng và mật khẩu trong bộ nhớ cục bộ!
BeniRose

2
@BeniRose chúng tôi không thể lưu trữ mã thông báo trong kho lưu trữ cục bộ và sử dụng mã thông báo đó trong các yêu cầu sẽ xác định duy nhất người dùng?
Nikhil Sahu

1
Localst Storage có rất nhiều mối quan tâm về bảo mật từ những gì tôi hiểu. Nhưng cũng có một loạt các mối quan tâm khác với các phiên phía khách hàng, như làm mất hiệu lực mã thông báo, đăng xuất người dùng, v.v.
BeniRose

3
bạn sử dụng JWT có chữ ký, xác minh chữ ký nhanh để bạn có thể kiểm tra tính hợp lệ của trạng thái đó.
Archimedes Trajano

36

Bạn hoàn toàn đúng, việc hỗ trợ các tương tác hoàn toàn không trạng thái với máy chủ sẽ tạo thêm gánh nặng cho khách hàng. Tuy nhiên, nếu bạn xem xét mở rộng một ứng dụng, sức mạnh tính toán của các khách hàng tỷ lệ thuận với số lượng khách hàng. Do đó, việc nhân rộng số lượng khách hàng cao là khả thi hơn nhiều.

Ngay khi bạn đặt một chút trách nhiệm lên máy chủ để quản lý một số thông tin liên quan đến tương tác của một khách hàng cụ thể, gánh nặng đó có thể nhanh chóng tăng lên để tiêu thụ máy chủ.

Đó là một sự đánh đổi.


32

Quan điểm lịch sử của quản lý nhà nước ứng dụng người dùng

Các phiên theo nghĩa truyền thống giữ trạng thái của người dùng trong ứng dụng bên trong máy chủ. Đây có thể là trang hiện tại trong một luồng hoặc những gì đã được nhập trước đó nhưng chưa được lưu vào cơ sở dữ liệu chính.

Lý do cho nhu cầu này là do thiếu các tiêu chuẩn ở phía máy khách để duy trì hiệu quả trạng thái mà không tạo ra các ứng dụng hoặc trình cắm cụ thể (cụ thể của trình duyệt).

Yêu cầu Tiêu đề HTML5 và XML theo thời gian đã tiêu chuẩn hóa khái niệm lưu trữ dữ liệu phức tạp bao gồm trạng thái ứng dụng theo cách tiêu chuẩn ở phía máy khách (tức là trình duyệt) mà không cần dùng đến giữa máy chủ.

Sử dụng chung các dịch vụ REST

Các dịch vụ REST thường được gọi khi có một giao dịch cần được thực hiện hoặc nếu nó cần lấy dữ liệu.

Các dịch vụ REST có nghĩa là được gọi bởi ứng dụng phía máy khách chứ không phải người dùng cuối trực tiếp.

Chứng thực

Đối với bất kỳ yêu cầu nào đến máy chủ, một phần của yêu cầu phải chứa mã thông báo ủy quyền. Cách thức triển khai là ứng dụng cụ thể, nhưng nói chung là một BASIChoặcCERTIFICATE hình thức xác thực.

Xác thực dựa trên mẫu không được sử dụng bởi các dịch vụ REST. Tuy nhiên, như đã lưu ý ở trên, các dịch vụ REST không được gọi bởi người dùng, mà bởi ứng dụng. Ứng dụng cần quản lý để nhận mã thông báo xác thực. Trong trường hợp của tôi, tôi đã sử dụng cookie với JASPIC với OAuth 2.0 để kết nối với Google để xác thực và Xác thực HTTP đơn giản để kiểm tra tự động. Tôi cũng đã sử dụng xác thực HTTP Header qua JASPIC để thử nghiệm cục bộ (mặc dù cách tiếp cận tương tự có thể được thực hiện trong SiteMinder)

Theo các ví dụ đó, xác thực được quản lý ở phía máy khách (mặc dù SiteMinder hoặc Google sẽ lưu trữ phiên xác thực ở cuối), không có gì có thể được thực hiện về trạng thái đó, nhưng nó không phải là một phần của ứng dụng dịch vụ REST.

Yêu cầu truy xuất

Các yêu cầu truy xuất trong REST là các GEThoạt động trong đó một tài nguyên cụ thể được yêu cầu và có thể lưu trong bộ nhớ cache. Không cần phiên máy chủ vì yêu cầu có mọi thứ cần thiết để truy xuất dữ liệu: xác thực và URI.

Kịch bản giao dịch

Như đã lưu ý ở trên, ứng dụng phía máy khách tự gọi các dịch vụ REST cùng với xác thực mà nó cũng quản lý ở phía máy khách.

Điều này có nghĩa gì đối với các dịch vụ REST [nếu được thực hiện chính xác] là đưa một yêu cầu đến máy chủ REST sẽ chứa mọi thứ cần thiết cho một thao tác người dùng thực hiện mọi thứ cần thiết trong một giao dịch, Tập lệnh giao dịch là mẫu nào được gọi là.

Điều này được thực hiện thông qua một POSTyêu cầu thường, nhưng những thứ khác như PUTcũng có thể được sử dụng.

Rất nhiều ví dụ giả định về REST (bản thân tôi đã làm điều này) đã cố gắng làm theo nhiều như những gì đã được xác định trong giao thức HTTP, sau khi trải qua điều đó, tôi quyết định thực dụng hơn và chỉ để nó NHẬN và POST . Các POSTphương pháp thậm chí không có để thực hiện mô hình POST-REDIRECT-GET.

Mặc dù vậy, như tôi đã lưu ý ở trên, ứng dụng phía máy khách sẽ là ứng dụng gọi dịch vụ và nó sẽ chỉ gọi POSTyêu cầu với tất cả dữ liệu khi cần (không phải mọi lúc). Điều này ngăn chặn các yêu cầu liên tục đến máy chủ.

Bỏ phiếu

Mặc dù REST cũng có thể được sử dụng để bỏ phiếu, nhưng tôi sẽ không đề xuất trừ khi bạn phải sử dụng nó vì tính tương thích của trình duyệt. Vì vậy, tôi cũng sẽ sử dụng WebSockets mà tôi đã thiết kế một hợp đồng API . Một lựa chọn khác cho các trình duyệt cũ hơn là CometD.


27

REST rất trừu tượng. Nó giúp có một số ví dụ tốt, đơn giản, trong thế giới thực.

Lấy ví dụ tất cả các ứng dụng truyền thông xã hội lớn - Tumblr, Instagram, Facebook và Twitter. Tất cả đều có chế độ xem mãi mãi trong đó bạn càng cuộn xuống càng xa, bạn càng thấy nhiều nội dung, càng ngày càng quay ngược thời gian. Tuy nhiên, tất cả chúng ta đều đã trải nghiệm khoảnh khắc mà bạn mất nơi bạn được cuộn đến và ứng dụng sẽ đặt bạn trở lại đầu trang. Giống như nếu bạn thoát khỏi ứng dụng, thì khi bạn mở lại ứng dụng, bạn sẽ quay lại đầu trang một lần nữa.

Lý do tại sao là vì máy chủ không lưu trữ trạng thái phiên của bạn. Đáng buồn thay, vị trí cuộn của bạn chỉ được lưu trữ trong RAM trên máy khách.

May mắn là bạn không phải đăng nhập lại khi kết nối lại, nhưng đó chỉ là do chứng chỉ đăng nhập được lưu trữ phía khách hàng của bạn chưa hết hạn. Xóa và cài đặt lại ứng dụng và bạn sẽ phải đăng nhập lại, vì máy chủ không liên kết địa chỉ IP của bạn với phiên của bạn.

Bạn không có phiên đăng nhập trên máy chủ, vì họ tuân thủ REST.


Bây giờ các ví dụ trên không liên quan đến trình duyệt web, nhưng ở mặt sau, các ứng dụng đang liên lạc qua HTTPS với máy chủ lưu trữ của chúng. Quan điểm của tôi là REST không phải liên quan đến cookie và trình duyệt, v.v ... Có nhiều cách khác nhau để lưu trữ trạng thái phiên phía máy khách.

Nhưng hãy nói về trình duyệt web trong một giây, bởi vì điều đó mang đến một lợi thế lớn khác của REST mà không ai ở đây đang nói đến.

Nếu máy chủ cố lưu trữ trạng thái phiên, làm thế nào để xác định từng khách hàng riêng lẻ?

Nó không thể sử dụng địa chỉ IP của họ, vì nhiều người có thể đang sử dụng cùng địa chỉ đó trên một bộ định tuyến dùng chung. Vậy thì thế nào?

Nó không thể sử dụng địa chỉ MAC vì nhiều lý do, không phải ít nhất là vì bạn có thể đăng nhập vào nhiều tài khoản Facebook khác nhau trên các trình duyệt khác nhau cộng với ứng dụng. Một trình duyệt có thể dễ dàng giả vờ là một trình duyệt khác và địa chỉ MAC cũng dễ giả mạo.

Nếu máy chủ phải lưu trữ một số trạng thái phía máy khách để nhận dạng bạn, thì nó phải lưu trữ nó trong RAM lâu hơn thời gian xử lý các yêu cầu của bạn hoặc nếu không nó phải lưu trữ dữ liệu đó. Máy chủ có số lượng RAM và bộ nhớ cache hạn chế, chưa kể tốc độ xử lý. Trạng thái phía máy chủ thêm vào cả ba, theo cấp số nhân. Ngoài ra, nếu máy chủ sẽ lưu trữ bất kỳ trạng thái nào về các phiên của bạn thì nó phải lưu trữ riêng cho từng trình duyệt và ứng dụng bạn hiện đang đăng nhập và cho từng thiết bị khác nhau mà bạn sử dụng.


Vì vậy, tôi hy vọng rằng bạn thấy bây giờ tại sao REST lại quan trọng đối với khả năng mở rộng. Tôi hy vọng bạn có thể bắt đầu xem lý do tại sao trạng thái phiên phía máy chủ là khả năng mở rộng của máy chủ, cái đe được hàn trên xe tăng tốc.


Nơi mọi người bị lẫn lộn là do nghĩ rằng "trạng thái" đề cập đến, như, thông tin được lưu trữ trong cơ sở dữ liệu. Không, nó đề cập đến bất kỳ thông tin nào cần có trong RAM của máy chủ khi bạn đang sử dụng nó.


13

Tôi thấy rằng vấn đề cơ bản ở đây là trộn lẫn Phiên với Nhà nước . Và trong khi REST chỉ định rằng bạn KHÔNG nên lưu trữ Trạng thái trên máy chủ, không có gì ngăn bạn lưu trữ Phiên người dùng .

Quản lý nhà nước trên máy chủ có nghĩa là máy chủ của bạn biết chính xác khách hàng đang làm gì (trang nào họ đang xem trong phần nào của ứng dụng). Và đây là những gì bạn không cần phải làm.

Tôi đồng ý với những người khác nói rằng bạn nên giữ dung lượng lưu trữ phiên ở kích thước tối thiểu; và mặc dù đó là lẽ thường, nó thực sự cũng phụ thuộc vào ứng dụng. Vì vậy, trong ngắn hạn, bạn vẫn có thể giữ một phiên với dữ liệu được lưu trong bộ nhớ cache để xử lý các yêu cầu với tải ít hơn trên máy chủ và quản lý xác thực bằng cách cung cấp mã xác thực / mã thông báo truy cập tạm thời cho khách hàng sử dụng. Bất cứ khi nào phiên / mã thông báo hết hạn, hãy tạo một cái mới và yêu cầu khách hàng sử dụng nó.

Ai đó có thể lập luận rằng khách hàng nên tạo mã thông báo tốt hơn. Tôi nói rằng nó hoạt động theo cả hai cách và nó sẽ phụ thuộc vào ứng dụng và ai sẽ làm việc với API.

Ngoài ra, giữ một số dữ liệu phiên nhạy cảm trên máy chủ là cách làm đúng đắn. Bạn không thể tin tưởng khách hàng giữ cho giỏ hàng của họ (ví dụ) có chứa một trường có tên "isFreeGift". Thông tin như vậy nên được lưu giữ trên máy chủ.

Liên kết video được cung cấp bởi Santanu Dey trong câu trả lời của anh ấy rất hữu ích. Xem nó nếu bạn không có.

Chỉ là một lưu ý phụ: Dường như tất cả các câu trả lời đã được đưa ra dường như không quan tâm đến thực tế rằng một số hoạt động có thể gây ra tải nặng trên máy chủ. Điều đó có liên quan về mức tiêu thụ năng lượng, mức tiêu thụ phần cứng và chi phí (đối với các máy chủ được thuê theo chu kỳ CPU). Một nhà phát triển giỏi không nên lười biếng trong việc tối ưu hóa ứng dụng của họ, ngay cả khi hoạt động có thể được thực hiện rất nhanh trên CPU hiện đại trên một số máy chủ được thuê mà họ không trả hóa đơn tiền điện và bảo trì.

Althoght câu hỏi là một vài năm tuổi, tôi hy vọng rằng câu trả lời của tôi vẫn sẽ hữu ích.


4
Tôi thường đồng ý với tình cảm này, nhưng đã có một xu hướng gần đây để tuyên bố rằng ngay cả một định danh phiên cũng không nên được lưu trữ trên máy chủ. Tôi chưa tìm ra những giải pháp thay thế là, JWT cũng được chào mời, nhưng đi kèm với một số ít các gotchas: cryto.net/~joepie91/blog/2016/06/19/...
BeniRose

11

Không quốc tịch có nghĩa là trạng thái của dịch vụ không tồn tại giữa các yêu cầu và phản hồi tiếp theo. Mỗi yêu cầu mang thông tin người dùng riêng và được xác thực riêng. Nhưng trong trạng thái, mỗi yêu cầu được biết từ bất kỳ yêu cầu trước. Tất cả các yêu cầu trạng thái được định hướng theo phiên, tức là mỗi yêu cầu cần biết và giữ lại các thay đổi được thực hiện trong các yêu cầu trước đó.

Ứng dụng ngân hàng là một ví dụ về ứng dụng nhà nước. Trường hợp người dùng đăng nhập đầu tiên sau đó thực hiện giao dịch và đăng xuất. Nếu sau khi người dùng đăng xuất sẽ cố gắng thực hiện giao dịch, anh ta sẽ không thể làm như vậy.

Đúng, giao thức http về cơ bản là một giao thức không trạng thái nhưng để làm cho nó trở nên rõ ràng, chúng tôi tạo cho chúng tôi các cookie HTTP. Vì vậy, là SOAP theo mặc định. Nhưng nó có thể được thực hiện tương tự như vậy, tùy thuộc vào khuôn khổ bạn đang sử dụng.

HTTP không trạng thái nhưng chúng ta vẫn có thể duy trì phiên trong ứng dụng java của mình bằng cách sử dụng cơ chế theo dõi phiên khác nhau.

Có, Chúng tôi cũng có thể duy trì phiên trong dịch vụ web cho dù đó là REST hay SOAP. Nó có thể được thực hiện bằng cách sử dụng bất kỳ thư viện của bên thứ ba hoặc bạn có thể tự thực hiện.

Lấy từ http://gopaldas.org/webservice/soap/webservice-is-stateful-or-statless-rest-soap


11

Không có muỗng.

Đừng nghĩ về trạng thái không trạng thái như "gửi tất cả nội dung của bạn đến máy chủ nhiều lần". Không đời nào. Luôn luôn có trạng thái - cơ sở dữ liệu một loại trạng thái, bạn là người dùng đã đăng ký, do đó, bất kỳ bộ thông tin phía máy khách nào sẽ không hợp lệ nếu không có phía máy chủ. Về mặt kỹ thuật, bạn không bao giờ thực sự không quốc tịch.

Một từ trên Cuộc tranh luận mỗi lần đăng nhập

Điều gì có nghĩa là không giữ một phiên và đăng nhập mỗi lần? Một số có nghĩa là "gửi mật khẩu mỗi lần", điều đó thật ngu ngốc. Một số người nói "tất nhiên là không, thay vào đó hãy gửi mã thông báo " - lo và kìa, phiên PHP đang thực hiện gần như chính xác điều đó. Nó sẽ gửi một id phiên là một loại mã thông báo và nó giúp bạn tiếp cận công cụ cá nhân của mình mà không cần gửi lại u / pw mỗi lần. Nó cũng khá đáng tin cậy và được thử nghiệm tốt. Và vâng, thuận tiện, có thể biến thành một nhược điểm, xem đoạn tiếp theo.

Giảm dấu chân

Những gì bạn nên làm , thay vào đó, và những gì có ý nghĩa thực sự, là làm giảm dấu chân máy chủ web của bạn đến mức tối thiểu. Các ngôn ngữ như PHP giúp dễ dàng chỉ nhét mọi thứ vào bộ lưu trữ phiên - nhưng các phiên có thẻ giá. Nếu bạn có một số máy chủ web, họ cần chia sẻ thông tin phiên, vì họ cũng chia sẻ tải - bất kỳ ai trong số họ cũng có thể phải phục vụ yêu cầu tiếp theo.

Một lưu trữ được chia sẻ là phải. Máy chủ cần biết ít nhất nếu ai đó đăng nhập hay không. (Và nếu bạn làm phiền cơ sở dữ liệu mỗi khi bạn cần quyết định điều này, thì thực tế bạn sẽ phải chịu số phận.) Kho lưu trữ được chia sẻ cần phải nhanh hơn rất nhiều so với cơ sở dữ liệu. Điều này mang lại sự cám dỗ: được rồi, tôi có một kho lưu trữ rất nhanh, tại sao không làm mọi thứ ở đó? - và đó là nơi mọi thứ trở nên khó chịu theo cách khác.

Vì vậy, bạn đang nói, giữ lưu trữ phiên ở mức tối thiểu?

Một lần nữa, đó là quyết định của bạn. Bạn có thể lưu trữ nội dung ở đó vì lý do hiệu suất (cơ sở dữ liệu hầu như luôn chậm hơn Redis), bạn có thể lưu trữ thông tin một cách dự phòng, thực hiện bộ nhớ đệm của riêng bạn, bất cứ điều gì - chỉ cần lưu ý rằng các máy chủ web sẽ có tải lớn hơn nếu bạn lưu trữ nhiều rác. về họ. Ngoài ra, nếu chúng phá vỡ dưới tải nặng (và chúng sẽ), bạn sẽ mất thông tin có giá trị; với cách suy nghĩ REST, tất cả những gì xảy ra trong trường hợp này là khách hàng gửi lại cùng một yêu cầu (!) và nó sẽ được phục vụ lần này.

Làm thế nào để làm điều đó ngay sau đó?

Không có giải pháp nào phù hợp cho tất cả ở đây. Tôi muốn nói chọn một mức độ không quốc tịch và đi với điều đó. Phiên có thể được một số người yêu thích và ghét bởi những người khác nhưng họ sẽ không đi đâu cả. Với mỗi yêu cầu, hãy gửi càng nhiều thông tin càng có ý nghĩa, có lẽ hơn một chút; nhưng không giải thích trạng thái không trạng thái là không có phiên, cũng như không đăng nhập mỗi lần. Bằng cách nào đó máy chủ phải biết đó là bạn ; Id phiên PHP là một cách tốt, mã thông báo được tạo thủ công là một cách khác.

Hãy suy nghĩ và quyết định, đừng để xu hướng thiết kế nghĩ cho bạn.


1
"Hãy suy nghĩ và quyết định, đừng để xu hướng thiết kế nghĩ cho bạn." Thật không may, ngày nay nó trở nên rất phổ biến khi chỉ ngu ngốc theo xu hướng. Đôi khi đọc SO bạn sẽ nhận được tất cả các câu trả lời giống nhau chỉ vì xu hướng.
l00k

Vâng, tôi đã thấy điều này xung quanh nhiều chủ đề và khi tôi nhận ra những gì đang xảy ra, đôi khi tôi ngừng tranh luận. Trước đó, mọi người đều phát cuồng về cách hộp nội dung tốt hơn hộp viền; đó là một cách để thể hiện sự căm thù đối với IE. Sau đó đến bootstrap và đột nhiên mọi người là một tín đồ hộp biên giới. Xu hướng đến nhưng rồi họ đi. Sử dụng goto, sử dụng bảng, sử dụng iframe, chỉ cần biết bạn đang làm gì và tại sao. Những người theo xu hướng sẽ cố gắng đưa bạn xuống, sau đó họ đăng ký và trả tiền trên trang web của bạn. Thế giới lại được cứu.
dkellner

@dkellner Tôi không hiểu phần đó: "Máy chủ cần biết ít nhất là có ai đó đăng nhập hay không (Và nếu bạn làm phiền cơ sở dữ liệu mỗi khi bạn cần quyết định điều này, thì thực tế bạn sẽ phải chịu số phận." ". Giả sử bạn lưu trữ dữ liệu phiên trong cơ sở dữ liệu với PHP. Tại sao truy vấn DB cho đăng nhập xấu (cam chịu là một từ mạnh) vì dù sao sẽ có nhiều yêu cầu DB tiếp theo để có được dữ liệu người dùng hoàn chỉnh và các nội dung khác, dựa trên ID phiên PHP? Nói cách khác, các truy vấn DB là không thể tránh khỏi trong mọi trường hợp. Ngoài ra, nếu bạn không nhận được ID phiên PHP, bạn biết người dùng không được xác thực, không cần phải truy vấn.
dùng2923322

Khi bạn có hàng ngàn hoặc thậm chí hàng triệu người dùng, bạn không thể đủ khả năng kết nối với db mỗi khi bạn muốn thực hiện cập nhật, cập nhật vị trí, thăm dò tin nhắn hoặc bất cứ điều gì cần đăng ký ngắn. Bạn phải thực hiện các cuộc gọi này mà không có (hoặc có quyền truy cập cơ sở dữ liệu tối thiểu), đó là lý do tại sao tôi nói rằng nó có thể gây chết người nếu bạn xây dựng toàn bộ khái niệm của mình xung quanh db. Một lần nữa, có thể có trường hợp một giải pháp db được thiết kế tốt sẽ hoạt động, nhưng lập trình viên điển hình sẽ giải quyết mọi thứ bằng cách nói "được rồi, trước tiên chúng tôi kết nối và lấy một số thông tin người dùng". Baaaad thực hành.
dkellner


3

Sự khác biệt chính giữa trạng thái không trạng thái và trạng thái là dữ liệu được truyền trở lại máy chủ mỗi lần. Trong trường hợp không trạng thái, khách hàng phải cung cấp tất cả thông tin để có thể cần phải truyền nhiều thông số trong mỗi yêu cầu. Trong Stateful, cliet chuyển các tham số đó một lần và chúng được duy trì bởi máy chủ cho đến khi máy khách sửa đổi lại.

IMO, API nên không trạng thái cho phép tăng quy mô thực sự nhanh chóng.


2

Bạn phải quản lý phiên khách hàng về phía khách hàng. Điều này có nghĩa là bạn phải gửi dữ liệu xác thực với mọi yêu cầu và có thể, nhưng không cần thiết phải có bộ đệm trong bộ nhớ trên máy chủ, kết hợp dữ liệu xác thực với thông tin người dùng như danh tính, quyền, v.v ...

Hạn chế không trạng thái REST này là rất quan trọng. Nếu không áp dụng ràng buộc này, ứng dụng phía máy chủ của bạn sẽ không mở rộng quy mô , bởi vì việc duy trì mỗi phiên máy khách sẽ là điểm yếu của Achilles .


Nếu bạn gửi dữ liệu xác thực với mỗi yêu cầu, bạn sẽ lưu thông tin đăng nhập trên máy khách ở đâu để làm thế nào để người dùng không phải nhập lại dữ liệu theo từng yêu cầu?
Amber

1

Khi bạn phát triển dịch vụ RESTful, để đăng nhập, bạn sẽ cần xác thực người dùng của mình. Một tùy chọn có thể là gửi tên người dùng và mật khẩu mỗi khi bạn định thực hiện hành động của người dùng. Trong trường hợp này, máy chủ sẽ không lưu trữ dữ liệu phiên.

Một tùy chọn khác là tạo id phiên trên máy chủ và gửi nó đến máy khách, vì vậy máy khách sẽ có thể gửi id phiên tới máy chủ và xác thực điều đó. Điều này an toàn hơn nhiều so với việc gửi tên người dùng và mật khẩu mỗi lần, vì nếu ai đó có được dữ liệu đó, thì anh ấy / cô ấy có thể mạo danh người dùng cho đến khi tên người dùng và mật khẩu được thay đổi. Bạn có thể nói rằng thậm chí id phiên có thể bị đánh cắp và người dùng sẽ bị mạo danh trong trường hợp đó và bạn đã đúng. Tuy nhiên, trong trường hợp này, việc mạo danh người dùng sẽ chỉ có thể trong khi id phiên là hợp lệ.

Nếu API RESTful mong muốn tên người dùng và mật khẩu để thay đổi tên người dùng và mật khẩu, thì ngay cả khi ai đó mạo danh người dùng bằng id phiên, tin tặc sẽ không thể khóa người dùng thực.

Id phiên có thể được tạo bằng cách khóa một chiều (mã hóa) thứ gì đó xác định người dùng và thêm thời gian vào id phiên, theo cách này có thể xác định thời gian hết hạn của phiên.

Máy chủ có thể hoặc không thể lưu trữ id phiên. Tất nhiên, nếu máy chủ lưu trữ id phiên, thì nó sẽ vi phạm các tiêu chí được xác định trong câu hỏi. Tuy nhiên, điều quan trọng là phải đảm bảo rằng id phiên có thể được xác thực cho người dùng nhất định, không bắt buộc phải lưu trữ id phiên. Hãy tưởng tượng một cách mà bạn có mã hóa một chiều của email, id người dùng và một số dữ liệu riêng tư của người dùng, như màu yêu thích, đây sẽ là cấp độ đầu tiên và bằng cách nào đó thêm ngày tên người dùng vào chuỗi được mã hóa và áp dụng hai cách mã hóa. Kết quả là khi nhận được id phiên, cấp độ thứ hai có thể được giải mã để có thể xác định tên người dùng mà người dùng tuyên bố là gì và liệu thời gian phiên có đúng hay không. Nếu điều này là hợp lệ, sau đó mức mã hóa đầu tiên có thể được xác nhận bằng cách thực hiện lại mã hóa đó và kiểm tra xem nó có khớp với chuỗi không. Bạn không cần lưu trữ dữ liệu phiên để đạt được điều đó.


điều này có ý nghĩa
bắt đầu từ

0

Toàn bộ khái niệm là khác nhau ... Bạn không cần phải quản lý phiên nếu bạn đang cố gắng thực hiện giao thức RESTFul. Trong trường hợp đó, tốt hơn là thực hiện quy trình xác thực cho mọi yêu cầu (trong khi đó phải trả thêm chi phí cho hiệu suất - mật khẩu băm sẽ là một ví dụ tốt. Không phải là vấn đề lớn ...). Nếu bạn sử dụng phiên - làm thế nào bạn có thể phân phối tải trên nhiều máy chủ? Tôi cá là giao thức RESTFul có nghĩa là loại bỏ các phiên bất kỳ - bạn không thực sự cần chúng ... Đó là lý do tại sao nó được gọi là "không trạng thái". Phiên chỉ được yêu cầu khi bạn không thể lưu trữ bất cứ thứ gì ngoài Cookie ở phía máy khách sau khi yêu cầu được thực hiện (lấy trình duyệt cũ, không hỗ trợ Javascript / HTML5 làm ví dụ). Trong trường hợp máy khách RESTFul "đầy đủ tính năng", việc lưu trữ thường an toànbase64(login:password) ở phía máy khách (trong bộ nhớ) cho đến khi lời khen vẫn được tải - ứng dụng được sử dụng để truy cập vào máy chủ duy nhất và cookie không thể bị xâm phạm bởi tập lệnh của bên thứ ba ...

Tôi chắc chắn sẽ khuyên bạn nên tắt xác thực cookie cho các dịch vụ RESTFul ... kiểm tra Auth cơ bản / tiêu hóa - điều đó là đủ cho các dịch vụ dựa trên RESTFul.


3
Điều gì là a client side (in memory) an toàn và tiết kiệm base64(login:password)ở phía khách hàng?
RN Kushwaha

1
Không có gì được định nghĩa là "hoàn toàn an toàn". Tuy nhiên, bạn có thể xem xét sử dụng OAuth2 cung cấp bảo mật tốt hơn so với lưu chuỗi cơ sở64 cho yêu cầu API (Auth cơ bản), nếu bạn sử dụng Auth cơ bản, bạn có thể sử dụng HTTPS để bảo mật tốt hơn.
felixwcf

3
RN Kushwaha, đây là câu hỏi dường như không ai muốn trả lời khi họ bảo bạn ngừng lưu trữ phiên trên máy chủ và lưu trữ nó trong máy khách.
BeniRose

0

REST không trạng thái và không duy trì bất kỳ trạng thái nào giữa các yêu cầu. Cookie / tiêu đề của khách hàng được đặt để duy trì trạng thái người dùng như xác thực. Giả sử tên người dùng / mật khẩu của khách hàng được xác thực theo cơ chế xác thực phần thứ ba - Gerneation cấp độ 2, v.v. . Bây giờ thông tin nhất định của người dùng như IP được duy trì trong bộ đệm và sau đó nếu yêu cầu đến từ cùng một Ip (địa chỉ mac) cho các tài nguyên được liệt kê Người dùng được phép. Và bộ nhớ cache được duy trì trong một thời gian cụ thể bị vô hiệu hóa khi thời gian trôi đi. Vì vậy, bộ đệm có thể được sử dụng hoặc các mục DB có thể được sử dụng để duy trì thông tin b / w các yêu cầu.


0

Không quốc tịch ở đây có nghĩa là dữ liệu trạng thái hoặc meta của yêu cầu không được duy trì ở phía máy chủ. Bằng cách duy trì từng yêu cầu hoặc trạng thái của người dùng trên máy chủ, nó sẽ dẫn đến tắc nghẽn hiệu suất. Máy chủ chỉ được yêu cầu với các thuộc tính bắt buộc để thực hiện bất kỳ hoạt động cụ thể nào.

Đến với việc quản lý phiên hoặc cung cấp trải nghiệm tùy chỉnh cho người dùng, nó yêu cầu duy trì một số dữ liệu meta hoặc trạng thái tùy chọn của người dùng, lịch sử yêu cầu trong quá khứ. Điều này có thể được thực hiện bằng cách duy trì cookie, thuộc tính ẩn hoặc vào đối tượng phiên.

Điều này có thể duy trì hoặc theo dõi trạng thái của người dùng trong ứng dụng.

Hi vọng điêu nay co ich!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.