gcs新的发展趋势_锁定多个节点的简单方法:GCS

gcs新的发展趋势

gcs新的发展趋势

它发生在我们所有人身上。 我们开发了无状态应用程序,可以不费力地水平扩展。但是,有时会出现需要进行某种协调的情况。

您可以在此方面真正地前进。 例如,您可以使用Akka之类的框架及其集群功能。 或者,您也可以像简单地自己滚动机制一样简单,只要它可以为您提供所需的结果即可。 另外,根据您需要他们进行的工作,您可以拥有不同的节点组。 选项和解决方案可以根据问题进行更改。

如果您的问题可以通过一个简单的选项解决,那么在您使用Google Cloud Storage的情况下,一种解决方法是使用其锁定功能。例如,假设有一个4个节点的场景,它们确实会动态扩展,但是每当一个新节点注册时,您想要通过获取一个唯一的配置来更改其操作,该配置不会与另一个节点可能收到的配置发生冲突。

该策略可以是使用Google Cloud Storage上的文件进行锁定,以及充当集中配置注册表的文件。

锁定文件不过是应在云存储上创建和删除的文件。 赋予我们锁定能力的是GCS上仅当文件不存在时才创建文件的选项。因此,来自一个节点的进程将尝试创建“锁”文件,此操作等同于获取锁。一旦该过程完成,将删除文件,此操作等同于释放锁定。同时,其他进程将尝试创建文件(获取锁)并失败(文件已存在),因为其他进程已创建文件。同时,成功创建文件(获取锁)的过程将更改集中式配置注册表,完成后将删除文件(释放锁)。

因此,让我们从锁定对象开始。

 package com.gkatzioura.gcs.lock;
 import java.util.Optional;
 import com.google.cloud.storage.Blob;
 import com.google.cloud.storage.BlobInfo;
 import com.google.cloud.storage.Storage;
 import com.google.cloud.storage.StorageException;

public class GCSLock { 
    public static final String LOCK_STRING = "_lock" ;

    private final Storage storage;

    private final String bucket;

    private final String keyName; 
    private Optional<Blob> acquired = Optional.empty(); 
    GCSLock(Storage storage, String bucket, String keyName) {

        this .storage = storage;

        this .bucket = bucket;

        this .keyName = keyName;

    }

    public boolean acquire() {

        try {

            var blobInfo = BlobInfo.newBuilder(bucket, keyName).build();

            var blob = storage.create(blobInfo, LOCK_STRING.getBytes(), Storage.BlobTargetOption.doesNotExist());

            acquired = Optional.of(blob);

            return true ;

        } catch (StorageException storageException) {

            return false ;

        }

    }

    public void release() {

        if (!acquired.isPresent()) {

            throw new IllegalStateException( "Lock was never acquired" );

        }

        storage.delete(acquired.get().getBlobId());

    }
 }

如您所见,write指定仅当对象不存在时才写入对象。 幕后该操作使用x-goog-如果代匹配头,其用于对并发。因此,一个节点将能够获取锁并更改配置文件。之后,它可以删除锁。 如果引发异常,则操作可能会失败并且该锁已被获取。

为了使示例更完整,让我们制作配置文件。 配置文件将是用于键映射操作的简单json文件。

 package com.gkatzioura.gcs.lock;
 import java.util.HashMap;
 import java.util.Map;
 import com.google.cloud.storage.BlobId;
 import com.google.cloud.storage.BlobInfo;
 import com.google.cloud.storage.Storage;
 import org.json.JSONObject;
 public class GCSConfiguration { 
    private final Storage storage;

    private final String bucket;

    private final String keyName; 
    GCSConfiguration(Storage storage, String bucket, String keyName) {

        this .storage = storage;

        this .bucket = bucket;

        this .keyName = keyName;

    }

    public void addProperty(String key, String value) {

        var blobId = BlobId.of(bucket, keyName);

        var blob = storage.get(blobId);

        final JSONObject configJson; 
        if (blob== null ) {

            configJson = new JSONObject();

        } else {

            configJson = new JSONObject( new String(blob.getContent()));

        }

        configJson.put(key, value);

        var blobInfo = BlobInfo.newBuilder(blobId).build();

        storage.create(blobInfo, configJson.toString().getBytes());

    }

    public Map<String,String> properties() { 
        var blobId = BlobId.of(bucket, keyName);

        var blob = storage.get(blobId);

        var map = new HashMap<String,String>(); 
        if (blob!= null ) {

            var jsonObject = new JSONObject( new String(blob.getContent()));

            for (var key: jsonObject.keySet()) {

                map.put(key, jsonObject.getString(key));

            }

        }

        return map;

    }
 }

