一、创建euraka集群
-
创建父项目,包含父pom文件和子项目,并增加依赖,主要是:spring-cloud-starter-parent
<parent> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-parent</artifactId> <version>Camden.RELEASE</version> </parent> <groupId>com.sohu.tv</groupId> <artifactId>spring-cloud-test</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>eureka-test</module> <module>provider-test</module> <module>consumer-test</module> </modules>
-
创建eureka-test,并在pom添加依赖spring-cloud-starter,spring-cloud-starter-eureka-server
<parent> <groupId>com.sohu.tv</groupId> <artifactId>spring-cloud-test</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>eureka-test</artifactId> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
-
euraka代码很简单:
@SpringBootApplication @EnableEurekaServer public class SpringCloudEurekaApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudEurekaApplication.class, args); } }
-
euraka-test配置application.yml
spring: application: name: eureka-test server: port: 8000 eureka: instance: preferIpAddress: true instanceId: ${spring.cloud.client.ipAddress}:${server.port} --- spring: profiles: node1 eureka: client: serviceUrl: defaultZone: http://eureka:8000/eureka/,http://eureka2:8000/eureka/ --- spring: profiles: node2 eureka: client: serviceUrl: defaultZone: http://eureka2:8000/eureka/,http://eureka3:8000/eureka/ --- spring: profiles: node3 eureka: client: serviceUrl: defaultZone: http://eureka3:8000/eureka/,http://eureka:8000/eureka/
-
在对应的机器上启动euraka-test,即完成集群创建,启动命令如下:
nohup /opt/cloud/jdk/bin/java -Dspring.profiles.active=node1 -server -Xmx4g -Xms4g -Xss256k -XX:+UseG1GC -XX:+PrintGCDateStamps -Xloggc:/opt/cloud/gc.log -jar /opt/cloud/eureka-test.jar > /opt/cloud/stdout.log & nohup /opt/cloud/jdk/bin/java -Dspring.profiles.active=node2 -server -Xmx4g -Xms4g -Xss256k -XX:+UseG1GC -XX:+PrintGCDateStamps -Xloggc:/opt/cloud/gc.log -jar /opt/cloud/eureka-test.jar > /opt/cloud/stdout.log & nohup /opt/cloud/jdk/bin/java -Dspring.profiles.active=node3 -server -Xmx4g -Xms4g -Xss256k -XX:+UseG1GC -XX:+PrintGCDateStamps -Xloggc:/opt/cloud/gc.log -jar /opt/cloud/eureka-test.jar > /opt/cloud/stdout.log &
二、增加provider-test
-
pom很简单:
<parent> <groupId>com.sohu.tv</groupId> <artifactId>spring-cloud-test</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>provider-test</artifactId> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies>
-
代码主要是rest接口(hello10:返回10个字符,hello100:返回100个字符,hello1000:返回1000个字符):
private String c10 = "abcvdfjiel"; private String c100 = "abcvdfjiel0938271648losdgshaiougoiewnavoienoidsa[yg[0e0u9g-rendsvsatg439098u6y480vb309ja0sv[nsdijfd"; private String c1000 = "abcvdfjiel0938271648losdgshaiougoiewnavoienoidsa[yg[0e0u9g-rendsvsatg439098u6y480vb309ja0sv[nsdijfdabcvdfjiel0938271648losdgshaiougoiewnavoienoidsa[yg[0e0u9g-rendsvsatg439098u6y480vb309ja0sv[nsdijfddabcvdfjiel0938271648losdgshaiougoiewnavoienoidsa[yg[0e0u9g-rendsvsatg439098u6y480vb309ja0sv[nsdijfdabcvdfjiel0938271648losdgshaiougoiewnavoienoidsa[yg[0e0u9g-rendsvsatg439098u6y480vb309ja0sv[nsdijfddabcvdfjiel0938271648losdgshaiougoiewnavoienoidsa[yg[0e0u9g-rendsvsatg439098u6y480vb309ja0sv[nsdijfdabcvdfjiel0938271648losdgshaiougoiewnavoienoidsa[yg[0e0u9g-rendsvsatg439098u6y480vb309ja0sv[nsdijfddabcvdfjiel0938271648losdgshaiougoiewnavoienoidsa[yg[0e0u9g-rendsvsatg439098u6y480vb309ja0sv[nsdijfdabcvdfjiel0938271648losdgshaiougoiewnavoienoidsa[yg[0e0u9g-rendsvsatg439098u6y480vb309ja0sv[nsdijfddabcvdfjiel0938271648losdgshaiougoiewnavoienoidsa[yg[0e0u9g-rendsvsatg439098u6y480vb309ja0sv[nsdijfdabcvdfjiel0938271648losdgshaiougoiewnavoienoidsa[yg[0e0u9g-rendsvsatg439098u6y480vb309ja0sv[nsdijfdddsds"; @RequestMapping("/hello10") public String hello10() { return c10; } @RequestMapping("/hello100") public String hello100() { return c100; } @RequestMapping("/hello1000") public String hello1000() { return c1000; }
-
还有一个主类:
@SpringBootApplication @EnableDiscoveryClient public class ProviderApplication { public static void main(String[] args) { SpringApplication.run(ProviderApplication.class, args); } }
-
配置文件如下:
spring: application: name: spring-cloud-server server: port: 9003 tomcat: maxThreads: 500 uriEncoding: utf-8 eureka: instance: preferIpAddress: true instanceId: ${spring.cloud.client.ipAddress}:${server.port} client: serviceUrl: defaultZone: http://eureka3:8000/eureka/,http://eureka:8000/eureka/,http://eureka2:8000/eureka/
-
启动两台机器提供服务,启动脚本如下:
nohup /data/cloud/jdk/bin/java -server -Xmx4g -Xms4g -Xss256k -XX:+UseG1GC -XX:+PrintGCDateStamps -Xloggc:/data/cloud/gc.log -jar /data/cloud/provider-test.jar > /data/cloud/stdout.log &
三、增加consumer-test实现
-
pom如下:
<parent> <groupId>com.sohu.tv</groupId> <artifactId>spring-cloud-test</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>consumer-test</artifactId> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> </dependencies>
-
代码如下:
1 启动类: @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class ConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class, args); } } 2 feign 服务 @FeignClient(name = "spring-cloud-server"/**) public interface ConsumerService { @RequestMapping("/hello10") public String hello10(); @RequestMapping("/hello100") public String hello100(); @RequestMapping("/hello1000") public String hello1000(); } 3 对外的rest接口 @RestController public class ConsumerController { @Autowired ConsumerService consumerService; @RequestMapping("/hello10") public String hello10() { return consumerService.hello10(); } @RequestMapping("/hello100") public String hello100() { return consumerService.hello100(); } @RequestMapping("/hello1000") public String hello1000() { return consumerService.hello1000(); } }
-
配置文件如下:
spring: application: name: spring-cloud-consumer server: port: 9001 tomcat: maxThreads: 1000 uriEncoding: utf-8 eureka: instance: preferIpAddress: true instanceId: ${spring.cloud.client.ipAddress}:${server.port} client: serviceUrl: defaultZone: http://eureka3:8000/eureka/,http://eureka:8000/eureka/,http://eureka2:8000/eureka/ feign: hystrix: enabled: false spring-cloud-server: ribbon: MaxAutoRetries: 1 ConnectTimeout: 2000 ReadTimeout: 1000 OkToRetryOnAllOperations: false EnableGZIPContentEncodingFilter: true
-
启动脚本:
nohup /opt/cloud/jdk/bin/java -server -Xmx4g -Xms4g -Xss256k -XX:+UseG1GC -XX:+PrintGCDateStamps -Xloggc:/opt/cloud/gc.log -jar /opt/cloud/consumer-test.jar > /opt/cloud/stdout.log &
四、feign性能测试
为了测试不同的http客户端的表现,并未增加hystrix的支持,consumer的链接超时为2秒,读取超时为1秒,另外,每次测试都经过了预热,只测试小数据传输
-
为consumer增加client依赖
<dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency> 或 <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> </dependency> 或什么都不依赖,采用jdk的URLConnection
进行性能压测,并发3000,压测10万次,采用长链,分别压测3个接口:
ab -k -n 100000 -c 3000 http://127.0.0.1:9001/hello10
ab -k -n 100000 -c 3000 http://127.0.0.1:9001/hello100
ab -k -n 100000 -c 3000 http://127.0.0.1:9001/hello1000
-
机器配置如下:
cpu核数 主频 consumer-test 16 2.40GHz provider-test 16 2.27GHz -
具体数据如下(并发3000,压测10万次表现如下(压测3次以上,取最好表现)):
client 10个字符 100个字符 1000个字符 吞吐量 响应时间中位值 吞吐量 响应时间中位值 吞吐量 响应时间中位值 httpclient 3542 846ms 3526 850ms 3427 875ms okhttp 14389 208ms 13782 217ms 13761 218ms JDK URLConnection 13728 218ms 13577 220ms 13800 217ms
五、resttemplate性能测试
-
consumer采用resttemplate作为测试,代码比较简单,如下:
1 默认实现 - 采用jdk的HttpURLConnection @LoadBalanced @Bean public RestTemplate restTemplate() { return new RestTemplate(f); } 2 采用okhttp3 @LoadBalanced @Bean public RestTemplate restTemplate() { OkHttp3ClientHttpRequestFactory f =new OkHttp3ClientHttpRequestFactory(); f.setConnectTimeout(2000); f.setReadTimeout(1000); f.setWriteTimeout(1000); return new RestTemplate(f); } 3 采用httpclient 4.3 @LoadBalanced @Bean public RestTemplate restTemplate() { HttpComponentsClientHttpRequestFactory f = new HttpComponentsClientHttpRequestFactory(); f.setConnectTimeout(2000); f.setReadTimeout(1000); return new RestTemplate(f); }
-
压测表现如下:(并发3000,压测10万次表现如下(压测3次以上,取最好表现)):
client 10个字符 100个字符 1000个字符 吞吐量 响应时间中位值 吞吐量 响应时间中位值 吞吐量 响应时间中位值 httpclient 6058 495ms 6051 495ms 6021 498ms okhttp 16134 185ms 16194 185ms 15885 188ms JDK URLConnection 16009 187ms 15695 191ms 15172 197ms
六、结论
从压测数据表现来看,性能上resttemplate整体上更胜一筹(可能由于feign采用了动态代理和反射机制)。
在各个http客户端默认配置下,okhttp3性能更好一些。
从代码优雅角度来讲,feign更简洁,易懂。
测试结果依赖于测试的环境和数据,及依赖的软硬件版本和性能,不代表所有情况!