由於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