[英]Spring Boot - Execute setter statements in parallel to optimise response time
[英]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.