gpt4 book ai didi

java - 使用 Elastic Beanstalk,我能否以编程方式确定我是否在领导节点上?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:49:09 24 4
gpt4 key购买 nike

我在 Tomcat 上运行的 Elastic Beanstalk Java 应用程序中有一些内务管理任务,我需要经常运行它们。我希望这些任务仅在领导节点上运行(或者更准确地说,在单个节点上,但领导者似乎是一个显而易见的选择)。

我一直在研究在 Elastic Beanstalk 中运行 cron 作业,但感觉这应该比我想出的更简单。理想情况下,我希望在我的网络应用程序中使用以下两个选项之一:

  1. 在当前 JRE 中测试此服务器是否是领导节点的某种方法
  2. 一些方法可以点击特定的 URL(wget?)来触发任务,但也可以将该 URL 限制为来自本地主机的请求。

建议?

最佳答案

这是不可能的,按设计( leaders are only assigned during deployment ,并且在其他情况下不需要)。但是,您可以为此目的调整和使用 EC2 元数据。

这是一个有关如何实现此结果的工作示例 (original source)。调用 getLeader 后,它将找到 - 或分配 - 一个要设置为领导者的实例:

package br.com.ingenieux.resource;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import org.apache.commons.io.IOUtils;

import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.model.CreateTagsRequest;
import com.amazonaws.services.ec2.model.DeleteTagsRequest;
import com.amazonaws.services.ec2.model.DescribeInstancesRequest;
import com.amazonaws.services.ec2.model.Filter;
import com.amazonaws.services.ec2.model.Instance;
import com.amazonaws.services.ec2.model.Reservation;
import com.amazonaws.services.ec2.model.Tag;
import com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalk;
import com.amazonaws.services.elasticbeanstalk.model.DescribeEnvironmentsRequest;

@Path("/admin/leader")
public class LeaderResource extends BaseResource {
@Inject
AmazonEC2 amazonEC2;

@Inject
AWSElasticBeanstalk elasticBeanstalk;

@GET
public String getLeader() throws Exception {
/*
* Avoid running if we're not in AWS after all
*/
try {
IOUtils.toString(new URL(
"http://169.254.169.254/latest/meta-data/instance-id")
.openStream());
} catch (Exception exc) {
return "i-FFFFFFFF/localhost";
}

String environmentName = getMyEnvironmentName();

List<Instance> environmentInstances = getInstances(
"tag:elasticbeanstalk:environment-name", environmentName,
"tag:leader", "true");

if (environmentInstances.isEmpty()) {
environmentInstances = getInstances(
"tag:elasticbeanstalk:environment-name", environmentName);

Collections.shuffle(environmentInstances);

if (environmentInstances.size() > 1)
environmentInstances.removeAll(environmentInstances.subList(1,
environmentInstances.size()));

amazonEC2.createTags(new CreateTagsRequest().withResources(
environmentInstances.get(0).getInstanceId()).withTags(
new Tag("leader", "true")));
} else if (environmentInstances.size() > 1) {
DeleteTagsRequest deleteTagsRequest = new DeleteTagsRequest().withTags(new Tag().withKey("leader").withValue("true"));

for (Instance i : environmentInstances.subList(1,
environmentInstances.size())) {
deleteTagsRequest.getResources().add(i.getInstanceId());
}

amazonEC2.deleteTags(deleteTagsRequest);
}

return environmentInstances.get(0).getInstanceId() + "/" + environmentInstances.get(0).getPublicIpAddress();
}

@GET
@Produces("text/plain")
@Path("am-i-a-leader")
public boolean isLeader() {
/*
* Avoid running if we're not in AWS after all
*/
String myInstanceId = null;
String environmentName = null;
try {
myInstanceId = IOUtils.toString(new URL(
"http://169.254.169.254/latest/meta-data/instance-id")
.openStream());

environmentName = getMyEnvironmentName();
} catch (Exception exc) {
return false;
}

List<Instance> environmentInstances = getInstances(
"tag:elasticbeanstalk:environment-name", environmentName,
"tag:leader", "true", "instance-id", myInstanceId);

return (1 == environmentInstances.size());
}

protected String getMyEnvironmentHost(String environmentName) {
return elasticBeanstalk
.describeEnvironments(
new DescribeEnvironmentsRequest()
.withEnvironmentNames(environmentName))
.getEnvironments().get(0).getCNAME();
}

private String getMyEnvironmentName() throws IOException,
MalformedURLException {
String instanceId = IOUtils.toString(new URL(
"http://169.254.169.254/latest/meta-data/instance-id"));

/*
* Grab the current environment name
*/
DescribeInstancesRequest request = new DescribeInstancesRequest()
.withInstanceIds(instanceId)
.withFilters(
new Filter("instance-state-name").withValues("running"));

for (Reservation r : amazonEC2.describeInstances(request)
.getReservations()) {
for (Instance i : r.getInstances()) {
for (Tag t : i.getTags()) {
if ("elasticbeanstalk:environment-name".equals(t.getKey())) {
return t.getValue();
}
}
}
}

return null;
}

public List<Instance> getInstances(String... args) {
Collection<Filter> filters = new ArrayList<Filter>();

filters.add(new Filter("instance-state-name").withValues("running"));

for (int i = 0; i < args.length; i += 2) {
String key = args[i];
String value = args[1 + i];

filters.add(new Filter(key).withValues(value));
}

DescribeInstancesRequest req = new DescribeInstancesRequest()
.withFilters(filters);
List<Instance> result = new ArrayList<Instance>();

for (Reservation r : amazonEC2.describeInstances(req).getReservations())
result.addAll(r.getInstances());

return result;
}
}

关于java - 使用 Elastic Beanstalk,我能否以编程方式确定我是否在领导节点上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21917598/

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