3

データベースから国際化された json コンテンツ項目を読み取り、API URL の要求を介してそれらを渡すように、Spring、Hibernate、および Wicket アプリケーションをセットアップしました。データの送信を担当するコードベースは、エンタープライズ クライアント向けに開発された Web サイト構造全体の小さな部分です。

API は 90% 以上のケースで正常に機能しますが、クライアントは孤立した休止状態セッションに起因する可能性がある興味深い時折の問題を経験しています。リクエストは php スクリプト経由で失敗し、次のエラーが表示されます。

Warning: file_get_contents( http://client.net/api/attachment_lines?ce=false&language=en&region=na&ts=1341592326) [function.file-get-contents]: failed to open stream: Redirection limit reached, aborting in client_api->send_request() (line 38 of <sitepath>/api.class.php).

また、Tomcat サーバー ログに次のエラーが生成されます。

09:15:00,200 ERROR [RequestCycle] failed to lazily initialize a collection of role: com.client.data.AttachmentLineCode.attachmentSublineCodes, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.client.data.AttachmentLineCode.attachmentSublineCodes, no session or session was closed

アプリケーションは、Spring 内で OpenSessionInViewFilter および @Transactional アノテーション デザイン パターンを使用するように構成されているため、断続的な要求の失敗の原因がわかりません。これに加えて、クライアントは、API が問題の後約 15 分間失敗し続けると述べています。web.xml 内で、フィルターの宣言を次に示します。

<filter>
    <filter-name>openEntityManagerInView</filter-name>
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>openEntityManagerInView</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

コード内では、コンテンツ アイテム DAO によって拡張された汎用 DAO のトランザクション アノテーションを次に示します。

@Transactional(noRollbackFor={javax.persistence.EntityNotFoundException.class, org.springframework.orm.ObjectRetrievalFailureException.class})
public class GenericDaoHibernate<T, PK extends Serializable> implements GenericDao<T, PK> {
    @Autowired
    private SessionFactory sessionFactory;

一般的な DAO 内でも、セッションを取得して使用する場所は次のとおりです。

protected Session getSession() {
    return sessionFactory.getCurrentSession();
}

protected Criteria createCacheableCriteria(Class<T> clazz) {
    Criteria criteria = createNonCacheableCriteria(clazz);
    criteria.setCacheable(true);
    criteria.setCacheMode(CacheMode.NORMAL);
    return criteria;
}

protected Criteria createCacheableCriteria(Class<?> clazz, String alias) {
    Criteria criteria = createNonCacheableCriteria(clazz, alias);
    criteria.setCacheable(true);
    criteria.setCacheMode(CacheMode.NORMAL);
    return criteria;
}

protected Criteria createNonCacheableCriteria(Class<?> clazz) {
    Session session = getSession();
    Criteria criteria = session.createCriteria(clazz);
    criteria.setCacheable(false);
    criteria.setCacheMode(CacheMode.IGNORE);
    return criteria;
}

protected Criteria createNonCacheableCriteria(Class<?> clazz, String alias) {
    Session session = getSession();
    Criteria criteria = session.createCriteria(clazz, alias);
    criteria.setCacheable(false);
    criteria.setCacheMode(CacheMode.IGNORE);
    return criteria;
}

このセットアップでセッションが孤立する可能性がある方法はありますか? この問題を引き起こしている可能性のあるセッションを休止状態にするための組み込みのタイムアウトはありますか? おそらくキャッシングに問題がありますか?よろしくお願いします。

4

1 に答える 1

1

ここでの解決策は、Hibernate や Spring とは何の関係もありません。本番環境と開発/ステージングの違いに注意しなかった私の誤りにのみ存在します。本番環境では、スティッキー セッションを使用せずに複雑な負荷分散戦略を実装しました。

Wicket の Request/Response サイクルには、POST に続くバッファリングされた応答のキャッシュが含まれていることがわかりました。その応答を取得するために戻ってくる対応する GET は、ときどき 302 をスローします。これは、ロード バランシングがキャッシュされた応答なしで要求をサーバーに転送し、プロキシ オブジェクトが忘れ去られるためです。これを解決するために実装することを選択した関連コードは、init() の下の Application.java 内に配置されます。

public class ClientApplication extends SpringWebApplication {  
    ... 
    public void init() {
        ...
        getRequestCycleSettings().setRenderStrategy(IRequestCycleSettings.ONE_PASS_RENDER);

これにより、応答をバッファしないように Wicket のレンダリング戦略の構成が変更されます。その結果、従来の「更新の二重送信」の問題が発生するという問題が発生します。結果として、これは必ずしも理想的なソリューションではありませんが、クライアントはスティッキー セッション対応のロード バランシングを使用したくなく、二重送信の問題を気にしませんでした。

この問題の詳細と、より雄弁で構造化された回答については、http: //blog.comsysto.com/2011/04/08/lost-in-redirection-with-apache-wicket/を参照してください。

于 2012-08-06T17:03:07.623 に答える