这是GCS支持的简单配置工具。 最终,可以对其进行更改,并将锁操作放入addProperty操作中,这取决于用户和代码。 就本博客而言,我们仅需获取锁即可更改配置并释放锁。我们的主要班级将像这样。

 package com.gkatzioura.gcs.lock;
 import com.google.cloud.storage.StorageOptions;
 public class Application { 
    public static void main(String[] args) {

        var storage = StorageOptions.getDefaultInstance().getService();

        final String bucketName = "bucketName" ;

        final String lockFileName = "lockFileName" ;

        final String configFileName = "configFileName" ; 
        var lock = new GCSLock(storage, bucketName, lockFileName);

        var gcsConfig = new GCSConfiguration(storage, bucketName, configFileName); 
        var lockAcquired = lock.acquire();

        if (lockAcquired) {

            gcsConfig.addProperty( "testProperty" , "testValue" );

            lock.release();

        }

        var config = gcsConfig.properties();

        for (var key: config.keySet()) {

            System.out.println( "Key " +key+ " value " +config.get(key));

        }

    }
 }

现在让我们进行一些多线程处理。 十个线程将尝试放置值,预计它们会有一些故障。

 package com.gkatzioura.gcs.lock;
 import java.util.ArrayList;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import com.google.cloud.storage.Storage;
 import com.google.cloud.storage.StorageOptions;
 public class ApplicationConcurrent { 
    private static final String bucketName = "bucketName" ;

    private static final String lockFileName = "lockFileName" ;

    private static final String configFileName = "configFileName" ; 
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        var storage = StorageOptions.getDefaultInstance().getService();

        final int threads = 10 ;

        var service = Executors.newFixedThreadPool(threads);

        var futures = new ArrayList<Future>(threads); 
        for (var i = 0 ; i < threads; i++) {

            futures.add(service.submit(update(storage, "property-" +i, "value-" +i)));

        }

        for (var f : futures) {

            f.get();

        }

        service.shutdown();

        var gcsConfig = new GCSConfiguration(storage, bucketName, configFileName);

        var properties = gcsConfig.properties();

        for (var i= 0 ; i < threads; i++) { System.out.println(properties.get( "property-" +i)); } } +i)); } } private static Runnable update( final Storage storage, String property, String value) { return () -> {

            var lock = new GCSLock(storage, bucketName, lockFileName);

            var gcsConfig = new GCSConfiguration(storage, bucketName, configFileName); 
            boolean lockAcquired = false ; 
            while (!lockAcquired) {

                lockAcquired = lock.acquire();

                System.out.println( "Could not acquire lock" );

            }

            gcsConfig.addProperty(property, value);

            lock.release();

        };

    }
 }

显然,有10个线程可以显示这些功能。 在线程初始化和执行期间,一些线程将尝试同时获取锁,而一个锁将失败,而其他线程将延迟并失败,并等待直到锁可用。

最后,期望它们都将其值添加到配置中。而已。 如果您的问题性质简单,则此方法可以解决问题。 显然,您可以使用http api代替sdk。 您可以在github上找到代码。

翻译自: https://www.javacodegeeks.com/2020/10/locking-for-multiple-nodes-the-easy-way-gcs.html

gcs新的发展趋势

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值