5

Başlıkta belirtildiği gibi, aynı istemci aynı anda aynı istemciyle aynı istemciyi belirten iki işlemin eşzamanlı olarak son nokta noktasını sorguladığında sorunu yaşıyorum. zaman).Spring OAuth2: Ağır yük altında JdbcTokenStore ve DefaultTokenServices kullanıldığında DuplicateKeyException

yetkilendirme sunucusunun günlüklerinde mesajı aşağıdaki gibidir:

2016-12-05 19:08:03.313 INFO 31717 --- [nio-9999-exec-5] o.s.s.o.provider.endpoint.TokenEndpoint : Handling error: DuplicateKeyException, PreparedStatementCallback; SQL [insert into oauth_access_token (token_id, token, authentication_id, user_name, client_id, authentication, refresh_token) values (?, ?, ?, ?, ?, ?, ?)]; ERROR: duplicate key value violates unique constraint "oauth_access_token_pkey" 
     Detail: Key (authentication_id)=(4148f592d600ab61affc6fa90bcbf16f) already exists.; nested exception is org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "oauth_access_token_pkey" 
     Detail: Key (authentication_id)=(4148f592d600ab61affc6fa90bcbf16f) already exists. 

Böyle tabloyla PostgreSQL kullanıyorum:

CREATE TABLE oauth_access_token 
(
    token_id character varying(256), 
    token bytea, 
    authentication_id character varying(256) NOT NULL, 
    user_name character varying(256), 
    client_id character varying(256), 
    authentication bytea, 
    refresh_token character varying(256), 
    CONSTRAINT oauth_access_token_pkey PRIMARY KEY (authentication_id) 
) 

Ve başvurum benziyor:

@SpringBootApplication 
public class OAuthServTest { 
    public static void main (String[] args) { 
     SpringApplication.run (OAuthServTest.class, args); 
    } 

    @Configuration 
    @EnableAuthorizationServer 
    @EnableTransactionManagement 
    protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { 

     @Autowired 
     private AuthenticationManager authenticationManager; 

     @Autowired 
     private DataSource   dataSource; 

     @Bean 
     public PasswordEncoder passwordEncoder () { 
     return new BCryptPasswordEncoder (); 
     } 

     @Override 
     public void configure (AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 
     endpoints.authenticationManager (authenticationManager); 
     endpoints.tokenServices (tokenServices ()); 
     } 

     @Override 
     public void configure (ClientDetailsServiceConfigurer clients) throws Exception { 
     clients.jdbc (this.dataSource).passwordEncoder (passwordEncoder ()); 
     } 

     @Override 
     public void configure (AuthorizationServerSecurityConfigurer oauthServer) throws Exception { 
     oauthServer.passwordEncoder (passwordEncoder ()); 
     } 

     @Bean 
     public TokenStore tokenStore () { 
     return new JdbcTokenStore (this.dataSource); 
     } 

     @Bean 
     @Primary 
     public AuthorizationServerTokenServices tokenServices () { 
     final DefaultTokenServices defaultTokenServices = new DefaultTokenServices (); 
     defaultTokenServices.setTokenStore (tokenStore ()); 
     return defaultTokenServices; 
     } 

    } 
} 

Araştırmam beni her zaman this problem adresine yönlendiriyor. Ancak bu hata uzun zaman önce düzeltildi ve ben Spring Boot'un son sürümü (v1.4.2).

Tahminimce yanlış bir şey yapıyorum ve DefaultTokenServices numaralı etikette işlemin gerçekleşmesi gerçekleşmiyor.

cevap

1

Sorun, DefaultTokenServices adresindeki bir yarış koşuludur.

Bir geçici çözüm buldum. Muhteşem olduğunu söylemiyor ama işe yarıyor.

@Aspect 
@Component 
public class TokenEndpointRetryInterceptor { 

    private static final int MAX_RETRIES = 4; 

    @Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.*(..))") 
    public Object execute (ProceedingJoinPoint aJoinPoint) throws Throwable { 
    int tts = 1000; 
    for (int i=0; i<MAX_RETRIES; i++) { 
     try { 
     return aJoinPoint.proceed(); 
     } catch (DuplicateKeyException e) { 
     Thread.sleep(tts); 
     tts=tts*2; 
     } 
    } 
    throw new IllegalStateException("Could not execute: " + aJoinPoint.getSignature().getName()); 
    } 

} 
+0

sen açar mısınız: Fikir TokenEndpoint etrafında bir AOP Önerileri kullanarak yeniden deneme mantığı eklemektir? Aynı hatayı aldım, neden buna ihtiyacım var? Benim bahar önyükleme uygulamasında yok: 'Aspect ',' Around' ve 'ProceedingJoinPoint'. Aynı sorunu nasıl çözebilirim? – BigDong