之前的实现中,已经有了很多的微服务API,如:天气数据API微服务、天气预报API微服务等。每个微服务提供各自的API,其他第三方是通过微服务的名称进行调用,这样的管理是有一个问题-----API没有一个统一的管理。自己想要哪个微服务就调用哪个微服务,没有一个统一的入口。而API网关就是来做一个统一的入口。
常见的API网关的实现方式:
Zuul是Spring Cloud全家桶中的微服务API网关。
所有从设备或网站来的请求都会经过Zuul到达后端的Netflix应用程序。作为一个边界性质的应用程序,Zuul提供了动态路由、监控、弹性负载和安全功能。Zuul底层利用各种filter实现如下功能:
这里将“weather-eureka-client”微服务集成Zuul
1)、导入依赖
org.springframework.cloud
spring-cloud-starter-netflix-zuul
2)、修改主类
在主类上添加注解@EnableZuulProxy
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableZuulProxy
public class WeatherEurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(WeatherEurekaClientApplication.class, args);
}
}
3)、修改配置application.yml
spring:
application:
name: weather-eureka-client
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
zuul:
routes:
# 在本地用什么来映射,比如/cities会映射成本地的/city/cities
city.path: /city/**
# 服务名
city.serviceId: weather-city-server
4)、运行测试
先在IDE中启动“weather-eureka-server”,再在命令行通过指定端口8081来启动“weather-city-server”,最后在IDE中启动“weather-eureka-client”
The bean 'proxyRequestHelper', defined in class path resource [org/springframework/cloud/netflix/zuul/ZuulProxyAutoConfiguration$NoActuatorConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/cloud/netflix/zuul/ZuulProxyAutoConfiguration$EndpointConfiguration.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
Disconnected from the target VM, address: 'javadebug', transport: 'shared memory'
根据报错信息,原因是SpringBoot的版本和SpringCloud的版本不兼容。
解决启动Zuul时报错
再次修改SpringCloud版本:Greenwich.RELEASE
5)、浏览器访问:http://localhost:8080/city/cities
【注意】:8080端口对应的是“weather-eureka-client”。当以上面的那条连接进行访问时,
由于天气预报API微服务依赖于天气数据API微服务和城市数据API微服务。所以,这里改造“weather-report-server”
1)、配置网关:
spring:
application:
name: weather-eureka-client
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
zuul:
routes:
city.path: /city/**
city.serviceId: weather-city-server
data.path: /data/**
data.serviceId: weather-data-server
删除之前两个接口,添加一个新接口“DataClient”
DataClient
@FeignClient("weather-eureka-client") // API网关
public interface DataClient {
// 获取城市列表
@GetMapping("/city/cities")
List listCity() throws Exception;
// 根据城市id查询天气数据
@GetMapping("/data/weather/cityId/{cityId}")
WeatherResponseVO getDataByCityId(@PathVariable("cityId") String cityId);
}
WeatherReportController
@RestController
@RequestMapping("/report")
@Slf4j
public class WeatherReportController {
@Autowired
private DataClient dataClient;
@GetMapping("/cityId/{cityId}")
public ModelAndView getReportByCityId(@PathVariable("cityId") String cityId, Model model) throws Exception {
// 改为由城市数据API微服务提供数据
List cityList = null;
...
}
WeatherReportServiceImpl
@Service
public class WeatherReportServiceImpl implements WeatherReportService {
@Autowired
private DataClient dataClient;
...
}
先启动Redis + Eurake Server(weather-eureka-server)+启动四个微服务(命令行指定端口)+一个API网关(weather-eureka-client)
启动四个微服务时,注意顺序: