13.09.19 — 14:39
Сервер 1С находится на одном сервере, пользователи подключаются с другого сервера по тонкому клиенту.
Столкнулись с проблемой: после какого-то кол-ва пользователей зашедших в базу, новых перестает пускать — просто падает платформа. Началось внезапно, ничего не меняли, ни конфигурацию, ни платформу, ни сервер. На текущей платформе проработали больше месяца нормально. Через технологический журнал на клиенте выцепил ошибку, с которой падает платформа «Обычно разрешается одно использование адреса сокета (протокол/сетевой адрес/порт)». Ошибку это возвращает платформе винда, везде пишут, что проблема в том, что не хватает динамических портов, которые можно расширить через реестр, но это не помогло.
Через netstat -ano на сервере удаленных рабочих столов, откуда подключаются пользователи видно, что заняты все порты с 1560 по 1591 тонким клиентом. Но многие клиенты сидят на рандомных портах типа 45434. Заметили, что новые пользователи не могут зайти в базу, когда все порты 1560-1591 заняты. Если убить любого тонкого клиента, который занимает порт в этом диапазоне и порт освобождается, то новый пользователь может зайти в базу.
Так же, когда все эти порты заняты, не получается запустить отладку из конфигуратора, ругается на «Для выполнения отладки необходимо включить поддержку сетевого протокола TCP/IP» — что тоже описано в инете как проблема занятых портов.
Не понятно, зачем тонкому клиенту на сервере удаленных рабочих столов занимать эти порты, ведь используются они сервером 1С для рабочих процессов. И почему когда свободных портов нет на РДП сервере, клиент не может подключиться к серверу 1С. Но часть клиентов спокойно висят на рандомных портах типа 45434. Такое ощущение, что при коннекте, клиент все таки занимает какой-то из портов в этом диапазоне, а после этого его перекидывает на любой свободный до 65535, но эти порты из диапазона 1560-1591 не успевают освободиться.
Объясните, по какому принципу клиент занимает порты и можно ли это как-то где-то настроить? То, что происходит в описанной ситуации это какой-то сбой либо некорректная настройка и достаточно в настройках службы 1С указать бОльший пул портов? Но никогда не слышал, чтобы в базах, где работает большое кол-во пользователей, увеличивали диапазон портов для рабочих процессов на сервере 1С.
1 — 13.09.19 — 14:57
В первый раз появилось на платформе 8.3.14.1854, после этого откатились на 8.3.12.1685, на которой были несколько месяцев, ситуация не изменилась.
2 — 13.09.19 — 15:53
вам хватит на 1 локальный порт 1561 всех подключить
сбрасывайте настройки в дефолт, переустанавливайте платформу.
3 — 13.09.19 — 16:03
(2) Так какие настройки? На РДП сервере стоит только тонкий клиент, какие и где там настройки можно сбросить?
4 — 13.09.19 — 16:05
https://its.1c.ru/db/metod8dev#content:5908:hdoc
6. Необходимо настроить сетевой стек для обеспечения возможности обработки большого числа подключений
Настройки, которые необходимо выполнить (в дополнение к настройке 5.2. Настроить рабочий сервер в соответствии с инструкцией):
Запустить regedit и в ветке HKLMSystemCurrentControlSetServicesTcpipParameters указать
MaxFreeTcbs= 100000
TcpTimedWaitDelay= 30
MaxUserPort= 65535
Запустить regedit и в ветке HKLMSystemCurrentControlSetServicesAFDParameters указать
EnableDynamicBacklog= 1
MinimumDynamicBacklog= 20
MaximumDynamicBacklog= 20000
DynamicBacklogGrowthDelta= 10
Устанавливаем диапазон исходящих портов (1025; 65535)
Выполнить: netsh int ipv4 set dynamic port tcp start=1025 num=64510
Выполнить: netsh int ipv4 set dynamic port udp start=1025 num=64510
5 — 13.09.19 — 16:16
(4) Все эти настройки сделаны, это все как раз гуглится по ошибке «Обычно разрешается одно использование адреса сокета (протокол/сетевой адрес/порт)». Но легче не стало вообще. Да и 80 пользователей не так много.
6 — 13.09.19 — 16:17
Проблема в том, что тонкий клиент почему-то занимает 1560-1591 порты на рдп сервере (не на 1С сервере) и из-за этого не могут подключаться новые клиенты. Так как если через netstat выбрать клиента, который занял 1560 порт, завершить его, то другой пользователь сможет зайти.
7 — 13.09.19 — 16:19
кто-то подкрутил параметр количество соединений на процесс?
8 — 13.09.19 — 16:19
сколько rphost на сервере?
9 — 13.09.19 — 16:27
(7) Вроде никто ничего не крутил. Сейчас стоит 128.
(8) 1.
10 — 13.09.19 — 17:59
режим отладки при запуске клиента?
11 — 13.09.19 — 18:43
(10) О, интересная мысль, надо будет проверить. Вообще запускается все без отладки, но вдруг каким-то образом она включается…
12 — 13.09.19 — 18:46
(10) (11) Во блин, точно! На одном из клиентов, который занял 1562 порт запущена отладка. Каким образом она могла включиться сама то?
13 — 16.09.19 — 11:25
Нашел в чем была причина, очень все нетривиально оказалось ) У нас в одном документе добавлено очень много доп.реквизитов, а чтобы они не подряд располагались на форме, была изменена форма в пользовательском режиме, красиво и по группам расположили доп.реквизиты.
Чтобы эта настройка применилась у всех, копировали все настройки эталонного пользователя другим пользователям. Видимо, в момент копирования настроек эталонного пользователя, у него была включена отладка, которая так и прилетела всем. Ну и в какой-то момент пользователей просто стало слишком много и проблема проявилась.
P_Mis
14 — 16.09.19 — 11:28
(13) Соответственно решение это в личных настройках пользователей очистить настройку из закладки Прочие настройки — Прочие настройки. Ну и переписать копирование настроек, если это делается автоматом.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using UnityEngine; class StateObject { public Socket workSocket = null; //сокет клиента public const int bufferSize = 1024; //максимальные размер буфера public byte[] buffer = new byte[bufferSize]; //буфер public StringBuilder sb = new StringBuilder(); //полученные данные в виде строки } //Все, что поступает на сервер, обрабатывается и в зависимости от принятого, делаются те или иные действия. //Для удобства написания кода, вынесем всю логику работы с клиентом в отдельный класс. public class ServerHandler { private Socket client_socket; // сокет клиента private Thread thread_for_check; // поток для проверки состояния подключения // конструктор public ServerHandler(Socket client_socket) { this.client_socket = client_socket; // запуск потока проверки состояния подключения this.thread_for_check = new System.Threading.Thread(CheckConnection); this.thread_for_check.Start(); } //будет инициализировать новый экземпляр класса StateObject и вызывать асинхронную операцию приема данных BeginReceive() private void Receive() { try { StateObject state = new StateObject(); state.workSocket = this.client_socket; //BeginReceive() принимает следующие аргументы: буфер (он же массив байт), смещение, размер буфера, флаг сокета(используется для различных режимов приема данных, мы не будем использовать какой-либо из них, так как нет в этом необходимости), метод для завершения операции и объект для хранения данных. state.workSocket.BeginReceive(state.buffer, 0, StateObject.bufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallBack), state); } //что должен делать сервер при отключении от него клиента. Тут два варианта развития событий: первый, клиент вышел корректно, через Disconnect; второе, при отправке или приеме сообщения на стороне сервера произошла ошибка. catch (SocketException) { Disconnect(); } } // метод завершения операции приема. В нем будет происходить извлечение класса StateObject, проверка на количество принятых байт, конвертирование байт в строку, вывод принятых данных и повторный вызов метода Receive(). private void ReceiveCallBack(IAsyncResult ar) { try { string cmd = String.Empty; //создается пустая строка, для хранения принятых данных. StateObject state = ar.AsyncState as StateObject; // инициализируется новый экземпляр класса StateObject из переменной ar. Socket handler = state.workSocket; // Теперь нам надо создать сокет, который в дальнейшем завершит операцию. if (handler.Connected) { //количество принятых байт int bytes = handler.EndReceive(ar); // Когда мы вызываем метод EndReceive(ar) в качестве возвращаемого аргумента, мы получаем количество принятых байт, поэтому мы сохраняем это количество в переменную bytes. if (bytes > 0) // Далее надо проверить, сколько байт мы получили, если их количество равно нулю, то вызываем повторно метод BeginReceive(), передаем те же переменные, что в методе Receive(). { //сохраняем принятые данных в классе state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, bytes)); cmd = Encoding.UTF8.GetString(state.buffer, 0, bytes); if (!String.IsNullOrEmpty(cmd)) // Если все нормально, то есть количество принятых байт больше нуля, то сохраняем эти байты, перекодировав байты в строку. Перекодировкой занимается метод GetString(). Но прежде чем к нему перейти, надо выбирать вид кодировки. Я использовал UTF-8, так как нам пригодятся русские буквы. Чтобы получить строку методу нужно передать буфер, смещение и длину буфера. Все эти данные достаются из класса StateObject, за исключение последнего. Количество принятых данных мы получаем после завершения операции, поэтому передаем то количество, которое сохранили в переменную bytes. { Debug.Log("Receive: " + cmd); Send(cmd); // пере-отправка сообщения } else //если приняли пустую строку, то принимаем дальше { handler.BeginReceive(state.buffer, 0, StateObject.bufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallBack), state); } } } } catch (Exception) { Debug.Log("Error"); } } ///////////////////////////////////////////////////////////////////////// //Этот метод будет вызывать метод Receive. public void StartReceiver() { Receive(); } // отправитель сообщений private void Send(string msg) { try { Socket socket = this.client_socket; byte[] buffer = Encoding.UTF8.GetBytes(msg); socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(SendCallBack), socket); } //что должен делать сервер при отключении от него клиента. Тут два варианта развития событий: первый, клиент вышел корректно, через Disconnect; второе, при отправке или приеме сообщения на стороне сервера произошла ошибка. catch (SocketException) { Disconnect(); } } // метод завершения операции отправки сообщений private void SendCallBack(IAsyncResult ar) { Socket handler = ar.AsyncState as Socket; handler.EndSend(ar); //после завершения операции отправки, добавим вызов метода Receive, чтобы сервер продолжал принимать данные. //продолжить прием данных Receive(); } ///////////////////////////////////////////////////////////////////////// // При возникновении какой-либо ошибки, следует отключать клиента, так как нам не нужен висящий в списке «ошибочный клиент». С таким клиентом сервер не будет работать, поэтому лучше, чтобы клиент пере зашёл. // Чтобы отключить клиента, надо вызвать метод Shutdown, указав в аргументе отключения для отправки и приема сообщений. Далее в блоке finally разрешить существующее соединение между клиентом и сервером, вызвав метод Close. public void Disconnect() { Debug.Log("Client disconnected"); try { this.thread_for_check.Abort(); // Abort немедленно завершает поток. Это нужно из-за того, что метод CheckConnection никогда не закончится, так как в нем используется бесконечный цикл. this.client_socket.Shutdown(SocketShutdown.Both); } catch (Exception ex) { Debug.Log(ex.ToString()); } finally { this.client_socket.Close(); } } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // Осталась ситуация, когда клиент сам вызывает отключение. Это очень важный момент, так как ошибок мы при этом не получаем, а свойство сокета IsConnected не покажет вам реальное состояние // Мы же будем проверять состояние сокета, и смотреть на количество передаваемых байтов в сети. Начнем с написания метода, который возвращает нам состояние подключения. private bool IsConnected(Socket socket) { try { // Poll. Он принимает два параметра: первый – интервал в миллисекундах, второй – состояние сокета, либо чтение, либо запись. Так как наш сервер является пассивным, что значит, что он всегда слушает сокет методом Receive, более логично проверять, что состояние сокета доступно на чтение данных. // Available – оно показывает, сколько байт доступно для чтения. Как только наш сокет не может прочитать данные, либо данные вообще отсутствуют – мы делаем вывод, что соединение разорвано. return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0); } catch (SocketException) { return false; } } // Чтобы сильно не нагружать систему, добавим вызов бесконечного цикла, с интервалом в 5 секунд, запущенный в новом потоке. Нам метод будет просто вызывать метод IsConnected, и в случае false, будет отключать клиента. private void CheckConnection() { while (true) { System.Threading.Thread.Sleep(5000); if (!IsConnected(this.client_socket)) { Disconnect(); return; } } } } |
Полагаю, некоторые коллеги уже оказывались в ситуации, когда отладка внезапно пропадала, и различные «шаманские» методики (переустановка платформы, чистка локального кэша и прочее) результата не давали. Опишу свой опыт по выявлению и устранению причины.
Преамбула
Данная статья содержит основные моменты из моей публикации. Рассчитываю, что эта информация поможет оказавшимся в подобной ситуации решить проблему. Или хотя бы послужит примером диагностики в конкретной ситуации.
Начальное состояние
Периодические отваливается отладка. Основные подозреваемые — брандмауэр и антивирус выключены.
Анализ
Текущий порт отлачика tcp://srv1c:1562.
netstat -naot 1 | find «1562» при запуске сеанса отладки показывает наличие состояний SYN_SENT.
Настроен полный технологический журнал, поскольку заранее неизвестны события, содержащие необходимую информацию. Для сбора данных по клиентским сеансам моего пользователя файл настроек расположен в %UserProfile%AppDataLocal1C1cv8conf
<config xmlns="http://v8.1c.ru/v8/tech-log">
<log location="C:v8clientlogs" history="1">
<event>
<ne property="name" value=""/>
</event>
<property name="all">
</property>
</log>
</config>
Значимые события технологического журнала клиента, собранного с момента запуска сеанса отладки до момента прекращения появления состояний SYN_SENT:
30:25.862000-0,EXCP,1,process=1cv8,ClientID=0,Exception=NetDataExchangeException,Descr='server_addr=any:1560 descr=10048(0x00002740): Обычно разрешается только одно использование адреса сокета (протокол/сетевой адрес/порт). line=261 file=srcDataExchangeServerImpl.cpp'
30:25.862003-0,EXCP,1,process=1cv8,ClientID=0,Exception=NetDataExchangeException,Descr='server_addr=any:1561 descr=10048(0x00002740): Обычно разрешается только одно использование адреса сокета (протокол/сетевой адрес/порт). line=261 file=srcDataExchangeServerImpl.cpp'
30:25.862006-0,EXCP,1,process=1cv8,ClientID=0,Exception=NetDataExchangeException,Descr='server_addr=any:1562 descr=10048(0x00002740): Обычно разрешается только одно использование адреса сокета (протокол/сетевой адрес/порт). line=261 file=srcDataExchangeServerImpl.cpp'
30:30.199000-0,EXCP,3,process=1cv8,Usr=Админ,ClientID=3,Exception=NetDataExchangeException,Descr='server_addr=tcp://127.0.0.1:1562 descr=127.0.0.1:1562:10060(0x0000274C): Попытка установить соединение была безуспешной, т.к. от другого компьютера за требуемое время не получен нужный отклик, или было разорвано уже установленное соединение из-за неверного отклика уже подключенного компьютера. ;
line=1043 file=srcDataExchangeTcpClientImpl.cpp'
30:34.208000-0,EXCP,3,process=1cv8,Usr=Админ,ClientID=4,Exception=NetDataExchangeException,Descr='server_addr=tcp://127.0.0.1:1562 descr=127.0.0.1:1562:10060(0x0000274C): Попытка установить соединение была безуспешной, т.к. от другого компьютера за требуемое время не получен нужный отклик, или было разорвано уже установленное соединение из-за неверного отклика уже подключенного компьютера. ;
line=1043 file=srcDataExchangeTcpClientImpl.cpp'
Ошибка 10048(0x00002740) является причиной, 10060(0x0000274C) — следствие.
Настройка TCP протокола
MaxUserPort
При соединение по TCP/IP открывается сокет и выбирается динамический порт. По умолчанию, диапазон динамических портов от 1024 по 5000. Увеличиваем до максимума.
Key: HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTcpipParameters
Value: MaxUserPort
Data Type: REG_DWORD
Range: 5000 to 65534
Default value: 5000
Recommended value: 65534

TcpTimedWaitDelay
Когда соединение TCP закрывается, то сокет сразу не освобождается, а переходит в статус TIME_WAIT и ресурсы освободятся только через определённое время. По умолчанию, только через 4 минуты. Снизим это время до минимума — 30 секунд.
Key: HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTcpipParameters
Value: TcpTimedWaitDelay
Data Type: REG_DWORD
Range: 30 to 300
Default value: 240
Recommended value: 30

Отключение автотюнинга tcp протокола:
netsh int tcp set global autotuninglevel=disabled
Выполняем перезагрузку.
Результат
Мониторинг сервера в течении нескольких дней показал, что после проведенных изменений даже при большом количестве сессий 1С отладка перестала отваливаться.
-
-
January 15 2016, 17:30
- IT
- История
- Cancel
Доброго дня.
А есть среди нас спецы по 1С, в частности по настройке сервера приложений?
Столкнулся со странной ошибкой, которая дословно выглядит так:
«Ошибка загрузки сетевой инфраструктуры свободный порт из заданных диапазонов не найден»
Путем небольших исследований удалось вычислить, что проблема возникает при 32 одновременных сеансах 1С с одного терминального сервера.
т.е. 32 человека — работают норм, а 33-й и все последующие — получает вот такую ошибку.
Если пользователь который только-что получил эту ошибку зайдет на другой терминальный сервер — 1С запустится корректно.
Версия 1С: 8.3.7.1805 (последняя)
База — на сервере приложений (в качестве БД — MS SQL).
Параметры запуска сервера приложений — стандартные. Ничего специально не меняли, кроме одного параметра
«Количество ИБ на процесс = 1». (Но в любом случае это изменение было сделано уже после возникновения ошибки и на нее (на ошибку) не повлияло.)
База конечно самописная, на базе УТ, но программеры мамой клянутся, что ничего там такого не ставили, что мол все стандартное.
Это очень похоже на какие-то ограничения типа «принимать не более N сеансов с одного IP», но где порыться в 1С чтобы это увеличить — моя не понимать…
Облазил все настройки — не нахожу чего-то что могло помочь.
Помогите, а…
позязя.
UPD1: сделали тест: запустили на сервере терминалов другую базу много раз — запускается без вопросов. довели до 50 одновременных успешных запусков и пока успокоились.
на основной базе, которая нас интересует, проблема — сохраняется. Похоже что-то в самой базе не так, а не на сервере приложений…
Понимаю, что тем с таким заголовком уже уйма, но ответа я так и не увидел. А точнее — что делать в моем случае.
Итак, делаю сервер, который слушает локалку по указанному порту. За основу взял эту библиотеку — https://github.com/nterry/AwesomeSockets.
Вот так выглядит метод запуска прослушивания:
public async void StartListening(int port)
{
if (CancellationTokenSource == null)
CancellationTokenSource = new CancellationTokenSource();
_cancellationToken = CancellationTokenSource.Token;
Clients = new ObservableCollection<Client>();
BindingOperations.EnableCollectionSynchronization(Clients, _lockObject);
try
{
while (_tcpListen == null)
{
ShowCallbackMessageAction?.Invoke("Try to start server");
_tcpListen = AweSock.TcpListen(port);
if (_tcpListen != null)
{
ShowCallbackMessageAction?.Invoke("Server started");
var waitForConnectionTask = Task.Run(() => WaitForConnectionLoop(), _cancellationToken);
var checkClientsConnectionTask = Task.Run(() => CheckClientsConnectionLoop(), _cancellationToken);
await Task.WhenAll(waitForConnectionTask, checkClientsConnectionTask);
}
// https://stackoverflow.com/a/32768637/4944499
await Task.Delay(1000, _cancellationToken).ContinueWith(task => { });
}
}
catch (Exception exception)
{
ShowCallbackMessageAction?.Invoke($"Error on start server: {exception.Message}");
}
}
Вот так метод остановки прослушивания:
public void StopListening()
{
ShowCallbackMessageAction?.Invoke("Begin stop server...");
ShowCallbackMessageAction?.Invoke("Disconnect all clients");
DisconnectAllClients();
CancellationTokenSource?.Cancel();
_tcpListen?.Close();
_tcpListen = null;
ShowCallbackMessageAction?.Invoke("Server stopped");
}
Метод из библиотеки, вызываемый в моем методе StartListening:
public static ISocket TcpListen(int port, int backlog = 10)
{
var listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//var ip = new IPAddress(new byte[] { 0, 0, 0, 0 });
//var localEndPoint = new IPEndPoint(ip, port);
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, port);
listenSocket.Bind(localEndPoint);
listenSocket.Listen(backlog);
return AwesomeSocket.New(listenSocket);
}
Так вот — это все работает до того момента, пока я приложение свое не закрою без отписки от прослушивания. Т.е., например, случился крэш. После того, как я повторно запускаю сервер, то вижу сообщение:

Везде пишут, что это нормально и порт сам освободится через некоторое время (вроде 240 секунд), но в моем случае этого не происходит. Помогает только перезагрузка компа.
Как быть?
- Remove From My Forums
-
Общие обсуждения
-
Всем доброго дня,
Никак не получается забороть проблему со службой «Сервер политики сети». Она не стартует с ошибкой:
Служба «Сервер политики сети» завершена из-за ошибки
Обычно разрешается только одно использование адреса сокета (протокол/сетевой адрес/порт).Мне она нужна, чтобы служба Шлюза удаленных рабочих столов запустилась. До обновления сервера, которое было около месяца назад, служба работала.
Я проверял занятость портов 1813, 1646, 1812, 1645. Никто эти порты не занимает. Пробовал копировать папку C:windowssystem32ias с другого похожего сервера — ошибка та же.
Вот кое-что еще, что уже не помогло:
- netsh nps reset config
- переустановка службы
- HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesVSSVssAccessControl параметр NT AuthorityNetworkService со значением 1
- права на папку C:windowssystem32ias
В общем, застрял.
-
Изменен тип
20 сентября 2016 г. 7:30