负载平衡环境中的ServiceStack会话处理

时间:2016-10-03 12:22:47

标签: session servicestack

我在我的一个项目中使用ServiceStack作为基础库。 我将我的应用程序构建在两部分API和WEB应用程序中,它们是独立的项目和存储库。

身份验证应该在API层上进行,并且应该在那里缓存。我在API服务器中使用Ormlite缓存客户端。

在API AppHost.cs

var dbFactory = new OrmLiteConnectionFactory("ConnectionString",SqlServerDialect.Provider);
container.RegisterAs<OrmLiteCacheClient, ICacheClient>();
container.Resolve<ICacheClient>().InitSchema();
Plugins.Add(new AuthFeature(() => new APISession(),
  new IAuthProvider[] {
    new APICredentialsAuthProvider(new AppSettings())
 }));

在APICredentialsAuthProvider中,我正在保存会话,该会话存储在CacheEntry表中的Db中

我正在使用apiurl/auth通过ajax调用在Web应用程序中对用户进行身份验证,并使用AuthenticateResponse返回sessionId。 我将此会话ID更新为Cookie s-id,稍后更新为预先请求过滤器,具体取决于ss-idss-pid中正在更新的请求类型。

//Inside Web application apphost
this.PreRequestFilters.Add((req, res) =>
{
  System.Net.Cookie cookie = req.Cookies["s-id"];
  req.Cookies["ss-id"] = cookie;
  req.SetSessionId(cookie.Value)
});

这种方法不会从我的案例中的Ormlite缓存中获取会话,也不会在Web和Api应用程序中提供相应的配置。

实现这一目标的最佳方式是什么?

但是我可以使用缓存客户端

访问会话
//Inside Web application apphost
this.PreRequestFilters.Add((req, res) =>
{
  System.Net.Cookie cookie = req.Cookies["s-id"];
  req.Cookies["ss-id"] = cookie;
  req.SetSessionId(cookie.Value);
 APISession cachedSession = GetCacheClient(req).Get<APISession(SessionFeature.GetSessionKey(cookie.Value));
 WEBSession session.PopulateWith<WEBSession, APISession>(cachedSession);

});

这工作正常,我能够获取会话,但通过将此放入预请求过滤器增加来自我的Web应用程序的db调用(在每个请求上)。

是否有可用的替代解决方案?

提前致谢!!

1 个答案:

答案 0 :(得分:3)

如果您负载均衡多个网络应用在同一个域后面,那么使用OrmLiteCacheClient之类的任何ss-id/ss-pid都会发送ServiceStack&#39; s http://example.org/app1 -> http://internal:8001/ /app2 -> http://internal:8002/ /app3 -> http://internal:8003/ 在向任一应用程序提出请求时使用Cookie:

OrmLiteCacheClient

然后,只要每个应用配置相同的IRequest.Items,就可以在所有3个应用中看到在一个应用中创建的会话。

您可以通过在req.Items[Keywords.Session] = session; 上设置该请求来阻止进一步的数据库访问以检索该请求的会话,例如:

IRequest

然后,对该请求的会话的任何访问都将从import React from 'react'; import Question from './Question'; import firebase from 'firebase'; var questions = [{ qtext : "", options: [], id:0, answer: ""}, { qtext : "", options: [], id:1, answer: "" }]; const QuizBuilderForm = React.createClass({ getInitialState: function() { return { questions }; }, addQuestion: function(questions, id) { questions = this.state.questions; questions.push({ qtext : "", options: [], id: this.state.questions.length }); this.setState({ questions: questions }); }, handleSubmit: function(event) { event.preventDefault(); console.log(this.state.questions); this.firebaseRef = firebase.database().ref('quizzes'); this.firebaseRef.push({ question: this.state.questions }); this.refs.form.reset(); this.setState({ question: [{ qtext : "", options:[], id: 0, answer: ""}, {qtext: "", options:[], id: 1, answer: ""}] }); }, render: function() { {this.state.questions.map((question, index) => { <Question {...this.props} key={index} index={index} question={question} /> console.log(question); } )}; return ( <form className="quiz-form" onSubmit={this.handleSubmit} ref="form"> <Question /> <button type="button" className="add-question" onClick= {this.addQuestion} disabled={this.state.questions.length === 5}>{this.state.questions.length < 5 ? 'Add another question' : 'Question limit reached!'}</button> <button type="submit">Create Quiz</button> </form> ); } }); export default QuizBuilderForm; 项词典中解析,而不是点击数据库。

另一种可让您在所有3个应用中进行身份验证的Auth解决方案是使用无状态distributed Caching Providers