apolloconfig / apollo-java

Apollo Java Clients
Apache License 2.0
40 stars 72 forks source link

addOrModifyProperty修改apollo,异步转同步方法的2个疑问 #59

Closed cheese8 closed 5 months ago

cheese8 commented 7 months ago

如题,testcase中演示了2种方法: 1、以future / Semaphore方式,非侵入(ApolloMockServerApiTest)

Config otherConfig = ConfigService.getConfig(anotherNamespace);

    final SettableFuture<ConfigChangeEvent> future = SettableFuture.create();

    otherConfig.addChangeListener(new ConfigChangeListener() {
      @Override
      public void onChange(ConfigChangeEvent changeEvent) {
        future.set(changeEvent);
      }
    });
 embeddedApollo.deleteProperty(anotherNamespace, "key4");

  ConfigChangeEvent changeEvent = future.get(5, TimeUnit.SECONDS);

疑问1:将这个异步转同步的代码,封装进ApolloTestingServer的addOrModifyProperty是否更合适?

2、埋点(ApolloMockServerSpringIntegrationTest,需拿到TestBean和TestInterestedKeyPrefixesBean对象)

embeddedApollo.addOrModifyProperty(otherNamespace, "someKey", "someValue");
ConfigChangeEvent changeEvent = testBean.futureData.get(5000, TimeUnit.MILLISECONDS);

疑问2:对于这种使用方式,我们需要使用EmbeddedApollo来mock么?直接使用ReflectionTestUtils.setField()更方便?@nobodyiam

nobodyiam commented 7 months ago

我理解 testcase 中的代码主要是为了测试 EmbeddedApollo/ApolloTestingServer 的功能而不是为了演示如何使用,比如实际场景中不会写一个ConfigChangeEvent changeEvent = future.get(5, TimeUnit.SECONDS);去单独拿到 changeEvent,而是在已有的代码中本来就有针对配置变化的逻辑会被触发。

cheese8 commented 7 months ago

我这么理解的: 1、如果能注入拿到apollo key所在对象,那么可以调用ReflectionTestUtils.setField()反射给apollo key赋值,这是同步的,很方便。 2、如果拿不到apollo key所在对象,这是apollo-mock-server的用武之地了,模拟web页面修改apollo的值,并热更新到spring容器了。

问题来了,热更新到spring容器是个异步过程,实际情况中,spring context肯定比demo复杂,那么在调用addOrModifyProperty方法后,肯定得等待一段时间(这个时间不好计算),好让apollo热更新到spring容器中。

参考下面测试代码,调用addOrModifyProperty方法,keySwitch更新为WHITELIST并不是实时同步的,如果不等待一段时间的话,会导致下面代码的断言不稳定(其实到底等待多久,需考虑不同spring容器的复杂程度,所以也会导致断言不稳定)。

    @Test
    public void test_getUser_ok_WHITELIST() throws Exception {
/** 重复代码
        Config otherConfig = ConfigService.getConfig("application");
                final SettableFuture<ConfigChangeEvent> future = SettableFuture.create();
                otherConfig.addChangeListener(new ConfigChangeListener() {
                    @Override
                    public void onChange(ConfigChangeEvent changeEvent) {
                        future.set(changeEvent);
                    }
                });
*/
        embeddedApollo.addOrModifyProperty("application", "keySwitch", "WHITELIST");
/** 重复代码
ConfigChangeEvent changeEvent = future.get(5, TimeUnit.SECONDS);
*/
        ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/user/1"));
        String content = resultActions.andReturn().getResponse().getContentAsString();
        Assert.assertEquals(content, "user-WHITELIST-1");
    }
stale[bot] commented 6 months ago

This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in 7 days unless it is tagged "help wanted" or other activity occurs. Thank you for your contributions.

stale[bot] commented 5 months ago

This issue has been automatically closed because it has not had activity in the last 7 days. If this issue is still valid, please ping a maintainer and ask them to label it as "help wanted". Thank you for your contributions.