use different WebDAV urls
This commit is contained in:
parent
c17be4426f
commit
58e5b4789e
8 changed files with 191 additions and 75 deletions
|
|
@ -3,6 +3,7 @@ package ervu.client.fileupload;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.Authenticator;
|
||||
import java.net.ConnectException;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.URI;
|
||||
import java.net.URLEncoder;
|
||||
|
|
@ -10,14 +11,26 @@ import java.net.http.HttpClient;
|
|||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import com.github.sardine.DavResource;
|
||||
import com.github.sardine.Sardine;
|
||||
import com.github.sardine.SardineFactory;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import ervu.model.webdav.Server;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
|
@ -38,21 +51,46 @@ import org.springframework.web.multipart.MultipartFile;
|
|||
public class WebDavClient {
|
||||
private static final Logger logger = LoggerFactory.getLogger(WebDavClient.class);
|
||||
|
||||
@Value("${file.webdav.upload.username}")
|
||||
@Value("${webdav.urls}")
|
||||
private String[] urls;
|
||||
@Value("${webdav.username}")
|
||||
private String username;
|
||||
@Value("${file.webdav.upload.password}")
|
||||
@Value("${webdav.password}")
|
||||
private String password;
|
||||
@Value("${webdav.bad_servers.cache.expire.seconds:120}")
|
||||
private long cacheExpireSec;
|
||||
|
||||
private List<Server> servers;
|
||||
private LoadingCache<String, String> badServersCache;
|
||||
private final AtomicInteger counter = new AtomicInteger(0);
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
CacheLoader<String, String> loader = new CacheLoader<>() {
|
||||
@Override
|
||||
public String load(String key) {
|
||||
return key;
|
||||
}
|
||||
};
|
||||
badServersCache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(cacheExpireSec, TimeUnit.SECONDS)
|
||||
.build(loader);
|
||||
logger.info("WebDAV urls: {}", Arrays.asList(urls));
|
||||
servers = Arrays.stream(urls)
|
||||
.map(url -> new Server(url, ZonedDateTime.now().toInstant().toEpochMilli()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Retryable(value = {IOException.class}, backoff = @Backoff(delayExpression = "${webdav.retry.delay:500}"))
|
||||
public boolean uploadFile(String url, MultipartFile multipartFile) {
|
||||
public String uploadFile(MultipartFile multipartFile) {
|
||||
String fileName = getNewFilename(multipartFile.getOriginalFilename());
|
||||
Sardine sardine = initClient(username, password);
|
||||
|
||||
try {
|
||||
sardine.put(url, multipartFile.getBytes());
|
||||
return sardine.exists(url);
|
||||
return putAndGetUrl(multipartFile.getBytes(), fileName, sardine);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException("Failed to put or check file in WebDAV", e);
|
||||
throw new RuntimeException("Failed to put file into WebDAV", e);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
|
|
@ -64,6 +102,60 @@ public class WebDavClient {
|
|||
}
|
||||
}
|
||||
|
||||
private String getNewFilename(String filename) {
|
||||
int lastIndexOf = filename.lastIndexOf(".");
|
||||
String fileExtension = lastIndexOf == -1 ? "" : filename.substring(lastIndexOf);
|
||||
return UUID.randomUUID() + fileExtension;
|
||||
}
|
||||
|
||||
public String putAndGetUrl(byte[] fileBytes, String fileName, Sardine client) throws IOException {
|
||||
if (badServersCache.size() == urls.length) {
|
||||
return null;
|
||||
}
|
||||
Server server;
|
||||
|
||||
if (urls.length == 1) {
|
||||
server = servers.get(0);
|
||||
}
|
||||
else {
|
||||
Predicate<Server> isNotBad = s -> badServersCache.getIfPresent(s.getUrl()) == null;
|
||||
server = servers.stream()
|
||||
.filter(isNotBad.and(s -> servers.indexOf(s) == index()))
|
||||
.findFirst()
|
||||
.orElseGet(() -> servers.stream()
|
||||
.filter(isNotBad)
|
||||
.min(Comparator.comparing(Server::getLastCallTime))
|
||||
.orElse(null));
|
||||
}
|
||||
|
||||
if (server == null) {
|
||||
return null;
|
||||
}
|
||||
boolean isBad = false;
|
||||
String serverUrl = server.getUrl();
|
||||
String fileUploadUrl = serverUrl + "/" + fileName;
|
||||
|
||||
try {
|
||||
client.put(fileUploadUrl, fileBytes);
|
||||
server.setLastCallTime(System.currentTimeMillis());
|
||||
}
|
||||
catch (ConnectException | ClientProtocolException ignore) {
|
||||
isBad = true;
|
||||
}
|
||||
|
||||
if (isBad) {
|
||||
badServersCache.getUnchecked(serverUrl);
|
||||
return putAndGetUrl(fileBytes, fileName, client);
|
||||
}
|
||||
|
||||
return fileUploadUrl;
|
||||
}
|
||||
|
||||
private int index() {
|
||||
counter.compareAndSet(Integer.MAX_VALUE, 0);
|
||||
return counter.getAndIncrement() % urls.length;
|
||||
}
|
||||
|
||||
@Retryable(value = {IOException.class, InterruptedException.class},
|
||||
backoff = @Backoff(delayExpression = "${webdav.retry.delay:500}"))
|
||||
public ResponseEntity<Resource> webDavDownloadFile(String url) {
|
||||
|
|
@ -109,8 +201,7 @@ public class WebDavClient {
|
|||
}
|
||||
|
||||
@Retryable(value = {IOException.class}, backoff = @Backoff(delayExpression = "${webdav.retry.delay:500}"))
|
||||
public void deleteFilesOlderThan(long seconds, String url, String username, String password,
|
||||
String... extensions) {
|
||||
public void deleteFilesOlderThan(long seconds, String url, String... extensions) throws IOException {
|
||||
Sardine sardine = initClient(username, password);
|
||||
|
||||
try {
|
||||
|
|
@ -124,14 +215,11 @@ public class WebDavClient {
|
|||
sardine.delete(url + davResource.getPath());
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException("Failed to delete file " + davResource.getName(), e);
|
||||
logger.error("Failed to delete file {}", davResource.getName(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException("Failed to delete old files from WebDAV", e);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
sardine.shutdown();
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
|||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import ru.micord.ervu.security.webbpm.jwt.UserIdsPair;
|
||||
import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil;
|
||||
|
||||
/**
|
||||
* @author Alexandr Shalaginov
|
||||
|
|
@ -28,12 +30,15 @@ public class EmployeeInfoFileUploadController {
|
|||
@RequestParam("file") MultipartFile multipartFile,
|
||||
@RequestHeader("X-Employee-Info-File-Form-Type") String formType,
|
||||
@RequestHeader("Client-Time-Zone") String clientTimeZone) {
|
||||
UserIdsPair userIdsPair = SecurityUtil.getUserIdsPair();
|
||||
|
||||
String offset = ZonedDateTime.now(TimeZone.getTimeZone(clientTimeZone).toZoneId())
|
||||
.getOffset().getId();
|
||||
if (userIdsPair != null) {
|
||||
String offset = ZonedDateTime.now(TimeZone.getTimeZone(clientTimeZone).toZoneId())
|
||||
.getOffset().getId();
|
||||
|
||||
if (this.fileUploadService.saveEmployeeInformationFile(multipartFile, formType, offset)) {
|
||||
return ResponseEntity.ok("File successfully uploaded.");
|
||||
if (this.fileUploadService.saveEmployeeInformationFile(multipartFile, formType, offset, userIdsPair)) {
|
||||
return ResponseEntity.ok("File successfully uploaded.");
|
||||
}
|
||||
}
|
||||
|
||||
return ResponseEntity.internalServerError().body("An error occurred while uploading file.");
|
||||
|
|
|
|||
27
backend/src/main/java/ervu/model/webdav/Server.java
Normal file
27
backend/src/main/java/ervu/model/webdav/Server.java
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
package ervu.model.webdav;
|
||||
|
||||
/**
|
||||
* @author gulnaz
|
||||
*/
|
||||
public class Server {
|
||||
|
||||
private final String url;
|
||||
private long lastCallTime;
|
||||
|
||||
public Server(String url, long lastCallTime) {
|
||||
this.url = url;
|
||||
this.lastCallTime = lastCallTime;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public long getLastCallTime() {
|
||||
return lastCallTime;
|
||||
}
|
||||
|
||||
public void setLastCallTime(long lastCallTime) {
|
||||
this.lastCallTime = lastCallTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,6 @@ import ru.micord.ervu.security.esia.model.PersonModel;
|
|||
import ru.micord.ervu.security.esia.service.UlDataService;
|
||||
import ru.micord.ervu.security.esia.token.EsiaTokensStore;
|
||||
import ru.micord.ervu.security.webbpm.jwt.UserIdsPair;
|
||||
import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil;
|
||||
import ru.micord.ervu.service.InteractionService;
|
||||
|
||||
import static ervu.enums.FileStatusCode.FILE_CLEAN;
|
||||
|
|
@ -61,8 +60,6 @@ public class EmployeeInfoFileUploadService {
|
|||
|
||||
@Value("${av.kafka.message.topic.name}")
|
||||
private String kafkaTopicName;
|
||||
@Value("${file.webdav.upload.url:http://localhost:5757}")
|
||||
private String url;
|
||||
|
||||
public EmployeeInfoFileUploadService(
|
||||
WebDavClient webDavClient,
|
||||
|
|
@ -78,29 +75,32 @@ public class EmployeeInfoFileUploadService {
|
|||
}
|
||||
|
||||
public boolean saveEmployeeInformationFile(MultipartFile multipartFile, String formType,
|
||||
String offset) {
|
||||
String offset, UserIdsPair userIdsPair) {
|
||||
|
||||
if (!isValid(multipartFile)) {
|
||||
return false;
|
||||
}
|
||||
String fileUploadUrl = this.url + "/" + getNewFilename(multipartFile.getOriginalFilename());
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String fileId = UUID.randomUUID().toString();
|
||||
String fileName = multipartFile.getOriginalFilename();
|
||||
EmployeeInfoFileFormType employeeInfoFileFormType = EmployeeInfoFileFormType.valueOf(formType);
|
||||
String esiaUserId = userIdsPair.getEsiaUserId();
|
||||
String ervuId = userIdsPair.getErvuId();
|
||||
String accessToken = EsiaTokensStore.getAccessToken(esiaUserId);
|
||||
EmployeeModel employeeModel = ulDataService.getEmployeeModel(accessToken);
|
||||
PersonModel personModel = employeeModel.getPerson();
|
||||
|
||||
if (this.webDavClient.uploadFile(fileUploadUrl, multipartFile)) {
|
||||
FileStatus fileStatus = new FileStatus();
|
||||
fileStatus.setStatus("Загрузка");
|
||||
String fileUploadUrl = this.webDavClient.uploadFile(multipartFile);
|
||||
FileStatus fileStatus = new FileStatus();
|
||||
fileStatus.setStatus(fileUploadUrl == null ? "Невозможно проверить файл ЛК РП" : "Загрузка");
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
interactionService.setStatus(fileId, fileStatus.getStatus(), fileName,
|
||||
employeeInfoFileFormType.getFilePatternCode(), Timestamp.valueOf(now),
|
||||
convertToFio(personModel.getFirstName(), personModel.getMiddleName(), personModel.getLastName()),
|
||||
ervuId);
|
||||
|
||||
if (fileUploadUrl != null) {
|
||||
fileStatus.setCode(FILE_UPLOADED.getCode());
|
||||
fileStatus.setDescription("Файл принят до проверки на вирусы");
|
||||
String fileId = UUID.randomUUID().toString();
|
||||
String fileName = multipartFile.getOriginalFilename();
|
||||
EmployeeInfoFileFormType employeeInfoFileFormType = EmployeeInfoFileFormType.valueOf(
|
||||
formType);
|
||||
UserIdsPair userIdsPair = SecurityUtil.getUserIdsPair();
|
||||
String esiaUserId = userIdsPair.getEsiaUserId();
|
||||
String ervuId = userIdsPair.getErvuId();
|
||||
String accessToken = EsiaTokensStore.getAccessToken(esiaUserId);
|
||||
EmployeeModel employeeModel = ulDataService.getEmployeeModel(accessToken);
|
||||
PersonModel personModel = employeeModel.getPerson();
|
||||
String departureDateTime = now.format(DateTimeFormatter.ofPattern(FORMAT));
|
||||
String jsonMessage = getJsonKafkaMessage(
|
||||
employeeInfoKafkaMessageService.getKafkaMessage(
|
||||
|
|
@ -117,17 +117,10 @@ public class EmployeeInfoFileUploadService {
|
|||
personModel
|
||||
)
|
||||
);
|
||||
interactionService.setStatus(fileId, fileStatus.getStatus(), fileName,
|
||||
employeeInfoFileFormType.getFilePatternCode(), Timestamp.valueOf(now),
|
||||
convertToFio(personModel.getFirstName(), personModel.getMiddleName(),
|
||||
personModel.getLastName()
|
||||
),
|
||||
ervuId
|
||||
);
|
||||
return sendMessage(jsonMessage);
|
||||
}
|
||||
else {
|
||||
logger.error("Fail upload file: {}", multipartFile.getOriginalFilename());
|
||||
logger.error("Failed to upload file: {}", fileName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -172,27 +165,15 @@ public class EmployeeInfoFileUploadService {
|
|||
|
||||
try {
|
||||
this.kafkaTemplate.send(record).get();
|
||||
logger.debug("Success send record: {}", record);
|
||||
logger.debug("Successfully sent record: {}", record);
|
||||
return true;
|
||||
}
|
||||
catch (Exception exception) {
|
||||
logger.error("Fail send message.", exception);
|
||||
logger.error("Failed to send message", exception);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private String getNewFilename(String oldFilename) {
|
||||
return UUID.randomUUID() + getFileExtension(oldFilename);
|
||||
}
|
||||
|
||||
private String getFileExtension(String filename) {
|
||||
int lastIndexOf = filename.lastIndexOf(".");
|
||||
if (lastIndexOf == -1) {
|
||||
return "";
|
||||
}
|
||||
return filename.substring(lastIndexOf);
|
||||
}
|
||||
|
||||
private String getJsonKafkaMessage(EmployeeInfoKafkaMessage employeeInfoKafkaMessage) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
package ervu.service.scheduler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import ervu.client.fileupload.WebDavClient;
|
||||
import net.javacrumbs.shedlock.core.SchedulerLock;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
|
@ -11,15 +16,11 @@ import org.springframework.stereotype.Service;
|
|||
*/
|
||||
@Service
|
||||
public class WebDavSchedulerService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(WebDavSchedulerService.class);
|
||||
private final WebDavClient webDavClient;
|
||||
|
||||
@Value("${file.webdav.upload.url}")
|
||||
private String url;
|
||||
@Value("${file.webdav.upload.username}")
|
||||
private String username;
|
||||
@Value("${file.webdav.upload.password}")
|
||||
private String password;
|
||||
@Value("${webdav.urls}")
|
||||
private String[] urls;
|
||||
@Value("${file.webdav.lifetime.seconds:300}")
|
||||
private long fileLifetime;
|
||||
@Value("${file.webdav.extensions:}")
|
||||
|
|
@ -30,8 +31,15 @@ public class WebDavSchedulerService {
|
|||
}
|
||||
|
||||
@Scheduled(cron = "${webdav.cleanup.cron:0 0 0 * * *}")
|
||||
@SchedulerLock
|
||||
@SchedulerLock(name = "webDavOldFilesCleaning")
|
||||
public void deleteOldFiles() {
|
||||
webDavClient.deleteFilesOlderThan(fileLifetime, url, username, password, fileExtensions);
|
||||
Arrays.stream(urls).forEach(url -> {
|
||||
try {
|
||||
webDavClient.deleteFilesOlderThan(fileLifetime, url, fileExtensions);
|
||||
}
|
||||
catch (IOException e) {
|
||||
logger.error("Failed to clean up WebDAV on {}", url, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
11
config.md
11
config.md
|
|
@ -790,9 +790,14 @@ JBPM использует 3 корневых категории логирова
|
|||
- `ERVU_FILE_UPLOAD_MAX_FILE_SIZE` - определяет максимальный размер загружаемого файла в байтах. Указывает предел размера для каждого индивидуального файла, который может быть загружен. Если файл превышает этот размер, загрузка будет прервана, и может быть вызвано исключение.
|
||||
- `ERVU_FILE_UPLOAD_MAX_REQUEST_SIZE` - устанавливает максимальный общий размер всех файлов в одном многозадачном запросе в байтах. Это ограничение на весь запрос, включающий данные и файлы. Если общий размер запроса превышает этот параметр, загрузка файлов будет остановлена.
|
||||
- `ERVU_FILE_UPLOAD_FILE_SIZE_THRESHOLD` - указывает размер (в байтах), при достижении которого файл будет записан во временное хранилище на диск. Это позволяет улучшить производительность, исключая непосредственную запись мелких файлов на диск, если они не превышают указанного порога. Файлы, меньшие этого значения, могут быть сохранены в памяти.
|
||||
- `FILE_WEBDAV_UPLOAD_URL` - url для подключения к WebDav
|
||||
- `FILE_WEBDAV_UPLOAD_USERNAME` - логин пользователя для подключения к WebDav
|
||||
- `FILE_WEBDAV_UPLOAD_PASSWORD` - пароль пользователя для подключения к WebDav
|
||||
- `WEBDAV_URLS` - список url для подключения к WebDav
|
||||
- `WEBDAV_USERNAME` - логин пользователя для подключения к WebDav
|
||||
- `WEBDAV_PASSWORD` - пароль пользователя для подключения к WebDav
|
||||
- `WEBDAV_BAD_SERVERS_CACHE_EXPIRE_SECONDS` - время жизни кэша адресов недоступных серверов WebDav (секунды)
|
||||
- `WEBDAV_CLEANUP_CRON` - крон по очистке WebDav
|
||||
- `WEBDAV_RETRY_DELAY` - количество попыток по операциям с файлами WebDav
|
||||
- `FILE_WEBDAV_LIFETIME_SECONDS` - время жизни файла в WebDav (секунды)
|
||||
- `FILE_WEBDAV_EXTENSIONS` - список расширений файлов, удаляемых с WebDav
|
||||
- `AV_KAFKA_BOOTSTRAP_SERVERS` - список пар хост:порт, использующихся для установки первоначального соединения с кластером Kafka
|
||||
- `AV_KAFKA_SECURITY_PROTOCOL` - протокол, используемый для взаимодействия с брокерами
|
||||
- `AV_KAFKA_SASL_MECHANISM` - механизм SASL, используемый для клиентских подключений
|
||||
|
|
|
|||
|
|
@ -6,9 +6,6 @@ DB_APP_HOST=10.10.31.119
|
|||
DB_APP_PORT=5432
|
||||
DB_APP_NAME=ervu_lkrp_ul
|
||||
|
||||
FILE_WEBDAV_UPLOAD_URL=https://ervu-webdav.k8s.micord.ru
|
||||
FILE_WEBDAV_UPLOAD_USERNAME=test
|
||||
FILE_WEBDAV_UPLOAD_PASSWORD=test
|
||||
AV_KAFKA_MESSAGE_TOPIC_NAME=file-to-upload
|
||||
AV_KAFKA_BOOTSTRAP_SERVERS=http://10.10.31.11:32609
|
||||
AV_KAFKA_SECURITY_PROTOCOL=SASL_PLAINTEXT
|
||||
|
|
@ -52,6 +49,10 @@ ERVU_FILE_UPLOAD_FILE_SIZE_THRESHOLD=0
|
|||
ESIA_TOKEN_CLEAR_CRON=0 0 */1 * * *
|
||||
COOKIE_PATH=/ul
|
||||
|
||||
WEBDAV_URLS=https://ervu-webdav.k8s.micord.ru
|
||||
WEBDAV_USERNAME=test
|
||||
WEBDAV_PASSWORD=test
|
||||
WEBDAV_BAD_SERVERS_CACHE_EXPIRE_SECONDS=120
|
||||
WEBDAV_CLEANUP_CRON=0 0 0 * * *
|
||||
WEBDAV_RETRY_DELAY=500
|
||||
FILE_WEBDAV_LIFETIME_SECONDS=300
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@
|
|||
<property name="security.password.regex" value="^((?=(.*\d){1,})(?=.*[a-zа-яё])(?=.*[A-ZА-ЯЁ]).{8,})$"/>
|
||||
<property name="fias.enable" value="false"/>
|
||||
<property name="com.arjuna.ats.arjuna.allowMultipleLastResources" value="true"/>
|
||||
<property name="file.webdav.upload.url" value="https://ervu-webdav.k8s.micord.ru"/>
|
||||
<property name="file.webdav.upload.username" value="test"/>
|
||||
<property name="file.webdav.upload.password" value="test"/>
|
||||
<property name="webdav.urls" value="https://ervu-webdav.k8s.micord.ru"/>
|
||||
<property name="webdav.username" value="test"/>
|
||||
<property name="webdav.password" value="test"/>
|
||||
<property name="av.kafka.download-request-topic" value="ervu.lkrp.download.request"/>
|
||||
<property name="av.kafka.bootstrap.servers" value="localhost:9092"/>
|
||||
<property name="av.kafka.security.protocol" value="SASL_PLAINTEXT"/>
|
||||
|
|
@ -97,6 +97,7 @@
|
|||
<property name="webdav.retry.delay" value="500"/>
|
||||
<property name="file.webdav.lifetime.seconds" value="300"/>
|
||||
<property name="file.webdav.extensions" value="csv,xlsx"/>
|
||||
<property name="webdav.bad_servers.cache.expire.seconds" value="120"/>
|
||||
</system-properties>
|
||||
<management>
|
||||
<audit-log>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue