Spring Cloud+Dubbo對Feign進行RPC改造

由於Spring Cloud Feign是基於Http Restful的調用,在高併發下的性能不夠理想(雖然他是基於Ribbon以及帶有熔斷機制,能夠防止雪崩),成爲性能瓶頸,因此咱們今天對Feign進行Dubbo的RPC改造。git

咱們Spring Cloud的項目結構以下github

其中user-center是咱們的用戶中心,game-center是咱們的遊戲中心,以遊戲中心調用用戶中心的Feign以下spring

@Component
@FeignClient("user-center")
public interface UserClient {

    @PutMapping("/api-u/users-anon/internal/updateAppUser")
    AppUser updateUser(@RequestBody AppUser appUser);

    @PostMapping("/api-u/users-anon/internal/users/updateUserBanlance")
    String updateUserBanlance(@RequestParam("id") long id, @RequestParam("banlance") BigDecimal banlance);
}

咱們先來改造用戶中心做爲Dubbo的提供者,pom添加Dubbo的引用api

<dependency>
   <groupId>com.alibaba.spring.boot</groupId>
   <artifactId>dubbo-spring-boot-starter</artifactId>
   <version>2.0.0</version>
</dependency>
<dependency>
   <groupId>com.github.sgroschupf</groupId>
   <artifactId>zkclient</artifactId>
   <version>0.1</version>
</dependency>

將service接口放入公共模塊api-model併發

public interface AppUserService {
   void addTestUser(AppUser user);

   void addAppUser(AppUser appUser);

   void updateAppUser(AppUser appUser);

   LoginAppUser findByUsername(String username);

   AppUser findById(Long id);

   void setRoleToUser(Long id, Set<Long> roleIds);

   void updatePassword(Long id, String oldPassword, String newPassword);

   void updateWithdrawal(Long id, String oldPassword, String newPassword);

   Page<AppUser> findUsers(Map<String, Object> params);

   Set<SysRole> findRolesByUserId(Long userId);

   void bindingPhone(Long userId, String phone);

   int updateUserBanlance(long id, BigDecimal banlance);

   Map<String, Object> findUserMapById(long userId);

   Page<Map<String, Object>> findUsers(String username, BigDecimal minBanlance, BigDecimal maxBanlance, String startTime, String endTime, Integer groupId, Integer control, int pageNo, int pageSize);

   void deleteTestUser(Assist assist);
}

用戶中心資源配置,添加dubbo配置app

spring:
  application:
    name: user-center
  cloud:
    config:
      discovery:
        enabled: true
        serviceId: config-center
      profile: dev
  dubbo:
    application:
      id: user-center-dubbo-prodiver
      name: user-center-dubbo-prodiver
    registry:
      address: zookeeper://192.168.5.129:2181
    server: true
    protocol:
      name: dubbo
      port: 20880

接口實現類的標籤修改負載均衡

@Slf4j
@Service(interfaceClass = AppUserService.class)
@Component
public class AppUserServiceImpl implements AppUserService {

其中這個@Service已經再也不是spring的標籤,而須要使用,spring-boot

import com.alibaba.dubbo.config.annotation.Service;

的Dubbo標籤高併發

以前的spring @Service改用@Component性能

在Springboot的主類添加Dubbo的配置標籤

@EnableDubboConfiguration
@EnableScheduling
@EnableSwagger2
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class UserCenterApplication {

   public static void main(String[] args) {
      SpringApplication.run(UserCenterApplication.class, args);
   }

}

此時啓動用戶中心項目,能夠在Dubbo主控臺中看到

點進去能夠看到提供者註冊信息

而後再來看看遊戲中心的消費者

pom依賴跟用戶中心同樣

資源文件配置添加Dubbo配置

spring:
  application:
    name: game-center
  cloud:
    config:
      discovery:
        enabled: true
        serviceId: config-center
      profile: dev
  dubbo:
    application:
      name: game-center-dubbo-consumer
      id: game-center-dubbo-consumer
    protocol:
      port: 20800
      name: dubbo
    registry:
      address: zookeeper://192.168.5.129:2181

在使用的Controller中註釋掉以前的feign注入,使用Dubbo的接口

//    @Autowired
//    private UserClient userClient;
@Reference
private AppUserService appUserService;

由於該接口在公共模塊api-model中,因此任何模塊均可以識別的到,此時須要使用Dubbo的註釋

import com.alibaba.dubbo.config.annotation.Reference;

在Springboot主類中添加Dubbo註釋

@EnableDubboConfiguration
@EnableScheduling
@EnableSwagger2
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class GameCenterApplication {

   public static void main(String[] args) {
      ApplicationContext context = SpringApplication.run(GameCenterApplication.class, args);
      SpringBootUtil.setApplicationContext(context);
   }
}

啓動遊戲中心項目,在Dubbo控制檯中的消費者中,咱們能夠看到

點進去能夠看到消費者註冊信息

這樣咱們在實際使用中,將以前的feign代碼改爲直接使用該service接口就能夠經過RPC的遠程調用了

//調用userService更新用戶信息 TODO
//        userClient.updateUser(user);
        appUserService.addAppUser(user);

最後就是進行壓測,性能要絕對優於Feign調用的吞吐量。

另外Springboot Dubbo的調試直連提供者,只鏈接固定IP的提供者,繞過註冊中心,不進行負載均衡

@Reference(url = "dubbo://192.168.5.33:20880")
private AppUserService appUserService;

此方法只能在測試時使用,生產環境中必須去掉。

消息只訂閱

dubbo:
  application:
    id: user-center-dubbo-prodiver
    name: user-center-dubbo-prodiver
  registry:
    address: zookeeper://192.168.5.129:2188
    register: false
  server: true
  protocol:
    name: dubbo
    port: 20880

這麼寫,註冊中心註冊不到你,其餘消費者調用不到你這個服務,只有像上面直連提供者那種才能夠調用的到。

這個也只是在測試環境裏面使用,生產環境必須去掉 register: false 

相關文章
相關標籤/搜索