首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

使用Spring Cloud连接不同服务(3)

使用Spring Cloud连接不同服务(3)

Spring Cloud Config Client修改logbook服务使其从新增的Config Server中读取配置,这一过程只需要几个简单的步骤。首先在build.gradle文件中为spring-cloud-starter-config`增加一个依存项;
compile("org.springframework.cloud:spring-cloud-starter-config:1.1.1.BUILD-SNAPSHOT")
随后提供Config Client所需的基本自举配置。考虑到Config Server会通过一个名为repmax.properties的文件暴露配置,此时要向Config Client提供应用程序的名称。此类自举配置位于logbook服务的bootstrap.properties文件中:spring.application.name=repmax
默认情况下,Config Client会通过http://localhost:8888查找Config Server。若要修改这个地址,可在启动客户端应用程序时指定SPRING_CLOUD_CONFIG_URI环境。
一旦客户端,即本例中的logbook启动后,即可访问http://localhost:8081/env以确认来自Config Server的配置是否正确加载:

确认Config Client可以访问Config Server
将logbook服务配置为使用Config Client后,可修改ConfigurableLeaderBoardApi以从Config Server暴露的leaderboard.lb.url属性中获取负载平衡器的地址。
启用动态刷新通过将配置信息集中存储在一个位置,可以轻松更改repmax配置,使其能够被所有服务直接使用。然而为了应用这些配置依然需要重启动服务。实际上可以通过更好的方式实现。可以借助Spring Boot提供的@ConfigurationProperties标注将配置直接映射给JavaBeans。Spring Cloud Config更进一步为每个客户端服务暴露了一个/refresh端点。带有@ConfigurationProperties标注的Bean可在通过/refresh端点触发刷新后更新自己的属性。
任何Bean均可添加@ConfigurationProperties标注,但是有必要对刷新操作进行限制,只应用于包含配置数据的Bean。为此可以用一个专门用于保存leaderboard地址的LeaderboardConfig Bean:
[url=][/url]
@ConfigurationProperties("leaderboard.lb")public class LeaderboardConfig {    private volatile String url;    public String getUrl() {        return this.url;    }    public void setUrl(String url) {        this.url = url;    }}[url=][/url]

@ConfigurationProperties标注的值实际上是希望映射至Bean的配置值的前缀。随后每个值可使用标准的JavaBean命名规则进行映射。这种情况下,url Bean属性可映射至配置中的leaderboard.lb.url。
随后要修改ConfigurableLeaderBoardApi以接受LeaderboardConfig实例,而非原始的leaderboard地址:
[url=][/url]
public class ConfigurableLeaderBoardApi extends AbstractLeaderBoardApi {    private final LeaderboardConfig config;    @Autowired    public ConfigurableLeaderBoardApi(LeaderboardConfig config) {        this.config = config;    }    @Override    protected String getLeaderBoardAddress() {        return this.config.getLeaderboardAddress();    }}[url=][/url]

为了触发配置刷新操作,可向logbook服务的/refresh端点发送一个HTTP POST请求:curl -X POST http://localhost:8081/refresh
有关服务发现通过使用Spring Cloud Config,并在logbook和leaderboard服务之间使用负载平衡代理,应用程序已经基本完成了。然而还需要进行一定的完善。
如果在AWS或GCP中部署,可以充分利用这些环境中提供的高弹性负载平衡器,但如果使用诸如HAProxy或NGINX之类的市售负载平衡代理产品,此时必须自行处理服务的发现和注册工作。leaderboard的每个新增实例,以及每个因为故障要从代理中移除的实例,都必须在代理中进行配置。我们真正需要的是动态发现技术,每个服务实例都需要能自行注册以供发现和使用。
使用负载平衡代理的情况下还存在另一个潜在问题:可靠性。由于所有流量需要通过代理进行路由,因此整个系统的可靠性都受制于代理本身的可靠性。代理停机同时会导致整个系统停机。此外还需要考虑客户端和代理之间,以及代理和服务器之间通信所产生的开销。
为解决这些问题Netflix开发了Eureka。Eureka是一种用于提供服务注册和发现能力的客户端-服务器系统。服务实例启动后,可将自己与Eureka服务器进行注册。诸如logbook等客户端服务可以联系Eureka服务器以获取可用服务列表。客户端和服务器之间采用了点对点的通信方式。
Eureka使得我们不再需要代理,这样可以改善整个系统的可靠性。如果leaderboard代理故障,logbook服务将完全无法联系leaderboard服务。通过使用Eureka,logbook可以知道所有可用leaderboard实例,就算一个实例故障,logbook也只需要联系下一个leaderboard实例并重试。
那么在整个系统体系结构中,Eureka服务器本身是否会成为一个故障点?抛开为Eureka服务器创建集群这种做法不谈,每个Eureka客户端都可以在本地缓存服务的运行状态。只要在Eureka服务器上运行了服务监视器,例如systemd,就可以顺利应对偶尔出现的崩溃等问题。
与Config Server类似,Eureka服务器也可以作为一个小巧的Spring Boot应用程序来运行:
[url=][/url]
@SpringBootApplication@EnableEurekaServerpublic class RepmaxEurekaServerApplication {    public static void main(String[] args) {        SpringApplication.run(RepmaxEurekaServerApplication.class, args);    }}[url=][/url]

在应用程序启动时,@EnableEurekaServer标注会通知Spring Boot启动Eureka。出于高可用目的,默认情况下服务器会尝试联系其他服务器。在独立安装的情况下可以考虑在application.yml中关闭该功能:
[url=][/url]
server:  port: 8761eureka:  instance:    hostname: localhost  client:    registerWithEureka: false    fetchRegistry: false[url=][/url]

请注意,按照惯例可在8761端口运行Eureka服务器。访问http://localhost:8761可以查看Eureka仪表板。由于目前尚未注册任何服务,可用实例列表中什么也没显示:

空白的Eureka仪表板
若要将leaderboard服务注册至Eureka,可为该应用程序类添加一个@EnableEurekaClient标注。随后通过application.properties告诉Eureka客户端在哪里可以找到服务器,以及应用程序在服务器上注册时所用的名称:
spring.application.name=repmax-leaderboardeureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka
leaderboard服务启动时,Spring Boot会检测到@EnableEurekaClient标注并启动Eureka客户端,随后该客户端会将leaderboard服务注册至Eureka服务器。Eureka仪表板将会显示出新注册的服务:

服务注册后Eureka仪表板显示的内容
logbook服务可以通过与leaderboard服务相同的方式配置为Eureka客户端,需要添加@EnableEurekaClient标注并配置Eureka服务URL。
通过在logbook服务中启用Eureka客户端,Spring Cloud会暴露一个用于查询服务实例的DiscoveryClient Bean:
[url=][/url]
@Componentpublic class DiscoveryLeaderBoardApi extends AbstractLeaderBoardApi {    public DiscoveryLeaderBoardApi(DiscoveryClient discoveryClient) {        this.discoveryClient = discoveryClient;    }    private final DiscoveryClient discoveryClient;    @Override    protected String getLeaderBoardAddress() {        List<ServiceInstance> instances = this.discoveryClient.getInstances("repmax-leaderboard");        if(instances != null && !instances.isEmpty()) {            ServiceInstance serviceInstance = instances.get(0);            return String.format("http://%s:%d", serviceInstance.getHost(), serviceInstance.getPort());        }        throw new IllegalStateException("Unable to locate a leaderboard service");    }}[url=][/url]


调用DiscoveryClient.getInstances可获得ServiceInstances列表,列表中每一项均对应了一个注册到Eureka服务器的leaderboard服务。从简化的角度考虑,可以从列表中选择第一项服务用于远程调用。
返回列表