保险销售系统对接保险公司接口的常见技术架构
保险销售系统对接保险公司接口的常见技术架构
API网关集成
保险系统常使用API网关作为统一入口,实现对各类渠道和后端服务的流量治理、安全鉴权和路由管理。常见方案包括基于Nginx的Kong、Netflix Zuul、Spring Cloud Gateway、Apigee、阿里云API网关或开源Apache APISIX等。网关可部署在DMZ与内网之间,外部网关用于对外暴露服务,内部网关用于系统间调用。
例如,和谐健康险的中台架构中使用Zuul网关实现高可用、高性能服务接入,并提供Swagger/OpenAPI接口以加速对接;众安保险采用Apache APISIX,将多渠道流量隔离,提供精细化的路由和计费能力。
API网关还可做限流熔断、黑白名单、证书认证等安全管控,简化下游服务对接。
- 示例特性: 支持HTTPS、TLS互验、OAuth2鉴权、动态路由等。
- 实战案例: 太保车险移动项目提出“统一接入平台”,对接报价服务,减轻核心系统压力并提高效率;深度学习集成方案中提到通过API网关对接核心承保、理赔等系统,并使用Kafka做数据采集。
中台/统一接入平台
随着渠道和险种增多,越来越多保险机构或中介构建保险业务中台/统一接入平台。此类中间层封装共享能力(产品计算、规则引擎、核保服务等)并对外提供标准化API接口,屏蔽不同保险公司之间差异。
比如,InsureMO 保险云中台通过云原生微服务架构,为全球保险公司和渠道提供统一的保单下单、核保、支付、出单、理赔等API服务;该平台已覆盖40多个国家、服务300多家保险公司及数千个渠道。
国内案例方面,和谐健康险的银保中台集成了微服务和私有云技术,以统一接口对接上游展业系统,提升了复用性和交付效率;中国太保车险项目要求构建共享中台,将常用交易服务微服务化,并采用统一接入平台完成各渠道接入。
- 优势:快速集成多渠道,复用业务逻辑,减少对接工作量;通过“产品工厂”实现一次开发、多处使用;可在中台预加载热点数据,提高响应速度。
- 不足:投入成本高,架构设计复杂;需要统一业务标准和接口规范,推进难度大。适用于对接保险公司数目众多、产品多样化且对接频繁的场景。
异步消息中间件
在高并发或批量处理场景下,保险系统常引入消息队列进行异步调用和解耦。常见选型包括Apache Kafka、RabbitMQ、RocketMQ、Apache Pulsar等。
例如,阳光保险集团在信息化建设中广泛应用RocketMQ、Kafka、RabbitMQ等消息中间件,以支撑数据同步和流式计算需求;在AI智能方案中采用“混合消息队列”架构:实时核保用Apache Pulsar、批量理赔用RabbitMQ、客户画像更新用Kafka等。
这种方式能有效缓冲并发请求、提高吞吐量,并支持峰值弹性扩展;但也增加了系统复杂度,对监控、事务和一致性提出更高要求。
- 典型应用:大批量保单处理、批量核保/理赔、跨系统事件通知等。
- 实践示例:和谐健康险中台在基础组件层按需使用RabbitMQ、Kafka等消息队列进行交易处理;深度学习方案中使用消息队列异步采集车联网数据和处理事件。
多保险公司接口管理与路由
对接多家保险公司的接口,往往需要协议适配和路由策略。常见做法是为每家保险公司开发适配器或微服务模块,通过配置中心统一维护映射关系。
系统接收到上游请求后,根据渠道标识或业务规则,路由到对应保险公司的对接模块,再将结果转换为统一格式返回。
在实际场景中,也可使用企业服务总线(ESB)、微服务注册中心等技术,对多终端的请求进行集中管理和监控。
- 策略示例:可在API网关中根据API Key或请求头区分保险公司;也可在中台层使用规则引擎确定路由;或在消息中间层增加渠道标记,确保数据正确导向。
- 优势与挑战:这种方式能够简化新增对接,只需配置或增加模块;但需维护协议转换规则和路由表,接口格式的一致性验证和日志审计也较为复杂。
架构方案优劣对比
架构/方式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
直接API对接 | 实现简单、低延迟,开发成本小(无需网关等组件) | 每家保险独立开发对接,维护成本高;难统一鉴权和监控;可扩展性差 | 接入的保险公司和渠道较少,业务规模较小时 |
API网关 + 微服务 | 统一入口、安全集中管理(鉴权、限流、监控等);可横向扩展;不同渠道可通过路由隔离 | 增加系统复杂度;需投入网关和运维;可能出现单点,需要集群冗余 | 多渠道、高并发场景,需要统一治理时 |
统一中台/ESB | 中心化管理复用能力,减少重复开发;能够支撑多产品、多渠道;易做日志审计和版本迭代 | 平台建设周期长、成本高;需要统一业务标准;对接规范复杂 | 大型保险集团或经代公司,集成需求量大 |
异步消息队列 | 解耦各系统,提高系统弹性;可平滑高峰负载;适合批量和事件驱动场景 | 调试和监控困难;需处理事务和一致性;增加延迟,不适合实时业务 | 批量核保、理赔、大数据同步等异步场景 |
行业实践与案例
- 云端保险中台:InsureMO 平台基于亚马逊云原生技术构建保险云中台,为保险公司、代理商和科技公司提供统一的保险微服务API。该平台支持全球多国家和保险公司快速上线新产品,提高创新效率。
- 企业消息平台:阳光保险集团自研“风信子”消息中间件平台,将Kafka、RabbitMQ、RocketMQ等开源组件统一管控,以满足集团内部应用的数据同步和流式计算需求。
- 微服务网关选型:众安保险作为互联网保险先行者,在网关选型时对比了Kong、Traefik、阿里云MSE等,最终采用开源Apache APISIX,并利用其插件实现了多租户、多渠道的流量隔离和计量计费。
- 银保移动平台:中国太保产险车险移动平台项目提出将底层共用服务做高内聚低耦合的中台改造,并建立统一数据下发和异步接口机制,实现前后台端到端实时交互,降低核心系统负载。
API网关 + 微服务方式调用保司接口
以下内容阐述了在「API网关 + 微服务」架构下,独立开发的保险销售系统如何调用各家保险公司(保司)的接口,包括调用流程、网关配置、微服务适配、鉴权方式、错误处理及安全隔离等,并给出实践建议。
概要
通过 API 网关,销售系统对外暴露统一入口,承担路由转发、流量治理、安全鉴权等功能;在内网侧,各家保司对接 微服务适配器(Adapter Service)完成协议转换、签名加密和响应处理,最终调用保司标准 API 并返回结果至销售系统。该方案既保证了调用的灵活性和可扩展性,又实现了多家保司接口的统一管理和安全隔离。
架构示意与调用流程
1. 外部 API 网关层
- 统一入口
- 将所有来自前端或渠道的请求汇聚到 API 网关,简化客户端集成,并基于域名、路径或请求头做路由分发。
- 安全与限流
- 在网关层配置 TLS 互信、IP 白名单、OAuth2/JWT 或 API Key 等鉴权插件;通过限流、熔断策略应对突发流量和下游压力。
- 协议转换
- 部分保司可能只支持 SOAP、XML-RPC 或自定义协议,可在网关层或下游微服务中做请求格式转换;如使用 Kong Forward Proxy 插件,可实现正向代理并进行 Host 修改和证书管理。
2. 内部微服务适配层
- 适配器微服务
- 针对每家保司编写专属适配器(Adapter Service),主要职责包括:
- 构造符合保司要求的请求报文(签名、报文字段映射);
- 调用保司接口并做响应解析与异常转换;
- 将结果统一封装为销售系统可识别的 DTO(Data Transfer Object)。
- 针对每家保司编写专属适配器(Adapter Service),主要职责包括:
- 服务注册与发现
- 使用注册中心(如 Eureka、Zookeeper、Consul)管理各适配器服务实例,实现调用时的动态路由和负载均衡。
- 熔断与降级
- 在适配器层或网关侧引入断路器(Hystrix、Resilience4j),对保司接口调用进行熔断监控,并在必要时返回降级处理或缓存数据。
调用示例流程
认证与鉴权
- 客户端到网关:采用 OAuth2.0 Client Credentials 流或者 API Key,确保只有合法渠道能访问。
- 网关到适配器:可使用内部 JWT 或 mTLS(双向 TLS)保证调用链的安全;也可在 HTTP Header 中透传网关身份令牌。
- 适配器到保司:严格按照保司文档要求进行签名算法(HMAC、RSA)处理,部分保司还会校验请求源 IP 或证书。
错误处理与重试
- 同步调用:
- 设置合理的超时(Connect Timeout、Read Timeout),并使用重试策略(如指数退避)对接网络抖动或保司系统短暂不可用场景。
- 异步处理(可选):
- 对于非实时业务(批量核保、短信通知等),可在适配器层结合消息队列(Kafka、RabbitMQ)进行异步解耦,避免接口抖动影响前端性能。
安全隔离与网络布局
- DMZ 区与内网隔离:
- 外部网关部署于 DMZ 区,内部适配器服务部署于内网,并在防火墙上仅开放必要端口。
- 审计与日志:
- 在网关侧和适配器层都要记录请求链日志(含请求 ID、链路追踪 traceId),以便对接故障定位与安全审计。
实践建议
- 统一中台演进:当接入保司数量增多时,可考虑建设保险中台,将通用能力(鉴权、签名、降级、缓存等)放到中台服务中,减少各适配器重复开发。
- 接口模拟与测试:利用 契约测试(Pact) 或 WireMock 模拟保司接口,提前做集成测试,避免对生产环境保司系统造成影响。
- 监控与指标:引入 Prometheus + Grafana,对 API 网关与适配器服务的调用成功率、延时分布、熔断状态等关键指标进行可视化监控。
一、为何要为保司A开发专属适配器微服务
1. 解耦核心业务与第三方差异
各保司接口在认证、请求格式(JSON vs. XML vs. SOAP)、加密签名和错误码上存在显著差异,若将这些逻辑散落在主业务服务中,会导致代码高度耦合,难以维护。适配器微服务封装所有与保司A相关的协议转换、DTO 映射和异常处理,主业务服务只需调用统一的本地 API,保持业务代码简洁、聚焦于业务流程本身。
2. 独立部署与隔离风险
适配器微服务可以独立扩容、独立下线及灰度发布,降低单一保司故障对销售系统整体可用性的影响。当保司A系统升级或规则变动,仅需对其适配器进行回归测试,而不触及其他业务模块或适配器,测试和发布效率更高。
3. 专属监控与告警
每个适配器微服务可配置与保司接口相关的专属监控指标(调用成功率、平均响应时长、错误码分布等),帮助运维快速定位是保司端问题还是网络抖动,无需在庞杂的主业务监控中筛查。
二、微服务数量不断增多是否合理?
1. “微服务过多”反模式
“一对一”地将每个外部 API 封装成单独微服务,在保司数十或上百时,会导致服务数量激增,增加运维复杂度,并带来网络调用开销和治理难题,被认为是一种反模式。
2. 优化策略
2.1 插件化适配器框架
将各家保司的差异逻辑(URI、签名算法、DTO 转换器)提取成可热插拔的插件,在一个统一的“适配器引擎”中加载。新增保司时,只需提供对应插件,无需再多跑一个独立服务实例。
2.2 动态路由与配置驱动
使用动态路由中心(如 Spring Cloud Gateway + 配置中心),在同一适配器服务内,通过路由规则将请求分发到不同的处理器模块;规则和处理逻辑可在线变更,无需重启服务。
2.3 中台 + 扩展点模式
在更大型架构中,建立一个“保险中台”,提供包括认证、签名、限流、降级、日志等通用模块;针对各保司差异的“扩展点”仅包含少量配置或脚本,避免为每家保司都新开一个微服务。
三、综合对比与建议
方案 | 优势 | 限制 |
---|---|---|
独立适配器微服务 | 最高程度隔离,易于独立测试与扩展;监控细粒度高 | 大量服务实例,部署与运维成本高;网络调用延迟略增 |
插件化适配器引擎 | 插件轻量,易扩展;服务实例数少,流量集中管理 | 插件框架设计复杂;需保证插件隔离与安全 |
动态路由配置驱动 | 配置中心动态更新;无缝路由多保司;易实现灰度与A/B测试 | 路由逻辑集中,需做好热更新和灰度;代码内部仍需维护多种协议 |
中台+扩展点 | 将通用能力抽象;减少重复开发;适合超大规模接入 | 中台建设成本高,需统一标准;扩展点脚本/配置管理复杂 |
建议:
- 接入保司数量在 5–10 家内,可继续使用独立微服务适配器,运维成本可控。
- 当接入规模突破 10–20 家时,应优先考虑插件化或配置驱动的适配器引擎方案,并逐步演进到保险中台,以平衡开发效率与运维复杂度。
面试回答示例:开发保司A适配器微服务并对接保司接口
面试官问:“你们在销售系统中怎么对接保司A的接口?请简要说明技术方案与要点。”
一、背景介绍
在我们的架构里,销售系统和保司属于完全隔离的两套系统。为了保持核心业务服务的稳定,我们采用了API网关 + 微服务适配器的方式,其中针对保司A专门开发了一个适配器微服务 (Adapter Service)。
二、关键技术点
- 协议与格式适配
- 保司A接口采用 SOAP/XML,而我们内部微服务普遍使用 REST/JSON。适配器负责请求报文的 XML 构造与响应的 JSON 解析,屏蔽协议差异。
- 认证与签名
- 按保司A文档要求,使用 RSA-SHA256 签名,并通过双向 TLS(mTLS)或 HMAC 校验身份,保证请求的合法性和机密性。
- 服务注册与发现
- 适配器微服务注册到 Eureka 或 Consul,由 API 网关如 Spring Cloud Gateway 实现动态路由与负载均衡。
- 熔断与限流
- 借助 Resilience4j 或 Hystrix 实现对保司A接口的熔断与限流,避免对端抖动影响整体可用性。
三、调用流程
- 客户端→API网关:统一鉴权、限流、监控;
- 网关→适配器:基于服务发现路由;
- 适配器→保司A:构造签名报文、发送请求;
- 保司A→适配器:响应解析、异常包装;
- 适配器→网关→客户端:返回统一的 JSON 结果。
四、异常与可用性保障
- 超时与重试
- 设置 Connect/Read Timeout,并在适配器中实现指数退避重试策略,避免网络抖动导致的短暂失败。
- 降级与异步
- 对于非关键路径(如保单查询等),采用异步消息(Kafka/RabbitMQ)解耦,并在超时或熔断时返回缓存或降级提示。
- 监控与告警
- 利用 Prometheus/Grafana 采集适配器调用的成功率、延时、错误码分布,并通过 Alertmanager 及时告警。
五、非功能需求
- 安全:全链路加密(TLS/mTLS)、细粒度权限控制;
- 可扩展:横向扩容适配器实例,可热插拔新保司;
- 可维护:独立部署、CI/CD 自动化测试与发布;
- 可审计:请求链路追踪(TraceId)、集中日志与分布式追踪(Zipkin/Jaeger)。
六、最佳实践与演进
- 抽象共性:将签名、限流、熔断等能力提炼到中台模块,减少各适配器重复代码。
- 插件化框架:后续可将各保司差异逻辑做成可插拔插件,统一加载到同一适配器引擎中,避免微服务泛滥。
- 契约测试:使用 Pact 等工具模拟保司接口,确保接口变更时适配器自动验证兼容性。
以上内容可在面试中作为回答示例,体现系统化思路与落地经验。
保司A 适配器微服务示例
以下示例展示了基于 Spring Boot 的“保司A 适配器微服务”项目结构及核心代码,实现了对保司A SOAP 接口的对接,并集成了服务发现、熔断、重试、异常处理等能力。
项目结构
insurance-adapter-a/
├── src/main/java/com/example/adaptera
│ ├── AdapterAApplication.java
│ ├── config
│ │ ├── SoapClientConfig.java
│ │ └── ResilienceConfig.java
│ ├── controller
│ │ └── PolicyController.java
│ ├── service
│ │ ├── AdapterAClient.java
│ │ └── AdapterAService.java
│ ├── dto
│ │ ├── PolicyRequest.java
│ │ └── PolicyResponse.java
│ └── exception
│ └── AdapterAException.java
└── pom.xml
1. 启动类 & 服务注册
// AdapterAApplication.java
package com.example.adaptera;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@SpringBootApplication
@EnableEurekaClient
public class AdapterAApplication {public static void main(String[] args) {SpringApplication.run(AdapterAApplication.class, args);}
}
2. SOAP 客户端配置
// config/SoapClientConfig.java
package com.example.adaptera.config;import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ws.transport.http.HttpComponentsMessageSender;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;@Configuration
public class SoapClientConfig {@Beanpublic WebServiceTemplate webServiceTemplate(RestTemplateBuilder builder) {HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender();CloseableHttpClient httpClient = HttpClients.custom().setMaxConnPerRoute(20).setMaxConnTotal(50).build();messageSender.setHttpClient(httpClient);WebServiceTemplate template = new WebServiceTemplate();template.setDefaultUri("https://api.bx-company.com/soap");template.setMessageSender(messageSender);return template;}
}
3. Resilience4j 熔断与重试配置
// config/ResilienceConfig.java
package com.example.adaptera.config;import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.retry.RetryConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.time.Duration;@Configuration
public class ResilienceConfig {@Beanpublic io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry circuitBreakerRegistry() {CircuitBreakerConfig cbConfig = CircuitBreakerConfig.custom().failureRateThreshold(50).waitDurationInOpenState(Duration.ofSeconds(30)).slidingWindowSize(20).build();return io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry.of(cbConfig);}@Beanpublic io.github.resilience4j.retry.RetryRegistry retryRegistry() {RetryConfig retryConfig = RetryConfig.custom().maxAttempts(3).waitDuration(Duration.ofMillis(500)).build(); return io.github.resilience4j.retry.RetryRegistry.of(retryConfig);}
}
4. DTO 定义
// dto/PolicyRequest.java
package com.example.adaptera.dto;public class PolicyRequest {private String applicantName;private String idNumber;private String productCode;
}
// dto/PolicyResponse.java
package com.example.adaptera.dto;public class PolicyResponse {private boolean success;private String policyNo;private String message;
}
5. AdapterAClient: 调用保司 SOAP 接口
// service/AdapterAClient.java
package com.example.adaptera.service;import com.example.adaptera.dto.PolicyRequest;
import com.example.adaptera.dto.PolicyResponse;
import com.example.adaptera.exception.AdapterAException;
import org.springframework.stereotype.Component;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.beans.factory.annotation.Autowired;@Component
public class AdapterAClient {@Autowiredprivate WebServiceTemplate webServiceTemplate;public PolicyResponse callUnderwrite(PolicyRequest req) {try {Object soapReq = buildSoapRequest(req);Object soapResp = webServiceTemplate.marshalSendAndReceive(soapReq);return parseSoapResponse(soapResp);} catch (Exception ex) {throw new AdapterAException("调用保司A核保接口失败", ex);}}private Object buildSoapRequest(PolicyRequest req) {return null; // TODO: 根据 WSDL 生成的类填充数据}private PolicyResponse parseSoapResponse(Object soapResp) {return new PolicyResponse(); // TODO: 将 SOAP 响应转换为 PolicyResponse}
}
6. AdapterAService: 业务封装
// service/AdapterAService.java
package com.example.adaptera.service;import com.example.adaptera.dto.PolicyRequest;
import com.example.adaptera.dto.PolicyResponse;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.retry.annotation.Retry;
import org.springframework.stereotype.Service;@Service
public class AdapterAService {private final AdapterAClient client;public AdapterAService(AdapterAClient client) {this.client = client;}@CircuitBreaker(name = "adapterA")@Retry(name = "adapterA")public PolicyResponse underwrite(PolicyRequest req) {return client.callUnderwrite(req);}
}
7. Controller: 外部调用入口
// controller/PolicyController.java
package com.example.adaptera.controller;import com.example.adaptera.dto.PolicyRequest;
import com.example.adaptera.dto.PolicyResponse;
import com.example.adaptera.service.AdapterAService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/api/adapterA")
public class PolicyController {private final AdapterAService service;public PolicyController(AdapterAService service) {this.service = service;}@PostMapping("/underwrite")public ResponseEntity<PolicyResponse> underwrite(@RequestBody PolicyRequest req) {PolicyResponse resp = service.underwrite(req);return ResponseEntity.ok(resp);}
}
8. 异常处理
// exception/AdapterAException.java
package com.example.adaptera.exception;public class AdapterAException extends RuntimeException {public AdapterAException(String message, Throwable cause) {super(message, cause);}
}
// controller/GlobalExceptionHandler.java
package com.example.adaptera.controller;import com.example.adaptera.exception.AdapterAException;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(AdapterAException.class)public ResponseEntity<String> handleAdapterAError(AdapterAException ex) {return ResponseEntity.status(502).body(ex.getMessage());}
}