一、創建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更簡潔,易懂。
測試結果依賴於測試的環境和數據,及依賴的軟硬件版本和性能,不代表所有情況!