preface
Why suddenly want to write a summary of it, in fact, is also abused. At the beginning of March this year, our mall received a XX bank of a purchase activity (say white point is to pull wool), that time is the first phase of the activity, did not think of activities when the entrance is open, flow can directly CPU rush to 100%, resulting in short service 502. During this period, an emergency plan was adopted until the end of the campaign, but it was not expected that there would be a second campaign and a third campaign, which was launched last week. Think of the recent period of time also did some things, there are some pits, take this opportunity, don’t lazy record.
What did the activity do from the first to the third period
Technical background & bottlenecks
The project is based on Vue+SSR architecture, and there is no cache processing. The main reason for the lack of cache is that the first reason is that the original APPLICATION of TPS is relatively low, and the transformation power is not strong, and the page rendering results contain user data and server time, so it cannot be directly cached without modification. So it’s easy to hit the CPU to 100% with high concurrency when the first phase activity hits with a lot of traffic.
Issue in unknown circumstances, service directly carry not to live, to activities can be carried out as normal and at that time, the first solution is to add the machine manage partial pressure, and then add cache, there are two kinds of buffer solution, cache pages or cache components, but because we need to cache the commodity details page component involves the dynamic information, poor maintainability and mental cost is high, The former was chosen. We sorted out the information data about dynamic changes (time/user related data, etc.) on the business page. During the activity, we urgently blocked some dynamic content that does not affect the function, and then the CDN on the page.
After the activity, we did a review. To ensure the stable operation of the application under the condition of large traffic, performance optimization is inevitable. To this end, we have made the following four plans:
-
Separation of dynamic and dynamic data: we can classify data into dynamic and static data. Static data is the data that does not change with time/user in a period of time, while dynamic data is on the contrary, which changes frequently and is related to time and user. Data can be classified as dynamic data. The biggest obstacle to caching the original page is that node renders the template by default, fetching the user data, or invoking the user interface in asyncData. In addition, dynamic data such as server time is set. So the idea is to put static data in node to get the dynamic data in the client (browser read asyncData, mounted and other browser life cycle) to get the server clean.
-
Page access to CDN: After dynamic and static separation, its path can be added to the CDN. However, it is necessary to pay attention to whether parameters such as Query on the path will affect the rendering. If so, it is necessary to move the logic to the client. At the same time, it is necessary to pay attention to whether the expiration time (such as 10 minutes) will affect the business
-
Application caching: If, in a bad case, the CDN fails and the return rate increases, the application itself still needs to be prepared. Select the memory cache/Redis cache according to the project needs.
-
Automatic degradation: In extreme cases where the previous cache is not blocking the traffic, the ultimate solution is to degrade the render. The so-called degrade rendering, is not into the route, directly return the empty template, completely left to the browser to do rendering. The biggest benefit of this is that node stress is completely avoided and an SSR application becomes static. The downside is obvious. The user sees an empty template waiting for initialization. Then how to automatically degrade it, you can always detect the CPU, load and other pressure through the timer, to determine the load of the current machine, so as to determine whether to degrade; You can also explicitly determine whether or not to degrade by carrying a specific identifier on the QUERY of the URL.
After the above performance optimization of the project scheme, the following is the pressure test, which can be regarded as a smooth online. ðĪŠ
The second phase of the campaign came soon after, but as we expected, the project held up well, adding traffic interfaces and friendly tips. However, one of the pain points needs to do a copy processing for a few special commodities. These copies are not returned by the interface, but also some temporary eye-catching prompts. There is no need to return them in the interface of the detail page. Due to the urgency of time, we are not sure whether there are specific copywriting needs (related to specific pages and specific areas) in the future, so we decide to write some low codes temporarily: temporarily add copywriting for specific activity commodity ID, and remove copywriting after the activity goes offline. This is risky, since the code is temporary, requires up-and-down, and has time delays. But fortunately, the end of the activity is the weekend, the last day of traffic access is not large, to the corresponding guidance copy and after-sales processing, evaluation down the impact is not big, acceptable.
The following pictures show the specific copy that needs to be added to the product details page and product purchase page:
Wool pulling activity is really sweet scene ~ ~ at the end of June products and I said hello, XX activities and have three, but the overall program is still the same as the second. My heart: still come?? Because the final time has not been decided, and after the lesson of the second phase, I have discussed with the students in the back end, and it is feasible to consider the activity commodities in the direction of configuration, and put them in our configuration background Chinese case module. For the commodity details page, considering that the separation of activity and activity is not damaged, the data returned by the configured interface is static and can be obtained on the server. The following three specific things to do:
- Make the copywriting of the commodities participating in the activity into configuration, get it from the configuration interface, and remove the low code
- After the TPS of the interface reaches a certain level, the interface returns to the 429 state. The front end performs fault tolerance processing to ensure that the page functions can be accessed normally and the interface faults are blocked.
- For the purchase of traffic limiting interfaces, you need to give busy hints (the activity is too hot, please try again later)
/ / the United States in 429 at getResponseErrorInterceptor do processing export const getResponseErrorInterceptor = ({errorCallback}) = > (error) => { if (! isClient) { ... } else {// if (+error.response.status === 429) {// If (+error.response.status === 429) { ErrorCallback (error.config.needbusYMsg? 'Activity is too hot, please try again later' : null); } else { ... ) ; } } return throwError(error); };Copy the code
After a busy week of pressure testing and testing last week, the third phase was finally put online. ð ð ð ð
For more information on Vue SSR performance optimization, go to Vue SSR Performance Optimization Practices
Some Coding questions encountered in the actual process
- In the local project (VUe-SSR architecture), when a dynamic interface is placed on the server to obtain, there is a code very easy, a member identifier to open the member button implicit, the code is as follows (the code is simplified) :
<redirect v-if="! "> < span style =" box-sizing: border-box; color: RGB (255, 255, 255); line-height: 22px; font-size: 13px! Important; white-space: normal;"Copy the code
Vue.esm.js :6428 Mismatching childNodes vs. VNodes: NodeList(2) [div, a.DetailVip-right.Redirect] (2) [VNode, VNode]
[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.
But update to the test environment, the page will be invalid, click invalid, etc. Failed to execute ‘appendChild’ on ‘Node’: This Node type does not support This method
Analysis of the
The Vue SSR guide just mentions some of the pitfalls in client activation. One thing to be aware of when using the “SSR + client mix” is the particular HTML structure that the browser may change. For example, missing in the table can cause the static HTML returned by the server to be inconsistent with the content rendered by the browser:
- invalid
HTML
(e.g.: < p > < p > Text < / p > < / p >
) - Different status of the server and client
- Such as the impact of uncertain variables such as dates, time stamps, and randomization
- Third-party scripts affect component rendering
- Authentication is required when relevant
Of course, after determining the cause, there are several ways to solve this problem:
- Check the code to make sure the HTML is valid
- One of the simplest ways to do this is to use
v-show
To replacev-if
, you know the build time generationHTML
Is stateless, and all parts of the application related to authentication should be rendered only on the client side. Specifically, data can be fetched under diff and content rendered on the server/client side, resolving state inconsistencies between the server and client - For third-party scripts and the like, you can avoid rendering components on the server side by wrapping them in tags
- . (Additional information is welcome)
According to this kind of problem, can also take a look at this article: blog. Lichter. IO/posts/vue – h…
2: The same H5 page, open in the browser configuration takes effect, and open in the public number & small program is invalid?
In the third issue, we configured the activity commodity ID and corresponding copywriting. The configuration mode is as follows:
After going through json.stringify (), you will undoubtedly get the following string:
455164527672033280 | dragon pay minus 10 yuan | full 40 stood minus 10 # XX card (only) \ \ n623841656577658880 | dragon pay set minus 10 yuan (only XX card) | full 40 set minus 10 (XX only Card) # \ \ n350947143063699456 | dragon pay test set minus 10 yuan (only XX card) | full 40 set minus 10 # test (only XX card)Copy the code
In the details page to get all the item ID list information, we use # to distinguish, write a simple re as follows:
activityItems() { return this.getFieldValue('activity_item')? .split('#\\n'); },Copy the code
But open our H5 link in the public account, will automatically escape # into \, the content will become:
455164527672033280 | dragon cover set minus 10 yuan (only XX card) | full 40 set minus 10 (only XX card) \ \ \ n623841656577658880 | dragon pay set minus 10 yuan (only XX card) | full 40 set minus 10 (XX only Card) \ \ \ n350947143063699456 | dragon pay test set minus 10 yuan (only XX card) | full 40 set minus 10 test \ XX card (only)Copy the code
Oh, really? ðĐ Fix: immediately replace the # character with a character that cannot be transferred; .
In addition, the failure of opening in the small program was due to the extension of the second phase scheme. At that time, the restriction judgment was made, which only needed to be opened in the main station and the main APP. The small program has its own separate APPID, and the third phase activity has multiple entrances, so the restriction can be released.
conclusion
While collecting wool to participate in three periods, but also accumulated some experience, step on some pits, thinking too long did not write the record, first summed up here, and forget to add ~
conclusion
- Vue SSR preview: ssr.vuejs.org/zh/
- Vue SSR performance practice: juejin.cn/post/688788…
- Vur hydration – error: blog. Lichter. IO/posts/vue – h…