gpt4 book ai didi

spring-cloud - 在 PWS 上使用 Spring Cloud/Netflix 堆栈进行蓝/绿部署的规范方法是什么?

转载 作者:行者123 更新时间:2023-12-04 02:56:44 27 4
gpt4 key购买 nike

我正在试验一种与此处图片中详述的设置非常相似的设置:https://raw.githubusercontent.com/Oreste-Luci/netflix-oss-example/master/netflix-oss-example.png

enter image description here

在我的设置中,我使用了一个客户端应用程序 (https://www.joedog.org/siege-home/)、一个代理 (Zuul)、一个发现服务 (Eureka) 和一个简单的微服务。一切都部署在 PWS 上。

我想从我的简单微服务的一个版本迁移到下一个版本 没有任何停机时间 .最初我开始使用这里描述的技术:https://docs.cloudfoundry.org/devguide/deploy-apps/blue-green.html

在我看来,这种方法与 Eureka 等发现服务不“兼容”。事实上,我的服务的新版本已在 Eureka 中注册并在我重新映射所有路由(CF 路由器)之前接收流量。

这将我引向另一种方法,在该方法中我依赖 Spring Cloud/Netflix 中的故障转移机制:

  • 我启动了我的服务的新(向后兼容)版本。
  • 当 Zuul/Eureka 选择这个版本时,它开始获得 50% 的流量。
  • 一旦我确认新版本正常工作,我就会删除“旧”实例。 (我只是在 PWS 中单击“停止”按钮)

  • 据我了解,Zuul 在幕后使用 Ribbon(负载平衡),因此在旧实例仍在 Eureka 但实际上关闭的那一瞬间,我希望重试新实例而不会对客户端产生任何影响。

    然而,我的假设是错误的。我的客户端出现了一些 502 错误:
    Lifting the server siege...      done.

    Transactions: 5305 hits
    Availability: 99.96 %
    Elapsed time: 59.61 secs
    Data transferred: 26.06 MB
    Response time: 0.17 secs
    Transaction rate: 89.00 trans/sec
    Throughput: 0.44 MB/sec
    Concurrency: 14.96
    Successful transactions: 5305
    Failed transactions: 2
    Longest transaction: 3.17
    Shortest transaction: 0.14

    我的 application.yml 的一部分
    server:
    port: ${PORT:8765}

    info:
    component: proxy

    ribbon:
    MaxAutoRetries: 2 # Max number of retries on the same server (excluding the first try)
    MaxAutoRetriesNextServer: 2 # Max number of next servers to retry (excluding the first server)
    OkToRetryOnAllOperations: true # Whether all operations can be retried for this client
    ServerListRefreshInterval: 2000 # Interval to refresh the server list from the source
    ConnectTimeout: 3000 # Connect timeout used by Apache HttpClient
    ReadTimeout: 3000 # Read timeout used by Apache HttpClient

    hystrix:
    threadpool:
    default:
    coreSize: 50
    maxQueueSize: 100
    queueSizeRejectionThreshold: 50
    command:
    default:
    execution:
    isolation:
    thread:
    timeoutInMilliseconds: 10000

    我不确定出了什么问题。

    这是技术问题吗?

    还是我做出了错误的假设(我确实在某处读到过 POST 无论如何都不会重试,我不太明白)?

    我很想听听你是怎么做的。

    谢谢,安迪

    最佳答案

    我也想过这个问题。我不会声称使用过 Spring Cloud “In Anger”。我刚刚尝试了一段时间。

    假设:我们假设所有实例状态的真实来源都存储在 Eureka 中,那么 Eureka 应该是我们的操作控制机制。我们可以使用 Eureka 通过将实例状态设置为 OUT_OF_SERVICE 来使实例停止服务。 .当 Ribbon 刷新其服务器列表时,它不会使用这些停止服务的实例。 Eureka 提供了一个用于查询实例和设置实例状态的 REST API。伟大的。

    问题是:如何确定哪些实例在 Blue 组中,哪些实例在 Green 组中?

    我在想…… Eureka 为每个实例提供了一个元数据映射。说在我们的构建/烘焙步骤中,我们在元数据映射中设置了一个版本 ID?我们可以使用 Git 提交 ID 或一些语义版本控制方案或其他任何东西。好的,现在我可以查看 Eureka 元数据并根据该版本值识别 Blue 与 Green 实例。我们可以使用属性在每个服务中设置元数据值。

    例如eureka.instance.metadataMap.version=8675309
    现在如果我们能告诉 Eureka 就好了。 “让 FUBAR 服务的所有实例和版本 8675309 停止服务。”好吧,我认为这不是开箱即用的。 Spring Cloud 很酷的一点是,包括 Eureka Server 在内的所有这些服务都只是 Spring 应用程序,我们可以根据自己的需要进行破解。下面的代码公开了一个端点,该端点根据应用程序名称和版本将实例设置为“停止服务”。只需将此 Controller 添加到您的 Eureka 服务器即可。它不是生产就绪的,只是一个想法。

    现在,一旦 Eureka 停止服务这些实例并且 Ribbon 刷新其服务器列表,就可以安全地杀死或路由远离这些实例。

    发布到:

    http://[eurekahost:port]/takeInstancesOutOfService?applicationName=FOOBAR&version=8675309

    希望有帮助吗?
    import java.util.Collection;
    import java.util.function.Predicate;
    import java.util.stream.Collectors;

    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;

    import com.netflix.appinfo.InstanceInfo;
    import com.netflix.appinfo.InstanceInfo.InstanceStatus;
    import com.netflix.discovery.shared.Application;
    import com.netflix.eureka.EurekaServerContextHolder;
    import com.netflix.eureka.registry.PeerAwareInstanceRegistry;

    @RestController
    public class EurekaInstanceStateController {

    @RequestMapping(value="/instancesQuery", method=RequestMethod.POST)
    public Collection<String> queryInstancesByMetaData(
    @RequestParam("applicationName") String applicationNameCriteria,
    @RequestParam("version") String versionCriteria)
    {
    return getRegistry().getSortedApplications()
    .stream()
    .filter(hasApplication(applicationNameCriteria))
    .flatMap(app -> app.getInstances().stream())
    .filter(hasVersion(versionCriteria))
    .map(info -> info.getAppName() + " - " + info.getId() + " - " + info.getStatus() + " - " + info.getMetadata().get("version"))
    .collect(Collectors.toList());
    }

    @RequestMapping(value="/takeInstancesOutOfService", method=RequestMethod.POST)
    public Collection<String> takeInstancesOutOfService(
    @RequestParam("applicationName") String applicationNameCriteria,
    @RequestParam("version") String versionCriteria)
    {
    return getRegistry().getSortedApplications()
    .stream()
    .filter(hasApplication(applicationNameCriteria))
    .flatMap(app -> app.getInstances().stream())
    .filter(hasVersion(versionCriteria))
    .map(instance -> updateInstanceStatus(instance, InstanceStatus.OUT_OF_SERVICE) )
    .collect(Collectors.toList());
    }

    /**
    * @param instance
    * @return
    */
    private String updateInstanceStatus(InstanceInfo instance, InstanceStatus status)
    {
    boolean isSuccess = getRegistry().statusUpdate(instance.getAppName(), instance.getId(),
    status, String.valueOf(System.currentTimeMillis()),
    true);

    return (instance.getAppName() + " - " + instance.getId() + " result: " + isSuccess);
    }

    /**
    * Application Name Predicate
    * @param applicationNameCriteria
    * @return
    */
    private Predicate<Application> hasApplication(final String applicationNameCriteria)
    {
    return application -> applicationNameCriteria.toUpperCase().equals(application.getName());
    }

    /**
    * Instance Version Predicate. Uses Eureka Instance Metadata value name "version".</br>
    *
    * Set / Bake the instance metadata map to contain a version value.</br>
    * e.g. eureka.instance.metadataMap.version=85839c2
    *
    * @param versionCriteria
    * @return
    */
    private Predicate<InstanceInfo> hasVersion(final String versionCriteria)
    {
    return info -> versionCriteria.equals(info.getMetadata().get("version"));
    }

    private PeerAwareInstanceRegistry getRegistry() {
    return EurekaServerContextHolder.getInstance().getServerContext().getRegistry();
    }
    }

    关于spring-cloud - 在 PWS 上使用 Spring Cloud/Netflix 堆栈进行蓝/绿部署的规范方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36773334/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com