Транзакция CICS не равна HTTP-запросу
Транзакция CICS не равна HTTP-запросу. Как смоделировать состояние, COMMAREA, точки синхронизации и распределённый commit без поломки логики.

Самая опасная модернизация CICS выглядит очевидной. Команда находит код транзакции, заворачивает входные данные в JSON, назначает маршрут POST и считает границу понятой. На демонстрации экраны работают. Под настоящей нагрузкой появляются повторные отправки, устаревшее состояние, преждевременные commits и частично выполненные распределённые обновления.
Транзакция CICS представляет задачу с ресурсами под управлением CICS, правилами восстановления и точным моментом завершения. HTTP-запрос представляет транспортный обмен, в котором сервер может потерять клиента прежде, чем любая сторона поймёт результат. Оба способны передать одну бизнес-команду, но не задают одну единицу работы. Безопасная переработка сохраняет бизнес-автомат состояний и явно определяет границу commit, а не отдаёт её на усмотрение веб-фреймворка.
Семантику определяет граница задачи
Транзакция CICS начинается, когда CICS присоединяет задачу, и заканчивается, когда программа верхнего уровня возвращает управление или задача аварийно завершается. Задача может вызвать несколько программ через LINK или передать управление через XCTL. Такие вызовы не создают новых транзакций лишь из-за перехода между модулями. Идентификатор транзакции выбирает точку входа. Он не описывает метод запроса, ресурс или контракт ответа.
HTTP даёт другую оболочку. У запроса есть заголовки, тело, соединение и ответ, но протокол не знает, какие записи в базу образуют одно бизнес-действие. Сервер может выполнить commit до отправки ответа. Клиент может получить тайм-аут после commit и повторить запрос, не зная, завершилась ли операция. Прокси может повторить запрос, безопасность которого приложение не определило. Сам HTTP не связывает доставку ответа с долговечностью записей. У этих событий нет прямого аналога в модели задач CICS.
Поэтому первый вопрос проектирования касается не URL вместо четырёхсимвольного идентификатора. Нужно определить, какие восстанавливаемые изменения обязаны вместе завершиться или откатиться, какие данные запускают решение и какой долговечный факт подтверждает завершение. Только после этого маршрут сможет честно представлять команду.
Это различие предотвращает частую ошибку масштаба. Одно действие на экране может запустить задачу CICS, несколько связанных программ и обновления Db2 и восстанавливаемых ресурсов CICS. Разбиение каждой программы на сетевой сервис добавляет точки отказа внутрь единицы, которая раньше откатывалась целиком. Объединение нескольких псевдодиалоговых шагов в длинный HTTP-запрос создаёт обратную ошибку: работа остаётся открытой, пока человек думает.
Используйте старый граф вызовов как свидетельство, а не целевую архитектуру. Отметьте запуск задач, рёбра LINK и XCTL, изменения файлов и баз, исходящие сообщения, явные точки синхронизации и возвраты верхнего уровня. Границы восстанавливаемой работы редко совпадут с экранами или программами.
Псевдодиалог освобождает задачу между экранами
Псевдодиалоговое приложение выглядит для пользователя как сеанс, но выполняет последовательность коротких задач. Задача получает данные, восстанавливает нужный контекст, отправляет следующий экран, называет транзакцию для следующего ввода, передаёт данные продолжения и возвращается в CICS. Пока пользователь читает экран, задача приложения не ждёт ответа.
Документация IBM по CICS описывает эту схему как недиалоговые транзакции, встроенные в последовательность. Она экономит память и не удерживает эксклюзивные ресурсы, пока человек размышляет. Видимый диалог относится к пользовательскому интерфейсу, а не к непрерывной транзакции.
Упрощённое завершение программы COBOL часто выглядит так:
EXEC CICS SEND MAP('ACCT1') MAPSET('ACCT')
END-EXEC
EXEC CICS RETURN
TRANSID('AC02')
COMMAREA(WS-CONTINUATION)
LENGTH(WS-CONTINUATION-LEN)
END-EXEC
В обычном случае RETURN TRANSID не вызывает AC02 немедленно. Команда сообщает CICS, какая транзакция должна получить следующий ввод с терминала. Текущая задача заканчивается. Когда ввод приходит, CICS присоединяет новую задачу, а первая программа получает доступ к переданной COMMAREA. Эту роль может выполнить и channel.
Сопоставление всей последовательности с одним объектом HTTP-сеанса обычно скрывает две независимые сущности. У браузера есть состояние представления: текущая страница и редактируемые поля. У приложения есть состояние процесса: выбранный счёт, прочитанная версия, проверенные права и допустимые команды. Для второй категории нужна версионная запись на сервере или защищённый от подмены токен. Такая запись позволяет проверить конкурентное изменение до применения следующего решения пользователя. Карта сеансов в памяти процесса недостаточно долговечна и однозначна.
Современная граница должна представлять каждое решение пользователя короткой командой. GET может получить проекцию для экрана. POST может отправить решение для конкретной версии процесса. Транзакция базы не остаётся открытой, пока браузер ждёт. Такой подход сохраняет эксплуатационный смысл псевдодиалога, хотя транспорт устроен иначе.
COMMAREA задаёт продолжение, а не сеанс
COMMAREA представляет байтовый контракт между программами или последовательными задачами. Copybook придаёт байтам значение. В нём могут находиться код функции, идентификаторы, флаги, экранные поля, коды возврата и данные для следующей задачи. Там же бывает исторический мусор, который не читает ни одна активная ветвь. Название всей структуры состоянием сеанса подменяет анализ, необходимый для миграции.
В псевдодиалоге CICS сохраняет переданную COMMAREA для первой программы следующей задачи. IBM документирует важное ограничение: COMMAREA не относится к восстанавливаемым ресурсам. Если задача делает commit изменения базы, а затем готовит байты продолжения, эти байты не попадают в тот же восстанавливаемый ресурс только потому, что CICS передаёт их дальше.
Практическое ограничение размера тоже не позволяет считать COMMAREA хранилищем объектов. Документированный теоретический предел RETURN составляет около 32 КБ, причём IBM традиционно рекомендовала меньший безопасный размер. Channels и containers снимают ограничение одной COMMAREA и дают именованные отсеки, но не превращают продолжение в долговечную бизнес-истину.
При разборе разделите COMMAREA на три категории. Бизнес-идентичность включает стабильные значения: номер клиента, обращения или заказа. Управление процессом включает этап, код функции, предыдущее действие и оптимистическую версию. Остатки представления включают скопированные подписи, константы экрана, положение курсора и поля, которые можно запросить заново. Храните бизнес-состояние надёжно, явно моделируйте процесс и отбрасывайте представление, если от него не зависит наблюдаемое поведение.
Длина входит в контракт. Получающая программа COBOL часто проверяет EIBCALEN перед чтением DFHCOMMAREA; новые версии copybook могут добавлять поля в конец. Декодер JSON, требующий каждое новое поле, иногда менее совместим, чем старая программа. Зафиксируйте допустимые длины, правила инициализации, соглашения о пробелах и нулях, преобразование EBCDIC, packed decimal и ветви REDEFINES до проектирования типизированной замены.
Не сериализуйте copybook в огромный JSON под видом сохранения поведения. Так разметка памяти станет публичным API, клиент получит контроль над недопустимыми полями, а каждое изменение copybook затронет API. Преобразуйте байты в команду с названным намерением, а исходный ввод храните только в тестах и аудиторских свидетельствах, если политика это разрешает.
Точка синхронизации фиксирует работу, а не ответ
CICS подтверждает восстанавливаемые изменения в точке синхронизации. Приложение может выполнить EXEC CICS SYNCPOINT, а при нормальном завершении задачи верхнего уровня CICS создаёт неявную точку. Abend обычно запускает динамический backout изменений восстанавливаемых ресурсов текущей единицы работы. Этот цикл никак автоматически не связан с доставкой HTTP-ответа вызывающей стороне.
В обёртке последствие легко пропустить. Допустим, задача обновляет Db2, пишет в восстанавливаемую очередь, нормально возвращает управление, а шлюз теряет соединение до доставки ответа. CICS уже сделал commit. Клиент видит тайм-аут. Если замена считает его неудачей и повторяет команду без правила идемпотентности, бизнес-действие выполняется дважды.
Возможна и обратная ошибка. Веб-обработчик может записать 200 OK в буфер, а затем упасть, когда commit базы выполняется после возврата прикладного кода. Абстракции фреймворка представляют создание ответа как завершение, хотя долговечный результат ещё не появился. Замена должна считать успехом подтверждённый бизнес-результат и строить выдачу ответа вокруг него.
Найдите все явные точки синхронизации, а не считайте завершение задачи единственной. Явная точка закрывает текущую единицу работы и открывает новую, пока задача продолжается. Rollback отменяет изменения только после последней точки. Если программа в середине подтверждает строку аудита, а позже откатывает счёт, одна транзакция базы вокруг всего обработчика изменит видимое восстановление.
Невосстанавливаемые эффекты требуют отдельного подхода. Вызов внешнего сервиса, письмо в нетранзакционную систему или запись в невосстанавливаемое назначение не откатятся вместе с Db2. Старое приложение может полагаться на определённый порядок, контролируемые повторы или исправление оператором после частичного сбоя. Эти правила нужно сначала найти в программе и рабочих инструкциях, а затем перенести в явную модель восстановления. Сохраните наблюдаемый результат, а не удобную иллюзию контроля всех ресурсов одной языковой транзакцией.
Двухфазный commit не заменяется повторами
Двухфазный commit координирует восстанавливаемые менеджеры ресурсов в распределённой единице работы. В первой фазе участники готовятся и обещают выполнить решение. Во второй координатор приказывает подтвердить или откатить. При обрыве связи после подготовки участник может остаться в неопределённом состоянии до получения решения координатора. Эта неопределённость относится к состоянию протокола, а не к обычной ошибке приложения.
CICS умеет координировать распределённую работу между подходящими ресурсами и диалогами. В документации IBM указано, что распределённый процесс должен иметь одного инициатора точки синхронизации, а агенты могут согласиться или заставить всех откатиться. Recovery Manager журналирует достаточно состояния для повторной синхронизации после восстановления связи. Цепочка HTTP-вызовов сама этого не делает.
Замена распределённой единицы схемой сервис A вызывает B и повторяет при ошибке создаёт бесхозный разрыв. Если B подтвердил работу, а A потерял ответ, A не знает, повторять, компенсировать или сообщать успех. Повтор может удвоить эффект. Компенсация может отменить действие, которого не было. Ошибка может сообщить пользователю о неудаче уже завершённого действия.
Есть два честных варианта. Оставьте атомарную работу в одной транзакционной границе, если данные помещаются под одним менеджером. Если сервисы должны владеть разными данными, создайте явный процесс с долговечными командами, идемпотентными потребителями, outbox или равнозначной атомарной записью сообщения и компенсациями в форме бизнес-операций. Второй вариант отказывается от мгновенной атомарности и показывает состояния ожидания, завершения, отказа и ремонта.
Не называйте второй вариант двухфазным commit. Saga координирует отдельные commits и возможные компенсации. Двухфазный commit координирует единое решение между подготовленными участниками. Смешение понятий обещает атомарность, а реализует последующий ремонт.
Типичная ошибка обёртки имеет точную последовательность
Полезный анализ прослеживает одну команду через границу и фиксирует знания каждой стороны. Рассмотрим платёжную задачу CICS за POST. Она проверяет счёт, обновляет Db2, записывает восстанавливаемую запись для дальнейшей обработки и нормально возвращает управление.
- Клиент отправляет запрос с платёжной ссылкой
P7319. - Шлюз запускает задачу CICS и ждёт.
- Задача обновляет оба ресурса и достигает конечной точки синхронизации.
- CICS делает commit, но соединение закрывается до доставки ответа.
- Клиент повторяет запрос после тайм-аута, и вторая задача получает ту же команду.
Если программа создаёт новую ссылку при каждом вызове, вторая задача не распознает первую. Если она проверяет только текущий баланс, пройти могут обе попытки. Если HTTP-слой создаёт токен идемпотентности вне commit бизнес-изменения, сбой оставит токен и платёж в противоречии.
Исправление начинается со стабильного клиентского ID команды и атомарного резервирования этого ID. В единице, подтверждающей платёж, сохраните ID, отпечаток запроса, состояние и ссылку на результат. Дубликат с тем же отпечатком получает сохранённый результат. Тот же ID с другим содержимым вызывает конфликт. Незавершённый результат получает честное состояние ожидания, а не слепой повтор.
Минимальный ответ границы может выглядеть так:
{
"command_id": "P7319",
"workflow_version": 12,
"status": "completed",
"result_ref": "PAY-88421"
}
Эта запись не ограничивается удалением дублей. Она даёт эксплуатации долговечный ответ при неоднозначном транспортном журнале. Замена также сможет воспроизвести подтверждённый результат старой системы, не объявляя доставку TCP и commit одним событием.
Моделируйте границу командами и состояниями
Новая граница должна показывать бизнес-намерение, состояние процесса и владельца commit. Начните с таблицы переходов, а не контроллеров. Для каждой команды укажите допустимые исходные состояния, версию, проверку, восстанавливаемые записи, внешние эффекты, новое состояние и поведение дубликата.
Полезная оболочка команды намеренно меньше COMMAREA:
{
"command_id": "7f6c2b1a",
"workflow_id": "CLAIM-2048",
"expected_version": 4,
"action": "approve",
"input": {
"amount": "125.00",
"currency": "USD"
}
}
Обработчик загружает CLAIM-2048, проверяет версию 4 и переход approve, применяет бизнес-правила, пишет новое состояние и результат команды в одной локальной транзакции и возвращает сохранённый результат. Если последующая работа не может войти в транзакцию, тот же commit пишет запись outbox. Диспетчер повторяет доставку, не повторяя бизнес-переход.
Не помещайте протокольные понятия в доменную модель. Статусы HTTP описывают обмен и должны выводиться из доменных результатов. Устаревшая версия может дать 409 Conflict. Завершённая команда с тем же отпечатком возвращает прежний результат. Принятая асинхронная команда может вернуть 202 Accepted со ссылкой на состояние. Это политика границы, а не правило счёта.
Идентификатор следующей псевдодиалоговой транзакции превращается в решение о допустимых переходах, а не в переадресацию под видом бизнес-логики. Интерфейс спрашивает у представления процесса доступные действия. Сервер всё равно их контролирует. Клиент не перескочит от проверки к завершению, угадав маршрут.
Проект устраняет привязку к терминалу без потери порядка. Любой экземпляр сервиса обрабатывает следующую команду, потому что долговечное состояние хранит версию и результат. Если состояние остаётся у клиента, подпишите его, добавьте версию, проверьте возраст и ожидайте повторов. Не кладите полномочия, цены или решения о доступе в неподписанный токен.
Идемпотентности нужен контракт восстановления
Один заголовок не делает команду безопасной. Системе нужны правила области, хранения, сравнения содержимого, одновременного прихода, срока и восстановления. Иначе заголовок лишь украшает прежнюю неоднозначность.
Ограничьте ключ субъектом и операцией, чтобы разные клиенты не столкнулись. Свяжите его с каноническим отпечатком. Обеспечьте уникальность в транзакции, владеющей бизнес-изменением. Возвращайте результат только при совпадении отпечатка. Срок хранения определяйте бизнес-окном повторения, а не удобным истечением кэша.
У одновременных дублей должен быть один победитель. Уникальное ограничение или заблокированная строка резервирует исполнение. Остальные видят pending и опрашивают состояние либо ждут в строгом пределе, а не запускают работу заново. При падении победителя до commit резервирование и изменения откатываются вместе. После commit остальные находят завершённую запись.
Для восстановления нужны видимые операторам состояния. received, completed и rejected описывают чистый путь, а dispatch_pending, compensation_pending и manual_review относятся к работе за нетранзакционной границей. Не сводите всё к HTTP 500. Оператору нужны ID команды и процесса, последний долговечный переход, попытка эффекта и безопасное следующее действие.
Повторы должны находиться на уровне, который знает, допустимо ли повторение. Транспортная библиотека может повторить установление соединения или чтение без изменения данных. Она не должна молча повторять меняющий состояние POST без контракта идемпотентности от приложения. Внутри системы диспетчер outbox может повторять сообщение, потому что потребитель удаляет дубли по ID сообщения, а производитель уже подтвердил намерение в своей локальной транзакции.
Это строже многих обёрток CICS, но выражает защиту, которую CICS давал восстановлением задач и координацией точек. После перехода через HTTP и независимые базы приложение должно явно владеть неопределённостью.
Адаптер должен назвать владельца commit
HTTP-адаптер может работать вне CICS, внутри региона или через шлюз и Distributed Program Link. Размещение влияет на задержку и эксплуатацию, но владелец commit важнее. Компонент, сообщающий успех, должен знать о подтверждении единицы работы и не изображать участие удалённого вызова в локальной транзакции без настоящего координатора.
Тонкий внешний адаптер рассматривает старую транзакцию как обработчик команд с неоднозначным транспортным исходом. Он отправляет стабильный ID, ждёт и может запросить результат после тайм-аута. Он не открывает локальную транзакцию, не вызывает CICS и не обновляет свою таблицу в предположении общего действия. Без координации это два commits и разрыв между ними.
DPL требует той же осторожности. Связанная серверная программа не всегда владеет точкой синхронизации. IBM документирует, что без SYNCONRETURN DPL-сервер не может создать независимую точку, а распределённой единицей владеет клиент. С SYNCONRETURN сервер подтверждает работу при возврате, но отделяет изменения от прежней работы клиента. Это выбор транзакционной схемы, а не настройка скорости.
Перед выбором места ответьте на четыре вопроса:
- Какой процесс выдаёт стабильный ID команды?
- Какой ресурс хранит авторитетный результат?
- Какой координатор охватывает всех восстанавливаемых участников?
- Как клиент разрешает тайм-аут без повторения эффекта?
Если ответы называют две независимые базы и ни одного координатора, создайте асинхронную границу. Вместе подтвердите команду и outbox у инициатора. Сторона CICS резервирует ID и сохраняет результат вместе со старым обновлением. Сверяйте подтверждения, не считая доставку бизнес-commit. Дополнительные состояния описывают уже существующую неопределённость.
Синхронный HTTP может остаться перед процессом. Адаптер недолго ждёт completed или rejected, затем возвращает 202 Accepted, если обработка идёт. Чтение состояния показывает долговечный результат. Обычно пользователь быстро получает завершение, а при задержке видит честное ожидание. Не держите соединение открытым для имитации диалоговой задачи.
Границы безопасности следуют той же явной модели. Аутентифицируйте клиента на веб-границе, но передавайте обработчику ограниченного субъекта и разрешённый контекст. Не доверяйте номеру счёта, коду оператора или флагу прав только потому, что раньше значение лежало в защищённой COMMAREA. Данные из браузера или брокера повторно проверяет сторона, применяющая переход.
Сохраните исходный код ответа CICS и диагностику в свидетельстве адаптера, затем сопоставьте их небольшому публичному контракту ошибок. Публикация каждого EIBRESP связывает клиентов с реализацией. Удаление всех значений мешает проверке паритета и ремонту. Границе нужны оба взгляда: стабильный доменный результат для клиента и детали старой системы для доказательства равенства.
Проверка паритета должна разрывать диалоги
Сравнение полей успешного пути не докажет миграцию. Стенд паритета должен сравнить подтверждённое поведение через границы задач, повторы, abends, устаревшее продолжение и сбои около точки синхронизации. Одинаковый итог на экране может скрывать другую единицу работы.
Стройте трассы из записанного производственного трафика только по правилам обработки данных организации. Для каждого случая сохраните исходное состояние, байты и поля ввода, транзакцию, изменения ресурсов, положения точек, выходные поля, следующую транзакцию и конечное состояние. Маскирование обязано сохранять различия, влияющие на ветви, например пробелы и low values либо коды с одинаковой подписью.
Запускайте старый и новый пути на изолированных данных, которые можно вернуть в одно исходное состояние перед каждым случаем. Сравнивайте бизнес-результаты, а не шум реализации. Время, созданные ID и порядок записей можно нормализовать по заранее объявленным правилам, но суммы, состояния, решения о доступе и подтверждённые побочные эффекты должны совпасть точно.
Матрица сбоев должна включать:
- Повтор команды до и после завершения.
- Потерю ответа после commit и повтор с тем же ID.
- Сбой до точки и сразу после невосстанавливаемого эффекта.
- Верную команду с устаревшей версией процесса.
- Продолжение с каждой длиной и версией COMMAREA.
При переработке CICS и соседних старых программ CodeHero использует стенд паритета на записанном производственном трафике, потому что сходство исходников не показывает различия восстановления. До передачи записи новой системе тот же стенд должен внедрять сбои границы, а не только воспроизводить чистые запросы.
Сохраняйте поведение, а не случайную форму
Правильная модель не требует воссоздавать CICS внутри веб-сервиса. Она сохраняет наблюдаемые правила: допустимые команды, совместно подтверждаемые изменения, поведение дубля, представление незавершённой работы и возврат восстановления в известное состояние.
Часть старых деталей пора убрать. Четырёхсимвольному ID не обязательно становиться маршрутом. Разметке COMMAREA не обязательно становиться публичной нагрузкой. Привязке терминала не обязательно превращаться в sticky session. Граница менеджера ресурсов должна жить, пока команда сознательно не заменит её атомарность процессом и ремонтом.
Напишите спецификацию границы для каждой бизнес-команды. Укажите стабильную идентичность, исходное состояние, правило версии, владельца транзакции, эффекты внутри и вне commit, результат дубля и действие оператора. Проверьте документ с людьми, которые сейчас разбирают сбои CICS. В первом варианте они часто находят пропущенную неявную точку, поведение очереди или предположение о перезапуске.
Сложная проверка состоит в потере ответа после успешного commit. Если проект точно объясняет, что повторяет клиент, что читает сервер, какой результат возвращает и почему эффект не дублируется, граница, скорее всего, настоящая. Если ответ зависит от совместного завершения запроса и транзакции, проект всё ещё путает HTTP с CICS.
Вопросы
Транзакция CICS равна транзакции базы данных?
Нет. Транзакция CICS представляет задачу, выбранную идентификатором, а транзакция базы участвует в её единице работы. CICS может координировать Db2 и другие восстанавливаемые ресурсы в точке синхронизации.
Можно ли превратить одну транзакцию CICS в REST endpoint?
Иногда, но одинаковые имена не доказывают совпадение границ. Сопоставляйте endpoint бизнес-команде после определения перехода, записей, точек синхронизации, дублей и результата.
Что происходит с COMMAREA между псевдодиалоговыми задачами?
CICS сохраняет переданные байты для первой программы следующей задачи, связанной с терминалом. COMMAREA несёт продолжение, но не относится к восстанавливаемым записям базы.
Нужно ли хранить COMMAREA в HTTP-сеансе после миграции?
Не по умолчанию. Храните бизнес-состояние и процесс в версионной серверной записи, пересчитывайте представление и оставляйте у клиента только подписанные значения, которые безопасно повторять.
Когда CICS делает commit?
В явной точке синхронизации или при нормальном завершении задачи верхнего уровня. Abend обычно откатывает неподтверждённые изменения восстанавливаемых ресурсов текущей единицы.
Означает ли HTTP 200, что работа CICS подтверждена?
Только если адаптер строит ответ из известного подтверждённого результата. Соединение может оборваться после commit, а фреймворк подготовить ответ до настоящего commit базы.
Могут ли повторы заменить двухфазный commit CICS?
Нет. Повтор запускает попытку заново, но не координирует одно решение между подготовленными менеджерами. Используйте локальную транзакцию либо проектируйте долговечные состояния, идемпотентность, outbox и компенсации.
Как обрабатывать повторные HTTP-запросы?
Дайте команде стабильный ID и сохраните его, отпечаток и результат в одной транзакции с бизнес-изменением. Для точного дубля верните результат, а ID с другим содержимым отклоните.
Являются ли channels и containers CICS долговечным состоянием?
Нет. Они улучшают передачу структуры и снимают предел одной COMMAREA, но не заменяют долговечную запись процесса и не меняют commit бизнес-ресурсов.
Что сравнивает тест паритета миграции CICS?
Сравнивайте начальное и конечное состояние, переходы, выходы, эффекты и дубли. Внедряйте тайм-ауты, abends, старые версии и потерю ответа около точек синхронизации.