繁体   English   中英

Spring 引导 - 多租户 - 优化 API 的响应时间

[英]Spring Boot - Multitenancy - Optimise response time for API

我有一个 spring 启动应用程序,它实现了多模式多租户。 在没有多租户的情况下,同样的 API 响应时间为 300-400 毫秒。 但在实施多租户后,响应时间增加到 6-7 秒(在同一服务器和同一架构上)。

我知道读取header,切换数据库基于header等需要额外的处理。但我觉得应该不是6-7秒。 有人可以建议我如何减少此响应时间。 以下是为多租户添加的类

public class TenantAwareRoutingSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return ThreadLocalStorage.getTenantName();
    }
}
public class TenantNameInterceptor extends HandlerInterceptorAdapter {
    
    @Value("${schemas.list}")
    private String schemasList;
    private Gson gson = new Gson();
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String tenantName = request.getHeader("tenant-id");
        if(StringUtils.isBlank(schemasList)) {
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().write(gson.toJson(new Error("Tenants not initalized...")));
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            return false;
        }
        
        if(!schemasList.contains(tenantName)) {
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().write(gson.toJson(new Error("User not allowed to access data")));
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            return false;
        }
        ThreadLocalStorage.setTenantName(tenantName);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        ThreadLocalStorage.setTenantName(null);
    }
    
    @Setter
    @Getter
    @AllArgsConstructor
    public static class Error {
        private String message;
    }
}
public class ThreadLocalStorage {
    private static ThreadLocal<String> tenant = new ThreadLocal<>();

    public static void setTenantName(String tenantName) {
        tenant.set(tenantName);
    }

    public static String getTenantName() {
        return tenant.get();
    }
}
@Configuration
public class AutoDDLConfig
{

    @Value("${spring.datasource.username}")
    private String username;

    @Value("${spring.datasource.password}")
    private String password;

    @Value("${schemas.list}")
    private String schemasList;

    @Value("${db.host}")
    private String dbHost;

    @Bean
    public DataSource dataSource()
    {
        AbstractRoutingDataSource multiDataSource = new TenantAwareRoutingSource();
        if (StringUtils.isBlank(schemasList))
        {
            return multiDataSource;
        }

        String[] tenants = schemasList.split(",");
        Map<Object, Object> targetDataSources = new HashMap<>();
        for (String tenant : tenants)
        {
            System.out.println("####" + tenant);
            tenant = tenant.trim();
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName("com.mysql.jdbc.Driver"); // Change here to MySql Driver
            dataSource.setSchema(tenant);
            dataSource.setUrl("jdbc:mysql://" + dbHost + "/" + tenant
                    + "?autoReconnect=true&characterEncoding=utf8&useSSL=false&useTimezone=true&serverTimezone=Asia/Kolkata&useLegacyDatetimeCode=false&allowPublicKeyRetrieval=true");
            dataSource.setUsername(username);
            dataSource.setPassword(password);
            targetDataSources.put(tenant, dataSource);
            LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
            emfBean.setDataSource(dataSource);
            emfBean.setPackagesToScan("com"); // Here mention JPA entity path / u can leave it scans all packages
            emfBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
            emfBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
            Map<String, Object> properties = new HashMap<>();

            properties.put("hibernate.hbm2ddl.auto", "update");
            properties.put("hibernate.default_schema", tenant);
            properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
            emfBean.setJpaPropertyMap(properties);
            emfBean.setPersistenceUnitName(dataSource.toString());
            emfBean.afterPropertiesSet();
        }
        multiDataSource.setTargetDataSources(targetDataSources);
        multiDataSource.afterPropertiesSet();
        return multiDataSource;

    }

}

来自 application.properties 的片段

spring.datasource.username=<<username>>
spring.datasource.password=<<pssword>>


schemas.list=suncitynx,kalpavrish,riddhisiddhi,smartcity,businesspark
db.host=localhost


########## JPA Config ###############
spring.jpa.open-in-view=false
spring.jpa.show-sql=false
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.database=mysql
spring.datasource.initialize=false
spring.jpa.hibernate.ddl-auto=none
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.properties.hibernate.jdbc.time_zone = Asia/Kolkata
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect

##############Debug Logging#########################
#logging.level.org.springframework=DEBUG
#logging.level.org.hibernate.SQL=DEBUG
#logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE


#########    HIkari  Pool ##############
spring.datasource.hikari.maximum-pool-size=20

######### Jackson ############
spring.jackson.serialization.WRITE_ENUMS_USING_TO_STRING=true
spring.jackson.deserialization.READ_ENUMS_USING_TO_STRING=true
spring.jackson.time-zone: Asia/Kolkata


#common request logger
logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG

#Multi part file size
spring.servlet.multipart.max-file-size = 15MB
spring.servlet.multipart.max-request-size = 15MB

您确定维护每个租户的连接池吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM