精华内容
下载资源
问答
  • WEB API 多线程并发测试工具; WEB API 多线程并发测试工具
  • c#的webapi并发的问题

    2016-10-17 10:12:43
    基于framework4.0,它的webapi处理并发该怎么设计,原来使用tpl但是只能支持4.5,现在要求4.0该怎么做?
  • 简介 你是否还在为某些接口业务复杂、响应速度慢、并发量上不去而苦恼,今天给大家推荐一些小技巧,如何对复杂业务进行拆分、解耦。面对高并发可以记住这五点点:1、异步,削峰...本文将介绍如何缩短API接口的响...

    简介

    • 你是否还在为某些接口业务复杂、响应速度慢、并发量上不去而苦恼,今天给大家推荐一些小技巧,如何对复杂业务进行拆分、解耦。面对高并发可以记住这五点:1、异步,削峰填谷;2、缓存,缓存相对稳定高频热点数据,降低执行业务逻辑的性能开销;3、并行,缩短业务响应时间;4、优化你的业务代码,高效执行业务逻辑;5、限流和降级,保护你的核心服务在高并发下能正常工作。

    本文将介绍如何缩短API接口的响应时间、提升系统单位时间内的并发量和吞吐量,内容有

    • 应用场景分析
    • 常用解决方案和技巧
    • 接口异步化工具@Async的介绍
    • 异步化应用启动类配置
    • 利用@Async实现业务并行,提升接口响应速度

    原文:传送门

    注:本文基于springboot2.1.3.RELEASE 版本


    1、应用场景分析和优化方案

    1. 聚合查询接口,需要组装返回所有后端api的响应数据

      这类接口按传统的编程思维,会串行调用所有后端api,然后再组装,这样会导致接口响应时间会随着聚合的接口数呈比例增长,时间复杂度O(N)

      优化方案

      • 并行异步调用后端api接口

      • 主线程监听所有接口调用情况,等待到最后一个执行完成后一起返回

      分析:这样优化后,我们的聚合查询类接口响应时间最多只是与最慢的那个后端api接口速度相当而已,时间复杂度降到了O(1)。

      注意事项: 此方式要求聚合查询接口内的各个业务接口间无依赖关系。

    2. 复杂多IO型业务接口,业务逻辑等待IO操作居多。

      这类接口面对巨大流量压力时,往往表现为服务并发和吞吐量上不去,但服务器CPU、内存等资源充足

      优化方案

      • 从对接口响应内容的影响按业务进行拆分,将与接口响应数据相关的业务逻辑全拎出来,剩下的业务流程按需在各个阶段进行异步化处理,这部分可以走MQ、异步线程处理等等

      • 将拎出来的那部分业务逻辑再进行拆分,找出可以并行处理的业务进行异步并行执行,如果依赖异步执行的数据时,可以监听并等待异步业务执行成功后再进行处理;

      分析:优化思想就是,先砍掉部分和接口响应处理关系不大的业务,让他们在后台异步处理;再将其他业务操作按照业务操作间有无依赖关系进行拆分,可以并行的就尽量异步并行执行;最终统一处理响应内容再返回。

    3. 复杂多计算型业务接口,多个复杂耗时的计算流程。

      这类接口往往耗费非常多的CPU,导致服务器并发和吞吐量上不去。

      优化方案:

      • 增加服务器CPU配置
      • 如果数据实时性要求不高,可以对接口响应进行一定时效的缓存;
      • 将计算逻辑先从业务范围进行拆分,交给不同的服务去执行;
      • 增加服务实例个数,采用分布式计算方法MapReduce;
    4. 其他接口性能瓶颈场景

      如DB、缓存、队列、或者一些服务器组件的性能瓶颈不在本篇文章内容,以后会有篇幅做专门讲解;

    2、常用解决方案和技巧

    1. 异步,削峰填谷;

      • 一般指将瞬时的大流量请求放到消息队列中,让系统逐个去处理,不至于瞬时流量毛刺导致服务完全不可用;
      • 这样可以使服务器在其他时段内也能保持负荷工作,节约了服务器的性能;
      • 还预留了一些时间让系统在面对突然的高负载时,增加新的服务实例进行服务;
    2. 缓存,缓存相对稳定高频热点数据,降低对后端业务服务和中间件服务的性能开销;

      • 一般分为对热点数据进行缓存;
      • 对高频访问接口响应进行缓存;
      • 缓存又分分布式缓存、本地缓存,各个服务器中间件也提供了各个等级的缓存;
    3. 并行,缩短业务响应时间;

      • 将可以并行的业务剥离出来,异步并行执行,缩短整体业务执行时间,提升系统单位时间吞吐量;
    4. 优化你的业务代码,高效执行业务逻辑;

      • 这个没得说,根据实际情况梳理出业务执行流程,进行合理的优化即可;
    5. 限流和降级,保护你的核心服务在高并发下能正常工作;

      • 这个一般在流量入口进行限制,保证我们的后端业务不被大流量击垮;
      • 限流有很多种策略,常用的有对用户访问频率进行控制,对整体流量进行控制,避免后端业务处理不过来;
      • 降级,其实是最后的无赖之举,断臂求生,把所有资源都提供给核心业务,保证核心业务的正常服务,边缘业务暂停服务;

    3、接口异步化工具@Async的介绍

    简介:

    该工具可以为你的应用提供方便快捷的异步化执行业务的能力,只需要添加一个注解@Async既可以使你的业务异步执行,这里的异步执行,指的是新开一个线程执行你的业务;该注解可以使用到类上,也可以使用在方法上。

    3.1 组件介绍
    1. @EnableAsync启用异步化能力注解

      推荐该注解配置在springboot的Config类或者启动类上,用于开启异步化能力,做一些异步化线程池和相关组件的初始化工作。

    2. @Async开启异步化模式注解

      基于@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。

      该注解标注在类上,就代表调用该类的所有方法均会自动异步执行;标注在方法上,该方法就会异步执行;当调用该方法时,Async的切面会先向异步线程池申请一个线程,然后使用该线程执行该方法内的业务逻辑。

    3. AsyncConfigurer全局配置接口

      用于配置自定义异步线程池和异步线程执行异常捕获器,灵活定制合适的线程池和异常处理规则。

    4. AsyncUncaughtExceptionHandler异步化运行时全局异常捕获接口

      自定义异步线程池运行时异常统一处理方案。

    5. AsyncExecutor异步化执行线程池

      自定义异步执行线程池的大小、线程存活时间、队列信息等等,详情可以参考线程池的使用说明,这里就不展开讨论。

    3.2 异步化方法使用示例和说明

    说明:

    • 异步化注解@Async标注的方法返回值只能是void或者Future
    • @Async所修饰的方法不要定义为static类型,这样异步调用不会生效
    • @Async所修饰的方法不能和@Transactional一起使用,因为会启用新的子线程来执行方法内的业务,主线程内的事务注解无法控制子线程的业务操作,原因就是事务存在线程隔离的原因,如果要加事务,请在方法内嵌套其他事务标注后的方法即可生效

    示例:

    • 无参数异步化接口

      @Async
      public void executeTask(){
          //业务操作
          
      }
      
    • 带参数异步化接口

      @Async
      public Future<Dto> task2(){
          //业务操作
          
          //返回操作结果
          return new AsyncResult<>(new Dto("danyuan",22));
      }
      
      @Data
      @AllArgsConstructor
      public class Dto implements Serializable{
      	/** 
      	 *serialVersionUID
      	 */
      	private static final long serialVersionUID = 1L;
      
      	private String name;
      	
      	private Integer age;
      	
      }
      

    4、异步化应用启动类配置

    应用配置启动类示例如下:

    /**  
    * Title StartAsyncServer.java  
    * Description  
    * @author danyuan
    * @date Mar 8, 2020
    * @version 1.0.0
    * site: www.danyuanblog.com
    */ 
    package com.danyuanblog.test;
    
    import java.io.ByteArrayOutputStream;
    import java.io.PrintStream;
    import java.lang.reflect.Method;
    import java.util.concurrent.Executor;
    
    import lombok.extern.slf4j.Slf4j;
    
    import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.scheduling.annotation.AsyncConfigurer;
    import org.springframework.scheduling.annotation.EnableAsync;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    
    @SpringBootApplication
    @EnableAsync
    public class StartAsyncServer implements AsyncConfigurer {
    
    	public static void main(String[] args) {
    		SpringApplication.run(StartAsyncServer.class, args);
    	}
    	
    	@Override
    	public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    		
    		return new ExceptionHandler();
    	};
    	
    	@Slf4j(topic="异步线程池运行时异常捕获器")
    	static class ExceptionHandler implements AsyncUncaughtExceptionHandler{
    
    		/**
    		 * @author danyuan
    		 */
    		@Override
    		public void handleUncaughtException(Throwable e, Method method,
    				Object... params) {//全局捕获异步执行异常并处理
    			ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1024);
    	        PrintStream printStream = new PrintStream(outputStream);
    	        e.printStackTrace(printStream);
    	        log.error(outputStream.toString());
    		}
    		
    	}
    	/**
    	 * @author danyuan
    	 */
    	@Override
    	public Executor getAsyncExecutor() {
    		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(20);
            executor.setMaxPoolSize(400);
            executor.setQueueCapacity(10000);
            executor.setThreadNamePrefix("TestAsyncExecutor-");
            executor.initialize();
            return executor;
    	}
    }
    

    5、利用@Async实现业务并行,提升接口响应速度

    业务场景是这样的,task1、task2之间无依赖关系,task3依赖与task2的操作结果,代码示例如下:

    • AsyncTestService.java

      /**  
      * Title AsyncTestService.java  
      * Description  
      * @author danyuan
      * @date Mar 13, 2020
      * @version 1.0.0
      * site: www.danyuanblog.com
      */ 
      package com.danyuanblog.test.asyc;
      
      import java.util.concurrent.Future;
      
      import org.springframework.scheduling.annotation.Async;
      import org.springframework.scheduling.annotation.AsyncResult;
      import org.springframework.stereotype.Service;
      
      @Service
      public class AsyncTestService {
      	
      	@Async
      	public void task1(){
      		System.out.println("task1 execute begin .....");
      		try {
      			Thread.sleep(1000);
      		} catch (InterruptedException e) {
      			e.printStackTrace();
      		}
      		System.out.println("task1 execute success !");
      	}
      	
      	@Async
      	public Future<Dto> task2(){
      		System.out.println("task2 execute begin .....");
      		try {
      			Thread.sleep(6000);
      		} catch (InterruptedException e) {
      			e.printStackTrace();
      		}
      		System.out.println("task2 execute success !");
      		return new AsyncResult<>(new Dto("danyuan",22));
      	}
      	
      	@Async
      	public void task3(Dto dto){
      		System.out.println("task3 execute begin .....");
      		try {
      			Thread.sleep(1000);
      		} catch (InterruptedException e) {
      			e.printStackTrace();
      		}
      		if(dto.getAge() > 18){
      			System.out.println(dto.getName()+"已成年!");
      		}else{
      			System.out.println(dto.getName()+"未成年!");
      		}
      		System.out.println("task3 execute success !");
      	}
      	
      }
      
    • AsycTestController.java

      /**  
      * Title AsycTestController.java  
      * Description  业务异步化测试
      * @author danyuan
      * @date Mar 8, 2020
      * @version 1.0.0
      * site: www.danyuanblog.com
      */ 
      package com.danyuanblog.test.asyc;
      
      import java.util.concurrent.ExecutionException;
      import java.util.concurrent.Future;
      
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.scheduling.annotation.AsyncResult;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.RestController;
      
      @RestController
      public class AsycTestController {
      	
      	@Autowired
      	private AsyncTestService asyncTestService;
      	/**
      	 * 测试异步化任务
      	 * @author danyuan
      	 */
      	@GetMapping("/testAsync")
      	public void testAsync(){
      		asyncTestService.task1();
      		Future<Dto> result = asyncTestService.task2();
      		while(true){//task3需要等待task2执行完成
      			if(result.isDone() || result.isCancelled()){
      				break;
      			}
      			try {
      				Thread.sleep(1000);
      			} catch (InterruptedException e) {
      				e.printStackTrace();
      			}
      		}
      		try {
      			asyncTestService.task3(result.get());
      		} catch (ExecutionException | InterruptedException e) {
      			e.printStackTrace();
      		}
      	}
      
      }
      
      
    展开全文
  • c#中并发请求api接口Imagine the following scenario:想象以下情况: User A requests resource 1 via a GET endpoint 用户A通过GET端点请求资源1 User B requests resource 1 via a GET endpoint 用户B通过GET端点...

    c#中并发请求api接口

    Imagine the following scenario:

    想象以下情况:

    1. User A requests resource 1 via a GET endpoint

      用户A通过GET端点请求资源1
    2. User B requests resource 1 via a GET endpoint

      用户B通过GET端点请求资源1
    3. User A makes changes on resource 1 and saves its changes via a PUT request

      用户A对资源1进行更改,并通过PUT请求保存其更改
    4. User B makes changes on resource 1, on the same fields as user A, and saves its changes via a PUT request

      用户B在与用户A相同的字段上对资源1进行更改,并通过PUT请求保存其更改

    Since users A and B both requested the same version of resource 1, you now have a problem, because the PUT request triggered by user B erased the changes made by user A, and chances are, user A is mad and wondering why his changes do not show up anymore, even though he swears that he did not forget to save. Does that scenario sound familiar ? If so, read on.

    由于用户A和B都请求了相同版本的资源1,因此您现在遇到了问题,因为由用户B触发的PUT请求删除了用户A所做的更改,并且很可能用户A生气了,并且想知道为什么他的更改会即使他发誓他不会忘记保存,也不会再出现了。 听起来很熟悉吗? 如果是这样,请继续阅读。

    找出问题 (Identifying the problem)

    The problem is very simple: users A and B requested a resource more or less at the same time, and got the same version of this resource. Then, they both made changes to the resource in parallel, and whoever saved last erased the changes of the other.

    问题非常简单:用户A和B或多或少地同时请求了一个资源,并获得了该资源的相同版本。 然后,他们俩并行地对资源进行了更改,最后保存的人将擦除另一个资源的更改。

    There are actually 2 possible ways to solve this issue: through what’s called pessimistic locking or optimistic locking.

    解决此问题的方法实际上有两种:通过悲观锁定或乐观锁定。

    悲观与乐观锁定 (Pessimistic vs Optimistic locking)

    Pessimistic locking means that as soon as a user starts making changes on a resource, he locks this resource. While this resource is locked, no one else can edit this resource. When the user is done with his changes, he unlocks the resource so that other users can retrieve the resource and make changes to it. In other words, pessimistic locking ensures that 2 users can not make changes on one resource at the same time.

    悲观锁定意味着用户一旦开始对资源进行更改,就会锁定该资源。 锁定此资源后,没有其他人可以编辑此资源。 当用户完成更改后,他将资源解锁,以便其他用户可以检索该资源并对其进行更改。 换句话说,悲观锁定确保2个用户不能同时对一个资源进行更改。

    Optimistic locking on the other hand, allows users to retrieve a resource in parallel, however it will not allow a user to erase a previous version of a resource. If we take the example scenario above, in steps 1 and 2, users A and B will retrieve resource 1 both in, say, version 38. When user A saves resource 1, it will send to the API the information that the version being saved is version 38. The API will then retrieve the resource from the database and compare the version in database to the one provided in the API call, and if they differ, it will not accept the save operation. When user A saves version 38 of the resource, the save will be accepted and the version number will be incremented, but when user B tries to save version 38, the resource in the database will be at version 39, and therefore the save will not be accepted, preventing user B from overwriting user A’s changes.

    另一方面,乐观锁定允许用户并行检索资源,但是不允许用户擦除资源的先前版本。 如果我们以上述示例场景为例,则在步骤1和2中,用户A和B都将在版本38中检索资源1。当用户A保存资源1时,它将向API发送有关正在保存版本的信息是38版。API然后将从数据库中检索资源,并将数据库中的版本与API调用中提供的版本进行比较,如果它们不同,则它将不接受保存操作。 当用户A保存该资源的版本38时,将接受该保存,并且版本号将增加,但是当用户B尝试保存该版本38时,数据库中的资源将处于版本39,因此保存不会被接受,防止用户B覆盖用户A的更改。

    RESTful API应该实现什么? (What should be implemented in a RESTful API ?)

    So what kind of locking should you implement in your RESTful API ? Pessimistic or optimistic locking ?

    那么,您应该在RESTful API中实现哪种锁定? 悲观还是乐观锁定?

    Even though implementing pessimistic locking is not impossible, because a RESTful API is stateless, I would not recommend it, as this would mean that your API will need to rely on client applications to unlock resources automatically if users forget to do so.

    尽管实现悲观锁定不是不可能的,因为RESTful API是无状态的,但我不建议这样做,因为这意味着您的API将需要依赖客户端应用程序来自动解锁资源(如果用户忘记这样做)。

    Imagine the following scenario: user A retrieves resource 1 and the client application automatically locks the resource as user A starts making changes on it. After making some changes on resource 1 and saving them, user A closes the application and goes on vacation for 2 weeks… Unless your client application somehow automatically unlocked resource 1, resource 1 is now locked and can not be edited by anyone until user A is back from vacation… Unless you want to make your users mad at you, I do not advise you to go this way.

    设想以下情形:用户A检索资源1,并且当用户A开始对其进行更改时,客户端应用程序自动锁定该资源。 在对资源1进行一些更改并将其保存后,用户A关闭该应用程序并休假2周……除非您的客户端应用程序以某种方式自动解锁了资源1,否则资源1现在被锁定并且在用户A被锁定之前,任何人都无法对其进行编辑。从假期回来……除非您想让用户生气,否则我不建议您这样做。

    In optimistic locking however, users can not block each other from editing the same resource, so the issue created by pessimistic locking can not happen. In the scenario described in the introduction of this article, user B will simply get an error message telling him that his changes can not be saved because a new version of the resource was created by user A in the meantime. It is then up to you to decide whether you want to try to resolve conflicts between the changes made by user A and the changes made by user B automatically (which can be a nightmare) or whether you just ask user B to redo his changes after retrieving the new version of the resource.

    但是,在乐观锁定中,用户不能互相阻止编辑同一资源,因此,不会发生由悲观锁定造成的问题。 在本文引言中描述的场景中,用户B只会收到一条错误消息,告诉他由于用户A同时创建了新版本的资源,因此无法保存其更改。 然后由您决定是要尝试自动解决用户A所做的更改与用户B所做的更改之间的冲突(这可能是一场噩梦),还是只是要求用户B在更改后重做他的更改?检索资源的新版本。

    Note that, if for some reason, this “inconvenience” caused by optimistic locking is not acceptable for you, you can still implement pessimistic locking and set a lock expiration to, for example, automatically release a lock that was created 2 hours ago, and is therefore expired. Your client application will then have to reflect this expiration.

    请注意,如果由于某种原因您不能接受由乐观锁定引起的这种“不便”,您仍然可以实施悲观锁定并设置锁定有效期,例如,自动释放2小时前创建的锁定,并且因此已过期。 然后,您的客户端应用程序将必须反映此到期。

    如何实现乐观锁定 (How to implement optimistic locking)

    The standard way to implement optimistic locking in a RESTful API is using the Etags and If-Match headers. When a resource is retrieved, it is received with an Etag header, which is a string of characters identifying the version of the resource being retrieved. When a client later wants to update this resource, it has to provide the value of the Etag in the If-Match header. If the Etag provided in the If-Match header matches the version of the resource in the database, the resource can be updated, otherwise the update is rejected.

    在RESTful API中实现乐观锁定的标准方法是使用EtagsIf-Match标头。 检索资源时,将使用Etag标头接收该资源,该标头是一串字符串,用于标识所检索资源的版本。 当客户端以后想要更新此资源时,它必须在If-Match标头中提供Etag的值。 如果If-Match标头中提供的Etag与数据库中资源的版本匹配,则可以更新资源,否则,更新将被拒绝。

    Note that if you are using MongoDB as a backend and Mongoose as an ORM, you already have a built-in version mechanism and do not need to implement one. Mongoose stores versions of a document in a __v attribute of a document. All you need to do is to make sure this __v attribute is incremented on every save operation. In order to do this, Mongoose provides a very convenient option: optimisticConcurrency (see documentation here), which, if set, will automatically increment this __v attribute on every save operation. Note however that it will not increment this attribute on a findOneAndUpdate operation, so you will need to do this manually:

    请注意,如果您将MongoDB用作后端,而将Mongoose用作ORM,则您已经具有内置的版本机制,无需实现。 猫鼬将文档的版本存储在文档的__v属性中。 您需要做的就是确保在每个保存操作中都增加__v属性。 为了做到这一点,Mongoose提供了一个非常方便的选项: optimisticConcurrency (请参阅此处的文档),如果设置了该__v ,它将在每次保存操作时自动增加此__v属性。 但是请注意,它不会在findOneAndUpdate操作上增加此属性,因此您将需要手动执行此操作:

    await q.findOneAndUpdate({ _id }, {
    $set: body,
    $inc: { __v: 1 }
    }

    You will then need to provide this __v attribute on every GET request, either directly in the response payload or in the Etag header, and your client application will then need to send you this __v attribute, again either in the request payload or in the If-Match header.

    然后,您将需要在每个GET请求中直接在响应有效负载中或在Etag标头中提供此__v属性,然后您的客户端应用程序将再次在请求有效负载中或在If-Match向您发送此__v属性If-Match标头。

    When there is a conflict (a resource can not be saved because it was edited in the meantime), your API should reply with a 412 Precondition Failed HTTP status code. It will then be up to the client application to interpret this status code and to show a comprehensible error message to the user.

    发生冲突时(由于同时对其进行了编辑,无法保存资源),您的API应使用412 Precondition Failed HTTP状态代码进行回复。 然后,由客户端应用程序来解释此状态代码并向用户显示可理解的错误消息。

    结论:使用Etag和If-Match标头为您的资源实现乐观锁定 (Conclusion: Implement Optimistic locking for your resources using the Etag and If-Match headers)

    Depending on your resources, you might not need to implement optimistic locking at all: if your resources are edited by a single user, there is no risk of concurrent requests and you will not need to worry about implementing optimistic locking.

    根据您的资源,您可能根本不需要实现乐观锁定:如果您的资源是由单个用户编辑的,则不会存在并发请求的风险,并且您不必担心实现乐观锁定。

    If however some of your resources can be updated by different users, you will, sooner or later, encounter the scenario described at the beginning of this article. In this case, my recommendation is to implement optimistic locking using the Etag and If-Match headers, returning a 412 Precondition Failed if a resource can not be updated.

    但是,如果某些资源可以由不同的用户更新,则您迟早会遇到本文开头描述的情况。 在这种情况下,我的建议是使用EtagIf-Match标头实现乐观锁定, If-Match 412 Precondition Failed更新资源,则返回412 Precondition Failed

    翻译自: https://medium.com/@guillaume.viguierjust/handling-concurrent-requests-in-a-restful-api-5a25a4b81a1

    c#中并发请求api接口

    展开全文
  • .net mvc webapi使用异步请求处理并发

    千次阅读 2019-09-30 00:31:52
    model.cs中 #region 根据学年获取老师在的班级 public class TeacherClassForYearPara { public string YearCode { set; get; } public string UserCode { set; get; } ... publi...

    model.cs中

     #region 根据学年获取老师在的班级
        public class TeacherClassForYearPara
        {
            public string YearCode { set; get; }
            public string UserCode { set; get; }
    
        }
        public class TeacherClassForYearRet: BasPostMsg
        {
            public string ClassCode { set; get; }
            public string ClassName { set; get; }
    
        }
        #endregion

    repository.cs中

            public async Task<TeacherClassForYearRet> TeacherClassForYear(TeacherClassForYearPara para)
            {
                TeacherClassForYearRet ret = new TeacherClassForYearRet();
                try
                {
    
                    await Task.Run(() =>
                    {
                        if (string.IsNullOrEmpty(para.UserCode))
                            throw new Exception("UserCode不能为空");
                        if (string.IsNullOrEmpty(para.YearCode))
                            throw new Exception("YearCode不能为空");
    
                        DbCommand cmd = db.GetStoredProcCommond("TeacherClassForYear_P");
                        db.AddInParameter(cmd, "@UserCode", DbType.Int32, para.UserCode);
                        db.AddInParameter(cmd, "@YearCode", DbType.String, para.YearCode);
                        DataTable dt = db.ExecuteDataTable(cmd);
                        if (dt.Rows.Count > 0)
                        {
                            ret.ClassCode = dt.Rows[0]["ClassCode"].ToString();
                            ret.ClassName = dt.Rows[0]["ClassName"].ToString();
    
                        }
                        ret.Status = "1";
                        ret.Msg = "请求成功!";
                    }
                );
    
                }
                catch (Exception e)
                {
                    ret.Status = "0";
                    ret.Msg = e.Message;
                }
                return ret;
            }
    

      controller.cs中

     #region 根据学年获取老师在的班级
            [HttpPost]
            public async Task<IHttpActionResult> TeacherClassForYear([FromBody]TeacherClassForYearPara para)
                        => Ok(await repo.TeacherClassForYear(para));
            #endregion
    

      

    转载于:https://www.cnblogs.com/jiamengyang/p/9600042.html

    展开全文
  • java web开发 高并发处理

    千次阅读 2015-04-12 22:33:16
    java处理并发高负载类网站中数据库的设计方法(java教程,java处理大量数据,java高负载数据) 一:高并发高负载类网站关注点之数据库 没错,首先是数据库,这是大多数应用所面临的首个SPOF。尤其是Web2.0的...
    java处理高并发高负载类网站中数据库的设计方法(java教程,java处理大量数据,java高负载数据)
    

    一:高并发高负载类网站关注点之数据库

    没错,首先是数据库,这是大多数应用所面临的首个SPOF。尤其是Web2.0的应用,数据库的响应是首先要解决的。
    一般来说MySQL是最常用的,可能最初是一个mysql主机,当数据增加到100万以上,那么,MySQL的效能急剧下降。常用的优化措施是M-S(主-从)方式进行同步复制,将查询和操作和分别在不同的服务器上进行操作。我推荐的是M-M-Slaves方式,2个主Mysql,多个Slaves,需要注意的是,虽然有2个Master,但是同时只有1个是Active,我们可以在一定时候切换。之所以用2个M,是保证M不会又成为系统的SPOF。
    Slaves可以进一步负载均衡,可以结合LVS,从而将select操作适当的平衡到不同的slaves上。
    以上架构可以抗衡到一定量的负载,但是随着用户进一步增加,你的用户表数据超过1千万,这时那个M变成了SPOF。你不能任意扩充Slaves,否则复制同步的开销将直线上升,怎么办?我的方法是表分区,从业务层面上进行分区。最简单的,以用户数据为例。根据一定的切分方式,比如id,切分到不同的数据库集群去。

    全局数据库用于meta数据的查询。缺点是每次查询,会增加一次,比如你要查一个用户nightsailer,你首先要到全局数据库群找到nightsailer对应的cluster id,然后再到指定的cluster找到nightsailer的实际数据。
    每个cluster可以用m-m方式,或者m-m-slaves方式。这是一个可以扩展的结构,随着负载的增加,你可以简单的增加新的mysql cluster进去。

    需要注意的是:
    1、禁用全部auto_increment的字段
    2、id需要采用通用的算法集中分配
    3、要具有比较好的方法来监控mysql主机的负载和服务的运行状态。如果你有30台以上的mysql数据库在跑就明白我的意思了。
    4、不要使用持久性链接(不要用pconnect),相反,使用sqlrelay这种第三方的数据库链接池,或者干脆自己做,因为php4中mysql的链接池经常出问题。

    二:高并发高负载网站的系统架构之HTML静态化

    其实大家都知道,效率最高、消耗最小的就是纯静态化 http://www.ablanxue.com/shtml/201207/776.shtml的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是 最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点 的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限 管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。
      
      除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。
      
       同时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛 中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这 部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求高并发。
      

    网站HTML静态化解决方案
    当一个Servlet资源请求到达WEB服务器之后我们会填充指定的JSP页面来响应请求:

    HTTP请求---Web服务器---Servlet--业务逻辑处理--访问数据--填充JSP--响应请求

    HTML静态化之后:

    HTTP请求---Web服务器---Servlet--HTML--响应请求

    静态访求如下

    Servlet:

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        if(request.getParameter("chapterId") != null){
            String chapterFileName = "bookChapterRead_"+request.getParameter("chapterId")+".html";
            String chapterFilePath = getServletContext().getRealPath("/") + chapterFileName;
            File chapterFile = new File(chapterFilePath);
            if(chapterFile.exists()){response.sendRedirect(chapterFileName);return;}//如果有这个文件就告诉浏览器转向 
            INovelChapterBiz novelChapterBiz = new NovelChapterBizImpl();
            NovelChapter novelChapter = novelChapterBiz.searchNovelChapterById(Integer.parseInt(request.getParameter("chapterId")));//章节信息 
            int lastPageId = novelChapterBiz.searchLastCHapterId(novelChapter.getNovelId().getId(), novelChapter.getId());
            int nextPageId = novelChapterBiz.searchNextChapterId(novelChapter.getNovelId().getId(), novelChapter.getId());
            request.setAttribute("novelChapter", novelChapter);
            request.setAttribute("lastPageId", lastPageId);
            request.setAttribute("nextPageId", nextPageId);
            new CreateStaticHTMLPage().createStaticHTMLPage(request, response, getServletContext(), 
                    chapterFileName, chapterFilePath, "/bookRead.jsp");
        }
    }
    生成HTML静态页面的类:

    package com.jb.y2t034.thefifth.web.servlet;
    import java.io.ByteArrayOutputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpServletResponseWrapper;
    /**
    * 创建HTML静态页面
    * 功能:创建HTML静态页面
    * 时间:2009年1011日
    * 地点:home
    * @author mavk
    *
    */
    public class CreateStaticHTMLPage {
        /**
         * 生成静态HTML页面的方法
         * @param request 请求对象
         * @param response 响应对象
         * @param servletContext Servlet上下文
         * @param fileName 文件名称
         * @param fileFullPath 文件完整路径
         * @param jspPath 需要生成静态文件的JSP路径(相对即可)
         * @throws IOException
         * @throws ServletException
         */
        public void createStaticHTMLPage(HttpServletRequest request, HttpServletResponse response,ServletContext servletContext,String fileName,String fileFullPath,String jspPath) throws ServletException, IOException{
            response.setContentType("text/html;charset=gb2312");//设置HTML结果流编码(即HTML文件编码) 
            RequestDispatcher rd = servletContext.getRequestDispatcher(jspPath);//得到JSP资源 
            final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();//用于从ServletOutputStream中接收资源 
            final ServletOutputStream servletOuputStream = new ServletOutputStream(){//用于从HttpServletResponse中接收资源 
                public void write(byte[] b, int off,int len){
                    byteArrayOutputStream.write(b, off, len);
                }
                public void write(int b){
                    byteArrayOutputStream.write(b);
                }
            };
            final PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream));//把转换字节流转换成字符流 
            HttpServletResponse httpServletResponse = new HttpServletResponseWrapper(response){//用于从response获取结果流资源(重写了两个方法) 
                public ServletOutputStream getOutputStream(){
                    return servletOuputStream;
                }
                public PrintWriter getWriter(){
                    return printWriter;
                }
            };
            rd.include(request, httpServletResponse);//发送结果流 
            printWriter.flush();//刷新缓冲区,把缓冲区的数据输出 
            FileOutputStream fileOutputStream = new FileOutputStream(fileFullPath);
            byteArrayOutputStream.writeTo(fileOutputStream);//把byteArrayOuputStream中的资源全部写入到fileOuputStream中 
            fileOutputStream.close();//关闭输出流,并释放相关资源 
            response.sendRedirect(fileName);//发送指定文件流到客户端 
        }
    }


    三:高并发高负载类网站关注点之缓存、负载均衡、存储

    缓存是另一个大问题,我一般用memcached来做缓存集群,一般来说部署10台左右就差不多(10g内存池)。需要注意一点,千万不能用使用
    swap,最好关闭linux的swap。


    负载均衡/加速

    可能上面说缓存的时候,有人第一想的是页面静态化,所谓的静态html,我认为这是常识,不属于要点了。页面的静态化随之带来的是静态服务的
    负载均衡和加速。我认为Lighttped+Squid是最好的方式了。
    LVS <------->lighttped====>squid(s) ====lighttpd

    上面是我经常用的。注意,我没有用apache,除非特定的需求,否则我不部署apache,因为我一般用php-fastcgi配合lighttpd,
    性能比apache+mod_php要强很多。

    squid的使用可以解决文件的同步等等问题,但是需要注意,你要很好的监控缓存的命中率,尽可能的提高的90%以上。
    squid和lighttped也有很多的话题要讨论,这里不赘述。


    存储
    存储也是一个大问题,一种是小文件的存储,比如图片这类。另一种是大文件的存储,比如搜索引擎的索引,一般单文件都超过2g以上。
    小文件的存储最简单的方法是结合lighttpd来进行分布。或者干脆使用Redhat的GFS,优点是应用透明,缺点是费用较高。我是指
    你购买盘阵的问题。我的项目中,存储量是2-10Tb,我采用了分布式存储。这里要解决文件的复制和冗余。
    这样每个文件有不同的冗余,这方面可以参考google的gfs的论文。
    大文件的存储,可以参考nutch的方案,现在已经独立为hadoop子项目。(你可以google it)

    其他:
    此外,passport等也是考虑的,不过都属于比较简单的了。
    四:高并发高负载网站的系统架构之图片服务器分离
    大家知道,对于Web 服务器来说,不管是Apache、IIS还是其他容器,图片是最消耗资源的,于是我们有必要将图片与页面进行分离,这是基本上大型网站都会采用的策略,他 们都有独立的图片服务器,甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保证系统不会因为图片问题而崩溃,在应用 服务器和图片服务器上,可以进行不同的配置优化,比如apache在配置ContentType的时候可以尽量少支持,尽可能少的LoadModule, 保证更高的系统消耗和执行效率。


    利用Apache实现图片服务器的分离
    缘由:
    起步阶段的应用,都可能部署在一台服务器上(费用上的原因)
    第一个优先分离的,肯定是数据库和应用服务器。
    第二个分离的,会是什么呢?各有各的考虑,我所在的项目组重点考虑的节约带宽,服务器性能再好,带宽再高,并发来了,也容易撑不住。因此,我这篇文章的重点在这里。这里重点是介绍实践,不一定符合所有情况,供看者参考吧,
    环境介绍:
    WEB应用服务器:4CPU双核2G, 内存4G
      部署:Win2003/Apache Http Server 2.1/Tomcat6
    数据库服务器:4CPU双核2G, 内存4G
      部署:Win2003/MSSQL2000
    步骤:
    步骤一:增加2台配置为:2CPU双核2G,内存2G普通服务器,做资源服务器
      部署:Tomcat6,跑了一个图片上传的简单应用,(记得指定web.xml的<distributable/>),并指定域名为res1.***.com,res2.***.com,采用ajp协议
    步骤二:修改Apache httpd.conf配置
      原来应用的文件上传功能网址为:
       1、/fileupload.html
       2、/otherupload.html
      在httpd.conf中增加如下配置

    <VirtualHost *:80> 
      ServerAdmin webmaster@***.com 
      ProxyPass /fileupload.html balancer://rescluster/fileupload lbmethod=byrequests stickysession=JSESSIONID nofailover=Off timeout=5 maxattempts=3    
      ProxyPass /otherupload.html balancer://rescluster/otherupload.html lbmethod=byrequests stickysession=JSESSIONID nofailover=Off timeout=5 maxattempts=3    
      #<!--负载均衡--> 
      <Proxy balancer://rescluster/> 
        BalancerMember ajp://res1.***.com:8009 smax=5 max=500 ttl=120 retry=300 loadfactor=100 route=tomcat1 
        BalancerMember ajp://res2.***.com:8009 smax=5 max=500 ttl=120 retry=300 loadfactor=100 route=tomcat2 
      </Proxy> 
     
    </VirtualHost>
    步骤三,修改业务逻辑:
      所有上传文件在数据库中均采用全url的方式保存,例如产品图片路径存成:http://res1.***.com/upload/20090101/product120302005.jpg

    现在,你可以高枕无忧了,带宽不够时,增加个几十台图片服务器,只需要稍微修改一下apache的配置文件,即可。

    五:高并发高负载网站的系统架构之数据库集群和库表散列

    大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。
      
      在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是类似的方案,您使用了什么样的DB,就参考相应的解决方案来实施即可。
      
       上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并 且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者 功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这样的 架构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行散列数据库和表,最终可以在配置文件中进行简单的配置便能让系 统随时增加一台低成本的数据库进来补充系统性能。


    集群软件的分类:
    一般来讲,集群软件根据侧重的方向和试图解决的问题,分为三大类:高性能集群(High performance cluster,HPC)、负载均衡集群(Load balance cluster, LBC),高可用性集群(High availability cluster,HAC)。
    高性能集群(High performance cluster,HPC),它是利用一个集群中的多台机器共同完成同一件任务,使得完成任务的速度和可靠性都远远高于单机运行的效果。弥补了单机性能上的不足。该集群在天气预报、环境监控等数据量大,计算复杂的环境中应用比较多;
    负载均衡集群(Load balance cluster, LBC),它是利用一个集群中的多台单机,完成许多并行的小的工作。一般情况下,如果一个应用使用的人多了,那么用户请求的响应时间就会增大,机器的性能也会受到影响,如果使用负载均衡集群,那么集群中任意一台机器都能响应用户的请求,这样集群就会在用户发出服务请求之后,选择当时负载最小,能够提供最好的服务的这台机器来接受请求并相应,这样就可用用集群来增加系统的可用性和稳定性。这类集群在网站中使用较多;
    高可用性集群(High availability cluster,HAC),它是利用集群中系统 的冗余,当系统中某台机器发生损坏的时候,其他后备的机器可以迅速的接替它来启动服务,等待故障机的维修和返回。最大限度的保证集群中服务的可用性。这类系统一般在银行,电信服务这类对系统可靠性有高的要求的领域有着广泛的应用。
    2 数据库集群的现状
    数据库集群是将计算机集群技术引入到数据库中来实现的,尽管各厂商宣称自己的架构如何的完美,但是始终不能改变Oracle当先,大家追逐的事实,在集群的解决方案上Oracle RAC还是领先于包括微软在内的其它数据库厂商,它能满足客户高可用性、高性能、数据库负载均衡和方便扩展的需求。
    Oracle’s Real Application Cluster (RAC)
    Microsoft SQL Cluster Server (MSCS)
    IBM’s DB2 UDB High Availability Cluster(UDB)
    Sybase ASE High Availability Cluster (ASE)
    MySQL High Availability Cluster (MySQL CS)
    基于IO的第三方HA(高可用性)集群
    当前主要的数据库集群技术有以上六大类,有数据库厂商自己开发的;也有第三方的集群公司开发的;还有数据库厂商与第三方集群公司合作开发的,各类集群实现的功能及架构也不尽相同。
    RAC(Real Application Cluster,真正应用集群)是Oracle9i数据库中采用的一项新技术,也是Oracle数据库支持网格计算环境的核心技术。它的出现解决了传统数据库应用中面临的一个重要问题:高性能、高可伸缩性与低价格之间的矛盾。在很长一段时间里,甲骨文都以其实时应用集群技术(Real Application Cluster,RAC)统治着集群数据库市场

    六:高并发高负载网站的系统架构之缓存

    缓存一词搞技术的都接触过,很多地方用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。
      架构方面的缓存,对Apache比较熟悉的人都能知道Apache提供了自己的缓存模块,也可以使用外加的Squid模块进行缓存,这两种方式均可以有效的提高Apache的访问响应能力。
       网站程序开发方面的缓存,Linux上提供的Memory Cache是常用的缓存接口,可以在web开发中使用,比如用Java开发的时候就可以调用MemoryCache对一些数据进行缓存和通讯共享,一些大 型社区使用了这样的架构。另外,在使用web语言开发的时候,各种语言基本都有自己的缓存模块和方法,PHP有Pear的Cache模块,Java就更多 了,.net不是很熟悉,相信也肯定有。



    Java开源缓存框架
    JBossCache/TreeCache JBossCache是一个复制的事务处理缓存,它允许你缓存企业级应用数据来更好的改善性能。缓存数据被自动复制,让你轻松进行Jboss服务器之间的集群工作。JBossCache能够通过Jboss应用服务或其他J2EE容器来运行一个Mbean服务,当然,它也能独立运行。 JBossCache包括两个模块:TreeCache和TreeCacheAOP。 TreeCache --是一个树形结构复制的事务处理缓存。 TreeCacheAOP --是一个“面向对象”缓存,它使用AOP来动态管理POJO
    OSCache OSCache标记库由OpenSymphony设计,它是一种开创性的JSP定制标记应用,提供了在现有JSP页面之内实现快速内存缓冲的功能。OSCache是个一个广泛采用的高性能的J2EE缓存框架,OSCache能用于任何Java应用程序的普通的缓存解决方案。OSCache有以下特点:缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。 拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性。 永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive-to-create)数据来保持缓存,甚至能让应用重启。 支持集群--集群缓存数据能被单个的进行参数配置,不需要修改代码。 缓存记录的过期--你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。
    JCACHE JCACHE是一种即将公布的标准规范(JSR 107),说明了一种对Java对象临时在内存中进行缓存的方法,包括对象的创建、共享访问、假脱机(spooling)、失效、各JVM的一致性等。它可被用于缓存JSP内最经常读取的数据,如产品目录和价格列表。利用JCACHE,多数查询的反应时间会因为有缓存的数据而加快(内部测试表明反应时间大约快15倍)。
    Ehcache Ehcache出自Hibernate,在Hibernate中使用它作为数据缓存的解决方案。
    Java Caching System JCS是Jakarta的项目Turbine的子项目。它是一个复合式的缓冲工具。可以将对象缓冲到内存、硬盘。具有缓冲对象时间过期设定。还可以通过JCS构建具有缓冲的分布式构架,以实现高性能的应用。 对于一些需要频繁访问而每访问一次都非常消耗资源的对象,可以临时存放在缓冲区中,这样可以提高服务的性能。而JCS正是一个很好的缓冲工具。缓冲工具对于读操作远远多于写操作的应用性能提高非常显著。
    SwarmCache SwarmCache是一个简单而功能强大的分布式缓存机制。它使用IP组播来有效地在缓存的实例之间进行通信。它是快速提高集群式Web应用程序的性能的理想选择。
    ShiftOne ShiftOne Object Cache这个Java库提供了基本的对象缓存能力。实现的策略有先进先出(FIFO),最近使用(LRU),最不常使用(LFU)。所有的策略可以最大化元素的大小,最大化其生存时间。
    WhirlyCache Whirlycache是一个快速的、可配置的、存在于内存中的对象的缓存。它能够通过缓存对象来加快网站或应用程序的速度,否则就必须通过查询数据库或其他代价较高的处理程序来建立。
    Jofti Jofti可对在缓存层中(支持EHCache,JBossCache和OSCache)的对象或在支持Map接口的存储结构中的对象进行索引与搜索。这个框架还为对象在索引中的增删改提供透明的功能同样也为搜索提供易于使用的查询功能。
    cache4j cache4j是一个有简单API与实现快速的Java对象缓存。它的特性包括:在内存中进行缓存,设计用于多线程环境,两种实现:同步与阻塞,多种缓存清除策略:LFU, LRU, FIFO,可使用强引用(strong reference)与软引用(soft reference)存储对象。
    Open Terracotta 一个JVM级的开源群集框架,提供:HTTP Session复制,分布式缓存,POJO群集,跨越群集的JVM来实现分布式应用程序协调(采用代码注入的方式,所以你不需要修改任何)。
    sccache SHOP.COM使用的对象缓存系统。sccache是一个in-process cache和二级、共享缓存。它将缓存对象存储到磁盘上。支持关联Key,任意大小的Key和任意大小的数据。能够自动进行垃圾收集。
    Shoal Shoal是一个基于Java可扩展的动态集群框架,能够为构建容错、可靠和可用的Java应用程序提供了基础架构支持。这个框架还可以集成到不希望绑定到特定通信协议,但需要集群和分布式系统支持的任何Java产品中。Shoal是GlassFish和JonAS应用服务器的集群引擎。
    Simple-Spring-Memcached Simple-Spring-Memcached,它封装了对MemCached的调用,使MemCached的客户端开发变得超乎寻常的简单。
    展开全文
  • 前沿: 继续扩展我的golang服务端,这边有些数据库是没有权限的,对方给了我webservices的接口,针对异常的数据,我要去抓数据,再次分析,golang貌似没有python那么多的模拟浏览器访问的模块,还好默认的http就支持...
  • 并发API接口限流

    万次阅读 多人点赞 2018-08-29 17:56:08
    在开发高并发系统时有三... 限流 限流的目的是通过对并发访问/请求进行限速,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理 问题描述   某天A君突然...
  • 明人不说暗话,跟着阿笨一起玩WebApi。在我们平时开发项目中可能会出现下面这些情况; 1)、由于用户误操作,多次点击网页表单提交按钮。由于网速等原因造成页面卡顿,用户重复刷新提交页面。黑客或恶意用户使用...
  • SpringBoot使用异步线程处理热点接口提高接口并发环境参数配置步骤1.配置项 @Configuration SysConfigure2.配置文件 application.yml3.控制器 Controller4.业务接口 Service5.结果 环境参数 SpringBoot版本 :2.1.0....
  • Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快能实现高并发。得利于其 非阻塞的方式和对epoll的运用,Tornado 每秒可以处理数以千计的连接...
  • 衡量一个接口是否能够支撑高并发,我们最先想到的就是他的QPS是多少,影响QPS大小的关键因素是你的系统是否支持分布式、高并发,当提起这几三个词的时候,是不是很多人都认为分...
  • 点击上方“朱小厮的博客”,选择“设为星标”后台回复”加群“加入公众号专属技术群在开发分布式高并发系统时有三把利器用来保护系统:缓存、降级、限流缓存缓存的目的是提升系统访问速度和增大系统处...
  • import base64 import os import urllib import numpy as np import requests, time, json, threading, ... 并发压力测试 """ def __init__(self, press_url): self.press_url = press_url def test_interface(se.
  • 在某请求处理过程中,其它所有的请求将被忽略,因此,在并发请求较多的场景中将会出现严重的性能问题。(即一次只能处理一个请求) 二、多进程/多线程web服务器此种架构方式中,web服务器生成多个进程或线程并行...
  • 在使用Swagger WebApi文档框架时,一个Controll中写多个Post接口时,在MVC4中会提示无法识别的多个post请求,原因是WebApiConfig中默认路由配置中是没有配置{action}引起的。 【在MVC5中没有此问题,原因是MVC5有...
  • web并发量的处理方案

    万次阅读 2018-07-16 21:46:30
    随着互联网业务的不断丰富,网站相关的技术经过这些年的发展,已经细分到很细的方方面面,尤其对于大型网站来说,所采用的技术更是涉及面非常广,从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有...
  • Java高并发秒杀API(三)之Web

    千次阅读 2017-10-05 18:03:54
    Java高并发秒杀API(三)之Web层1. 设计前的分析 Web层内容相关前端交互设计 Restful规范 SpringMVC Bootstrap + jQuery 前端页面流程 详情页流程逻辑 为什么要获取标准系统时间(服务器的时间) 用户可能处在不同...
  • Java高并发秒杀API(四)之高并发优化

    万次阅读 多人点赞 2017-10-06 17:07:54
    Java高并发秒杀API(四)之高并发优化1. 高并发优化分析 关于并发 并发性上不去是因为当多个线程同时访问一行数据时,产生了事务,因此产生写锁,每当一个获取了事务的线程把锁释放,另一个排队线程才能拿到写锁,QPS...
  • 写在前面: 本文接上文前端篇,将为大家使用.NETWebAPI实现获取用户信息的接口 ...1.创建一个WebAPI项目 2.在Nuget中安装 Senparc.Weixin.MP 在程序包管理控制台中输入 Install-packageSenp...
  • REST API 并发控制

    千次阅读 2016-09-17 21:32:56
    对请求做并发限制是在后端处理能力有限的情况下,防止因某单一用户大量请求将服务器资源暂满导致无法响应其他用户请求的安全保护措施。常见的并发限制方法就是限制用户在某一段时间内的请求数目,如100r/s,即限制...
  • Web层涉及到的技术: 前端交互:页面之间的交互和交互细节 Restful:前端设计接口之间的一种常用的规范 Spring MVC:框架整合,以及如何应用设计和实现Restful接口 Bootstrap和jquery:前者负责页面布局和样式控制...
  • 解决web并发概括

    千次阅读 2018-11-12 14:37:08
    所谓高并发,就是同一时间有很多流量(通常指用户)访问程序的接口、页面及其他资源,解决高并发就是当流量峰值到来时保证程序的稳定性。 我们一般用QPS(每秒查询数,又叫每秒请求数)来衡量程序的综合性能,数值越高越...
  • 最近在处理项目的充值接口时遇到了并发操作,导致数据库重复插入充值记录,找了很多并发处理方法都没奏效,最后整理出一套成功的解决方案,用php文件锁定的方法来处理并发事件。亲测:非常好用,希望可以为你们的问题...
  • 并发接口性能设计思路与代码编写1. 引言2. 并发测试定义3. 并发测试分类4....因为我不管是在内部技术分享,还是对个人的培训中,都发现:很多人并不清楚接口并发测试的整体流程,或者说,并没有参与过整个
  • 基于laravel制作API接口

    千次阅读 2020-05-31 17:04:04
    基于laravel制作API接口 关于API API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或...
  • 提升WebAPI性能的几个小建议

    千次阅读 2020-05-06 08:18:00
    提升WebAPI性能的几个小建议原文来自互联网,由长沙DotNET技术社区编译。本文作者:德本德拉·达什(Debendra Dash)原文来自:https://www.c-sharpc...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 78,152
精华内容 31,260
关键字:

webapi接口并发处理