您好,登錄后才能下訂單哦!
這篇文章主要介紹“微服務架構的高并發問題有哪些”,在日常操作中,相信很多人在微服務架構的高并發問題有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”微服務架構的高并發問題有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
其中商品微服務的findById()方法設置休眠2秒,用來模擬網絡波動等情況:
package com.sunxiaping.product.controller; import com.sunxiaping.product.domain.Product; import com.sunxiaping.product.service.ProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping(value = "/product") public class ProductController { @Autowired private ProductService productService; @Value("${server.port}") private String port; @Value("${spring.cloud.client.ip-address}") private String ip; @PostMapping(value = "/save") public String save(@RequestBody Product product) { productService.save(product); return "新增成功"; } @GetMapping(value = "/findById/{id}") public Product findById(@PathVariable(value = "id") Long id) { try { //休眠2秒,用來模擬 網絡波動等情況 Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } Product product = productService.findById(id); product.setProductName("訪問的地址是:" + ip + ":" + port); return product; } }
設置訂單微服務的Tomcat的最大線程數是10:
server: port: 9002 # 微服務的端口號 tomcat: max-threads: 10 # 最大線程數是10 spring: application: name: service-order # 微服務的名稱 datasource: url: jdbc:mysql://192.168.1.57:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true driver-class-name: com.mysql.cj.jdbc.Driver username: root password: 123456 jpa: generate-ddl: true show-sql: true open-in-view: true database: mysql jmx: unique-names: true # 配置Eureka eureka: instance: # 實例的名稱 instance-id: service-order:9002 # 顯示IP信息 prefer-ip-address: true lease-renewal-interval-in-seconds: 5 # 發送心跳續約間隔(默認30秒) lease-expiration-duration-in-seconds: 10 # Eureka Client發送心跳給Eureka Server端后,續約到期時間(默認90秒) client: healthcheck: enabled: true service-url: # Eureka Server的地址 # defaultZone: http://localhost:9000/eureka/ defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ # Ribbon的重試機制 service-product: ribbon: # 修改ribbon的負載均衡策略 服務名 - ribbon - NFLoadBalancerRuleClassName :負載均衡策略 # NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 修改ribbon的負載均衡策略為權重策略 # Ribbon的重試機制參數 ConnectTimeout: 250 # Ribbon的連接超時時間 ReadTimeout: 1000 # Ribbon的數據讀取超時時間 OkToRetryOnAllOperations: true # 是否對所有操作都進行重試 MaxAutoRetriesNextServer: 50 # 切換實例的重試次數 MaxAutoRetries: 1 # 對當前實例的重試次數 # 微服務info內容詳細信息 info: app.name: xxx company.name: xxx build.artifactId: $project.artifactId$ build.version: $project.version$ # 開啟日志debug logging: level: root: info
訂單微服務中的SpringConfig.java
package com.sunxiaping.order.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class SpringConfig { @Bean // @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }
訂單微服務的OrderController.java
package com.sunxiaping.order.controller; import com.sunxiaping.order.domain.Product; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController @RequestMapping(value = "/order") public class OrderController { @Autowired private RestTemplate restTemplate; /** * @param id * @return */ @GetMapping(value = "/buy/{id}") public Product buy(@PathVariable(value = "id") Long id) { Product product = restTemplate.getForObject("http://localhost:9001/product/findById/" + id, Product.class); return product; } @GetMapping(value = "/findOrder") public String findOrder() { return "商品查詢到了"; } }
使用JMeter性能測試工具以50個線程每個線程循環50次測試:http://localhost:9002/order/buy/1接口,然后通過瀏覽器調用http://localhost:9002/order/findOrder接口,發現特別慢。
在微服務架構中,我們將業務拆成一個個的服務,服務和服務之間可以相互調用,由于網絡原因或者自身的原因,服務并不能保證100%可用,如果單個服務出現問題,調用這個服務就會出現網絡延遲,此時如果有大量的網絡請求涌入,會形成任務累計,導致服務癱瘓。
換句話說,Tomcat等容器會以線程池的方式對所有的請求進行統一的管理,如果某個方法可能存著耗時問題,隨著外面積壓的請求越來越多,勢必會造成系統的崩潰、癱瘓等。
為了不影響其他接口的正常訪問:對多個服務之間進行隔離。
服務隔離的方式:
:two:信號量隔離(計數器,就是對某個方法進行設置閾值,如果超過了閾值,直接報錯)。
:one:線程池隔離。
<dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-metrics-event-stream</artifactId> <version>1.5.12</version> </dependency> <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-javanica</artifactId> <version>1.5.12</version> </dependency>
配置HystrixCommand接口的實現類,在實現類中可以對線程池進行配置:
package com.sunxiaping.order.command; import com.netflix.hystrix.*; import com.sunxiaping.order.domain.Product; import org.springframework.web.client.RestTemplate; public class OrderCommand extends HystrixCommand<Product> { private RestTemplate restTemplate; private Long id; public OrderCommand(RestTemplate restTemplate, Long id) { super(setter()); this.restTemplate = restTemplate; this.id = id; } private static Setter setter() { // 服務分組 HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("order_product"); // 服務標識 HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey("product"); // 線程池名稱 HystrixThreadPoolKey threadPoolKey = HystrixThreadPoolKey.Factory.asKey("order_product_pool"); /** * 線程池配置 * withCoreSize : 線程池大小為10 * withKeepAliveTimeMinutes: 線程存活時間15秒 * withQueueSizeRejectionThreshold :隊列等待的閾值為100,超過100執行拒絕策略 */ HystrixThreadPoolProperties.Setter threadPoolProperties = HystrixThreadPoolProperties.Setter().withCoreSize(50) .withKeepAliveTimeMinutes(15).withQueueSizeRejectionThreshold(100); // 命令屬性配置Hystrix 開啟超時 HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter() // 采用線程池方式實現服務隔離 .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD) // 禁止 .withExecutionTimeoutEnabled(false); return Setter.withGroupKey(groupKey).andCommandKey(commandKey).andThreadPoolKey(threadPoolKey) .andThreadPoolPropertiesDefaults(threadPoolProperties).andCommandPropertiesDefaults(commandProperties); } @Override protected Product run() throws Exception { System.out.println(Thread.currentThread().getName()); return restTemplate.getForObject("http://localhost:9001/product/findById/" + id, Product.class); } /** * 服務降級 * * @return */ @Override protected Product getFallback() { Product product = new Product(); product.setProductName("不好意思,出錯了"); return product; } }
package com.sunxiaping.order.controller; import com.sunxiaping.order.command.OrderCommand; import com.sunxiaping.order.domain.Product; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController @RequestMapping(value = "/order") public class OrderController { @Autowired private RestTemplate restTemplate; /** * 使用OrderCommand調用遠程遠程服務 * * @param id * @return */ @GetMapping(value = "/buy/{id}") public Product buy(@PathVariable(value = "id") Long id) { return new OrderCommand(restTemplate, id).execute(); } @GetMapping(value = "/findOrder") public String findOrder() { System.out.println(Thread.currentThread().getName()); return "商品查詢到了"; } }
到此,關于“微服務架構的高并發問題有哪些”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。