学习 Spring-Cloud - 写一个微服务

  继续我的Spring-Cloud学习旅程,早些时候我已经学习了如何创建一个典型的以Spring-Cloud和Netflix OSS为基础的微服务环境 - 在这个具体的列子中两个关键的组件,Eureka用来注册、发现服务和Spring Cloud Configuration用来维护一个服务的配置文件的中央仓库。这里我将会展示我如何开发两个微服务样品,一个简单的“pong”服务和一个调用“pong”服务的“ping”服务。

Pong服务样例

  处理"ping"请求的端点是一个典型的spring mvc基础端点:
@RestController
public class PongController {

    @Value("${reply.message}")
    private String message;

    @RequestMapping(value = "/message", method = RequestMethod.POST)
    public Resource<MessageAcknowledgement> pongMessage(@RequestBody Message input) {
        return new Resource<>(
                new MessageAcknowledgement(input.getId(), input.getPayload(), message));
    }

}

 它获得了一个消息并且以一个确认应答。这里服务使用了配置服务器提供的"reply.message"属性。但"pong"服务是如何找到配置服务器的呢,有两种方法 - 直接定义配置服务器的位置,或者通过Eureka找到配置服务器。我使用了Eureka来找到配置文件服务器。Spring Cloud使这整个流程非常简单,所有它需要的只是一个包含了下面几行的"bootstrap.yml"属性文件:

---
spring:
  application:
    name: sample-pong
  cloud:
    config:
      discovery:
        enabled: true
        serviceId: SAMPLE-CONFIG

eureka:
  instance:
    nonSecurePort: ${server.port:8082}
  client:
    serviceUrl:
      defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/

  Eureka的位置定义通过 "eureka.client.serviceUrl"属性和 "spring.cloud.config.discovery.enabled" 设置为 "true" 来明确提出配置服务器将会通过Eureka服务器被发现(发布)。

  简单的说,这意味着Eureka和配置服务器在启动其他真正的服务之前必须已经完全启动,他们是预先必需的和在整个架构启动时让其中的组件可用的的基础。

  配置服务器拥有"sample-pong"服务需要的属性,它们可以在配置服务器的端点 - http://localhost:8888/sample-pong/default中被验证,8888是服务端点的端口号,和应该以下行的内容响应:

"name": "sample-pong",
  "profiles": [
    "default"
  ],
  "label": "master",
  "propertySources": [
    {
      "name": "classpath:/config/sample-pong.yml",
      "source": {
        "reply.message": "Pong"
      }
    }
  ]
}

  可以看到来自中心的"reply.message"属性将会被pong service使用作为确认的消息。

  现在来设置一个端点作为一个服务,作为一个Spring boot为基础的端点所需要的就是下面几行:

@SpringBootApplication
@EnableDiscoveryClient
public class PongApplication {
    public static void main(String[] args) {
        SpringApplication.run(PongApplication.class, args);
    }
}

  这些完成了"pong"服务的编码。

Ping服务样例

  现在集中完成一个"pong"微服务的消费者,命名它为"ping"微服务。Spring-Cloud和Netflix OSS提供了许多选项来调用Eureka上注册的服务端点,总结下我拥有的 选项:
  1.使用原始的Eureka DiscoveryClient 来找到服务实例的主机并且用Spring的RestTemplate来发起调用。
  2.使用Ribbon,一个使用Eureka来找到服务实例的客户端负载均衡解决方案
  3. 使用Feigin,它使用了一个说明性的方法来调用服务。它内部使用了Ribbon
  我使用了Feign。所有需要的是一个实现了调用服务的协议的接口:

package org.bk.consumer.feign;

import org.bk.consumer.domain.Message;
import org.bk.consumer.domain.MessageAcknowledgement;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@FeignClient("samplepong")
public interface PongClient {

    @RequestMapping(method = RequestMethod.POST, value = "/message",
            produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    MessageAcknowledgement sendMessage(@RequestBody Message message);
}

  注解@FeignClient("samplepong") 内部指向一个Ribbon"命名"叫"samplepong"客户端。这意味着在配置文件中肯定有一个以此命名的客户端记录,在我的例子中我把这些记录定义在application.yml文件中:

samplepong:
  ribbon:
    DeploymentContextBasedVipAddresses: sample-pong
    NIWSServerListClassName: com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
    ReadTimeout: 5000
    MaxAutoRetries: 2

  这里最重要的记录是"samplepong.ribbon.DeploymentContextBasedVipAddresses"指向被Ribbon调用时发现的"pong"服务实例的Eureka 注册地址

  剩下的应用是路由Spring Boot引用。我已经在Hystrix后面暴露了服务调用地址,Hystrix会给调用失败加上防护和从底层上保护了FeignClient:.

package org.bk.consumer.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.bk.consumer.domain.Message;
import org.bk.consumer.domain.MessageAcknowledgement;
import org.bk.consumer.feign.PongClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service("hystrixPongClient")
public class HystrixWrappedPongClient implements PongClient {

    @Autowired
    @Qualifier("pongClient")
    private PongClient feignPongClient;

    @Override
    @HystrixCommand(fallbackMethod = "fallBackCall")
    public MessageAcknowledgement sendMessage(Message message) {
        return this.feignPongClient.sendMessage(message);
    }

    public MessageAcknowledgement fallBackCall(Message message) {
        MessageAcknowledgement fallback = new MessageAcknowledgement(message.getId(), message.getPayload(), "FAILED SERVICE CALL! - FALLING BACK");
        return fallback;
    }
}

。。。

  对spring cloud的知识点都已经在上面的内容里,所以后面的启动过程就不继续翻译了

References

  1. The code is available at  my github location -  https://github.com/bijukunjummen/spring-cloud-ping-pong-sample 

  2. Most of the code is heavily borrowed from  the spring-cloud-samples repository -  https://github.com/spring-cloud-samples


原文:https://dzone.com/articles/learning-spring-cloud-writing

你可能感兴趣的:(spring,微服务,spring-cloud)