API⽹关springcloudgateway和负载均衡框架ribbon实战
通常我们如果有⼀个服务,会部署到多台服务器上,这些微服务如果都暴露给客户,是⾮常难以管理的,我们系统需要有⼀个唯⼀的出⼝,API⽹关是⼀个服务,是系统的唯⼀出⼝。API⽹关封装了系统内部的微服务,为客户端提供⼀个定制的API。客户端只需要调⽤⽹关接⼝,就可以调⽤到实际的微服务,实际的服务对客户不可见,并且容易扩展服务。
API⽹关可以结合ribbon完成负载均衡的功能,可以⾃动检查微服务的状况,及时剔除或者加⼊某个微服务到可⽤服务列表。此外⽹关可以完成权限检查、限流、统计等功能。下⾯我们将⼀⼀完成上⾯的功能。注意微服务只是提供rest的接⼝,不会有额外的组件依赖,不需要eureka等。只需要两个⼯程,⼀个是微服务,我们可以部署到多台服务器,那么只是访问的ip不同,在演⽰的时候,我们在本机演⽰,修改端⼝,达到启动多个微服务的⽬的,另⼀个就是⽹关,主要是spring cloud gateway 和 ribbon两⼤组件来实现⽹关和负载均衡等功能。
1、rest服务构建
1、创建⼀个⽗⼯程
删除src⽬录
pom⽂件增加如下内容:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
2、新建⼀个module
3、修改l⽂件,增加如下内容:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
4、在resources⽂件夹下⾯增加⼀个l⽂件,内容为:
server:
port: 1001
5、新增⼀个主⼊⼝类Provider1001Application,内容如下
fengyu.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Provider1001Application
{
public static void main(String[] args)
{
SpringApplication.run(Provider1001Application.class, args);
}
}
6、新增⼀个rest接⼝HelloWorldController,内容如下:
ller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloWorldController
{
@GetMapping("/hello")
@ResponseBody
public String hello()
{
return "hello spring cloud, 1001";
}
}
7、启动main⽅法,在浏览器输⼊可以看到:
8、同理,我们再建⽴2个rest服务,步骤如下
(1)新增module,参考第⼆⼩节,主要把名称改为:
provider1002
provider1003
(2)l⽂件参考第三⼩节,加上即可。
(3)参考第四⼩节,新建l⽂件,注意端⼝改为
1002
1003
(4)参考第五⼩节,新建⼀个主启动类,名称为如下,内容都⼀样。
Provider1002Application
Provider1003Application
(5)参考第六⼩节,新增⼀个HelloWorldController接⼝,其中只有下⾯这句中的 1001 改为 1002 或 1003,⽅便测试观察结果
return "hello spring cloud, 1001";
(6)参考第7⼩节测试成功新增的两个服务即可。
(7)现在的⼯程如下:
2、spring cloud gateway
Spring Cloud Gateway是Spring官⽅基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的⽹关,Spring Cloud Gateway旨在为微服务架构提供⼀种简单⽽有效的统⼀的API路由管理⽅式。
路由:Gateway的基础构建模块。它包括⼀个ID,⼀个⽬标URL,⼀个断⾔集合和⼀个过滤器集合。如果断⾔判断为真,则路由匹配。
断⾔:这是Java8的新增功能,输⼊的类型为Spring框架的ServerWebExchange。它可以匹配HTTP请求中的任何东西,⽐如:请求头或者参数。
过滤器:是Spring框架的GatewayFilter,请求和响应都可以被Filter修改。
1、新建⼀个module,按照上⾯的⽅式,名称叫: gateway
2、添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
</dependencies>
3、新建⼀个主启动类 GatewayApplication
fengyu.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GatewayApplication
{
public static void main(String[] args)
{
SpringApplication.run(GatewayApplication.class, args);
}
}
4、新增⼀个l⽂件,内容如下:
server:
port: 8080
spring:
application:
name: gateway_server
cloud:
gateway:
default-filters:
routes:
- id: my_route
spring framework是什么系统uri: localhost:1001/
predicates:
- Path=/gateway/**
filters:
- StripPrefix=1
5、测试
访问
上⾯只是简单的路由转发,可以先了解下⼯作原理:
url 中的会访问到gateway这个服务,spring cloud gateway会在配置的路由中做谓词匹配,也就是url中的gateway匹配到了id为my_route的路由,就会把替换为,并且filters中的规则(StripPrefix)会把中的gateway去掉,那么实际就会去访问也就是访问到了provider1001服务。
疑问?
上⾯的uri只配置了provider1001服务,如何使⽤geteway访问三个服务呢?需要使⽤负载均衡ribbon
3、ribbon负载均衡
下⾯的操作都是在gateway这个服务操作的:
1、添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
2、修改配置⽂件,增加或者修改见红⾊部分
server:
port: 8080
spring:
application:
name: gateway_server
cloud:
gateway:
default-filters:
routes:
- id: my_route
uri: lb://my-load-balanced-service
predicates:
-
Path=/gateway/**
filters:
- StripPrefix=1
my-load-balanced-service:
ribbon:
listOfServers: localhost:1001, localhost:1002,localhost:1003
NFLoadBalancerRuleClassName: comflix.loadbalancer.RoundRobinRule
3、重启gateway服务,不断访问,发现可以不断访问的时候在三个服务中来回切换,达到了负载均衡的⽬的。上⾯我们使⽤了轮询的负载均衡策略。
注意:
listOfServers:配置的微服务的服务器ip端⼝
NFLoadBalancerRuleClassName:使⽤的负载均衡策略,默认提供了⼏种,也可以⾃⼰实现(后续讲解),默认提供的如下:疑问:
如果上⾯listOfServers中的任何⼀个服务关闭了,然后使⽤gateway访问,会出现什么情况?
事实是这样的:
⽐如provider1003服务宕机。那么使⽤轮询算法的时候,不断访问gateway,会出现:
provider1001 正常,provider1002 正常,provider1003 异常,provider1001 正常,provider1002 正常,provider1003 异常。。。
provider1003 已经宕机,但是请求还是不断转发到该服务上,导致服务访问的过程中,部分请求异常。
我们需要有这样的功能,如果某个服务宕机,那么请求就不会发送到该服务器上,如果宕机的服务器恢复了,那么请求⼜可以发送到该服务器上,要实现这个功能,需要ribbon对服务进⾏健康检查。
(1)⾸先微服务需要有个rest接⼝,就叫做heath接⼝吧,调⽤heath接⼝返回ok表明服务正常。
(2)gateway需要有调⽤heath接⼝的功能,并且配置到ribbon可以不断调⽤该接⼝,时刻检查服务的状态,如果有服务器挂掉,可以很快感知到,并把该服务剔除可⽤服务列表。
4、健康检查
1、provider1001,provider1002,provider1003增加⼀个rest接⼝HealthController
ller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HealthController
{
@GetMapping("/heath")
@ResponseBody
public String heath()
{
return "ok";
}
}
2、在gateway⼯程⾥⾯做如下修改
(1)新建⼀个Config类
fig;
import t.annotation.Bean;
import t.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class MainConfig
{
@Bean
public RestTemplate restTemplate()
{
return new RestTemplate();
}
}
(2)新建⼀个健康检查的类,主要是调⽤heath接⼝。
fengyu.gateway.loadbanlance;
import comflix.loadbalancer.IPing;
import comflix.loadbalancer.Server;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class HealthExamination implements IPing
{
@Autowired
private RestTemplate restTemplate;
@Override
public boolean isAlive(Server server)
{
String url = "" + Id() + "/heath";
try
{
ResponseEntity<String> heath = ForEntity(url, String.class);
if (StatusCode() == HttpStatus.OK)
{
System.out.println("ping " + url + " success and response is " + Body());
return true;
}
System.out.println("ping " + url + " error and response is " + Body());
return false;
}
catch (Exception e)
{
System.out.println("ping " + url + " failed");
return false;
}
}
}
上⾯代码继承IPing接⼝,判断服务是否可⽤。我们在微服务中增加heath接⼝,在gateway中调⽤该接⼝,如果返回正常则认为微服务可⽤。
(3)修改配置⽂件,注意最后⼀⾏,这是唯⼀增加的。
server:
port: 8080
spring:
application:
name: gateway_server
cloud:
gateway:
default-filters:
routes:
- id: my_route
uri: lb://my-load-balanced-service
predicates:
- Path=/gateway/**
filters:
- StripPrefix=1
my-load-balanced-service:
ribbon:
listOfServers: localhost:1001,localhost:1002,localhost:1003
NFLoadBalancerRuleClassName: comflix.loadbalancer.RoundRobinRule
NFLoadBalancerPingClassName: fengyu.gateway.loadbanlance.HealthExamination
3、重新启动微服务和gateway服务,然后通过⽹关访问,可以看到可以正常访问,如果此时把某⼀台微服务停掉,访问的时候开始可能会报错,但是随着健康检查的运⾏,检测到该服务不可⽤,则会把该服务剔除,以后只会访问正常运⾏的服务。当宕机的服务重启,健康检查还会把该服务加⼊到可⽤服务列表,下次请求就会再次发送到该服务上。
5、⾃定义负载均衡策略
上⾯演⽰了随机、轮询等负载均衡算法,我们可以⾃定义负载均衡算法。需求是:每个服务器访问三次再跳转到下⼀个服务器。
只需要在gateway项⽬中实现AbstractLoadBalancerRule抽象类,然后配置到下⾯即可
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论