我对这类电台的演出有一些疑问(现在我的项目使用Spring Boot)。正如您将很快理解的那样,我在一次学习大量信息时有点困惑。所以我将分享我的不同类型的问题和一些测试,以了解流程并帮助像我这样困惑的其他人:
1)阅读像这样的application.properties:
@Value("${foo.name}")
private String name;
vs读取以poo开头的属性并使用getter获取其值。
@ConfigurationProperties(prefix = "foo")
public class FooBean {
private String name;
private String age;
...
// setters and getters
}
1a)那么哪种方法更快,为什么?如果存在差异,你能用记忆表现来解释吗? 1b)也可以说我使用FooBean方法,在Example1类中我只需要FooBean的名字。我应该将FooBean注入Example1类,而我只需要1个字段,或者我应该使用@Value样式并仅获取特定字段,现在性能更好吗?
2)我应该将FooBean的字段声明为静态吗?让我们看一个例子:
配置类:
@Component
@ConfigurationProperties(prefix = "openstack")
@Data
@Validated
public class OpenStackBean {
@NotNull
@Valid
private String container;
@NotNull
@Valid
private String keystoneEndpoint;
@NotNull
@Valid
private String password;
@NotNull
@Valid
private String swiftEndpoint;
@NotNull
@Valid
private String tenantName;
@NotNull
@Valid
private String userName;
}
并且假设这个类仅由其服务使用:
@Service
public class OpenStackService implements IOpenStackService {
private OpenStackBean openStackBean;
@Autowired
public OpenStackService(OpenStackBean openStackBean) {
this.openStackBean = openStackBean;
}
...
...
private OSClientV2 authenticate(Facing perspective) throws AuthenticationException {
return OSFactory
.builderV2()
.endpoint(openStackBean.getKeystoneEndpoint())
.credentials(openStackBean.getUserName(), blowfish.decryptString(openStackBean.getPassword()))
.tenantName(openStackBean.getTenantName())
.perspective(perspective)
.withConfig(Config
.newConfig()
.withConnectionTimeout(applicationBean.getConnectionTimeout())
.withReadTimeout(applicationBean.getReadTimeout())
.withMaxConnections(10)
.withMaxConnectionsPerRoute(2))
.authenticate();
}
如果我是正确的,情况将是这样的:
1)在这种情况下,我将把这些配置作为实例注入。 2)所以每个类(假设我在一分钟内有10.000个用户,这个类将被创建10.000次)将在堆栈中创建自己的配置,它将在完成时删除它,因此内存再次空闲。 3)但是因为会有这么多的请求,它不会造成内存问题吗?
如果此流程正确,那么我应该将OpenStackBean的字段创建为静态并将其注入private static OpenStackBean
?这将在堆中保留一次,所有用户都将从那里获取它。哪种表现更好?
3)这是我的一些测试结果,这让我开始考虑字符串操作'和注射的表现。以下是使用JMeter进行的样本压力测试,并使用Java VisualVM进行可视化
发送10.000个请求
但我不明白为什么堆使用总是会增加。以下是APP的工作原理:
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity all(@ApiIgnore GameParam param) {
try {
// get games by categories by default
if (param.getPageNo() == null) {
return new ResponseEntity<>(gameService.getGamesByCategories(), HttpStatus.OK);
}
所有请求都进入此条件并调用:
2)调用此函数。由于classifiedizedGameList是静态的(在APP启动时初始化,并且每天由调度程序从远程服务器更新),所有请求都直接返回2步。 GameList位于堆中,因此不会创建新实例。
GameList - &gt; 14 KB(14173字节)
@Override
public List<CategoryVO> getGamesByCategories() {
if (categorizedGameList != null) {
return categorizedGameList;
} else {
return getAndCategorizeGames();
}
}
3)为什么10000次请求后堆增加300MB(从100到400)?这意味着在内存中为每个请求创建30 KB。
3a)请求到达端点时到底发生了什么?是否将创建APP的所有实例变量或仅创建访问过的类?我这样想:
我知道这对于阅读来说太长了,但我试图在这条道路上给出我所有的经验。我对提高自己的表现感到有些困惑,因为我意识到我从未想过它。谢谢你的耐心等待。
答案 0 :(得分:0)
- 在这种情况下,我将注入那些配置作为实例。 2)因此,每个课程(假设我在一分钟内有10.000个用户, 类将创建10.000次)将创建自己的 堆栈中的配置,完成后将其删除, 因此,内存再次可用。 3)但是因为会有很多请求, 会不会引起内存问题?
不,这不是问题。缺省情况下,Spring Bean是“ Singleton”作用域(除非您显式设置了另一个作用域),因此将仅创建 OpenStackBean 的一个实例。 因此,无需创建静态字段。
那么为什么在10000个请求后,堆增加300MB(从100到400)?这意味着将为每个请求在内存中创建30 KB。
因为tomcat需要创建许多临时对象来处理请求,但是在请求得到响应后它们将消失(还请注意,由于Java仅在垃圾回收之后才删除未使用的对象,因此堆使用率不会降低)< / p>
调用控制器的服务。因此,为此创建了此服务 用户。
这也是错误的,如果您的控制器是Singletone作用域,则仅创建一次。
当请求到达端点时会发生什么?是要创建APP的所有实例变量,还是仅创建访问的类?
不骂人!当tomcat服务您的请求时,仅需要实例化cals。
通常,您已经结束了有关性能问题的关注。您应该关注的事情是何时未从内存中删除对象(GC使用直到应用程序崩溃后,内存使用量增加且没有减少)。同样涉及内存占用是真实的,但与通过次要GC创建和销毁的一些小对象无关。