- 服务网关特性
- 基于
RestTemplate自定义服务网关 Spring Cloud Netflix Zuul网关Spring Cloud Gateway网关
Spring Cloud服务网关
版本信息
Spring Cloud : Hoxton.SR1
Spring Boot : 2.2.2.RELEASE
Zookeeper : 3.5.6 (注册中心使用)
服务网关特性
服务网关是干什么用的?
- 认证
- 安全(授权)
- 动态路由
基于RestTemplate自定义服务网关
服务端演示提供服务
-
添加
pom依赖<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--zookeeper 客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency> -
服务网关服务应用
GatewayServerApplication/**
* 服务网关服务应用
*
* @author FelixFly <chenglinxu@yeah.net>
* @date 2020/2/8
*/
@SpringBootApplication
public class GatewayServerApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServerApplication.class, args);
}
} -
演示服务端点
/**
* 演示服务端点
*
* @author FelixFly <chenglinxu@yeah.net>
* @date 2020/2/8
*/
@RestController
public class EchoController {
@Autowired
private Environment environment;
@GetMapping("/echo")
public String echo(String message) {
// 由于采用的是随机端口,这地方必须采用这个方式获取端口
String port = environment.getProperty("local.server.port");
return "ECHO(" + port + "):" + message;
}
} -
服务配置
application.ymlspring:
application:
name: gateway-server
cloud:
zookeeper:
connect-string: 127.0.0.1:2181
server:
port: 0
启动服务,根据启动日志查看本地的随机端口,此次端口是
54692
http://127.0.0.1:54692/echo?message=Hello返回信息ECHO(54692):Hello
自定义服务网关
基于
Servlet
配置文件application.yml
spring:
application:
name: gateway-zuul
cloud:
zookeeper:
connect-string: 127.0.0.1:2181
server:
port: 7070
基于DiscoveryClient
GatewayCustomServlet网关Servlet
包名:
top.felixfly.cloud.gateway.custom
/**
* 服务网关Servlet实现
*
* @author FelixFly <chenglinxu@yeah.net>
* @date 2020/2/8
*/
@WebServlet(name = "gateway", urlPatterns = "/gateway/*")
public class GatewayCustomServlet extends HttpServlet {
@Autowired
private DiscoveryClient discoveryClient;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 访问地址的Uri:/{service-name}/${service-uri}
String pathInfo = req.getPathInfo();
String[] paths = StringUtils.split(pathInfo.substring(1), "/");
// 服务名称
String serverName = paths[0];
// 服务访问地址
String serverURI = paths[1];
// 获取服务实例
ServiceInstance serviceInstance = choose(serverName);
// 目标地址
String targetURL = createTargetURL(serviceInstance, serverURI, req);
RestTemplate restTemplate = new RestTemplate();
String method = req.getMethod();
ResponseEntity<byte[]> responseEntity = restTemplate
.exchange(targetURL, HttpMethod.resolve(method), null, byte[].class);
// 返回状态
resp.setStatus(responseEntity.getStatusCodeValue());
// 媒体类型
HttpHeaders headers = responseEntity.getHeaders();
MediaType contentType = headers.getContentType();
if (Objects.nonNull(contentType)) {
resp.setHeader(HttpHeaders.CONTENT_TYPE, contentType.toString());
}
// 返回内容
byte[] body = responseEntity.getBody();
if (Objects.nonNull(body)) {
ServletOutputStream outputStream = resp.getOutputStream();
outputStream.write(responseEntity.getBody());
outputStream.flush();
}
}
private String createTargetURL(ServiceInstance instance, String serverURI,
HttpServletRequest req) {
StringBuilder urlBuilder = new StringBuilder(64);
return urlBuilder.append(instance.isSecure() ? "https" : "http").append("://")
.append(instance.getHost()).append(":").append(instance.getPort())
.append(serverURI).append("?").append(req.getQueryString())
.toString();
}
private ServiceInstance choose(String serverName) {
List<ServiceInstance> instances = this.discoveryClient.getInstances(serverName);
if (CollectionUtils.isEmpty(instances)) {
throw new RuntimeException("无服务实例");
}
int index = new Random().nextInt(instances.size());
return instances.get(index);
}
}
服务启动类GatewayZuulApplication
/**
* 服务网关 Zuul 服务
*
* @author FelixFly <chenglinxu@yeah.net>
* @date 2020/2/8
*/
@SpringBootApplication
@ServletComponentScan(basePackages = "top.felixfly.cloud.gateway.custom")
public class GatewayZuulApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayZuulApplication.class, args);
}
}
启动服务,访问地址
http://127.0.0.1:7070/gateway/gateway-server/echo?message=hello返回信息ECHO(54692):Hello