一、网关和BFF的演进
- v1 使用nginx负载均衡简单的微服务体系;
-
v2 nginx直接暴露
-
v2.5无线BFF
-
v3 集群BFF+无线网关
-
v4无线网关、无线BFF根据业务集群化,废弃nginx集群
二、网关和反向代理
网关和反向代理的选择:
关于网关集群问题:需要根据公司业务大小进行选择
三、设计简单网关-faraday
1.核心思想
2.代码实现
- 路由映射表模块
-
MappingsProvider路由映射表
package xyz.staffjoy.faraday.core.mappings; import com.github.structlog4j.ILogger; import com.github.structlog4j.SLoggerFactory; import org.springframework.boot.autoconfigure.web.ServerProperties; import xyz.staffjoy.faraday.config.FaradayProperties; import xyz.staffjoy.faraday.config.MappingProperties; import xyz.staffjoy.faraday.core.http.HttpClientProvider; import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest; import java.util.List; import java.util.stream.Collectors; import static org.springframework.util.CollectionUtils.isEmpty; public abstract class MappingsProvider { private static final ILogger log = SLoggerFactory.getLogger(MappingsProvider.class); protected final ServerProperties serverProperties; protected final FaradayProperties faradayProperties; protected final MappingsValidator mappingsValidator; protected final HttpClientProvider httpClientProvider; protected List<MappingProperties> mappings; public MappingsProvider( ServerProperties serverProperties, FaradayProperties faradayProperties, MappingsValidator mappingsValidator, HttpClientProvider httpClientProvider ) { this.serverProperties = serverProperties; this.faradayProperties = faradayProperties; this.mappingsValidator = mappingsValidator; this.httpClientProvider = httpClientProvider; } public MappingProperties resolveMapping(String originHost, HttpServletRequest request) { if (shouldUpdateMappings(request)) { updateMappings(); } List<MappingProperties> resolvedMappings = mappings.stream() .filter(mapping -> originHost.toLowerCase().equals(mapping.getHost().toLowerCase())) .collect(Collectors.toList()); if (isEmpty(resolvedMappings)) { return null; } return resolvedMappings.get(0); } @PostConstruct protected synchronized void updateMappings() { List<MappingProperties> newMappings = retrieveMappings(); mappingsValidator.validate(newMappings); mappings = newMappings; httpClientProvider.updateHttpClients(mappings); log.info("Destination mappings updated", mappings); } protected abstract boolean shouldUpdateMappings(HttpServletRequest request); protected abstract List<MappingProperties> retrieveMappings(); }
resolveMapping:根据主机头获取路由映射;
updateMappings:更新路由表;
-
- http映射表
- 根据路由映射表获取到的路由,通过http映射表对目标服务发起调用
package xyz.staffjoy.faraday.core.http; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; import xyz.staffjoy.faraday.config.MappingProperties; import java.util.HashMap; import java.util.List; import java.util.Map; import static java.util.stream.Collectors.toMap; import static org.apache.http.impl.client.HttpClientBuilder.create; public class HttpClientProvider { protected Map<String, RestTemplate> httpClients = new HashMap<>(); public void updateHttpClients(List<MappingProperties> mappings) { httpClients = mappings.stream().collect(toMap(MappingProperties::getName, this::createRestTemplate)); } public RestTemplate getHttpClient(String mappingName) { return httpClients.get(mappingName); } protected RestTemplate createRestTemplate(MappingProperties mapping) { CloseableHttpClient client = createHttpClient(mapping).build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(client); requestFactory.setConnectTimeout(mapping.getTimeout().getConnect()); requestFactory.setReadTimeout(mapping.getTimeout().getRead()); return new RestTemplate(requestFactory); } protected HttpClientBuilder createHttpClient(MappingProperties mapping) { return create().useSystemProperties().disableRedirectHandling().disableCookieManagement(); } }
- 根据路由映射表获取到的路由,通过http映射表对目标服务发起调用
四、大型网关扩展
- 限流熔断:保障用户体验,保障服务不会挂断
- 动态路由和负载均衡:当服务多时,采用动态服务发现机制,k8s内部支持
- 基于Path的路由:通过域名映射到服务
- 截获器链:多个截获器构成的链状
- 日志采集和Metrics埋点:日志+日志分析;掌握后台性能状况
- 响应流优化:响应速度大时,内核态无需拷贝到用户态,直接以流的形式提供给网关
五、主流网关概览